文章目录

  • 实例初始化方法
  • 类初始化方法
  • 签名多态方法


实例初始化方法

实例初始化方法是类中的特殊方法,通常用于初始化类的实例,类似于Java编程语言中的构造函数。要被视为实例初始化方法,方法必须满足以下条件:它必须在类(而不是接口)中定义,必须具有名称<init>,并且返回类型必须为void。请注意,在类中,任何名为<init>的非void方法都不是实例初始化方法,而在接口中,任何名为<init>的方法都不是实例初始化方法。这些方法不能被任何JVM指令调用,并且会被格式检查拒绝。

实例初始化方法的声明和使用受JVM强加的约束。 对于声明,方法的access_flags项和代码数组是受约束的。 对于某个用途,实例初始化方法只能由未初始化类实例上的invokespecial指令调用。 但是,需要注意的是,因为名称<init>在Java编程语言中不是有效的标识符,所以不能直接在用Java编程语言编写的程序中使用。

实例初始化方法在对象实例化时由JVM调用,用于执行对象的初始化工作。实例初始化方法的定义与普通方法类似,只不过方法名与类名相同。

实例初始化方法可以有多个重载形式,每个形式对应不同的构造函数,以支持不同的参数列表。当创建一个新对象时,JVM会选择适当的构造函数,并调用它来初始化对象。在构造函数中可以对对象的成员变量进行初始化,并执行任何其他必要的操作,以确保对象能够正确地工作。

与类初始化方法不同,实例初始化方法可以被子类重写。在子类中定义构造函数时,通常需要调用父类的构造函数以确保父类的实例初始化方法被正确地执行。这可以通过使用super关键字来实现。

类初始化方法

在Java虚拟机启动时或者在程序第一次使用一个类或接口时,Java虚拟机必须调用该类或接口的初始化方法,以确保该类或接口的状态被正确初始化。

Java中的类或接口初始化是通过调用至多一种称为<clinit>方法的方法来完成的,该方法由JVM自动调用。要成为<clinit>方法,该方法必须具有特殊名称<clinit>并且返回类型必须为void。 此外,在版本号为51.0(JDK1.7)或更高版本的类文件中,该方法必须设置ACC_STATIC标志并且不带任何参数。 但是,在版本号为50.0(JDK1.6)或更低的类文件中,无效的<clinit>方法被视为初始化方法,而不管其ACC_STATIC标志设置或参数列表如何。

不满足这些条件的名为<clinit>的方法不是初始化方法,不能被JVM或任何JVM指令调用,并且会被格式检查拒绝。由于<clinit>在 Java编程语言中不是有效的标识符,因此不能直接在Java程序中使用。

在JVM执行初始化方法时,会执行该方法内的静态初始化语句,例如给静态变量赋值等操作。

签名多态方法

签名多态方法是指在Java虚拟机中,具有特定签名的方法,它们可以接受任意数量和任意类型的参数,并且返回任意类型的结果。这种方法通常被声明在java.lang.invoke.MethodHandle类或java.lang.invoke.VarHandle类中,并且具有特定的方法修饰符。

如果方法满足以下条件,则该方法被认为是签名多态的:

  • 它在java.lang.invoke.MethodHandle类或java.lang.invoke.VarHandle类中声明。
  • 它只有一个参数,即一个对象数组。
  • 它同时设置了ACC_VARARGSACC_NATIVE标志。

这些方法之所以被称为“签名多态方法”,是因为它们可以处理任意类型和数量的参数,而且无需为每个参数类型编写不同的方法。当JVM使用invokevirtual指令调用签名多态方法时,可以调用方法句柄或访问由java.lang.invoke.VarHandle实例引用的变量。
方法句柄是对低级操作(例如方法、构造函数、字段)的引用。它是动态和强类型的,可以包括参数或返回值的可选转换。而java.lang.invoke.VarHandle的实例是对变量或变量族(例如数组元素、静态字段或堆外数据结构的组件)的动态强类型引用。

JVM在使用签名多态方法时会给予特殊处理,以便正确地调用方法句柄或访问变量。它们通常用于实现高级的反射和元编程技术,例如动态代理、函数式编程和基于注解的框架。