Java:类型标记中的泛型类型

Java:类型标记中的泛型类型,java,generics,types,Java,Generics,Types,我有一个类,它接受一个类型标记,然后生成一个由该类型参数化的类型的对象(好的,它比这个复杂一点,但这是一个简洁的示例): 公共类测试{ 公共静态void main(字符串[]args)引发异常{ Holder i=newObjectHolder(HashSet.class);//此操作失败 } 静态类持有者{ 公共持有人(T newInstance){} } 公共静态持有者newObjectHolder(类typeToken)引发异常{ 构造函数ctor=typeToken.getConstru

我有一个类,它接受一个类型标记,然后生成一个由该类型参数化的类型的对象(好的,它比这个复杂一点,但这是一个简洁的示例):

公共类测试{
公共静态void main(字符串[]args)引发异常{
Holder i=newObjectHolder(HashSet.class);//此操作失败
}
静态类持有者{
公共持有人(T newInstance){}
}
公共静态持有者newObjectHolder(类typeToken)引发异常{
构造函数ctor=typeToken.getConstructor();
返回新的持有者(ctor.newInstance());
}
}
如果传递了非泛型类型(如:

Holder<Integer> i = Test.newObjectHolder(Integer.class);
Holder i=Test.newObjectHolder(Integer.class);
但是,如果传递的类型标记是泛型的,则它不起作用,如上面的指示行所示:

Holder<HashSet<Integer>> i = Test.newObjectHolder(HashSet.class);  // this fails
Holder i=Test.newObjectHolder(HashSet.class);//这失败了

我明白问题所在,但有解决办法吗?如果@SuppressWarnings(“unused”)不会降低安全性,我可以在
newObject
的代码中添加@SuppressWarnings(“unused”)。直观地说,似乎newObject应该能够进行有效的转换,我们知道一个已擦除泛型类型的“新”对象与任何其他对象相同,并且我们没有在方法中使用
t

在您现在更新的代码中,您仍然可以

 Holder<HashSet> i = newObjectHolder(HashSet.class);
我遗漏了什么吗?
所以,不好意思地回答我自己的问题

我找不到任何方法来使用
,但这种称为超级类型令牌的神奇技术似乎工作得很好。以下是更新的代码:

public class Test {

    static class A {}
    static class B extends A {}


    public static void main(String[] args) throws Exception {
        Holder<HashSet<Integer>> i = newObjectHolder(new TypeReference<HashSet<Integer>>() {});  // works
        Holder<A> j = newObjectHolder(new TypeReference<A>() {});  // works
        Holder<A> k = newObjectHolder(new TypeReference<B>() {});  // works
        Holder<B> l = newObjectHolder(new TypeReference<A>() {});  // doesn't compile (good)
    }

    static class Holder<T> {
        public Holder(T newInstance) {}
        T get() { return null; }
    }

    public static <T,U extends TypeReference<? extends T>> Holder<T> newObjectHolder(U typeToken) throws Exception {
        T obj = typeToken.newInstance();
        return new Holder<T>(obj);
    }
}
公共类测试{
静态类A{}
静态类B扩展了{}
公共静态void main(字符串[]args)引发异常{
Holder i=newObjectHolder(newTypeReference(){});//有效

Holder,尽管我怀疑Guice的也能正常工作(但它没有newInstance代码,您必须实现它)。

这是一个错误,在我的“使简洁”中引入从实际代码开始的阶段。让我来修复它。修复。注意它仍然不起作用。对
Foo.newObject
的调用是否应该是
Foo.newObjectHolder
?是的,我的示例在之前的编辑后不一致,以修复Nishant提出的问题。我现在用“看你是对的”更新了它,我的简化太多了(虽然上面的代码有一个未检查的警告)。让我来解决这个问题。是的,由于我对泛型知之甚少,我认为这是不可避免的。对不起,我已经解决了。错误基于您的示例(调用newObjectHolder)现在是:类型不匹配:无法从Test.Holder转换到Test.HolderYes,我仍然无法保持示例和现实生活之间的一致性。我想做的是:Holder I…最终我需要调用Holder上的方法,这些方法应该返回
HashSet
,而不仅仅是
HashSet
。是的,只要我看到问题标题,我就会立即返回伊迪丽想到了超级类型代币技术。回答你自己的问题很好!别忘了接受你的答案。@Taymon-我很高兴我能回答这个问题,是的,但我感到内疚,因为这基本上意味着我在转向前没有做足够的实验或挖掘。通常我不是通过问来得到答案的,但通过找到一个现有的问题(这些天来,这些问题常常位于谷歌搜索结果的顶部),因此,也许在这里找到这个问题会帮助其他人!你不应该感到内疚。你的答案仍然帮助其他人。作为后续,jackson使用此技术传递有关要[反]序列化的泛型类型的信息。
 Holder<HashSet<Integer>> i = newObjectHolder(HashSet.class);
public class Test {

    public static void main(String[] args) throws Exception {
        @SuppressWarnings("unchecked")
        HashSet<Integer> i = newObject(HashSet.class);
        i.add(new Integer(42));
        i.add(new Integer(666));
        System.out.println(i.size() +":" + Arrays.toString(i.toArray()));
    }

    public static <T> T newObject(Class<T> typeToken) throws Exception {
        Constructor<T> ctor = typeToken.getConstructor();
        return ctor.newInstance();
    }

}
2:[666, 42]
public class Test {

    static class A {}
    static class B extends A {}


    public static void main(String[] args) throws Exception {
        Holder<HashSet<Integer>> i = newObjectHolder(new TypeReference<HashSet<Integer>>() {});  // works
        Holder<A> j = newObjectHolder(new TypeReference<A>() {});  // works
        Holder<A> k = newObjectHolder(new TypeReference<B>() {});  // works
        Holder<B> l = newObjectHolder(new TypeReference<A>() {});  // doesn't compile (good)
    }

    static class Holder<T> {
        public Holder(T newInstance) {}
        T get() { return null; }
    }

    public static <T,U extends TypeReference<? extends T>> Holder<T> newObjectHolder(U typeToken) throws Exception {
        T obj = typeToken.newInstance();
        return new Holder<T>(obj);
    }
}