返回扩展抽象基类的具体类的类,而不是实例?

时间:2018-05-28 19:17:48

标签: java class reflection

如果我有这样的类层次结构

AbstractSuperClass
    ConcreteClassA
    ConcreteClassB

是否可以在AbstractSuperClass中使用静态方法返回两个具体类之一的类 - 而不是实例 - ?

我尝试过返回Class<AbstractSuperClass>,但IDE(Android Studio)说

Incompatible types.
Required: Class <com.example.AbstractSuperClass>
Found:    Class <com.example.ConcreteClassA>

这是我正在思考的一个例子,但是它无效:

public abstract class AbstractSuperClass{

    public abstract void someAbstractMethod();


    public static String getSomeText(){ 
        return "This is AbstractSuperClass"; 
    };

    public static Class<AbstractSuperClass> getConcreteClass(int x){
        switch( x ){
            case 0: return ConcreteClassA.class;
            case 1: return ConcreteClassB.class;
        }
    }
}


public class ConcreteClassA extends AbstractSuperClass{
    public abstract void someAbstractMethod(){
        // Do something
    }

    public static String getSomeText(){ 
        return "This is ConcreteClassA"; 
    };
}



public class ConcreteClassB extends AbstractSuperClass{
    public abstract void someAbstractMethod(){
        // Do something
    }

    public static String getSomeText(){ 
        return "This is ConcreteClassB"; 
    };
}



AbstractSuperClass.getConcreteClass(1).getSomeText(); // Should return "This is ConcreteClassB"

这在Java中根本不可能,或者我只是做错了吗?

4 个答案:

答案 0 :(得分:2)

您无法直接从static调用Class方法,就像您尝试的那样,您需要反思才能调用getSomeText()方法。像,

try {
    Method m = AbstractSuperClass.getConcreteClass(1).getMethod("getSomeText", 
            new Class[0]);
    System.out.println(m.invoke(null, new Object[0]));
} catch (Exception e) {
    e.printStackTrace();
}

然后,您可以使用capture-of extends getConcreteClass(生产者扩展,消费者超级)修复您的AbstractSuperClass方法。并且对于没有匹配的情况,您必须具有默认返回。像,

public static Class<? extends AbstractSuperClass> getConcreteClass(int x) {
    switch (x) {
    case 0: return ConcreteClassA.class;
    case 1: return ConcreteClassB.class;
    }
    return null;
}

我跑了(并得到了)

This is ConcreteClassB

答案 1 :(得分:1)

对于这种方法,

public Class<AbstractSuperClass> getConcreteClass(int x){
    switch( x ){
        case 0: return ConcreteClassA.class;
        case 1: return ConcreteClassB.class;
    }
}

签名应为

public Class<? extends AbstractSuperClass> getConcreteClass(int x)

表示返回值可以是AbstractSuperClass.class或其任何子类型。

答案 2 :(得分:0)

试试这个:

public abstract class AbstractSuperClass {

    public abstract void someAbstractMethod();

    public static String getSomeText() { 
        return "This is AbstractSuperClass"; 
    };

    public Class<? extends AbstractSuperClass> getConcreteClass() {
        return this.getClass();
    }
}

实际上你不需要int参数,因为子类的实例将知道它的类型,而不需要提示。

答案 3 :(得分:0)

我不确定它需要什么,但您的代码中存在几个问题。

  1. 您无法返回Class,因为您正在返回一个扩展AbstractSuperClass的类。因此,您必须通知编译器并将返回类型更改为Class
  2. 您不能直接从类调用any(无关静态或非静态方法)。您需要使用Reflections API,因此方法调用将如下所示:

    final class clazz = AbstractSuperClass.getConcreteClass(1);           Object result = clazz.getMethod(“getSomeText”)。invoke(clazz);

  3. 这就是你上课的完整代码。

    package com.mycompany.sandbox;
    
    import java.lang.reflect.InvocationTargetException;
    import java.util.Objects;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    
    abstract class AbstractSuperClass{
    
        public abstract void someAbstractMethod();
    
    
        public static String getSomeText(){ 
            return "This is AbstractSuperClass"; 
        };
    
        public static Class<? extends AbstractSuperClass> getConcreteClass(int x){
            switch( x ){
                case 0: return ConcreteClassA.class;
                case 1: return ConcreteClassB.class;
            }
          return null;
        }
    }
    
    
    class ConcreteClassA extends AbstractSuperClass{
        public void someAbstractMethod(){
            // Do something
        }
    
        public static String getSomeText(){ 
            return "This is ConcreteClassA"; 
        };
    }
    
    
    
    class ConcreteClassB extends AbstractSuperClass{
        public void someAbstractMethod(){
            // Do something
        }
    
        public static String getSomeText(){ 
            return "This is ConcreteClassB"; 
        };
    }
    
    
    
    
    // one class needs to have a main() method
    public class HelloWorld
    {
      // arguments are passed using the text field below this editor
      public static void main(String args[])
      {
          try {
              final Class<? extends AbstractSuperClass> clazz = AbstractSuperClass.getConcreteClass(1);
              Object result = clazz.getMethod("getSomeText").invoke(clazz);
              System.out.println(Objects.toString(result, "<NULL>"));
          } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
              Logger.getLogger(HelloWorld.class.getName()).log(Level.SEVERE, null, ex);
          }
      }
    }