【问题标题】:Accessing base class methods from an instance of derived class从派生类的实例访问基类方法
【发布时间】:2018-11-03 12:44:22
【问题描述】:

我有一个带有公共方法的基类。

`public class ClassA {
   private int a;
   public void setA() {
    a = 15;
    System.out.println(a);
   }
 }`

然后,有一个 ClassB 扩展了 ClassA,

`public class ClassB extends ClassA {
   public void test() {
      setA();
   }
 }`

现在,在main() 中,我创建了一个 ClassB 的实例。实例无法访问方法setA()test()

`public static void main( String[] args ) throws IllegalAccessException, InstantiationException {
   Class<?> cls = ClassB.class;
   Object obj = cls.newInstance();
   obj.setA(); //Not Accessible
   obj.test(); //Not Accessible

}`

谁能告诉我哪里出错了?

【问题讨论】:

  • Object 没有方法 testsetA。您需要将您的对象转换为ClassB
  • 另外,请问您为什么在这里使用反射而不是常规实例化?
  • 您是否有任何具体原因使用 .newInstance() 创建实例而不是简单的 ClassB b = new ClassB()
  • 您在哪个类中创建 main() 方法。

标签: java inheritance


【解决方案1】:

正如已在 cmets 中回答的那样,您应该将 obj 转换为 Class:

public static void main( String[] args ) throws IllegalAccessException, InstantiationException {
           Class<?> cls = ClassB.class;
           Object obj = cls.newInstance();
           ((ClassB) obj).setA();
           ((ClassA) obj).setA();
           ((ClassB) obj).test();

        }

【讨论】:

  • 如果我只有 cls 变量,有没有办法让“ClassB”进行类型转换。
【解决方案2】:

您正在通过调用cls.newInstance() 创建一个新的Object。然而,由于我们确定返回的对象将是我们想要的类,我们可以毫无问题地转换它:

public static void main( String[] args ) throws IllegalAccessException, InstantiationException {
   Class<?> cls = ClassB.class;
   ClassB obj = (ClassB)cls.newInstance();
   obj.setA(); //Accessible now
   obj.test(); //Accessible now

}

如果不强制转换为 ClassB,则返回的对象将被视为 java.lang.Object,因此只包含由它定义的 methods

但是正如大多数 cmets 已经说过的那样,使用 new 运算符简单地创建一个类型的新实例通常要容易得多:

public static void main( String[] args ) {
   ClassB obj = new ClassB();
   obj.setA(); //Accessible now
   obj.test(); //Accessible now

}

【讨论】:

    【解决方案3】:

    你可以用ClassB obj = new ClassB();正常实例化obj

    你可以试试这样的:

    ClassB obj = new ClassB();
    obj.setA(); //Accessible
    obj.test(); //Accessible
    

    或者,为了进一步改进 Abhishek 的回答:

      Class<?> cls = ClassB.class;
      ClassB obj = (ClassB) cls.newInstance();
      obj.setA();
      obj.setA();
      obj.test();
    

    注意:这会创建 ClassB 类型的 obj。如果您只需要 Object 类型,您可以每次都将其强制转换为 ClassB 类型,如下所示:

     Class<?> cls = ClassB.class;
     Object obj = cls.newInstance();
     ((ClassB) obj).setA();
     ((ClassA) obj).setA();
     ((ClassB) obj).test();
    

    如果这是您要在评论中提出的问题,如果您只知道 cls,则可以进行类型转换:

    Class<?> cls = ClassB.class;
    Object obj = cls.newInstance();
    ClassB.class.cast(obj).setA();
    ClassB.class.cast(obj).setA();
    ClassB.class.cast(obj).test();
    

    【讨论】:

    • 实际上我在评论中想问的是,如果假设变量 cls 作为参数传递,我们如何进行类型转换。
    • public void testMethod(Class&lt;?&gt; cls) { Object obj = cls.newInstance(); obj.setA(); //Not Accessible obj.test(); //Not Accessible }
    • stackoverflow.com/a/2127384/5058312 - 我想你正在寻找这样的东西
    【解决方案4】:

    Object 是所有类的基类,但在这种情况下,它不知道 setA() 方法和 test() 方法。您可以按照以下方式进行操作。

    Class<?> cls = ClassB.class;
    Object obj = cls.newInstance();
    (ClassB)obj.setA(); 
    (ClassB)obj.test(); 
    

    【讨论】:

      【解决方案5】:
      class ClassA {
             private int a;
      
             public void setA() {
              a = 15;
              System.out.println(a);
             }
           }
      
            class ClassB extends ClassA {
                public static void main( String[] args ) throws IllegalAccessException, InstantiationException {
                     Class cls = ClassB.class;
                     ClassB obj = (ClassB) cls.newInstance();
                     obj.setA(); //Accessible
                     obj.test(); // Accessible
      
                  }
                 public void test() {
                    setA();
                 }
               }
      

      应该是这样的。

      你想通过它的名字来实例化一个类吗?

      首先,你需要制作一个Class对象:

      类 cls = Class.forName(strClassName); 然后实例化 this(注意,这会抛出各种异常——访问冲突、ClassNotFound、没有没有参数的公共构造函数等)

      Object instance = cls.newInstance();
      

      然后你就可以施放它了:

      返回(SomeClass)实例; 请确保您了解以下各项之间的区别:

      一个类名(大约是一个文件名) 一个类对象(本质上是一个类型信息) 类实例(这种类型的实际对象) 如果需要,您还可以将 cls 对象强制转换为 Class 类型。不过,它并没有给你太多。您可以将其内联到:

      return (SomeClass)(Class.forName(strClassName).newInstance()); 哦,但是您可以在实例化之前使用 cls 对象进行类型检查。因此,您只需实例化它,前提是它满足您的 API(实现您想要获得的接口)。

      编辑:向反射添加更多示例代码。

      例如:

      if (cls.isInstance(request)) {
        // ...
      }
      

      【讨论】:

      • 那么为什么要使用反射而不是简单的实例化。
      • 完全正确,但我们可以通过多种方式实现对象,所以她正在使用反射。
      • 我在这里使用反射,因为我的项目需要它。如果我只有 cls 变量@rishabhkeshari123,有没有办法让“ClassB”进行类型转换
      • if (cls.isInstance(ClassB.class)) { //然后进行强制转换 }
      • Sathya 首先,您必须使用 forname 方法或 Class cls = ClassB.class; 加载该类。像这样只有你会得到ClassB的实例。进行类型转换
      猜你喜欢
      • 2012-04-28
      • 2016-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-22
      • 1970-01-01
      • 2018-03-21
      • 2019-07-25
      相关资源
      最近更新 更多