[java笔试面试知识点系列 一 ] 再入基础

407 阅读3分钟

一、不可变类

不可变类指的是一个对象被创建出来之后,在它的整个生命周期之中,它的成员变量就不能被修改了,它有点类似于常量,只允许别的程序读,不允许别的程序进行修改。 在java中,所有的包装类,都是不可变类如Integer/Float等。

如String类是不可变类,平时咱写的s+="helloword"这种操作并不是吧原来的字符串修改了,而是在内存中新创建了一个String对象,然后让s指向了它,而原来的字符串还是存在内存空间中的。

创建一个不可变类需要遵守的五条规则:

  • 所有的成员变量都使用private来修饰
  • 不提供修改器方法set,只提供构造函数,一次生成永远不变
  • 确保方法不会被子类覆盖,可以用final修饰类,也可以用final修饰方法
  • 如果一个成员变量不是不可变量,那么在提供访问器方法get的时候,需要返回clone的内容
  • 有必要的话可以重写equalhashcode,比较内容相同时,hashcode也相等,这样确认该类能正确使用hashmap等容器

不可变类的缺点

  • 会因为值不同而创建新的对象
  • 在常量池中被共享,即使这个对象不再使用(如密码),它也会在内存中存在一段时间,这时候有权限访问memory dump的程序都能访问到这块内容,就可能把敏感数据暴露出去。因此存密码用字符数组会更安全,一旦不再使用密码之后就可以手动把字符数组设置为空。

二、==和equal

对于==,基础类型比较值,引用类型比较地址。

如果没有重写对象中的equal()方法,那equal()是等价于==的。

开发人员可以通过重写equal()方法来决定什么类的比较逻辑。

这里得提到hashcode(),如果没有重写hashcode()方法,那么任何对象的hashcode都不相等。 同时在重写了equal()方法之后没有重写hashcode()方法的话,就无法与基于hash的集合类结合一起正常运行。

三、static

static关键字主要有两个作用:

  • 为某一个特定数据类型或者对象分配单一的储存空间,与创建对象的个数无关。
  • 实现某个方法或者属性与类关联,而不是对象

特点:被修饰的部分会随着类的加载而加载,不会重复加载,执行的顺序在main方法前,在jvm中存在与方法区。

四、final

三句话:

  • 被修饰的属性不可变
  • 被修饰的方法不能被重写
  • 被修饰的类不能被继承

需要注意的是,修饰的属性,如果是引用类型的话,是引用不可变,而不是对象不可变。

五、transient

被transient关键字修饰的属性,不会被序列化。

序列化的特点:

  • 如果一个类能被序列化,那它的子类也可以序列化。
  • static、transien修饰的属性不能序列化

六、volatile

保证线程安全中的可见性和有序性,不能保证原子性。

实现是基于内存栅栏:

一个volatile数据被修改的时候,jvm会执行一个Write-Barrier操作,把当前工作内存的数据写入主存,并且让引用了该地址的数据变成脏数据,那么其他程序去读取该数据时,发现工作内存的是脏数据啦,就回去主存中取,这就保证了可见性。

有序性是因为volatile修饰的属性不会被jvm重排序。