奇怪的Java方法重写中的无限循环。

huangapple go评论75阅读模式
英文:

Strange infinite loop in java method overriding

问题

在尝试不同的方法重写的排列组合时,我遇到了一个奇怪的无限循环。在超类的修改器方法中从一个被重写的超类方法调用时,程序进入了无限循环。我使用的代码如下:

class A {
    private int x = 10;
     public void show() {
         System.out.println("Inside A's show showing private X: " + x);
     }
     
    public void change(int num) {
        this.x = num;
        // show(); Line 1
        this.show();  // Line 2
        // 无论是使用Line 1还是Line 2进行交替使用,仍然会产生相同的无限循环。
    }
}

class B extends A {
     public void show() {
        System.out.println("Inside B's show cant show private X:");
        // change(8);           Line 3
        super.change(8);    //  Line 4
        // 无论是使用Line 3还是Line 4进行交替使用,仍然会产生相同的无限循环。
     }
}

public class Main
{
    public static void main(String[] args) {
        B b = new B();
        b.show();
    }
}

输出为:

Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
... 很多次,然后

at A.change(Main.java:9)
at B.show(Main.java:17)
at A.change(Main.java:9)
at B.show(Main.java:17)
at A.change(Main.java:9)
at B.show(Main.java:17)
at A.change(Main.java:9)
at B.show(Main.java:17)
at A.change(Main.java:9)
at B.show(Main.java:17)
... 很多次

是什么导致该程序进入这个无限循环,并且如何避免这种情况?

英文:

While trying out different permutations and combinations of method overriding, I encountered a strange infinite loop. While calling an overridden method of the superclass from a mutator method in the superclass, the program goes into an infinite loop. The code which I used is as follows:

class A {
    private int x = 10;
     public void show() {
         System.out.println("Inside A's show showing private X: " + x);
     }
     
    public void change(int num) {
        this.x = num;
        // show(); Line 1
        this.show();  // Line 2
        // Line 1 and Line 2 on using interchangeably still yields the same infinite loop.
    }
}

class B extends A {
     public void show() {
        System.out.println("Inside B's show cant show private X:");
        // change(8);           Line 3
        super.change(8);    //  Line 4
        // Line 3 and Line 4 on using interchangeably still yields the same infinite loop.
     }
}

public class Main
{
	public static void main(String[] args) {
		B b = new B();
		b.show();
	}
}

The output is:

Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
Inside B's show cant show private X:
... lots of times and then 

at A.change(Main.java:9)
at B.show(Main.java:17)
at A.change(Main.java:9)
at B.show(Main.java:17)
at A.change(Main.java:9)
at B.show(Main.java:17)
at A.change(Main.java:9)
at B.show(Main.java:17)
at A.change(Main.java:9)
at B.show(Main.java:17)
... lots of times

What is causing this program to go into this infinite loop and how can it be avoided?

答案1

得分: 1

在你的 A 类中,你调用了:this.show(),由于 this 表示 '这个对象',这将调用 '这个对象的 show() 实现',鉴于 '这个对象' 实际上是 B 的一个实例,'show() 的实现' 是在 B.java 中定义的,从而导致无限循环。注意,show(); 只是 this.show(); 的语法糖 - 难怪这两行会做相同的事情 - 这两行的意思是相同的。

听起来你的意图不是调用 '这个对象的 show() 方法的实现',而是:'在这个文件中定义的 show() 方法'。

在 Java 中你不能这样做。

你无法编写任何东西(既不是 this,也不是 super,也没有其他任何东西)来表示:我想要这个显式的实现。

当然,你可以通过以下方式解决这个问题:

public class A {
    public void show() {
        showImpl();
    }

    private static void showImpl() {
        // 这个方法是静态的。
        // 这意味着它完全不参与继承。
        System.out.println("Inside A's show showing private X: " + x);
    }

    public void change(int num) {
        this.x = num;
        showImpl();
    }
}

现在你已经解决了这个问题。对 showImpl 的调用将会准确地进入同一文件中的 showImpl 实现,这是有保障的,因为静态方法不会进行方法的动态查找。

英文:

In your A class, you call: this.show(), and as this means 'this object', that will call 'this object's show() implementation', and given that 'this object' is in fact an instance of B, the 'implementation of show()' is the one defined in B.java, thus causing the infinite loop. Note that show(); is just syntax sugar for this.show(); - no wonder then that both lines would do the same thing - both lines mean the same thing.

It sounds like your intent is not to call this object's implementation of the show() method, but: the show() method defined in this very file.

You cannot do that in java.

There is nothing you can write (not this, and not super, and nothing else either) to say: I want this explicit implementation.

You can work around this, of course:

public class A {
    public void show() {
        showImpl();
    }

    private static void showImpl() {
        // this method is static.
        // that means it has opted out, entirely, of inheritance.
        System.out.println("Inside A's show showing private X: " + x);
    }

    public void change(int num) {
        this.x = num;
        showImpl();
    }
}

Now you've fixed the problem. That call to showImpl will go to that exact implementation of showImpl in the same file, guaranteed, every time, because static methods don't 'do' dynamic lookup of the method.

huangapple
  • 本文由 发表于 2020年10月9日 22:20:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/64281881.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定