在java中实例化泛型类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2434041/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Instantiating generics type in java
提问by Mohd Farid
I would like to create an object of Generics Type in java. Please suggest how can I achieve the same.
我想在java中创建一个泛型类型的对象。请建议我如何实现相同的目标。
Note: This may seem a trivial Generics Problem. But I bet.. it isn't. :)
注意:这似乎是一个微不足道的泛型问题。但我敢打赌……不是。:)
suppose I have the class declaration as:
假设我的类声明为:
public class Abc<T> {
public T getInstanceOfT() {
// I want to create an instance of T and return the same.
}
}
采纳答案by Jens Schauder
public class Abc<T> {
public T getInstanceOfT(Class<T> aClass) {
return aClass.newInstance();
}
}
You'll have to add exception handling.
您必须添加异常处理。
You have to pass the actual type at runtime, since it is not part of the byte code after compilation, so there is no way to know it without explicitly providing it.
您必须在运行时传递实际类型,因为它不是编译后字节码的一部分,因此如果不明确提供它,就无法知道它。
回答by Martin Milan
It looks like you are trying to create the class that serves as the entry point to your application as a generic, and that won't work... The JVM won't know what type it is supposed to be using when it's instantiated as you start the application.
看起来您正在尝试创建作为泛型应用程序入口点的类,但这是行不通的……JVM 在实例化时不知道它应该使用什么类型你启动应用程序。
However, if this were the more general case, then something like would be what you're looking for:
但是,如果这是更一般的情况,那么您正在寻找的内容如下:
public MyGeneric<MyChoiceOfType> getMeAGenericObject(){
return new MyGeneric<MyChoiceOfType>();
}
or perhaps:
也许:
MyGeneric<String> objMyObject = new MyGeneric<String>();
回答by Roman
Abc<String> abcInstance = new Abc<String> ();
..for example
..例如
回答by Tedil
You don't seem to understand how Generics work. You may want to look at http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.htmlBasically what you coulddo is something like
你似乎不明白泛型是如何工作的。你可能想看看http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html基本上你可以做的是
public class Abc<T>
{
T someGenericThing;
public Abc(){}
public T getSomeGenericThing()
{
return someGenericThing;
}
public static void main(String[] args)
{
// create an instance of "Abc of String"
Abc<String> stringAbc = new Abc<String>();
String test = stringAbc.getSomeGenericThing();
}
}
回答by Martin
In the code you posted, it's impossible to create an instance of T
since you don't know what type that is:
在您发布的代码中,无法创建实例,T
因为您不知道它是什么类型:
public class Abc<T>
{
public T getInstanceOfT()
{
// There is no way to create an instance of T here
// since we don't know its type
}
}
Of course it is possible if you have a reference to Class<T>
and T
has a default constructor, just call newInstance()
on the Class
object.
当然,如果您有一个引用Class<T>
并T
有一个默认构造函数,则可以调用newInstance()
该Class
对象。
If you subclass Abc<T>
you can even work around the type erasure problem and won't have to pass any Class<T>
references around:
如果您子类化,Abc<T>
您甚至可以解决类型擦除问题,而不必传递任何Class<T>
引用:
import java.lang.reflect.ParameterizedType;
public class Abc<T>
{
T getInstanceOfT()
{
ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
Class<T> type = (Class<T>) superClass.getActualTypeArguments()[0];
try
{
return type.newInstance();
}
catch (Exception e)
{
// Oops, no default constructor
throw new RuntimeException(e);
}
}
public static void main(String[] args)
{
String instance = new SubClass().getInstanceOfT();
System.out.println(instance.getClass());
}
}
class SubClass
extends Abc<String>
{
}
回答by Hyman
What you wrote doesn't make any sense, genericsin Java are meant to add the functionality of parametric polymorphismto objects.
您写的内容没有任何意义,Java 中的泛型旨在为对象添加参数多态性的功能。
What does it mean? It means that you want to keep some type variablesof your classes undecided, to be able to use your classes with many different types.
这是什么意思?这意味着您希望保持类的某些类型变量未定,以便能够使用具有许多不同类型的类。
But your type variableT
is an attribute that is resolved at run-time, the Java compiler will compile your class proving type safety without trying to know what kind of object is T
so it's impossible for it to let your use a type variablein a static method. The type is associated to a run-time instance of the object while public void static main(..)
is associated to the class definition and at that scope T
doesn't mean anything.
但是您的类型变量T
是一个在运行时解析的属性,Java 编译器将编译您的类来证明类型安全,而无需尝试知道对象的类型,T
因此它不可能让您在静态方法中使用类型变量. 该类型与对象的运行时实例public void static main(..)
相关联,而与类定义相关联,并且在该范围T
内没有任何意义。
If you want to use a type variableinside a static method you have to declare the method as generic (this because, as explained type variablesof a template class are related to its run-time instance), not the class:
如果您想在静态方法中使用类型变量,您必须将该方法声明为泛型(这是因为,正如所解释的,模板类的类型变量与其运行时实例相关),而不是类:
class SandBox
{
public static <T> void myMethod()
{
T foobar;
}
}
this works, but of course not with main
method since there's no way to call it in a generic way.
这有效,但当然不能使用main
方法,因为无法以通用方式调用它。
EDIT: The problem is that because of type erasurejust one generic class is compiled and passed to JVM. Type checker just checks if code is safe, then since it proved it every kind of generic informationis discarded.
编辑:问题在于,由于类型擦除,只有一个泛型类被编译并传递给 JVM。类型检查器只是检查代码是否安全,然后因为它证明了它,所以所有类型的通用信息都被丢弃了。
To instantiate T
you need to know the type of T
, but it can be many types at the same time, so one solution with requires just the minimum amount of reflection is to use Class<T>
to instantiate new objects:
要实例化,T
您需要知道 的类型T
,但它可以同时是多种类型,因此只需要最少反射量的一种解决方案是Class<T>
用于实例化新对象:
public class SandBox<T>
{
Class<T> reference;
SandBox(Class<T> classRef)
{
reference = classRef;
}
public T getNewInstance()
{
try
{
return reference.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
{
SandBox<String> t = new SandBox<String>(String.class);
System.out.println(t.getNewInstance().getClass().getName());
}
}
Of course this implies that the type you want to instantiate:
当然,这意味着您要实例化的类型:
- is not a primitive type
- it has a default constructor
- 不是原始类型
- 它有一个默认构造函数
To operate with different kind of constructors you have to dig deeper into reflection.
要使用不同类型的构造函数,您必须深入研究反射。
回答by bruno conde
First of all, you can't access the type parameter T
in the static main method, only on non-static class members (in this case).
首先,您不能访问T
静态 main 方法中的类型参数,只能访问非静态类成员(在这种情况下)。
Second, you can't instantiate T
because Java implements generics with Type Erasure. Almost all the generic information is erased at compile time.
其次,您无法实例化,T
因为 Java 使用Type Erasure实现泛型。几乎所有的通用信息在编译时都会被删除。
Basically, you can't do this:
基本上,你不能这样做:
T member = new T();
Here's a nice tutorial on generics.
这是一个关于泛型的很好的教程。
回答by Hosam Aly
You need to get the type information statically. Try this:
您需要静态获取类型信息。尝试这个:
public class Abc<T> {
private Class<T> clazz;
public Abc(Class<T> clazz) {
this.clazz = clazz;
}
public T getInstanceOfT()
throws InstantiationException, IllegalAccessException {
return clazz.newInstance();
}
}
Use it as such:
像这样使用它:
Abc<String> abc = new Abc<String>(String.class);
abc.getInstanceOfT();
Depending on your needs, you may want to use Class<? extends T>
instead.
根据您的需要,您可能希望Class<? extends T>
改用。
回答by Mohd Farid
I was implementing the same using the following approach.
我正在使用以下方法实现相同的功能。
public class Abc<T>
{
T myvar;
public T getInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException
{
return clazz.newInstance();
}
}
I was trying to find a better way to achieve the same.
我试图找到一种更好的方法来实现同样的目标。
Isn't it possible?
不可能吗?
回答by BalusC
The only way to get it to work is to use Reified Generics. And this is not supported in Java (yet? it was plannedfor Java 7, but has been postponed). In C# for example it is supported assuming that T
has a defaultconstructor. You can even get the runtime type by typeof(T)
and get the constructors by Type.GetConstructor()
. I don't do C# so the syntax may be invalid, but it roughly look like this:
让它工作的唯一方法是使用Reified 泛型。这在 Java 中不受支持(但是?它计划用于 Java 7,但已被推迟)。例如,在 C# 中,假设T
具有默认构造函数,则支持它。您甚至可以通过 获取运行时类型typeof(T)
并通过获取构造函数Type.GetConstructor()
。我不使用 C#,因此语法可能无效,但大致如下所示:
public class Foo<T> where T:new() {
public void foo() {
T t = new T();
}
}
The best "workaround" for this in Java is to pass a Class<T>
as method argument instead as several answers already pointed out.
在 Java 中,最好的“解决方法”是传递一个Class<T>
as 方法参数,而不是正如已经指出的几个答案。