盒子
盒子
文章目录
  1. JAVA基础
    1. 1. JAVA中的几种基本数据类型是什么,各自占用多少字节。
    2. 2. String类能被继承吗,为什么
    3. 3. String,StringBuffer,StringBuilder的区别及扩容机制
    4. 4. ArrayList和LinkedList有什么区别
    5. 5. 讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序。
    6. 6. 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。
    7. 6.1 为什么HashMap是非线程安全的?什么情况下会出现线程安全问题?
    8. 7. JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计
    9. 8. 有没有有顺序的Map实现类,如果有,他们是怎么保证有序的
    10. 9. 抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么
    11. 10. 继承、组合、聚合有什么区别
    12. 11. IO模型有哪些,讲讲你理解的nio ,他和bio,aio的区别是啥,谈谈reactor模型
    13. 12. 反射的原理,反射创建类实例的三种方式是什么
    14. 13. 反射中,Class.forName和ClassLoader区别
    15. 14. 描述动态代理的几种实现方式,分别说出相应的优缺点
    16. 15. 为什么CGlib方式可以对接口实现代理
    17. 16. final的用途
    18. 17, 写出单例模式的三种实现方式
    19. 18. 如何在父类中为子类自动完成所有的hashcode和equals实现?这么做有何优劣
    20. 18. 请结合OO设计理念,谈谈访问修饰符public、private、protected、default在应用设计中的作用。
    21. 19. 深拷贝和浅拷贝区别
    22. 20. 数组和链表数据结构描述,各自的时间复杂度
    23. 21. error和exception的区别,CheckedException,RuntimeException的区别
    24. 22. 请列出5个运行时异常
    25. 23. 在自己的代码中,如果创建一个java.lang.String类,这个类是否可以被类加载器加载?为什么
    26. 24. 在jdk1.5中,引入了泛型,泛型的存在是用来解决什么问题(太保面试题)
    27. 25. 这样的a.hashcode() 有什么用,与a.equals(b)有什么关系
    28. 26. 有没有可能2个不相等的对象有相同的hashcode
    29. 27. Java中的HashSet内部是如何工作的
    30. 28. 什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决
    31. 29. java8的新特性

腾讯篇之JAVA基础

JAVA基础

1. JAVA中的几种基本数据类型是什么,各自占用多少字节。

数据类型 字节 默认值
byte 1 0
short 2 0
char 2 ‘\u0000’
int 4 0
float 4 0.0f
long 8 0
double 8 0.0d
boolean 4 false

PS: JVM规范中,boolean当做int处理,也就是4字节,而boolean数组当做byte数组处理,即boolean类型的数组里面每一个元素占一个字节

2. String类能被继承吗,为什么

不可以,因为String类有final,而final修饰的类是不能被继承的

3. String,StringBuffer,StringBuilder的区别及扩容机制

  • String:不可变,每次对String进行操作都会产生新对象,效率低且浪费内存空间
  • StringBuffer: 可变字符序列,效率低,线程安全
  • StringBuilder: 可变字符序列,效率高,线程不安全

StringBuilder、 StringBuffer继承AbstractStringBuilder,无参数默认初始容量为16,
追加字符串的时候长度超过16则扩容:增加自身长度一倍再加2,如果还放不下,则扩容为所需长度minCapacity

1
2
3
4
5
6
private int newCapacity(int minCapacity) {
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
}

4. ArrayList和LinkedList有什么区别

  • ArrayList: 基于数组实现的非线程安全的集合。查询速度快,插入、删除中间元素速度慢
  • LinkedList: 基于链表实现的非线程安全的集合。查询速度慢,插入、删除中间元素快
  • Vector: 基于数组实现的线程安全的集合。采用synchronize加锁,性能比ArrayList差
  • CopyOnWriteArrayList: 基于数组实现的线程安全的写时复制集合,采用ReentrantLock加锁,性能比Vector高,适合读多写少的场景

5. 讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序。

父类静态变量
父类静态代码块
子类静态变量
子类静态代码块

父类非静态变量(父类实例成员变量)
父类构造函数
子类非静态变量(子类实例成员变量)
子类构造函数

6. 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。

HashMap、ConcurrentHashMap、TreeMap、 LinkedHashMap

HashMap线程不安全,由数组(Node数组)+链表+红黑树(链表长度大于8转换为红黑树)实现,采用hash表来存储,key采用hashcode,数量超过threshold时进行2倍扩容,默认容量16,负载因子0.75,桶的数量11,
采用链地址法解决hash冲突,简单来说,就是数组加链表的结合。在每个数组元素上都一个链表结构,当数据被Hash后,得到数组下标,把数据放在对应下标元素的链表上
Java 8系列之重新认识HashMap

大量采用CAS操作,JDK1.7对Segment进行加锁,JDK1.8对桶中的头结点进行加锁
ConcurrentHashMap的实现原理

TreeMap和LinkedHashMap有序的(TreeMap默认升序,LinkedHashMap记录插入的顺序)

6.1 为什么HashMap是非线程安全的?什么情况下会出现线程安全问题?

HashMap会进行resize操作,在resize操作的时候会造成线程不安全
1)put的时候导致多线程数据不一致
2)get操作可能因为resize而引起死循环(cpu100%)

7. JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计

Segment继承ReentrantLock,每个锁控制一段,当每个Segment越来越大时,锁定粒度则变大,性能会下降
ConcurrentHashMap底层采用数组+链表+红黑树,大量采用CAS操作,加锁采用synchronized,只对桶的头节点进行加锁,粒度较小。

减少内存开销。如果采用ReentrantLock需要节点继承AQS来获得同步支持,增加内存开销,
内部优化。synchronized是有JVM直接支持的,JVM能够在运行时做相应优化如,锁粗化、锁消除、锁自旋等

8. 有没有有顺序的Map实现类,如果有,他们是怎么保证有序的

TreeMap和LinkedHashMap有序的(TreeMap默认升序,LinkedHashMap记录插入的顺序)
TreeMap是基于比较器Comparator实现有序的,LinkedHashMap是基于链表实现数据插入有序的

9. 抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么

  • 接口只能做方法声明,抽象类既可以做方法声明也可以做方法实现
  • 接口里定义的变量只能是公共的静态常量,抽象类中变量是普通变量
  • 抽象类里可以没有抽象类,如果一个类中有抽象方法,则一定是抽象类
  • 抽象方法要被实现,所以不能是静态的,也不能是私有的
  • 接口继承接口,并可多继承接口,但类只能单继承

类不能继承多个类
接口可以继承多个接口
类可以实现多个接口

10. 继承、组合、聚合有什么区别

继承: is-a的关系,指一个类继承另一个类 public class A extends B{}

聚合:has-a, A可以有B public class A {List<B> b}

组合:contains-a,强聚合,A一定有B public class A {B b}

11. IO模型有哪些,讲讲你理解的nio ,他和bio,aio的区别是啥,谈谈reactor模型

BIO、NIO、AIO

BIO: 同步并阻塞 客户端有一个IO请求,服务端就需要启动一个线程进行处理。适用于连接数比较少,tomcat采用传统的BIO+线程池模式
NIO: 同步非阻塞 客户端的IO请求会注册到多路复用器上,多路复用器轮询到有IO请求时才启动一个线程处理。适用于连接数多且连接比较短(轻操作)的架构,比如聊天服务器
AIO: 异步非阻塞 客户端的IO请求都是有OS完成后,在通知服务器启动线程处理。适用于连接数多且连接比较长(重操作)的架构,如相册服务器

Reactor模型

  • 事件驱动
  • 可以处理一个或多个输入源
  • 通过Service Handle同步的将输入事件采用多路复用分发给相应的Request Handler(一个或多个)处理

12. 反射的原理,反射创建类实例的三种方式是什么

所谓的反射机制就是JAVA语言在运行时拥有一项自观的能力

1
2
3
4
5
Class class1 = HelloWorld.class;
Class class2 = helloWorld.getClass();
Class class3 = Class.forName("online.shenjian.HelloWorld");

class1.newInstance();

13. 反射中,Class.forName和ClassLoader区别

Class.forName(className)内部实际调用的是Class.forName(className, true, classLoader), 其中true表示表示初始化,静态变量与静态代码块执行
ClassLoader.loadClass(className)内部实际调用的是ClassLoader.loadClass(className, false), false表示目标对象不进行链接(即验证、准备、解析),意味着也不进行初始化工作,静态变量与静态代码块不执行

14. 描述动态代理的几种实现方式,分别说出相应的优缺点

JAVA动态代理 借助JAVA内部反射机制来生成代理接口匿名类,在调用具体方法前调用InvocationHandler,反射机制在生成类的过程中比较高效,应用前提必须为目标类基于统一的接口
CGLIB动态代理 借助ASM来实现,对代理对象的class文件加载进来,通过修改其字节码生成子类来处理,ASM在生成类后执行过程中比较高效

实现示例详见代理实现方式

15. 为什么CGlib方式可以对接口实现代理

对接口进行代理的CGLIB,最后的源码是实现了该接口和Factory接口
对实现类进行代理的CGLIB,最后的源码时继承了实现类并实现了Factory接口

16. final的用途

final修饰符既可以修饰类、方法,也可以修饰变量

  • 用final修饰的类不能被继承
  • 用final修饰的方法不能被重写
  • 用final修饰的变量只能赋值一次且不可修改,静态、实例、局部变量必须被明确赋值

17, 写出单例模式的三种实现方式

单例的三种实现方式

18. 如何在父类中为子类自动完成所有的hashcode和equals实现?这么做有何优劣

父类的equals方法不一定满足子类equals的需求,比如所有的对象都继承Object,默认使用其equals方法,比较两个对象的时候,看他们是否指向同一个地址
但我们的需求是对象的某个属性相同,就相同,此时需要重写equals方法与hashcode方法,否则会降低map等集合的索引速度

18. 请结合OO设计理念,谈谈访问修饰符public、private、protected、default在应用设计中的作用。

OO设计理念:封装、继承、多态

关键字 类内部 本包 子类 外部包
public
protected ×
default × ×
private × × ×

19. 深拷贝和浅拷贝区别

如果一个对象内部只有基本数据类型,呢么clone()方法获取到的就是这个对象的深拷贝,而如果其内部还有引用数据类型,那么clone()方法

浅拷贝 对基本数据类型进行值拷贝,对引用数据类型进行引用传递般的拷贝,此为浅拷贝

深拷贝 对基本数据类型进行值拷贝,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝

  • 序列化
  • clone方法 对其内部引用类型的变量,在进行一次clone

20. 数组和链表数据结构描述,各自的时间复杂度

数组: 元素在内存中连续存放,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。
链表: 元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。

数组和链表的区别:
1、从逻辑结构角度来看:
数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)
2、数组元素在栈区,链表元素在堆区;
3、从内存存储角度来看:
(静态)数组从栈中分配空间, 对于程序员方便快速,但自由度小。
链表从堆中分配空间, 自由度大但申请管理比较麻烦。
数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);
数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。

21. error和exception的区别,CheckedException,RuntimeException的区别

Error: 程序无法处理的错误,如OutOfMemory
Exception: 程序可以处理的异常

RuntimeException表示虚拟机运行时可能遇到的错误,只要程序设计的没有问题通常不会发生。如空指针、数组下标越界异常
CheckedException与运行的上下文环境有关,即使程序设计无误,仍然可能因为使用问题而发生。
编译器不要求声明抛出RuntimeException,要求必须声明抛出CheckedException,

22. 请列出5个运行时异常

ClassCastException、IndexOutOfBoundsException、NullPointerException、ArrayStoreException、BufferOverflowException

23. 在自己的代码中,如果创建一个java.lang.String类,这个类是否可以被类加载器加载?为什么

不能。由于双亲委派模型限制,先从父加载器加载,依次为引导类加载器 > 扩展类加载器 > 应用程序类加载器,父加载器找不到,才从子加载器加载,依次类推

24. 在jdk1.5中,引入了泛型,泛型的存在是用来解决什么问题(太保面试题)

泛型主要针对向下转型时带来的安全隐患,其核心组成是在声明类或接口时,不设置参数或属性的类型

类型擦除: 编译器声明的类型擦除并替换为Object(如果设置了上限如 T extend List)则替换为上限,最后插入强制转换,代码才能正常运行

25. 这样的a.hashcode() 有什么用,与a.equals(b)有什么关系

hashcode()提供了对象的hashcode值,是一个native函数,返回的默认值与System.identityHashCode(obj)一致
作用是用一个数字标识对象,比如HashMap中的key就是基于hashcode, hashcode只能说是标识对象,在hash算法中可以将对象相对离散些,但不是唯一的,根据hashcode定位到具体的链表后,需要循环链表,然后通过equals()方法来对比key是否是一致的。
equals相等的两个对象,hashcode一定相等;hashcode相等的两个对象不一定equals相等

26. 有没有可能2个不相等的对象有相同的hashcode

有。同25

27. Java中的HashSet内部是如何工作的

HashSet内部采用HashMap实现。实现了Set接口,不允许有重复的值,只允许有一个null key

28. 什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决

什么是序列化

  • 序列化 把对象转换为字节序列的过程称为序列化
  • 反序列化 把字节序列转化为对象的过程称为序列化

为什么序列化
内存对象保存到文件或数据库时需要序列化;
用套接字在网络上传输对象的时需要序列化;
通过RMI传输对象的时候需要序列化

怎么序列化
对象实现Serializable接口,然后通过ObjectOutputStream.writeObject进行序列化,通过ObjectInputStream.readObject进行反序列化

问题及解决方式
serialVersionUID未定义,导致反序列化报InvalidClassException,这是由于在反序列化时Java会自动为serialVersionUI赋值,导致两边不一致找不到旧数据报错
当属性是对象时,也需要实现serializable接口,不然会报NotSerializableException

ps:
transient修饰的属性不参与序列化;静态属性不参与序列化

29. java8的新特性

  • 接口提供默认方法
  • Lambda表达式
  • 函数式接口
  • 方法与构造函数引用
  • 扩展了集合类,可以通过 Collection.stream() 或者 Collection.parallelStream() 来创建一个Stream
  • 在包java.time下包含了一组全新的时间日期API
支持一下
扫一扫,支持沈健
  • 微信扫一扫
  • 支付宝扫一扫