A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© cat73 黑马帝   /  2016-7-12 11:43  /  9558 人查看  /  50 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

5黑马币
本帖最后由 cat73 于 2016-7-13 20:28 编辑

我们知道,一个类可以通过 super.xxx() 来访问被自己覆盖的方法。那么要如何访问被父类覆盖的方法呢?


看代码:
  1.     abstract class A extends Object {
  2.         public void xxx() {
  3.             System.out.println("A");
  4.         }
  5.     }
  6.    
  7.     abstract class B extends A {
  8.         public void xxx() {
  9.             System.out.println("B");
  10.         }
  11.     }
  12.    
  13.     class C extends B {
  14.         public void xxx() {
  15.             // call A.xxx();

  16.         }
  17.     }
复制代码

我希望在不改变 A 类与 B 类的代码,并且 C 类要继承 B 类的前提下。
在 C 类的 xxx 方法中调用 A 类的 xxx 方法。
请问要如何写呢?

以下均为错误答案:
  1. super.super.xxx()
  2. A.super.xxx()
  3. A.this.xxx()
复制代码



=========更新======
鉴于有人回答了实例化一个新的 A 类的写法,我重新改了改示例代码,把 A 类跟 B 类增加了 abstract 前缀。
重新实例化的做法并不是访问被覆盖的方法,而是直接访问了方法,所以不予采纳为正确答案。

50 个回复

倒序浏览
    class A extends Object {
        public void xxx() {
            System.out.println("A");
        }
    }
   
    class B extends A {
        public void xxx() {
            System.out.println("B");
        }
    }
   
    class C extends B {
        public void xxx() {
            // call A.xxx();
           //方法一             new A().xxx();            //方法二
           Class clazz = Class.foName("A");
          Object object = clazz.newInstance();
          Method mothod = clazz.getDeclaredMethod("xxx");
          mothod.invoke(object);
          乱写一通,哈哈{:2_36:}
           
        }
    }

点评

那你为什么不干脆些成 new A().xxx() 呢?用反射有什么区别么?  发表于 2016-7-12 23:55
你这是重新实例化一个对象了。  发表于 2016-7-12 23:54
回复 使用道具 举报
技术有限,想出一种实现方式,看看是否满足需求:
package com.heima.me;

public class Test4 {

        public static void main(String[] args) {
                C c = new C();
                c.print();
               
        }

}
class A{
        public void print(){
                System.out.println("A");
        }
}
class B extends A{
        public void print(){
                System.out.println("B");
        }
}
class C extends B{
        public void print(){
//                System.out.println("C");
                Class cclazz = C.class;
                String name = cclazz.getSuperclass().getSuperclass().getName();//获取父类的父类类名
                System.out.println(name);                                                                        //打印出类名
                com.heima.me.A a = new com.heima.me.A();                                        //然后创建对象
                a.print();                                                                                                        //调用父类的父类中最初的方法
        }
}

点评

如果加了抽象类 哪能还让你直接这么用呢 只能使用匿名内部类来调用父类调用  发表于 2016-7-20 20:02
你这还是重新创建对象了呀  发表于 2016-7-13 20:20
回复 使用道具 举报
乱写一通,哈哈乱写一通,哈哈乱写一通,哈哈乱写一通,哈哈乱写一通,哈哈乱写一通,哈哈乱写一通,哈哈乱写一通,哈哈乱写一通,哈哈乱写一通,哈哈乱写一通,哈哈
回复 使用道具 举报
package test;

public class Test2
{
        public static void main(String[] args)
        {
                C c = new C();
                c.xxx();
        }
       
}
abstract class A extends Object {
    public void xxx() {
        System.out.println("A");
    }
}

abstract class B extends A {
    public void xxx() {
        System.out.println("B");
    }
    public void xxx2()
    {
            super.xxx();
    }
}

class C extends B {
    public void xxx() {
       xxx2();
    }
   
}
这是一种取巧的方法 不知道是都合乎你的要求

点评

不是任何时候父类都是可以改变的,因此我要求了不准改变父类的代码。  发表于 2016-7-14 09:58
回复 使用道具 举报
15820030540 发表于 2016-7-13 19:29
技术有限,想出一种实现方式,看看是否满足需求:
package com.heima.me;

这个题目是抽象类 你这写的已经不是抽象类,这不是限定死了不能用反射吗

点评

去掉抽象也没啥用吧- - 反射能调用?  发表于 2016-7-14 10:20
回复 使用道具 举报
我只想说  在你的这种要求下 根本无法做到 !!!!!!!!!!!!!!!!!!!!!!!!

点评

并不是每个题都一定是有答案的呀,或许这道题真的就无解也是可能的,我发出来只是希望看看有么有人知道一些我不知道的用法来实现这个。  发表于 2016-7-14 10:19
回复 使用道具 举报
好吧  我服!!!

点评

ASM库可以改变原本不可改变的父类,在里面加一个临时方法来调用 spuer.xxx()  发表于 2016-8-1 14:20
其实 ASM 库应该算是个解决方案了。  发表于 2016-7-14 10:29
回复 使用道具 举报
好吧,我发现都是大神,不懂啊
回复 使用道具 举报
我是来看大神解答的
回复 使用道具 举报
cat73 黑马帝 2016-7-17 23:12:04
11#
本帖最后由 cat73 于 2016-7-17 23:15 编辑

super.method() 的调用方法实际的字节码为 invokeinterface,没有参数
所以此题基本应该是无解了。
ASM 没什么卵用,invokeinterface 并没有参数。。。
反射在 Java 代码可控的范围内都是传的 A 类的 xxx 方法,到 native 代码里才根据传递的 obj 转为实际的方法。
所以反射也没什么卵用。。。
想实现这个大概就要改 JVM 虚拟机的源码了。。。

唯一的变通方案大概就是重新写一个继承 A 类的类,并构造一个对象,然后把属性全部复制过去,然后调用 xxx 方法,然后把属性再复制回来。

个人自己的理解,如有错误还请指出,谢谢。

点评

对的,我试了反射了,无解,AB类抽象,无法实例化,super这个隐式参数是类私有的,子类无法调用父类中的super,也就无法调用父类的父类中的对象  发表于 2016-8-16 18:03
回复 使用道具 举报
15242694137 发表于 2016-7-14 09:58
这个题目是抽象类 你这写的已经不是抽象类,这不是限定死了不能用反射吗 ...

他这抽象是后加的,不加抽象怎么调用不了??
回复 使用道具 举报
15820030540 发表于 2016-7-13 19:29
技术有限,想出一种实现方式,看看是否满足需求:
package com.heima.me;

按照你这种需求不创建对象,我想不出来,sorry
回复 使用道具 举报
15820030540 发表于 2016-7-13 19:29
技术有限,想出一种实现方式,看看是否满足需求:
package com.heima.me;

因为你要想调用一个类方法,不管是父类的父类或者还是其他类,最简单就是创建对象,我就要看这个方法,创建对象就完了呗!你这加个抽象以为就创建不了了吗??匿名内部类可以实现!怎么满足不了需求!
回复 使用道具 举报
ylca 中级黑马 2016-7-20 20:05:35
15#
这个目前个人无法不创建对象去使用A中的方法
回复 使用道具 举报
cat73 黑马帝 2016-7-20 20:30:50
16#
15820030540 发表于 2016-7-20 10:13
因为你要想调用一个类方法,不管是父类的父类或者还是其他类,最简单就是创建对象,我就要看这个方法,创 ...

其实我最初的想法是,方法可能会用到一些本类的字段,重新创建对象无法使用原来类里的字段。
不过实际上通过反射可以把字段都复制过去,执行完再复制回来0.0
回复 使用道具 举报
反射中,最后的invoke传入的参数可以是this吗? 试一试
回复 使用道具 举报
class c extent B{
void xxx(){
A a=new c();//向上转型
a.xxx();
}
}
回复 使用道具 举报
cat73 黑马帝 2016-7-22 12:06:54
19#
liubi01 发表于 2016-7-22 11:30
class c extent B{
void xxx(){
A a=new c();//向上转型

这样子实际被调用的还是 C 的方法哟。
回复 使用道具 举报
来看大神解答!
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马