0

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

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

4 回答 4

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();
}

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
于 2018-05-28T19:31:42.507 回答
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它的任何子类型。

于 2018-05-28T19:25:19.347 回答
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参数,因为子类的实例无需提示即可知道其类型。

于 2018-05-28T19:21:26.910 回答
0

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

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

    最终类 clazz = AbstractSuperClass.getConcreteClass(1); 对象结果 = clazz.getMethod("getSomeText").invoke(clazz);

这就是你类的完整代码。

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);
      }
  }
}
于 2018-05-28T19:37:36.943 回答