泛型转换

4
有没有一种方法可以将对象转换为返回方法的通用值?我尝试了这种方式,但会发生转换异常:
public <S extends Super> S get(Class<S> clazz) {
    return (S) new Super();
}

public class Super {

}

public class Sub1 extends Super {

}

public class Sub2 extends Super {

}

异常:

java.lang.ClassCastException: 
Cannot cast com.zarinak.app.model.Super to com.zarinak.app.model.Sub1

有没有办法?

1
尝试像这样更改方法的签名: public <S extends Super> S get(S clazz) { - Dazak
2
@Dazak 没有任何区别 :( - ImanX
你怎么称呼 get 方法? - f1l2
1
@f1l2 get(Sub1.class); - ImanX
你的问题在于你返回了一个通用值,然后将其转换为具体对象。这是不可能的。 - f1l2
1个回答

5
您试图将一个新的Super对象转换为扩展它的对象类型的方式是不正确的。
假设您想创建一个Sub1对象 - 通过在Super类中使用构造函数实例化一个Super对象,然后告诉编译器该对象实际上是Sub1,但它既不包含Sub1特定的方法或变量,也没有使用Sub1构造函数进行构造。编译器知道该对象不是Sub1,并且会在运行时抛出错误。虽然这在当前代码结构下可能不会有问题,但当Sub1包含Super没有的方法或变量时,这将成为一个问题。如果编译器允许这种形式的转换,那么尝试调用这些方法将会是一个重大问题。
以下方法可以实现您的目标。通过将S泛型类型限制为Super的扩展,您有效地绕过了实例化Super对象并从那里进行转换的过程。
public <S extends Super> S get(Class<S> clazz) throws IllegalAccessException, InstantiationException {
    S s = clazz.newInstance();
    return s;
}

拥有这个方法而没有任何额外的主体几乎完全没有意义,你可能会像调用clazz.newInstance()一样。不过,这确保了对象的类扩展了Super。

1
这种方法有什么好处呢?与其调用 get(Type.class);,你可以直接调用 Type.class.newInstance(); - Lino
1
@Lino 完全同意。这样写是为了向作者解释,但我会编辑一下以便注意到你的评论。它确实强制要求传递的对象扩展自 Super,这是问题中普遍存在的一个方面。 - Zachary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接