不断学习,做更好的自己!💪
Java 基础中考察频率比较高的是 Object
、String
、面向对象、集合、泛型和反射。
1. Object
equals 和 == 的区别?equals 和 hashcode 的关系?
- ==:基本类型比较值,引用类型比较地址。
- equals:默认情况下,equals 作为对象中的方法,比较的是地址,不过可以根据业务,修改 equals 方法。
equals 和 hashcode 之间的关系:
默认情况下,equals相等,hashcode 必相等,hashcode 相等,equals 不是必相等。hashcode 基于内存地址计算得出,可能会相等,虽然几率微乎其微。
2. String
String、StringBuffer 和 StringBuilder 的区别?
- String:String 属于不可变对象,每次修改都会生成新的对象。
- StringBuilder:可变对象,非多线程安全。
- StringBuffer:可变对象,多线程安全。
大部分情况下,效率是:StringBuilder > StringBuffer > String。
3. 面向对象的特性
Java 中抽象类和接口的特点?
共同点:
- 抽象类和接口都不能生成具体的实例。
- 都是作为上层使用。
不同点:
- 抽象类可以有属性和成员方法,接口不可以。
- 一个类只能继承一个类,但是可以实现多个接口。
- 抽象类中的变量是普通变量,接口中的变量是静态变量。
- 抽象类表达的是
is-a
的关系,接口表达的是like-a
的关系。
关于多态的理解?
多态是面向对象的三大特性:继承、封装和多态之一。
多态的定义:允许不同类对同一消息做出响应。
多态存在的条件:
- 要有继承。
- 要有复写。
- 父类引用指向子类对象。
Java 中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中的方法重载。
4. 集合
HashMap的特点是什么?HashMap的原理?
HashMap 的特点:
- 基于
Map
接口,存放键值对。 - 允许
key/value
为空。 - 非多线程安全。
- 不保证有序,也不保证使用的过程中顺序不会改变。
简单来讲,核心是数组+链表/红黑树,HashMap
的原理就是存键值对的时候:
- 通过键的 Hash 值确定数组的位置。
- 找到以后,如果该位置无节点,直接存放。
- 该位置有节点即位置发生冲突,遍历该节点以及后续的节点,比较key值,相等则覆盖。
- 没有就新增节点,默认使用链表,相连节点数超过8的时候,在jdk 1.8中会变成红黑树。
- 如果Hashmap中的数组使用情况超过一定比例,就会扩容,默认扩容两倍。
当然这是存入的过程,其他过程可以自行查阅。这里需要注意的是:
- key 的 hash 值计算过程是高 16 位不变,低 16 位和高 16 位取抑或,让更多位参与进来,可以有效的减少碰撞的发生。
- 初始数组容量为 16,默认不超过的比例为 0.75 。
5. 泛型
说一下对泛型的理解?
泛型的本质是参数化类型,在不创建新的类型的情况下,通过泛型指定不同的类型来控制形参具体限制的类型。也就是说在泛型的使用中,操作的数据类型被指定为一个参数,这种参数可以被用在类、接口和方法中,分别被称为泛型类、泛型接口和泛型方法。
泛型是 Java 中的一种语法糖,能够在代码编写的时候起到类型检测的作用,但是虚拟机是不支持这些语法的。
泛型的优点:
- 类型安全,避免类型的强转。
- 提高了代码的可读性,不必要等到运行的时候才去强制转换。
什么是类型擦除?
不管泛型的类型传入哪一种类型实参,对于 Java 来说,都会被当成同一类处理,在内存中也只占用一块空间。通俗一点来说,就是泛型只作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的信息擦除,也就是说,成功编译过后的 class 文件是不包含任何泛型信息的。
6. 反射
动态代理和静态代理
静态代理很简单,运用的就是代理模式:
声明一个接口,再分别实现一个真实的主题类和代理主题类,通过让代理类持有真实主题类,从而控制用户对真实主题的访问。
动态代理指的是在运行时动态生成代理类,即代理类的字节码在运行时生成并载入当前的 ClassLoader
。
动态代理的原理是使用反射,思路和上面的一致。
使用动态代理的好处:
- 不需要为
RealSubject
写一个形式完全一样的代理类。 - 使用一些动态代理的方法可以在运行时制定代理类的逻辑,从而提升系统的灵活性。