java基础(2)

1..java你用过的jdk版本

jdk1.8或者jdk11

关键问:

你知道jdk1.8相较于1.7有什么新特性吗

  • 新增Lambda表达式 :Lambda允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
  • 新增Stream API:对容器功能加强,可以对容器进行高效操作
  • 新增方法引用:通过方法的名字来指向一个方法,用::
  • 新增Optional类:解决空指针异常
  • 新增default:接口可以有具体方法
  • 新增日期API

(接下来可能会问Lambda表达式和StreamAPI)

你知道jdk11有什么新特性吗

  • 新增本地类型推断:用var直接定义变量,编译器能自动推断类型
  • Optianal类增强,可以转换成流使用
  • 字符类增加一些功能API

2.用过final关键字吗?它有什么作用

final关键字表示不可变,它可以修饰在类、方法、成员变量中。

  1. 如果修饰在类上,则表示该类不允许被继承
  2. 修饰在方法上,表示该方法无法被重写
  3. 修饰在变量上,表示该变量无法被修改,而且JVM会隐性定义为一个常量。(但是可以通过反射去破坏,但是反射无法修改被final和static同时修饰的变量)

另外,final修饰的关键字,还可以避免因为指令重排序带来的可见性问题,原因是,final遵循两个重排序规则

  1. 构造函数内,对一个 final 变量的写入,与随后把这个被构造对象的引用赋值给一个变量,这两个操作之间不可重排序。
  2. 首次读一个包含 final 变量的对象,与随后首次读这个 final 变量,这两个操作之间不可以重排序。

3.反射知道吗 通过反射可以获取到一些什么东西

反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。

① 通过反射获取类中的属性和属性值

② 通过反射获取反射类中的构造方法

③ 通过反射获取反射类的父类(超类)和接口

④通过反射获取反射类的方法

4.序列化ID有什么作用?怎么生成的?

作用:验证版本一致性

反序列化时,程序会比较磁盘中的序列化版本号ID是否与当前类结构生成的版本号ID一致,如果一致,则反序列化成功

下图就是反序列化异常情况

image-20220709221426112

生成方式:

首先,相关的类要实现Serializable接口

  • 手动生成

    1
    2
    private static final long serialVersionUID = 1L;
    好处就是即使在原来类上加字段,也不会发生上图的反序列化失败,老版本兼容
  • 代码调用

    1
    2
    ObjectStreamClass c = ObjectStreamClass.lookup(Student.class);
    long serialVersionUID = c.getSerialVersionUID();
  • ide快捷工具

5.为什么重写 equals 的同时必须重写 hashCode

程序先进行 hashcode 的比较,如果不同,那没就不必在进行 equals 的比较了,这样就大大减少了 equals 比较的次数,这对比需要比较的数量很大的效率提高是很明显的,一个很好的例子就是在集合中的使用

hashCode 和 equals 两个方法是用来协同判断两个对象是否相等的,采用这种方式的原因是可以提高程序插入和查询的速度,如果在重写 equals 时,不重写 hashCode,就会导致在某些场景下,例如将两个相等的自定义对象存储在 Set 集合时,就会出现程序执行的异常,为了保证程序的正常执行,所以我们就需要在重写 equals 时,也一并重写 hashCode 方法才行。

回答:因为程序会先进行hashcode,我们希望Set集合能过滤相同数值的对象,因为涉及对象的值比较,我们重写equals,但我们要保证两个对象 equals 相等,那么hashcode也要相同,所以要重写hashcode,否则还是不能去重。(hashcode不是内存地址,跟内存地址相关)