Java构造器

来源:互联网 发布:网络相亲平台 编辑:程序博客网 时间:2024/06/06 00:45
  • 1.构造器不是静态方法?
  • 从Java语言层面看,构造器不是静态方法。事实上规范专门规定了构造器不是方法。
  • 从JVM层面看,构造器属于特殊的初始化方法,但仍然不被归类为静态方法。
  • 无论从哪个层面看,构造器都是可以静态分派的(statically dispatched)。但要特别注意的是,并非所有可以静态分派的代码都是静态方法,这是规范里有定义的术语。
  • 无论从哪个层面看,构造器都要接收从调用方传入的隐藏this参数。Java的静态方法不需要接收该参数,而实例方法要接收该参数。这方面构造器更接近于可以静态分派的实例方法,例如私有实例方法。这就是为什么从构造器可以调用this上的实例方法。
  • 书中的Dog例子,确实当Dog被首次实例化或其静态方法/静态变量被首次访问时,会触发Dog类的初始化。但构造器在此并不可以归类到静态方法的一侧。事实上构造器并不能被单独调用,而必须用在new表达式里,此时触发类初始化的正是new,而不是对构造器的调用——new与构造器调用是两码事。
  • 我以前在博客上发过一篇详细讲解,请跳传送门:实例构造器是不是静态方法?
    有啥相关问题请先看看这篇讲解。
  • 2.new触发的构造器调用的就是getClass()方法吗?XX.Class这个实例也是在第一次加载该类的时候,JVM产生的?
  • Java语言层面的new表达式还是JVM层面的new字节码?
    Java语言层面的话,new Foo()表达式要做两件事情:分配空间,调用构造器。对应到JVM的字节码层面是:
    new Foo // 1. 分配空间给新对象
    dup
    invokespecial Foo::Foo()V // 2. 调用构造器

    这样就比较好解释了:new字节码负责分配空间,并且它会触发Foo类的加载与初始化——程序执行到这里如果Foo类尚未被加载与初始化,那么它就必须现在完成初始化之后再回来继续执行new的动作。
    invokespecial负责调用构造器,前面的dup是用于传递this参数的。它不负责触发Foo类的加载与初始化——前面的new字节码已经解决了这个问题。

    上面的描述都跟getClass()没有任何关系——Object.getClass()是要先有了对象实例才有意义的实例方法,执行new的时候对象还不存在呢。
    更有关系的是ClassLoader.loadClass()方法。JVM在使用用户自定义类加载器加载类的时候会调用这个loadClass()方法。

    Foo.class所得到的Class对象是在JVM加载Foo类时一并创建的。


    作者:RednaxelaFX
    链接:https://www.zhihu.com/question/35860619/answer/64802279
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0 0
    原创粉丝点击