Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的动态泛型类型_Java_Generics - Fatal编程技术网

Java中的动态泛型类型

Java中的动态泛型类型,java,generics,Java,Generics,如果我有一个使用泛型类型的类,比如 public class Record<T> { private T value; public Record(T value) { this.value = value; } } 公共类记录{ 私人T值; 公共记录(T值){ 这个值=值; } } 如果我知道所有使用的类型,比如本例中的情况,那么在设计期间键入所有内容是非常简单的: // I type explicitly String myStr =

如果我有一个使用泛型类型的类,比如

public class Record<T> {
    private T value;

    public Record(T value) {
        this.value = value;
    }
}
公共类记录{
私人T值;
公共记录(T值){
这个值=值;
}
}
如果我知道所有使用的类型,比如本例中的情况,那么在设计期间键入所有内容是非常简单的:

// I type explicitly
String myStr = "A";
Integer myInt = 1;
ArrayList myList = new ArrayList();

Record rec1 = new Record<String>(myStr);
Record rec2 = new Record<Integer>(myInt);
Record rec3 = new Record<ArrayList>(myList);
//我显式地键入
字符串myStr=“A”;
整数myInt=1;
ArrayList myList=新的ArrayList();
记录rec1=新记录(myStr);
记录rec2=新记录(myInt);
记录rec3=新记录(myList);
如果我从我不知道类型的“某处”获取对象列表,会发生什么?如何分配类型:

// now let's assume that my values come from a list where I only know during runtime what type they have

ArrayList<Object> myObjectList = new ArrayList<Object>();
    myObjectList.add(myStr);
    myObjectList.add(myInt);
    myObjectList.add(myList);

    Object object = myObjectList.get(0);

    // this fails - how do I do that?
    new Record<object.getClass()>(object);
//现在让我们假设我的值来自一个列表,在该列表中,我只知道它们在运行时的类型
ArrayList myObjectList=新建ArrayList();
myObjectList.add(myStr);
myObjectList.add(myInt);
myObjectList.add(myList);
Object=myObjectList.get(0);
//这失败了-我该怎么做?
新记录(对象);

> > p> java泛型不是C++模板。

Java泛型是编译时特性,而不是运行时特性

这里有一个链接到

这永远无法与Java一起使用:

new Record<object.getClass()>(object);

或者您可以使用。

如果您不知道类型,则无法对泛型强制执行编译时检查

只是为了使用它,你可以说

new Record<Object>(object);
新记录(对象);
在运行时从泛型类型创建实例 我不完全确定你想要实现什么,但乍一看,最简单的解决方案似乎是最好的解决方案

可以通过使用脚本环境(Groovy、JavaScript、JRuby、Jython)来解决这个问题,该环境可以动态地评估和执行任意代码来创建对象,但仅仅创建一个对象就变得极其复杂

但不幸的是,我认为它有一个非常简单的解决方案

只要有一组预定义的受支持类型,就可以使用
Factory
模式。这里我只是利用了
javax.inject
/
com.google.inject
包中的
ProviderT
接口

笔记:
  • 适用于具有默认无参数构造函数的类
  • 如果没有默认的无参数构造函数,则比使用直接反射效果更好
  • 应该很好地使用Guice,允许您使用
    .getRawType()
    生成的
    传递到喷油器的
    getInstance()
    。我还没试过,我只是想到了
  • 您可以使用
    Class.cast()
    进行不需要
    @SuppressWarning(“unchecked”)
    的强制转换

  • 泛型用于编译时强类型。如果你不知道你想推断的类型,那么它几乎是无用的。您应该以这样一种方式来设计它,即至少有一个已知的接口或基类可以使用。你可以做
    新记录(对象)
    我想。我不明白你的第一句话。你的措辞似乎暗示C++模板是运行时特性,但它们不是。与Java泛型相比,它们的编译时间更长。这种方法的问题是,最终您必须考虑将要创建的所有类型。如果您仅限于几种类型,这是可以的。如果您使用了很多类型,或者如果您想输入“any”类型,该怎么办?因为这个原因,我认为这是一个糟糕的解决方案。由于泛型的局限性,这个问题最终可能没有好的解决方案……您描述的问题是糟糕设计的症状,并不代表泛型的局限性,它代表的问题超出了泛型的范围。如果你需要玩“I R Guud four al typs”的游戏,请使用脚本语言。谢谢你提到的重载;在Python中工作之后,我现在从事Java工作,我忘记了这些存在。
    new Record<Object>(object);
    
    public class Q26289147_ProviderPattern
    {
        private static final List<String> CLASS_NAMES = ImmutableList.of("String", "Integer", "Boolean");
        private static final Map<String, Provider<StrawManParameterizedClass>> PROVIDERS;
    
        static
        {
            final ImmutableMap.Builder<String, Provider<StrawManParameterizedClass>> imb = ImmutableMap.builder();
            for (final String cn : CLASS_NAMES)
            {
                switch (cn)
                {
                    case "String":
                        imb.put(cn, new Provider<StrawManParameterizedClass>()
                        {
                            @Override
                            public StrawManParameterizedClass<String> get() { return new StrawManParameterizedClass<String>() {}; }
                        });
                        break;
                    case "Integer":
                        imb.put(cn, new Provider<StrawManParameterizedClass>()
                        {
                            @Override
                            public StrawManParameterizedClass<Integer> get() { return new StrawManParameterizedClass<Integer>() {}; }
                        });
                        break;
                    case "Boolean":
                        imb.put(cn, new Provider<StrawManParameterizedClass>()
                        {
                            @Override
                            public StrawManParameterizedClass<Integer> get() { return new StrawManParameterizedClass<Integer>() {}; }
                        });
                        break;
                    default:
                        throw new IllegalArgumentException(String.format("%s is not a supported type %s", cn, Joiner.on(",").join(CLASS_NAMES)));
                }
            }
            PROVIDERS = imb.build();
        }
    
        static <T> void read(@Nonnull final StrawManParameterizedClass<T> smpc) { System.out.println(smpc.type.toString()); }
    
        static abstract class StrawManParameterizedClass<T>
        {
            final TypeToken<T> type = new TypeToken<T>(getClass()) {};
    
            @Override
            public String toString() { return type.getRawType().getCanonicalName(); }
        }
    
        public static void main(final String[] args)
        {
            for (final String cn : CLASS_NAMES)
            {
                read(PROVIDERS.get(cn).get());
            }
        }
    }
    
    import com.google.common.reflect.TypeToken;
    
    public class Q26289147
    {
        public static void main(final String[] args) throws IllegalAccessException, InstantiationException
        {
            final StrawManParameterizedClass<String> smpc = new StrawManParameterizedClass<String>() {};
            final String string = (String) smpc.type.getRawType().newInstance();
            System.out.format("string = \"%s\"",string);
        }
    
        static abstract class StrawManParameterizedClass<T>
        {
            final TypeToken<T> type = new TypeToken<T>(getClass()) {};
        }
    }