1、多线程情况下,static修饰的变量方法是安全的吗?
static修饰的方法和变量位于方法区,为线程共享,static修饰的变量一定是非安全的,static修饰的方法如果里面含有静态变量,则为非安全,否则是线程安全的。
2、finalize
finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
使用finalize还需要注意一个事,调用super.finalize(); 一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样。
jdk里面是这样实现的:
//jdk9之后该方法就过期了
@Deprecated(since=9)
protected void finalize() throws Throwable { }
}
3、GCRoot有哪些?
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(即一般说的native方法)中引用的对象
4、java反射
https://blog.csdn.net/qq_44715943/article/details/120587716
5、Java序列化
https://blog.csdn.net/qq_35843514/article/details/115733904?spm=1001.2014.3001.5502
5.1 什么是序列化?
-
序列化:序列化是将对象转化为字节流。
-
反序列化:反序列化是将字节流转化为对象。
5.2 序列化的用途?
-
序列化可以将对象的字节序列持久化-保存在内存、文件、数据库中。
-
在网络上传送对象的字节序列。
-
RMI(远程方法调用)
5.3 序列化和反序列化
-
序列化:java.io.ObjectOutputStream 类的 writeObject() 方法可以实现序列化
-
反序列化:java.io.ObjectInputStream 类的 readObject() 方法用于实现反序列化。
5.4 Serializable 接口
-
被序列化的类必须属于 Enum、Array 和 Serializable 类型其中的任何一种。
-
如果不是 Enum、Array 的类,如果需要序列化,必须实现 java.io.Serializable 接口,否则将抛出 NotSerializableException 异常。
这是因为:在序列化操作过程中会对类型进行检查,如果不满足序列化类型要求,就会抛出异常。
5.5 serialVersionUID
1、serialVersionUID 有什么作用,如何使用 serialVersionUID?
serialVersionUID 是 Java 为每个序列化类产生的版本标识。它可以用来保证在反序列时,发送方发送的和接受方接收的是可兼容的对象。如果接收方接收的类的 serialVersionUID 与发送方发送的 serialVersionUID 不一致,会抛出 InvalidClassException。
如果可序列化类没有显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值。尽管这样,还是建议在每一个序列化的类中显式指定 serialVersionUID 的值。因为不同的 jdk 编译很可能会生成不同的 serialVersionUID 默认值,从而导致在反序列化时抛出 InvalidClassExceptions 异常。
serialVersionUID 字段必须是 static final long 类型。