[英]How to obtain type reference parameterized by the input class arg?
Is there any way to solve the following problem by using parameterized type?有没有办法通过使用参数化类型来解决以下问题? I have a parameterized class object and I want to obtain another class object parameterized with the same type.
我有一个参数化的 class object,我想获得另一个参数化的相同类型的 class object。 It's easier to check code than explain in words:
检查代码比用文字解释更容易:
public class GenericsCheck {
static class Fruit {}
static class Apple extends Fruit {}
static class Banana extends Fruit {}
static class FruitBox<T extends Fruit> {}
static class AppleBox extends FruitBox<Apple> {}
static class BananaBox extends FruitBox<Banana> {}
static class Puzzle<T extends Fruit> {
public Class<FruitBox<T>> getBoxByFruitType(Class<T> fruitType) {
// COMPILER ERROR
// Required type: Class<FruitBox<T>>
// Provided: Class<AppleBox>
if (fruitType == Apple.class) return AppleBox.class;
if (fruitType == Banana.class) return BananaBox.class;
throw new IllegalArgumentException("I don't know");
}
}
public static void main(String[] args) {
System.out.println(new Puzzle().getBoxByFruitType(Apple.class));
}
}
I know that generics are invariant.我知道 generics 是不变的。 The question is: are there any workarounds?
问题是:是否有任何解决方法? Maybe something that includes some kind of type reference wrapper...
也许包含某种类型引用包装器的东西......
You need to use wildcards :您需要使用通配符:
static class Puzzle<T extends Fruit> {
public Class<? extends FruitBox<? extends Fruit>> getBoxByFruitType(Class<T> fruitType) {
if (fruitType == Apple.class) return AppleBox.class;
if (fruitType == Banana.class) return BananaBox.class;
throw new IllegalArgumentException("I don't know");
}
}
What about this?那这个呢?
public class GenericsCheck {
static class Fruit {}
static class Apple extends Fruit {}
static class Banana extends Fruit {}
static class FruitBox<T extends Fruit> {}
static class AppleBox extends FruitBox<Apple> {}
static class BananaBox extends FruitBox<Banana> {}
static class Puzzle<T extends Fruit,D extends FruitBox<T>> {
@SuppressWarnings("unchecked")
public Class<D> getBoxByFruitType(Class<T> fruitType) {
if (fruitType == Apple.class)
return (Class<D>) AppleBox.class;
if (fruitType == Banana.class)
return (Class<D>) BananaBox.class;
throw new IllegalArgumentException("I don't know");
}
}
public static void main(String[] args) {
System.out.println(new Puzzle().getBoxByFruitType(Apple.class));
}
} }
Probably the most correct way to implement this is something like this:可能最正确的实现方式是这样的:
import java.util.Map;
import java.util.HashMap;
public class GenericsCheck {
static class Fruit {}
static class Apple extends Fruit {}
static class Banana extends Fruit {}
static class FruitBox<T extends Fruit> {}
static class AppleBox extends FruitBox<Apple> {}
static class BananaBox extends FruitBox<Banana> {}
static class Puzzle {
private Map<Class<? extends Fruit>,
Class<? extends FruitBox<? extends Fruit>>> map
= new HashMap<>();
public Puzzle() {
putBoxByFruitType(Apple.class, AppleBox.class);
putBoxByFruitType(Banana.class, BananaBox.class);
}
public <T extends Fruit> void putBoxByFruitType(
Class<T> fruitType, Class<? extends FruitBox<T>> boxType) {
map.put(fruitType, boxType);
}
@SuppressWarnings("unchecked")
public <T extends Fruit> Class<? extends FruitBox<T>> getBoxByFruitType(
Class<T> fruitType) {
return (Class<? extends FruitBox<T>>) map.get(fruitType);
}
}
public static void main(String[] args) {
System.out.println(new Puzzle().getBoxByFruitType(Apple.class));
}
}
And, yes, you cannot assign the result to a variable of type Class<AppleBox>
because that isn't safe -- as Konrad Rudolph mentioned, there can be another class SnappleBox extends FruitBox<Apple>
, so then the method might return a Class<SnappleBox>
.而且,是的,您不能将结果分配给类型为
Class<AppleBox>
的变量,因为这不安全——正如 Konrad Rudolph 提到的,可能还有另一个class SnappleBox extends FruitBox<Apple>
,因此该方法可能会返回一个Class<SnappleBox>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.