3
public class A{
    public static int x = 1;
    public int m(A a, B b){
        return a.m(b, b) + x;
    }
}

public class B extends A {
    public int m(A a1, B a2){
        if(a1 == a2)
            return x;
        return super.m(a1,a2);
    }
}

This is a question from a past exam of a subject I am taking.

public class Main{
    public static void main(String[] args){
        B b1 = new B(){int m(A a, A b){ return 10; }};
        System.out.println(b1.m(b1, b1));
    }
}

The question is, what does the following output. I was correct in the answer of 1. But I failed to fully understand why.

Since the inner class of the B object is (A,A). Am i correct in thinking it can not override the super method m since it is (A,B)? Would it be able to override, if the parameters of the two methods were swapped?

Since it can neither override or overload, it does nothing and simply uses the method m in B class?

Does the inner class of the object, only work for itself? Is it like an anon class?

Apologises about all the questions.

Thanks in advance.

Edit:

From my understanding so far, its because the static type is set to B, so the type B is unable to see the anon class. If this was set to public, it would be able to be seen, but it still wouldn't be used.

This confused me on another question.

public class A{
    public static int x = 1;
    public int m(A a, B b){
        return a.m(b, b) + x;
    }
}

public class Main{
 public static void main(String[] args){
  A a1=new A();
  A a2=new A(){ 
   int m(A a,B b){
    return 10;
   }};
  B b1=new B();
  System.out.println(a1.m(a2,b1));
 }
}

When the following is called, the output is 11. When a1.m is called, it passes a2 and b1.

In the A class, when a.m(b,b) is called. It calls the dynamic type. Is this because it changes to the dynamic type once parsed? So now it is able to use the anon class?

4

4 回答 4

6

让我们来看看 JVM:

B b1 = new B(){ int m(A a,A b) { return 10; } };

这将创建一个B具有匿名方法重载的实例,该方法m()具有两个类型的参数A。但这与类(或)定义的方法不同 ,因为它们的签名(vs )不同。m()BAA, AA, B

然后:

System.out.println(b1.m(b1, b1));

这调用带有两个类型参数的b1方法。m()B

现在JVM查找什么m()是:

  • 没有方法m()有两个类型的参数B
  • 在 class 中B,它找到一个匹配项:按名称的方法,m()其第一个参数是 a A(因为Binherits A)和第二个参数是 type B
  • b1这里完全忽略了匿名重载!(见https://gist.github.com/fge/5762353
  • 方法查找结束。

因此调用m()了类的方法。B在这种方法中,我们有:

if (a1 == a2) // TRUE!
   return x;

由于条件为真(方法已被调用,两个参数是完全相同的对象引用),x必须返回 的值;并且x由 class 定义A,哪个 class B extends

 public static int x = 1;

由于这是 A 类的静态成员(B 类没有隐藏),它同样可以通过实例方法从Aor的任何实例访问B;因此,该程序的返回码和输出为 1。

于 2013-06-12T00:57:39.880 回答
4

我是否认为它不能覆盖超级方法 m 因为它是(A,B)?

是的,你是对的:这会创建一个重载,而不是基类中方法的覆盖。

如果交换两个方法的参数,它是否能够覆盖?

否:要覆盖,方法签名必须完全匹配。

由于它既不能覆盖也不能重载,它什么也不做,只是使用B类中的方法m?

不完全是:(A, B)重载恰好比重(A, A)载更具体。

对象的内部类是否只为自己工作?它像一个匿名类吗?

A如果您向内部类传递了一对s ,您将能够调用内部类中的方法。

于 2013-06-12T00:58:03.320 回答
1

这里有几点:

  • 匿名内部类中的方法不是公共的,因此不能覆盖公共方法。@Override如果必须覆盖非抽象方法,请始终使用。
  • b1is的(静态)类型B,因此在匿名类型中声明的额外方法不可用。尽管您可以执行以下操作:

    B b1 = null;
    System.out.println(new B(){int m(B a, B b){ return 10; }.m(b1, b1));
    

或者

    final B b1 = null;
    new B() {
        {
            System.out.println(this.m(b1, b1));
        }
        int m(B a, B b) { return 10; }
    };
  • 语言选择具有最具体参数(如果存在)而不是最不具体的覆盖。在前面的例子中更正了。比如System.err.println("donkey".toCharArray());不调用println(Object)
  • 重写的方法可以放宽返回类型,“协变返回类型”(从 1.5 开始)。Comparable当超类型中的泛型参数类型(例如 for )时,参数发生的情况并不完全相同。
于 2013-06-12T01:43:53.990 回答
1

在每个人的答案之上添加。以下问题的答案应该是相关的,尤其是指向JLS (15.12.2.5 选择最具体的方法) 的问题。

于 2013-06-12T02:35:18.413 回答