简体   繁体   English

如何获取由输入 class arg 参数化的类型引用?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM