如何从其超类型列表中返回一个对象作为其类型?

时间:2017-03-24 01:03:31

标签: java generics

假设我有类似的类结构

public abstract class A
{
    public String id;
}

public class B extends A
{
    id = "b";
}

public class C extends A
{
    id = "c";
}

public class test
{
    ArrayList<A> as = new ArrayList<A>();
    a.add(new B());
    a.add(new C());

    public *what goes here* get(String s)//returns a subtype of A, not A
    {
        for(A a : as)
        {
            if(a.id.equals(s))//or a.getClass().toString()
            {
                return a;//but need as subtype of A, not A
            }
        }
        //throw some exception here when id is not found
    }
}

如果我跑了

,我该怎么做呢?
B b = get("b"); 

我不会在这里收到编译器警告?我不希望在我的代码中检查丑陋的instanceof,并且显式地转换为B也不是我想要的。我认为泛型可能是要走的路,但我对它们并不是很有经验。

我知道这不起作用,但这是我正在寻找的东西

public T extends A get(String s)

其中T扩展A是返回类型

2 个答案:

答案 0 :(得分:2)

我能够用泛型做到这一点。

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url   
{  
    // Do something with the url here  
} 

我必须使用类参数而不是String。

这里方法主要打印:

public class B extends A {
    public int n = 2;

    public void doBThing()
    {
        System.out.println(n);
    }
}


public class Runner
{
    static ArrayList<A> as = new ArrayList<>();

    public static void main(String[] args)
    {
        as.add(new B());
        as.add(new C());
        System.out.println(get(C.class).getClass().toString());
        System.out.println(get(B.class).getClass().toString());
        get(B.class).doBThing();
    }

    public static <T> T get(Class<T> toGet)
    {
        for(A a : as)
        {
            if(toGet.isInstance(a))
            {
                return toGet.cast(a);
            }
        }
        return (T)(new A());
    }
}

现在更频繁地使用这个技巧了!

get()没有返回类型B,但只要参数为B.class就被视为处理

答案 1 :(得分:0)

单个函数可能不会返回多个类型,必须在编译时知道。

所以你做不到

public (A or B) get(...) {}

如果不是类型擦除,你可以使用Java 5中引入的协变返回类型属性,它允许你这样做:

public C get(Class<C> t){
     //check match against t
     return istanceC;
}

public B get(Class<B> t){
    //check match against t
     return istanceB;    
}

但是你会得到一个编译错误,说Class和Class有相同的擦除(因为它们都被上传到Class)。

编辑

基于kreinerjm的回答和this answer,实际上可以使用以下形式进行上述工作:

public <T extends A> T get(Class<T> type) {
    //check and return
    return (T) a;  

}

这样,演员阵容更安全,因为你只能进入从A延伸的T。