在一个类的实例方法中,可以直接通过 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 2019-12-11 14:55:44 +08:00
我理解的是 super 本质是关键字 而非某对象的某成员变量 /函数 所以你无法使用对象调用关键字
|
2
Febers OP @anakinsky #1 有这种可能,我的疑惑是,既然方法引用有这种形式,把父类的方法引用限定在子类内部,其他地方无法调用,会不会没什么必要
无法使用对象调用关键字这件事还是存疑,实例化非静态内部类的时候,就会用到 OutClass.InnerClass innerClass = outClass.new OutClass.InnerClass() 这种形式,那么 outClass 后面的 .new 是不是调用关键字呢 |
3
gotonull 2019-12-11 16:08:26 +08:00
super 是当前类的一个私有成员
|
4
guxingke 2019-12-11 16:36:51 +08:00
1. super 是个关键字 , 用处就是标志当前类的父类, 此处可以 反编译 class 推断.
2. 外部为什么无法使用 xxx.super.yyy , 编译器约束. 3. 方法引用是个语法糖. 跟这个问题没有直接关系. 4. 个人推断, 不保证正确, 并没有找到官方说明. |
5
chendy 2019-12-11 16:38:00 +08:00
|
8
guyeu 2019-12-11 21:00:37 +08:00
因为不存在父类的实例这么个东西,你实例化一个类的时候,实例化出的就是一个对象,并不是父类有个对象子类有个对象。
但是在类内部有需求访问这个类继承自父类的方法、属性,所以有了 super 这么个关键字,用来区分当前类和它的父类,不会引起混淆的情况下你省略这个关键字也没关系。 但是在类外面不能使用这个关键字,这会破坏对象的封装和继承。 |
9
KentY 2019-12-11 21:15:10 +08:00
可能是我见的代码太少了, 好像我没见过 object.super.method()这种 super 夹在俩点儿中间的情况.
"object.super"是什么呢, super 应该是没有这个用法吧? 通常"super"只在子类自身里用 |
10
janus77 2019-12-11 21:29:42 +08:00
好像是在类的内部才能正常使用 super,直接用点去调用是不行的
|
11
mxalbert1996 2019-12-11 22:05:16 +08:00 via Android
这样做有什么意义?允许在类外访问超类成员完全违反了 OOP 的原则,并且不经过子类直接调用父类方法会导致子类无法正常工作。
|
12
Febers OP |
13
Febers OP @KentY #9 确实是没有这种用法的,不过可以在类的实例方法中调用 SubClass.super.function。
而我又想在外部 Main 类中进行方法引用,方法引用又有一一种父类方法引用的方式,所以才有这个问题 |
15
KentY 2019-12-12 00:08:07 +08:00
@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 2019-12-24 17:09:28 +08:00
写上 super 的地方, 会被 jvm 编译成 invokespecial 指令,
如果用字节码 INVOKESPECIAL 可以对一个 object 调用任意合法方法, 用反射是能做到的,我没验证,只是搜了一下有现成例子。 至于为什么 java 不允许, 继承时存在方法 override,不想被从外界胡乱使用。 |