Instantiating generics type in java

2019-01-01 13:39发布

Duplicate: Java generics why this won’t work

Duplicate: Instantiating a generic class in Java

I would like to create an object of Generics Type in java. Please suggest how can I achieve the same.

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.
    }
}

标签: java generics
12条回答
孤独总比滥情好
2楼-- · 2019-01-01 14:04

There are hacky ways around this when you really have to do it.

Here's an example of a transform method that I find very useful; and provides one way to determine the concrete class of a generic.

This method accepts a collection of objects as input, and returns an array where each element is the result of calling a field getter on each object in the input collection. For example, say you have a List<People> and you want a String[] containing everyone's last name.

The type of the field value returned by the getter is specified by the generic E, and I need to instantiate an array of type E[] to store the return value.

The method itself is a bit ugly, but the code you write that uses it can be so much cleaner.

Note that this technique only works when somewhere in the input arguments there is an object whose type matches the return type, and you can deterministically figure it out. If the concrete classes of your input parameters (or their sub-objects) can tell you nothing about the generics, then this technique won't work.

public <E> E[] array (Collection c) {
    if (c == null) return null;
    if (c.isEmpty()) return (E[]) EMPTY_OBJECT_ARRAY;
    final List<E> collect = (List<E>) CollectionUtils.collect(c, this);
    final Class<E> elementType = (Class<E>) ReflectionUtil.getterType(c.iterator().next(), field);
    return collect.toArray((E[]) Array.newInstance(elementType, collect.size()));
}

Full code is here: https://github.com/cobbzilla/cobbzilla-utils/blob/master/src/main/java/org/cobbzilla/util/collection/FieldTransformer.java#L28

查看更多
路过你的时光
3楼-- · 2019-01-01 14:06

In the code you posted, it's impossible to create an instance of T since you don't know what type that is:

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.

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:

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>
{
}
查看更多
时光乱了年华
4楼-- · 2019-01-01 14:06

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.

查看更多
宁负流年不负卿
5楼-- · 2019-01-01 14:08

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.

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>();
查看更多
冷夜・残月
6楼-- · 2019-01-01 14:09

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).

Second, you can't instantiate T because Java implements generics with Type Erasure. Almost all the generic information is erased at compile time.

Basically, you can't do this:

T member = new T();

Here's a nice tutorial on generics.

查看更多
萌妹纸的霸气范
7楼-- · 2019-01-01 14:13
Abc<String> abcInstance = new Abc<String> ();

..for example

查看更多
登录 后发表回答