What's the reason I can't create generic a

2018-12-31 04:03发布

What's the reason Java doesn't allow us to do

private T[] elements = new T[initialCapacity];

I could understand .NET didn't allow us to do that, as in .NET you have value types that at run-time can have different sizes, but in Java all kinds of T will be object references, thus having the same size (correct me if I'm wrong).

What is the reason?

14条回答
旧时光的记忆
2楼-- · 2018-12-31 04:42

I know I'm a little late to the party here, but I figured I might be able to help any future googlers since none of these answers fixed my issue. Ferdi265's answer helped immensely though.

I'm trying to create my own Linked list, so the following code is what worked for me:

package myList;
import java.lang.reflect.Array;

public class MyList<TYPE>  {

    private Node<TYPE> header = null;

    public void clear() {   header = null;  }

    public void add(TYPE t) {   header = new Node<TYPE>(t,header);    }

    public TYPE get(int position) {  return getNode(position).getObject();  }

    @SuppressWarnings("unchecked")
    public TYPE[] toArray() {       
        TYPE[] result = (TYPE[])Array.newInstance(header.getObject().getClass(),size());        
        for(int i=0 ; i<size() ; i++)   result[i] = get(i); 
        return result;
    }


    public int size(){
         int i = 0;   
         Node<TYPE> current = header;
         while(current != null) {   
           current = current.getNext();
           i++;
        }
        return i;
    }  

In the toArray() method lies the way to create an array of a generic type for me:

TYPE[] result = (TYPE[])Array.newInstance(header.getObject().getClass(),size());    
查看更多
不再属于我。
3楼-- · 2018-12-31 04:43

It is because generics were added on to java after they made it, so its kinda clunky because the original makers of java thought that when making an array the type would be specified in the making of it. So that does not work with generics so you have to do E[] array=(E[]) new Object[15]; This compiles but it gives a warning.

查看更多
时光乱了年华
4楼-- · 2018-12-31 04:44

The reason this is impossible is that Java implements its Generics purely on the compiler level, and there is only one class file generated for each class. This is called Type Erasure.

At runtime, the compiled class needs to handle all of its uses with the same bytecode. So, new T[capacity] would have absolutely no idea what type needs to be instantiated.

查看更多
人气声优
5楼-- · 2018-12-31 04:48

There surely must be a good way around it (maybe using reflection), because it seems to me that that's exactly what ArrayList.toArray(T[] a) does. I quote:

public <T> T[] toArray(T[] a)

Returns an array containing all of the elements in this list in the correct order; the runtime type of the returned array is that of the specified array. If the list fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list.

So one way around it would be to use this function i.e. create an ArrayList of the objects you want in the array, then use toArray(T[] a) to create the actual array. It wouldn't be speedy, but you didn't mention your requirements.

So does anyone know how toArray(T[] a) is implemented?

查看更多
看风景的人
6楼-- · 2018-12-31 04:51

The answer was already given but if you already have an Instance of T then you can do this:

T t; //Assuming you already have this object instantiated or given by parameter.
int length;
T[] ts = (T[]) Array.newInstance(t.getClass(), length);

Hope, I could Help, Ferdi265

查看更多
闭嘴吧你
7楼-- · 2018-12-31 04:58

By failing to provide a decent solution, you just end up with something worse IMHO.

The common work around is as follows.

T[] ts = new T[n];

is replaced with (assuming T extends Object and not another class)

T[] ts = (T[]) new Object[n];

I prefer the first example, however more acedemic types seem to prefer the second, or just prefer not to thing about it.

Most of the examples of why you can't just use an Object[] equally apply to List or Collection (which are supported), so I see them as very poor arguments.

Note: this is one of the reasons the Collections library itself doesn't compile without warnings. If you this usecase cannot be supported without warnings, something is fundermentally broken with the generics model IMHO.

查看更多
登录 后发表回答