
在一个类的实例方法中,可以直接通过 ClassName.super ( ClassName 可省略)获取其直接父类的实例,但是在其他类中,使用 classInstance.super 引用其父类却报错,IDE 报错信息为:Class name expected here,Java 这么做的考虑是什么呢?
学习 Java 的方法引用的时候遇到这个问题。方法引用有一种情况是,可以引用超类的方法,代码如下
public abstract class Animal { public void action() { System.out.println("The animal is running"); } } public class Bird extends Animal { public void action() { System.out.println("The bird is flying"); //引用父类方法 Runnable r = super::action; r.run(); } } 方法调用
public class Main { public static void main(String[] args) { Bird bird = new Bird(); //正常运行 Runnable r = bird::action; r.run(); //报错 Runnable r1 = bird.super::action; } } 1 anakinsky Dec 11, 2019 我理解的是 super 本质是关键字 而非某对象的某成员变量 /函数 所以你无法使用对象调用关键字 |
2 Febers OP @anakinsky #1 有这种可能,我的疑惑是,既然方法引用有这种形式,把父类的方法引用限定在子类内部,其他地方无法调用,会不会没什么必要 无法使用对象调用关键字这件事还是存疑,实例化非静态内部类的时候,就会用到 OutClass.InnerClass innerClass = outClass.new OutClass.InnerClass() 这种形式,那么 outClass 后面的 .new 是不是调用关键字呢 |
3 gotonull Dec 11, 2019 super 是当前类的一个私有成员 |
4 guxingke Dec 11, 2019 1. super 是个关键字 , 用处就是标志当前类的父类, 此处可以 反编译 class 推断. 2. 外部为什么无法使用 xxx.super.yyy , 编译器约束. 3. 方法引用是个语法糖. 跟这个问题没有直接关系. 4. 个人推断, 不保证正确, 并没有找到官方说明. |
8 guyeu Dec 11, 2019 因为不存在父类的实例这么个东西,你实例化一个类的时候,实例化出的就是一个对象,并不是父类有个对象子类有个对象。 但是在类内部有需求访问这个类继承自父类的方法、属性,所以有了 super 这么个关键字,用来区分当前类和它的父类,不会引起混淆的情况下你省略这个关键字也没关系。 但是在类外面不能使用这个关键字,这会破坏对象的封装和继承。 |
9 KentY Dec 11, 2019 可能是我见的代码太少了, 好像我没见过 object.super.method()这种 super 夹在俩点儿中间的情况. "object.super"是什么呢, super 应该是没有这个用法吧? 通常"super"只在子类自身里用 |
10 rb6221 Dec 11, 2019 好像是在类的内部才能正常使用 super,直接用点去调用是不行的 |
11 mxalbert1996 Dec 11, 2019 via Android 这样做有什么意义?允许在类外访问超类成员完全违反了 OOP 的原则,并且不经过子类直接调用父类方法会导致子类无法正常工作。 |
12 Febers OP |
13 Febers OP @KentY #9 确实是没有这种用法的,不过可以在类的实例方法中调用 SubClass.super.function。 而我又想在外部 Main 类中进行方法引用,方法引用又有一一种父类方法引用的方式,所以才有这个问题 |
15 KentY Dec 12, 2019 @Febers 没太懂你说的"在类的实例方法中"SubClass.super.function... 你是说你的例子 //报错 那行可以写 Bird.super.action() ? |
16 Febers OP @KentY #15 意思是 在 Bird 的非静态方法中可以调用 Bird.super.action() 实现调用父类方法的目的,但是在其他地方,想调用就不行 比如在 Main 中,第一种调用形式,Bird.super.action 明显不行,因为 Bird 没有实例,无法调用它自身或者它父类(如果有的话)的 action 这一个实例方法;第二种调用形式,Bird bird = new Bird(); bird.super.action(),报错,才有了我的疑惑 |
17 hitsmaxft Dec 24, 2019 写上 super 的地方, 会被 jvm 编译成 invokespecial 指令, 如果用字节码 INVOKESPECIAL 可以对一个 object 调用任意合法方法, 用反射是能做到的,我没验证,只是搜了一下有现成例子。 至于为什么 java 不允许, 继承时存在方法 override,不想被从外界胡乱使用。 |