java 静态方法 构造方法_请问java中构造方法是静态的吗?

这是一个比较复杂的问题,而题目中这本书所讲的内容。个人认为也确实不算严谨。Initialization of a class or interface consists of executing its class or interface initialization method.

A class or interface C may be initialized only as a result of:

1. The execution of any one of the Java Virtual Machine instructions new, getstatic, putstatic, or invokestatic that references C. These instructions reference a class or interface directly or indirectly through either a field reference or a method reference.

Upon execution of a new instruction, the referenced class is initialized if it has not been initialized already.

Upon execution of a getstatic, putstatic, or invokestatic instruction, the class or interface that declared the resolved field or method is initialized if it has not been initialized already.

2. The first invocation of a java.lang.invoke.MethodHandle instance which was the result of method handle resolution for a method handle of kind 2 (REF_getStatic), 4 (REF_putStatic), 6 (REF_invokeStatic), or 8 (REF_newInvokeSpecial).

This implies that the class of a bootstrap method is initialized when the bootstrap method is invoked for an invokedynamic instruction, as part of the continuing resolution of the call site specifier.

3. Invocation of certain reflective methods in the class library, for example, in class Class or in package java.lang.reflect.

4. If C is a class, the initialization of one of its subclasses.

5. If C is an interface that declares a non-abstract, non-static method, the initialization of a class that implements C directly or indirectly.

6. If C is a class, its designation as the initial class at Java Virtual Machine startup.

简单解释一下吧,有且只有以下六种场景会触发类的初始化:

1、当虚拟机执行了引用自一个类的new、getstatic、putstatic、invokestatic四个字节码指令之一

new指令的含义是Create new object,即实例化一个对象,但是并不调用其构造方法。

getstatic指令的含义是Get static field from class,即获取一个类的静态成员

putstatic指令的含义是Set static field in class,即为一个类的静态成员赋值

invokestatic指令的含义是Invoke a class ( static ) method,即调用一个类(静态)方法。

2、这与Java7新加入的动态语言支持有关,在此暂不讨论java.lang.invoke.MethodHandle这些

3、反射

比如java.lang.Class和java.lang.reflect.*

4、如果这是一个类,那么在它的任何一个子类被加载之前需要将其加载

5、如果这是一个实现了default方法的接口,那么在它的任何一个实现类被加载之前需要将其加载

接口的default 方法定义是在JDK8中加入的

6、如果这是在虚拟机启动时所指定的主类,那么会将其加载

比如我们经常声明public static void main(String[] args)方法的那个类,会在我们用终端使用java命令的时候将其加载

以上是Java SE 8版本的虚拟机规范。

问题就在于,书中提到了说类会在其静态方法被调用时加载,而构造一个类的新实例时也会加载这个类,从而把构造方法算成一种静态方法,这个逻辑是不正确的。

但是,尽管构造方法并不属于静态方法,但是同样不能够说构造方法属于实例。

在JVM的指令集中,仅有五条指令用于方法调用:

1、invokevirtual

调用实例方法

2、invokeinterface

调用接口方法

3、invokespecial

调用需要特殊处理的方法

4、invokestatic

调用类的静态方法

5、invokedynamic

Java7加入的动态调用

在此仍旧不讨论invokedynamic

invokestatic和invokevirtual这两个很好理解,分别调用静态方法与实例方法

invokeinterface 与invokevirtual类似但是有所不同,当一个对象的静态类型是接口时,调用这个接口的方法将使用invokeinterface这一指令。

最后就是这个invokespecial,由这个指令调用方法有三种:私有方法、构造方法、超类方法。

调用构造方法的指令是invokespecial,既不是invokestatic也不是invokevirtual 。

实际上方法也就是一种函数而已,实例方法和构造方法的第一个参数就是this,如果在编译期显式地声明到参数列表中,也一样可以通过编译。

而在构造一个类的实例时,之所以会将加载这个类,根据《Java虚拟机规范》,并不是由于invokespecial会调用构造方法,而是由于new指令会为这个实例分配空间,构造方法本身只是一个没有返回值的函数,它的名字叫。

最后附上一段代码,可以比对一下这几个指令所对应的源代码:

class Main implements AutoCloseable {

public static void main(String[] args) {

Main main = getInstance();

main.test();

try {

((AutoCloseable) main).close();

} catch (Exception e) {

e.printStackTrace();

}

}

public static Main getInstance() {

return INSTANCE;

}

private static final Main INSTANCE = new Main();

private Main() {

super();

super.equals(this);

}

private void test() {

return;

}

@Override

public final void close() {

return;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值