针对 Object o = new Object(); 这一句话,曾经美团面试针对这一句话问出了7个问题,第一个问题就是这个o对象初始化过程,顺便来记录一下😏😏😏
目标代码☃️
public class Test{
public static void main(String[] args) {
Object o = new Object();
}
}
来看看他的字节码,以下就是一个对象的创建所经历的大致过程
右边的这5条就是对应的字节码指令
new 申请空间
在c/c++申请一个空间问题遗留值问题😗
我们在c/c++申请一个空间的时候,假设现在申请一个int类型的o变量
这个o它的初始值是0吗?如果是Java的话,那么它的初始值肯定就是0,但是在c/c++当中,那可就不一定了!
这个o叫做遗留值,也就是在这片内存空间中,之前如果有别人使用过,那么这个o就等于上一个人使用过的值,所以这个o的值是不可控的(在刚申请完空间的时候)
所以这也就是为什么在c/c++当中,一定要初始化的原因,举个例子:如果上一个人使用这块内存存储的是类似密码、验证码这种比较隐私的信息的时候,那么下一个人就可以得到你的密码或者验证码等的隐私信息了,非常的危险🙀🙀🙀
java怎么做⭐
java针对上面的情况,在内部你要执行new操作的时候,就对这块内存空间做了默认值的清理,int类型全为0,引用类型全为空等等…🏌️♂️🏌️♂️🏌️♂️🏌️♂️🏌️♂️
所以,Java号称自己是一门安全的语言的原因之一,就是做了这个的考虑💡💡
而c/c++号称自己是效率高的语言,也就是它压根就不做Java做的事,所以速度肯定就比较快,不会帮你做清理
invokespecial调用构造方法
调用完invokespecial指令之后,就会为你给定的值了
astore_1建立关联
也就是o指向这一块内存空间~
案例😏
public class Test{
private int num = 2;
public Test() {
new Thread(() -> System.out.println(this.num)).start();
}
public static void main(String[] args) throws IOException {
new Test();
System.in.read();
}
}
问:这里输出的num值为多少?
这里是会有一种情况,num会为0
在《effective java》这本书中,就有讲到一个原则:不要在构造方法中启动一个线程,不然有可能造成非常严重的后果(用Java写过小游戏的朋友应该深有感触),这就是因为在创建对象的时候,有可能会读到它的默认值,而不是你设想的那个值