正确的写作方式“超级”

时间:2016-02-07 21:39:00

标签: java

如果我有对象并且我想在父类中调用方法的版本,我可以像x.super.method()super.x.method()那样调用它吗?

1 个答案:

答案 0 :(得分:0)

不仅仅是一个小小的研究答案。这是一个有趣的问题,所以只是为了好玩,我破解了一些测试代码。由于评论不支持格式化,因此我会在此处发布结果。

我怀疑使用super进行方法调用并实际编译的唯一方法是使用super unqualified ,即没有前缀表达式。

bar.blarch()按预期编译并运行(参见下面的示例)。

bar.super.blarch()没有编译(我也期望)。

Bar bar = new Bar();
System.out.println("bar.super.blarch() ==> " + bar.super.blarch() );

然而,错误消息让我感到惊讶。事实证明,javac抱怨"找不到符号"如下:

Bar.java:15: error: cannot find symbol
System.out.println("bar.super.blarch() ==> " + bar.super.blarch() ); // does not compile.
                                               ^
symbol:   class bar
location: class Bar

所以在这一点上看起来像是超级'在运行中并不是javac而是试图在条形图之后找到一个实例变量。表达

然后我认为反射可能会给你一种方法来调用你的首选方法实现,但这也看起来像是号码。
具体到输出中最后一个例子的下一个:
" fooBlarch.invoke(bar)= Bar.blarch"
尝试在类型为Bar的实例上调用Foo类中的方法,但它仍然以Bar开头并调用第一个匹配的方法名+签名。

$ javac *.java
Note: Bar.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
$ java Bar
foo.blarch() ==> Foo.blarch
bar.blarch() ==> Bar.blarch
bar.superBlarch() ==> Foo.blarch
moreFoo.blarch() ==> Bar.blarch
fooClass=class Foo
fooBlarch=public java.lang.String Foo.blarch()
fooBlarch.invoke(foo)=Foo.blarch
fooBlarch.invoke(bar)=Bar.blarch
fooBlarch.invoke((Foo)bar)=Bar.blarch
$ 

Foo.java

public class Foo {
   public String blarch() { return "Foo.blarch"; }
}

Bar.java

import java.lang.reflect.*;

public class Bar extends Foo {
   public String blarch() { return "Bar.blarch"; }

   public String superBlarch() { return super.blarch(); }

   public static void main( String[] args ) throws Exception {
      Foo foo = new Foo();
      System.out.println("foo.blarch() ==> " + foo.blarch() ); // prints Foo.blarch

      Bar bar = new Bar();
      System.out.println("bar.blarch() ==> " + bar.blarch() ); // prints Bar.blarch
      System.out.println("bar.superBlarch() ==> " + bar.superBlarch() ); // prints Foo.blarch
      // System.out.println("bar.super.blarch() ==> " + bar.super.blarch() ); // does not compile.
      // Bar.java:15: error: cannot find symbol
      //     System.out.println("bar.super.blarch() ==> " + bar.super.blarch() ); // does not compile.
      //                                                    ^
      //  symbol:   class bar
      //  location: class Bar

      Foo moreFoo = new Bar();
      System.out.println("moreFoo.blarch() ==> " + moreFoo.blarch() ); // prints Bar.blarch

      Class fooClass = foo.getClass();
      System.out.println("fooClass="+fooClass);
      Method fooBlarch = fooClass.getDeclaredMethod( "blarch", new Class[] { } );
      System.out.println("fooBlarch="+fooBlarch);

      System.out.println("fooBlarch.invoke(foo)="+ fooBlarch.invoke( foo ) ); // yields Foo.blarch

      // I think you're out of luck trying to use anything "super-like" outside of a given class.
      // looks like Method.invoke() walks the full instance ancestors looking for a suitable implementation.
      // I actually didn't expect this one to compile given that the method is from class Foo, not Bar.
      System.out.println("fooBlarch.invoke(bar)="+ fooBlarch.invoke( bar ) ); // yields Bar.blarch

      // casting matters not at all.
      System.out.println("fooBlarch.invoke((Foo)bar)="+ fooBlarch.invoke( (Foo)bar ) ); // yields Bar.blarch
   }

}