具有继承和 overriding/method-hiding 的实例和静态控制流
Instance and Static control-flow with inheritance and overriding/method-hiding
我在玩弄实例控制流和静态控制流,注意下面的代码
class A {
{
m1();
}
A(){
System.out.println("A constructor");
}
void m1(){
System.out.println("A m1");
}
}
public class Main extends A {
public static void main(String[] args) throws Exception {
Main m = new Main();
}
void m1(){
System.out.println("Main m1");
}
}
代码的输出是:
主要m1
构造函数
我知道这是因为:
首先,静态块和变量从上到下从父到子标识,在这种情况下,只有一个 main()
是静态的。
其次,执行静态块和变量赋值, 因此 main()
开始执行,并尝试创建新的 Main
对象。
所以第三,将识别父class 的实例块和变量。然后他们将自上而下执行。 (之后父 class 的构造函数将 运行,然后子 class 的实例块和变量将被识别,随后它们将自上而下执行,最后是子class'构造函数将执行)。
所以 A 中的实例块调用 `m1()`。然后,A 的构造函数执行。最后,控制流返回到 main() 并且程序终止。
现在,从 A 调用 `m1()` 调用了 `Main` 的 `m1()`。然而,如果我将两个 `m1()` 方法设为静态,其他一切保持不变,那么从 A 的实例块调用 `m1()` 就会调用 A 的 `m1()`。
我有两个问题(为什么?纯学术原因,还在学习中Java):
- 当
m1()
两个方法都是非静态方法时,是否可以从A的实例块中调用A的m1()?我尝试执行 this.m1()
但仍然调用了 Main 的 m1()。(为什么?)
- 当
m1()
两个方法都是static时,是否可以从A的实例块中调用Main的m1()? (我猜不,但我不确定)。
我知道在第一种情况下,它是压倒一切的,而在第二种情况下,它是方法隐藏。但我仍然不确定如何根据这些知识回答我的问题。
1.(当两个方法都是实例方法时)如果你在A(parent)里面class,如果你调用m1()
;或 this.m1();
你将调用 m1()
方法的 A 版本,但如果你在主 class (子)中,如果你调用 m1();
你将调用主版本m1 虽然如果你调用 super.m1();
你将调用 m1 方法的 A 版本。
2.(如果方法是静态的)你可以在任何地方调用每个版本,没有 class 的对象,例如,你可以在 A 块中调用 main's m1 方法下面一行 Main.m1(); // ClassName.StaticMethodName();
编译完成后java 8编译器你的代码看起来像这样:
class A {
A() {
this.m1(); // at runtime this refers to Main class instance
System.out.println("A constructor");
}
void m1() {
System.out.println("A m1");
}
}
public class Main extends A {
public Main() { }
public static void main(String[] args) throws Exception {
Main m = new Main();
m.m1();
}
void m1() {
System.out.println("Main m1");
}
}
现在回答你的第一个问题:不。你不能,除非你正在创建 A 的实例(A 的实际对象)。
关于你的第二个问题:
在使两个 m1 的静态编译看起来像这样之后:
class A {
A() {
m1(); // resolves to A's m1
System.out.println("A constructor");
}
static void m1() {
System.out.println("A m1");
}
}
public class Main extends A {
public Main() {
}
public static void main(String[] args) throws Exception {
new Main();
}
static void m1() {
System.out.println("Main m1");
}
}
现在无论您创建哪个实例(A 或 Main),您都会看到 A 的 m1 被执行。
我在玩弄实例控制流和静态控制流,注意下面的代码
class A {
{
m1();
}
A(){
System.out.println("A constructor");
}
void m1(){
System.out.println("A m1");
}
}
public class Main extends A {
public static void main(String[] args) throws Exception {
Main m = new Main();
}
void m1(){
System.out.println("Main m1");
}
}
代码的输出是:
主要m1
构造函数
我知道这是因为:
首先,静态块和变量从上到下从父到子标识,在这种情况下,只有一个 main()
是静态的。
其次,执行静态块和变量赋值, 因此 main()
开始执行,并尝试创建新的 Main
对象。
所以第三,将识别父class 的实例块和变量。然后他们将自上而下执行。 (之后父 class 的构造函数将 运行,然后子 class 的实例块和变量将被识别,随后它们将自上而下执行,最后是子class'构造函数将执行)。
所以 A 中的实例块调用 `m1()`。然后,A 的构造函数执行。最后,控制流返回到 main() 并且程序终止。
现在,从 A 调用 `m1()` 调用了 `Main` 的 `m1()`。然而,如果我将两个 `m1()` 方法设为静态,其他一切保持不变,那么从 A 的实例块调用 `m1()` 就会调用 A 的 `m1()`。
我有两个问题(为什么?纯学术原因,还在学习中Java):
- 当
m1()
两个方法都是非静态方法时,是否可以从A的实例块中调用A的m1()?我尝试执行this.m1()
但仍然调用了 Main 的 m1()。(为什么?) - 当
m1()
两个方法都是static时,是否可以从A的实例块中调用Main的m1()? (我猜不,但我不确定)。
我知道在第一种情况下,它是压倒一切的,而在第二种情况下,它是方法隐藏。但我仍然不确定如何根据这些知识回答我的问题。
1.(当两个方法都是实例方法时)如果你在A(parent)里面class,如果你调用m1()
;或 this.m1();
你将调用 m1()
方法的 A 版本,但如果你在主 class (子)中,如果你调用 m1();
你将调用主版本m1 虽然如果你调用 super.m1();
你将调用 m1 方法的 A 版本。
2.(如果方法是静态的)你可以在任何地方调用每个版本,没有 class 的对象,例如,你可以在 A 块中调用 main's m1 方法下面一行 Main.m1(); // ClassName.StaticMethodName();
编译完成后java 8编译器你的代码看起来像这样:
class A {
A() {
this.m1(); // at runtime this refers to Main class instance
System.out.println("A constructor");
}
void m1() {
System.out.println("A m1");
}
}
public class Main extends A {
public Main() { }
public static void main(String[] args) throws Exception {
Main m = new Main();
m.m1();
}
void m1() {
System.out.println("Main m1");
}
}
现在回答你的第一个问题:不。你不能,除非你正在创建 A 的实例(A 的实际对象)。
关于你的第二个问题: 在使两个 m1 的静态编译看起来像这样之后:
class A {
A() {
m1(); // resolves to A's m1
System.out.println("A constructor");
}
static void m1() {
System.out.println("A m1");
}
}
public class Main extends A {
public Main() {
}
public static void main(String[] args) throws Exception {
new Main();
}
static void m1() {
System.out.println("Main m1");
}
}
现在无论您创建哪个实例(A 或 Main),您都会看到 A 的 m1 被执行。