Create a shared array

Here is the code I'm using

public class aClass<T> { private T[] elements; public aClass(T[] elements) { this.elements = elements; } public void doSomething() { T[] newArray = (T[]) new Object[5]; ... } } 

I have seen people say that creating such an array is a bad idea because it is not a safe type. However, every time I use it, I have no problem with this. When will creating such an array cause a problem?

thanks

+8
java arrays generics
source share
7 answers

Here is an example that causes problems:

 public class Main { public static class List<E extends Number> { private E[] myE; public void hello(E e) { E[] newArray = (E[]) new Object[5]; for (int i = 0; i < newArray.length; i++) { newArray[i] = e; } myE = newArray; } } public static <T> T[] createArray(int size) { return (T[]) new Object[size]; } public static void main(String[] args) throws IOException { List<Integer> integers = new List<Integer>(); integers.hello(5); } } 

Your code works because when you declare your common <T> parameter, it is not bound, which means it extends Object . When you overlay an array on (T[]) , you actually execute (Object[]) because this is the best way the compiler can do. Now, if you store your array inside your code, you should not have too many problems. But if someone from your code can get this array and create an instance of your class with a type different from the object, it will have a ClassCastException.

+4
source share

You cannot create an array from T, because Java does not know at run time what type T is. This is because in Java generic tools are implemented with the type of erase. This means that the compiler dumps most of the information of a general type after everything is fine.

The story is different with arrays because Java needs to know the exact type of T to create the given array, and since such a thing cannot be defined, you cannot create an array of a generic type.

What you can do is provide an instance of the actual array that you want to use, and the Java compiler can guarantee that it has the appropriate type:

 public static <T> void fillWith(T[] destiny, List<? extends T> source){ for(int i=0; i<= destiny.length; i++){ destiny[i] = source.get(i); } } 

The java.utils.Arrays.copy method offers an alternative, carefully using generalizations and reflections, which you can use as a reference for what you want to do.

 public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); } public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; } 
+4
source share

Something that is not safe type does not create problems in itself. But it can hide problems during compilation that won't pop up until the right moment.

You could fully work in a safe environment without types, without problems, but it’s a bad habit just because a safe environment of type guarantees you that you will not have a set of common runtime errors. At any time you have any guarantees , and you have no guarantee, and this is really important, any security you can trust in means less effort.

+2
source share

Other people are wrong. There is no other way to create an array if you do not have an instance of the type at creation time. See Also How to create a shared array in Java?

If you have an instance of type (= something that is of type Class<T> ), you can call java.lang.reflect.Array.newInstance(Class<?>, int) , but even then you need a cast, so why bother ?

I would say that everything was different if the type of elements was Object instead of T , but since it is not, the code is fine.

If you want to hide it further, you can write a helper method:

  @SuppressWarnings( "unchecked" ) public static <T> T[] createArray( int size ) { return (T[]) new Object[size]; } 

This creates an array without the need to cast when it is called.

+1
source share

In this case, it is safer to use Collection . Just do something like

 ... Collection<T> newElements = new ArrayList<T>(5); ... 

In any case, from what I know, creating such a general array like this will not give you real problems, but it smells bad, because it requires explicit input of types. Do you really need an array in this case?

+1
source share

I saw people saying that creating such an array is a bad idea because it is not type safe. However, every time I use it, I have no problem with this. When will the array be created, a problem similar to this reason?

People say that this is a bad idea, because, logically, it is incorrect to enter an object whose execution type is Object[] to type T[] if T not Object .

However, you do not see any immediate problems, because inside the class (within T ), T is erased. Thus, listing from Object[] to T[] not checked.

If all you do is use this variable inside your class (inside the scope of a variable of type T ), and you never return it to people outside the class, and people outside the class cannot access it, then this will not cause any problems.

In fact, there are advantages in the way you do this - you get all the benefits of type-type checking when you get and configure array elements that you wouldn’t get if you just did the full “-safe type” using a variable of type Object[] , and in this case you will have to manually cast the things that you get out of it.

You will have a problem if you ever return this array variable to outside (or otherwise allow external access to it) as type T[] , because the calling code will expect a certain type of array and the generics will insert the cast into the calling code when it receives this array, and the cast will not be executed at run time (since, for example, Object[] not String[] , at run time they are different types). Here is a simple example:

 public class aClass<T> { private T[] elements; public aClass(T[] elements) { this.elements = elements; } public void doSomething() { elements = (T[]) new Object[5]; ... } public T[] getArray() { return elements; } } // some other code... aClass<String> foo = new aClass<String>(new String[2]); foo.doSomething(); String[] bar = foo.getArray(); // ClassCastException here 
+1
source share

You may have issues with mappings and printing. Basically, at any time when type knowledge is important for formatting. the way you have it, the system does not know what data is in the array

0
source share

All Articles