Java initializing a generic array - java

T[] genericArray= (T[])(new Object[2]);
T has a constraint that it implements Comparable. The line above fails with an exception
" java.lang.ClassCastException: [Ljava.lang.Object;
cannot be cast to [Ljava.lang.Comparable;
How do I initialize a generic array where the T has constraints?

Object doesn't implements Comparable.
Instead of creating it as Object[] create it as Comparable[].
Related to your comment:
A variable can be declared of any type. When you create an array you are not creating objects inside the array, but you are only allocating the memory to store the references to the objects.
So as you can write:
Comparable x = "Pippo"; // Because String is Comparable
you can also write
Comparable[] x = new Comparable[1];
x[0] = "Pippo"; // Here you add a concrete String that is a
// Comparable type on the first position

You get this error because Object does not implement Comparable and thus Object[] is not a sub-type of Comparable[] (which, because of type erasure, is the runtime type of your genericArray).
The underlying problem is that you want to create a generic array. This is not possible in Java. The reason is, that unlike generics, the type of the elements of an array is known at runtime. If you write new T[], it is not known which type of array must be created.
You try to circumvent this by creating an array of some supertype. But this is also not correct (and you should get a warning if you do it). If you create a an array with new Comparable[size], you create a an array of Comparables, not an array of some subtype of Comparable. A T[] might be a String[] or a Long[], and String[] and Long[] are different types than Comparable[] (also at runtime).
To demonstrate the problem, consider the following program:
public class Foo<T extends Comparable> {
T[] createArray() {
return (T[])new Comparable[1];
}
public static void main(String... args) {
Foo<String> foo = new Foo<>();
String[] ss = foo.createArray(); // here
}
}
It might look perfectly okay at first sight, but when your run it, you get a ClassCastException, because in the marked line a Object[] is cast to a String[].
The solution is to use Class<T> objects as so-called type tokens. These let you store the type so that you can access it at run-time. Now you can create an array with the correct type by using Array.newInstance(Class<T>, int...). For example:
public class Foo<T extends Comparable> {
private Class<T> type;
public Foo(Class<T> type) {
this.type = type;
}
T[] createArray() {
return (T[])Array.newInstance(type, 1);
}
public static void main(String... args) {
Foo<String> foo = new Foo<>(String.class);
String[] ss = foo.createArray();
}
}
(You may still get a warning from the compiler, because newInstance's return type is Object. You can ignore it because the object it returns is an array of the correct type.)

Related

Why can I declare a generic array but not initialize it?

Imagine this two sample codes:
public class TestCompile<T> {
private T[] array;
public static void main(String[] args) {
}
}
public class TestNoCompile<T> {
private T[] array = new T[5];
public static void main(String[] args) {
}
}
The first class TestCompile has no errors at compilation time and the second one TestNoCompile is not able to compile.
I understant why the second one doesnt compile since the arrays in Java are covariant and the type erasure is not compatible with that. But I cant understant why the first example compiles, why can I declare a generic array if then I cant initialize it?
On the other hand I cant unserstant this other example:
public class Example<T> {
private T[] array;
public static void main(String[] args) {
Example<Integer> example = new Example<>();
example.method(new Integer[5]);
}
public void method(T[] array) {
array[0] = 1; //This line doesnt compile.
}
Here it seems Im able to initialize a generic array in the method method(...) but then Im not able to store any value in it. Which is the explanation of this behaviour?
There's nothing wrong with the type T[] itself. It's perfectly fine to have a variable of type T[] and you can assign any value of type T[] to that variable fine, without any warnings. The question is how do you get a value of type T[].
I think you've answered your own question later when you showed that, for example, you can have a value of type T[] passed in from the outside, into a method (or a constructor) of your class. And in the caller's scope in your example, T is a concrete type (Integer), so the caller can create a T[] in its scope fine and pass it in.
As you have found, you can't create a value of type T[] (other than null) without a warning inside the class (where T is generic). This is because arrays know their component type at runtime (because arrays in Java check at runtime every element that is stored into the array is an instance of the component type), so to create an array object, you need to provide the component type of the array you want to create at runtime, and inside the class, you don't know what T is at runtime. So new T[5] is not a valid expression.
In Andreas's answer, they create an array of type Object[], and then cast it to T[], but this is basically lying to the compiler. Obviously, if T is any type other than Object, this cast is incorrect. For example, String[] foo = (String[]) new Object[5]; throws a class cast exception at runtime. However, T is erased to Object inside the class, so it does not immediately throw a class cast exception. You get an unchecked cast warning to warn you that you might not get an exception even if the cast is incorrect, so you may have a variable whose compile-time type is incompatible with its runtime type, and you may unexpectedly get a class cast exception somewhere else later. For example, if you have a method that returns the array to the outside of the class as type T[], and the place outside the class has a concrete type for T, it will cause a class cast exception where there is no cast:
public class Example<T> {
private T[] array = (T[]) new Object[5];
public T[] getArray() {
return array;
}
public static void main(String[] args) {
Example<Integer> example = new Example<>();
Integer[] foo = example.getArray(); // class cast exception
}
}
Your statement that you cannot store any value in the array is incorrect. You can store values in it, but you can only store values of type T. Inside the class, you don't know what T is, so where are you going to get a value of type T? You would either have to use null, or you have to get it from outside the class:
public class Example<T> {
private T[] array;
public Example(T[] a) {
array = a;
}
public void set(int i, T x) {
array[i] = x;
}
public static void main(String[] args) {
Example<Integer> example = new Example<>(new Integer[5]);
example.set(0, 1);
}
}
Because of type-erasure, a generic array becomes an Object[] at runtime, so you need to create it as such, cast it, and acknowledge that what you're doing is not safe:
#SuppressWarnings("unchecked")
private T[] array = (T[]) new Object[5];
As for the array[0] = 1 statement, the problem is that array is a T[], and that T can be anything, so the code isn't valid.
What is you changed the code in main as follows?
Example<String> example = new Example<>();
example.method(new String[5]);
The array[0] = 1 statement is now obviously not valid, and remember, declaring a Example<String> could easily be done elsewhere at the same time you have Example<Integer> in main.
The code in method must be value for all possible T's.

Declaring an Array in Java with a Generic Type [duplicate]

Due to the implementation of Java generics, you can't have code like this:
public class GenSet<E> {
private E a[];
public GenSet() {
a = new E[INITIAL_ARRAY_LENGTH]; // error: generic array creation
}
}
How can I implement this while maintaining type safety?
I saw a solution on the Java forums that goes like this:
import java.lang.reflect.Array;
class Stack<T> {
public Stack(Class<T> clazz, int capacity) {
array = (T[])Array.newInstance(clazz, capacity);
}
private final T[] array;
}
But I really don't get what's going on.
I have to ask a question in return: is your GenSet "checked" or "unchecked"?
What does that mean?
Checked: strong typing. GenSet knows explicitly what type of objects it contains (i.e. its constructor was explicitly called with a Class<E> argument, and methods will throw an exception when they are passed arguments that are not of type E. See Collections.checkedCollection.
-> in that case, you should write:
public class GenSet<E> {
private E[] a;
public GenSet(Class<E> c, int s) {
// Use Array native method to create array
// of a type only known at run time
#SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, s);
this.a = a;
}
E get(int i) {
return a[i];
}
}
Unchecked: weak typing. No type checking is actually done on any of the objects passed as argument.
-> in that case, you should write
public class GenSet<E> {
private Object[] a;
public GenSet(int s) {
a = new Object[s];
}
E get(int i) {
#SuppressWarnings("unchecked")
final E e = (E) a[i];
return e;
}
}
Note that the component type of the array should be the erasure of the type parameter:
public class GenSet<E extends Foo> { // E has an upper bound of Foo
private Foo[] a; // E erases to Foo, so use Foo[]
public GenSet(int s) {
a = new Foo[s];
}
...
}
All of this results from a known, and deliberate, weakness of generics in Java: it was implemented using erasure, so "generic" classes don't know what type argument they were created with at run time, and therefore can not provide type-safety unless some explicit mechanism (type-checking) is implemented.
You can do this:
E[] arr = (E[])new Object[INITIAL_ARRAY_LENGTH];
This is one of the suggested ways of implementing a generic collection in Effective Java; Item 26. No type errors, no need to cast the array repeatedly. However this triggers a warning because it is potentially dangerous, and should be used with caution. As detailed in the comments, this Object[] is now masquerading as our E[] type, and can cause unexpected errors or ClassCastExceptions if used unsafely.
As a rule of thumb, this behavior is safe as long as the cast array is used internally (e.g. to back a data structure), and not returned or exposed to client code. Should you need to return an array of a generic type to other code, the reflection Array class you mention is the right way to go.
Worth mentioning that wherever possible, you'll have a much happier time working with Lists rather than arrays if you're using generics. Certainly sometimes you don't have a choice, but using the collections framework is far more robust.
Here's how to use generics to get an array of precisely the type you’re looking for while preserving type safety (as opposed to the other answers, which will either give you back an Object array or result in warnings at compile time):
import java.lang.reflect.Array;
public class GenSet<E> {
private E[] a;
public GenSet(Class<E[]> clazz, int length) {
a = clazz.cast(Array.newInstance(clazz.getComponentType(), length));
}
public static void main(String[] args) {
GenSet<String> foo = new GenSet<String>(String[].class, 1);
String[] bar = foo.a;
foo.a[0] = "xyzzy";
String baz = foo.a[0];
}
}
That compiles without warnings, and as you can see in main, for whatever type you declare an instance of GenSet as, you can assign a to an array of that type, and you can assign an element from a to a variable of that type, meaning that the array and the values in the array are of the correct type.
It works by using class literals as runtime type tokens, as discussed in the Java Tutorials. Class literals are treated by the compiler as instances of java.lang.Class. To use one, simply follow the name of a class with .class. So, String.class acts as a Class object representing the class String. This also works for interfaces, enums, any-dimensional arrays (e.g. String[].class), primitives (e.g. int.class), and the keyword void (i.e. void.class).
Class itself is generic (declared as Class<T>, where T stands for the type that the Class object is representing), meaning that the type of String.class is Class<String>.
So, whenever you call the constructor for GenSet, you pass in a class literal for the first argument representing an array of the GenSet instance's declared type (e.g. String[].class for GenSet<String>). Note that you won't be able to get an array of primitives, since primitives can't be used for type variables.
Inside the constructor, calling the method cast returns the passed Object argument cast to the class represented by the Class object on which the method was called. Calling the static method newInstance in java.lang.reflect.Array returns as an Object an array of the type represented by the Class object passed as the first argument and of the length specified by the int passed as the second argument. Calling the method getComponentType returns a Class object representing the component type of the array represented by the Class object on which the method was called (e.g. String.class for String[].class, null if the Class object doesn't represent an array).
That last sentence isn't entirely accurate. Calling String[].class.getComponentType() returns a Class object representing the class String, but its type is Class<?>, not Class<String>, which is why you can't do something like the following.
String foo = String[].class.getComponentType().cast("bar"); // won't compile
Same goes for every method in Class that returns a Class object.
Regarding Joachim Sauer's comment on this answer (I don't have enough reputation to comment on it myself), the example using the cast to T[] will result in a warning because the compiler can't guarantee type safety in that case.
Edit regarding Ingo's comments:
public static <T> T[] newArray(Class<T[]> type, int size) {
return type.cast(Array.newInstance(type.getComponentType(), size));
}
This is the only answer that is type safe
E[] a;
a = newArray(size);
#SafeVarargs
static <E> E[] newArray(int length, E... array)
{
return Arrays.copyOf(array, length);
}
To extend to more dimensions, just add []'s and dimension parameters to newInstance() (T is a type parameter, cls is a Class<T>, d1 through d5 are integers):
T[] array = (T[])Array.newInstance(cls, d1);
T[][] array = (T[][])Array.newInstance(cls, d1, d2);
T[][][] array = (T[][][])Array.newInstance(cls, d1, d2, d3);
T[][][][] array = (T[][][][])Array.newInstance(cls, d1, d2, d3, d4);
T[][][][][] array = (T[][][][][])Array.newInstance(cls, d1, d2, d3, d4, d5);
See Array.newInstance() for details.
In Java 8, we can do a kind of generic array creation using a lambda or method reference. This is similar to the reflective approach (which passes a Class), but here we aren't using reflection.
#FunctionalInterface
interface ArraySupplier<E> {
E[] get(int length);
}
class GenericSet<E> {
private final ArraySupplier<E> supplier;
private E[] array;
GenericSet(ArraySupplier<E> supplier) {
this.supplier = supplier;
this.array = supplier.get(10);
}
public static void main(String[] args) {
GenericSet<String> ofString =
new GenericSet<>(String[]::new);
GenericSet<Double> ofDouble =
new GenericSet<>(Double[]::new);
}
}
For example, this is used by <A> A[] Stream.toArray(IntFunction<A[]>).
This could also be done pre-Java 8 using anonymous classes but it's more cumbersome.
You do not need to pass the Class argument to the constructor.
Try this.
public class GenSet<T> {
private final T[] array;
#SafeVarargs
public GenSet(int capacity, T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException(
"Do not provide values for dummy argument.");
this.array = Arrays.copyOf(dummy, capacity);
}
#Override
public String toString() {
return "GenSet of " + array.getClass().getComponentType().getName()
+ "[" + array.length + "]";
}
}
and
GenSet<Integer> intSet = new GenSet<>(3);
System.out.println(intSet);
System.out.println(new GenSet<String>(2));
result:
GenSet of java.lang.Integer[3]
GenSet of java.lang.String[2]
This is covered in Chapter 5 (Generics) of Effective Java, 2nd Edition, item 25...Prefer lists to arrays
Your code will work, although it will generate an unchecked warning (which you could suppress with the following annotation:
#SuppressWarnings({"unchecked"})
However, it would probably be better to use a List instead of an Array.
There's an interesting discussion of this bug/feature on the OpenJDK project site.
Java generics work by checking types at compile time and inserting appropriate casts, but erasing the types in the compiled files. This makes generic libraries usable by code which doesn't understand generics (which was a deliberate design decision) but which means you can't normally find out what the type is at run time.
The public Stack(Class<T> clazz,int capacity) constructor requires you to pass a Class object at run time, which means class information is available at runtime to code that needs it. And the Class<T> form means that the compiler will check that the Class object you pass is precisely the Class object for type T. Not a subclass of T, not a superclass of T, but precisely T.
This then means that you can create an array object of the appropriate type in your constructor, which means that the type of the objects you store in your collection will have their types checked at the point they are added to the collection.
Although the thread is dead, I would like to draw your attention to this.
Generics are used for type checking during compile time. Therefore, the purpose is to check
What comes in is what you need.
What you return is what the consumer needs.
Check this:
Don't worry about typecasting warnings when you are writing a generic class; worry when you are using it.
What about this solution?
#SafeVarargs
public static <T> T[] toGenericArray(T ... elems) {
return elems;
}
It works and looks too simple to be true. Is there any drawback?
The example is using Java reflection to create an array. Doing this is generally not recommended, since it isn't typesafe. Instead, what you should do is just use an internal List, and avoid the array at all.
Look also to this code:
public static <T> T[] toArray(final List<T> obj) {
if (obj == null || obj.isEmpty()) {
return null;
}
final T t = obj.get(0);
final T[] res = (T[]) Array.newInstance(t.getClass(), obj.size());
for (int i = 0; i < obj.size(); i++) {
res[i] = obj.get(i);
}
return res;
}
It converts a list of any kind of object to an array of the same type.
I have found a quick and easy way that works for me. Note that i have only used this on Java JDK 8. I don't know if it will work with previous versions.
Although we cannot instantiate a generic array of a specific type parameter, we can pass an already created array to a generic class constructor.
class GenArray <T> {
private T theArray[]; // reference array
// ...
GenArray(T[] arr) {
theArray = arr;
}
// Do whatever with the array...
}
Now in main we can create the array like so:
class GenArrayDemo {
public static void main(String[] args) {
int size = 10; // array size
// Here we can instantiate the array of the type we want, say Character (no primitive types allowed in generics)
Character[] ar = new Character[size];
GenArray<Character> = new Character<>(ar); // create the generic Array
// ...
}
}
For more flexibility with your arrays you can use a linked list eg. the ArrayList and other methods found in the Java.util.ArrayList class.
Passing a list of values...
public <T> T[] array(T... values) {
return values;
}
I made this code snippet to reflectively instantiate a class which is passed for a simple automated test utility.
Object attributeValue = null;
try {
if(clazz.isArray()){
Class<?> arrayType = clazz.getComponentType();
attributeValue = Array.newInstance(arrayType, 0);
}
else if(!clazz.isInterface()){
attributeValue = BeanUtils.instantiateClass(clazz);
}
} catch (Exception e) {
logger.debug("Cannot instanciate \"{}\"", new Object[]{clazz});
}
Note this segment:
if(clazz.isArray()){
Class<?> arrayType = clazz.getComponentType();
attributeValue = Array.newInstance(arrayType, 0);
}
for array initiating where Array.newInstance(class of array, size of array). Class can be both primitive (int.class) and object (Integer.class).
BeanUtils is part of Spring.
The forced cast suggested by other people did not work for me, throwing an exception of illegal casting.
However, this implicit cast worked fine:
Item<K>[] array = new Item[SIZE];
where Item is a class I defined containing the member:
private K value;
This way you get an array of type K (if the item only has the value) or any generic type you want defined in the class Item.
Actually an easier way to do so, is to create an array of objects and cast it to your desired type like the following example:
T[] array = (T[])new Object[SIZE];
where SIZE is a constant and T is a type identifier
No one else has answered the question of what is going on in the example you posted.
import java.lang.reflect.Array;
class Stack<T> {
public Stack(Class<T> clazz, int capacity) {
array = (T[])Array.newInstance(clazz, capacity);
}
private final T[] array;
}
As others have said generics are "erased" during compilation. So at runtime an instance of a generic doesn't know what its component type is. The reason for this is historical, Sun wanted to add generics without breaking the existing interface (both source and binary).
Arrays on the other hand do know their component type at runtime.
This example works around the problem by having the code that calls the constructor (which does know the type) pass a parameter telling the class the required type.
So the application would construct the class with something like
Stack<foo> = new Stack<foo>(foo.class,50)
and the constructor now knows (at runtime) what the component type is and can use that information to construct the array through the reflection API.
Array.newInstance(clazz, capacity);
Finally we have a type cast because the compiler has no way of knowing that the array returned by Array#newInstance() is the correct type (even though we know).
This style is a bit ugly but it can sometimes be the least bad solution to creating generic types that do need to know their component type at runtime for whatever reason (creating arrays, or creating instances of their component type, etc.).
I found a sort of a work around to this problem.
The line below throws generic array creation error
List<Person>[] personLists=new ArrayList<Person>()[10];
However if I encapsulate List<Person> in a separate class, it works.
import java.util.ArrayList;
import java.util.List;
public class PersonList {
List<Person> people;
public PersonList()
{
people=new ArrayList<Person>();
}
}
You can expose people in the class PersonList thru a getter. The line below will give you an array, that has a List<Person> in every element. In other words array of List<Person>.
PersonList[] personLists=new PersonList[10];
I needed something like this in some code I was working on and this is what I did to get it to work. So far no problems.
Generic array creation is disallowed in java but you can do it like
class Stack<T> {
private final T[] array;
public Stack(int capacity) {
array = (T[]) new Object[capacity];
}
}
According to vnportnoy the syntax
GenSet<Integer> intSet[] = new GenSet[3];
creates an array of null references, to be filled as
for (int i = 0; i < 3; i++)
{
intSet[i] = new GenSet<Integer>();
}
which is type safe.
You could create an Object array and cast it to E everywhere. Yeah, it's not very clean way to do it but it should at least work.
try this.
private int m = 0;
private int n = 0;
private Element<T>[][] elements = null;
public MatrixData(int m, int n)
{
this.m = m;
this.n = n;
this.elements = new Element[m][n];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
this.elements[i][j] = new Element<T>();
}
}
}
An easy, albeit messy workaround to this would be to nest a second "holder" class inside of your main class, and use it to hold your data.
public class Whatever<Thing>{
private class Holder<OtherThing>{
OtherThing thing;
}
public Holder<Thing>[] arrayOfHolders = new Holder<Thing>[10]
}
Maybe unrelated to this question but while I was getting the "generic array creation" error for using
Tuple<Long,String>[] tupleArray = new Tuple<Long,String>[10];
I find out the following works (and worked for me) with #SuppressWarnings({"unchecked"}):
Tuple<Long, String>[] tupleArray = new Tuple[10];
I'm wondering if this code would create an effective generic array?
public T [] createArray(int desiredSize){
ArrayList<T> builder = new ArrayList<T>();
for(int x=0;x<desiredSize;x++){
builder.add(null);
}
return builder.toArray(zeroArray());
}
//zeroArray should, in theory, create a zero-sized array of T
//when it is not given any parameters.
private T [] zeroArray(T... i){
return i;
}
Edit: Perhaps an alternate way of creating such an array, if the size you required was known and small, would be to simply feed the required number of "null"s into the zeroArray command?
Though obviously this isn't as versatile as using the createArray code.
You could use a cast:
public class GenSet<Item> {
private Item[] a;
public GenSet(int s) {
a = (Item[]) new Object[s];
}
}
I actually found a pretty unique solution to bypass the inability to initiate a generic array. What you have to do is create a class that takes in the generic variable T like so:
class GenericInvoker <T> {
T variable;
public GenericInvoker(T variable){
this.variable = variable;
}
}
and then in your array class just have it start like so:
GenericInvoker<T>[] array;
public MyArray(){
array = new GenericInvoker[];
}
starting a new Generic Invoker[] will cause an issue with unchecked but there shouldn't actually be any issues.
To get from the array you should call the array[i].variable like so:
public T get(int index){
return array[index].variable;
}
The rest, such as resizing the array can be done with Arrays.copyOf() like so:
public void resize(int newSize){
array = Arrays.copyOf(array, newSize);
}
And the add function can be added like so:
public boolean add(T element){
// the variable size below is equal to how many times the add function has been called
// and is used to keep track of where to put the next variable in the array
arrays[size] = new GenericInvoker(element);
size++;
}
If you really want to wrap a generic array of fixed size you will have a method to add data to that array, hence you can initialize properly the array there doing something like this:
import java.lang.reflect.Array;
class Stack<T> {
private T[] array = null;
private final int capacity = 10; // fixed or pass it in the constructor
private int pos = 0;
public void push(T value) {
if (value == null)
throw new IllegalArgumentException("Stack does not accept nulls");
if (array == null)
array = (T[]) Array.newInstance(value.getClass(), capacity);
// put logic: e.g.
if(pos == capacity)
throw new IllegalStateException("push on full stack");
array[pos++] = value;
}
public T pop() throws IllegalStateException {
if (pos == 0)
throw new IllegalStateException("pop on empty stack");
return array[--pos];
}
}
in this case you use a java.lang.reflect.Array.newInstance to create the array, and it will not be an Object[], but a real T[].
You should not worry of it not being final, since it is managed inside your class.
Note that you need a non null object on the push() to be able to get the type to use, so I added a check on the data you push and throw an exception there.
Still this is somewhat pointless: you store data via push and it is the signature of the method that guarantees only T elements will enter. So it is more or less irrelevant that the array is Object[] or T[].

"AWT-EventQueue-0" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to Bebidas [duplicate]

Due to the implementation of Java generics, you can't have code like this:
public class GenSet<E> {
private E a[];
public GenSet() {
a = new E[INITIAL_ARRAY_LENGTH]; // error: generic array creation
}
}
How can I implement this while maintaining type safety?
I saw a solution on the Java forums that goes like this:
import java.lang.reflect.Array;
class Stack<T> {
public Stack(Class<T> clazz, int capacity) {
array = (T[])Array.newInstance(clazz, capacity);
}
private final T[] array;
}
But I really don't get what's going on.
I have to ask a question in return: is your GenSet "checked" or "unchecked"?
What does that mean?
Checked: strong typing. GenSet knows explicitly what type of objects it contains (i.e. its constructor was explicitly called with a Class<E> argument, and methods will throw an exception when they are passed arguments that are not of type E. See Collections.checkedCollection.
-> in that case, you should write:
public class GenSet<E> {
private E[] a;
public GenSet(Class<E> c, int s) {
// Use Array native method to create array
// of a type only known at run time
#SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, s);
this.a = a;
}
E get(int i) {
return a[i];
}
}
Unchecked: weak typing. No type checking is actually done on any of the objects passed as argument.
-> in that case, you should write
public class GenSet<E> {
private Object[] a;
public GenSet(int s) {
a = new Object[s];
}
E get(int i) {
#SuppressWarnings("unchecked")
final E e = (E) a[i];
return e;
}
}
Note that the component type of the array should be the erasure of the type parameter:
public class GenSet<E extends Foo> { // E has an upper bound of Foo
private Foo[] a; // E erases to Foo, so use Foo[]
public GenSet(int s) {
a = new Foo[s];
}
...
}
All of this results from a known, and deliberate, weakness of generics in Java: it was implemented using erasure, so "generic" classes don't know what type argument they were created with at run time, and therefore can not provide type-safety unless some explicit mechanism (type-checking) is implemented.
You can do this:
E[] arr = (E[])new Object[INITIAL_ARRAY_LENGTH];
This is one of the suggested ways of implementing a generic collection in Effective Java; Item 26. No type errors, no need to cast the array repeatedly. However this triggers a warning because it is potentially dangerous, and should be used with caution. As detailed in the comments, this Object[] is now masquerading as our E[] type, and can cause unexpected errors or ClassCastExceptions if used unsafely.
As a rule of thumb, this behavior is safe as long as the cast array is used internally (e.g. to back a data structure), and not returned or exposed to client code. Should you need to return an array of a generic type to other code, the reflection Array class you mention is the right way to go.
Worth mentioning that wherever possible, you'll have a much happier time working with Lists rather than arrays if you're using generics. Certainly sometimes you don't have a choice, but using the collections framework is far more robust.
Here's how to use generics to get an array of precisely the type you’re looking for while preserving type safety (as opposed to the other answers, which will either give you back an Object array or result in warnings at compile time):
import java.lang.reflect.Array;
public class GenSet<E> {
private E[] a;
public GenSet(Class<E[]> clazz, int length) {
a = clazz.cast(Array.newInstance(clazz.getComponentType(), length));
}
public static void main(String[] args) {
GenSet<String> foo = new GenSet<String>(String[].class, 1);
String[] bar = foo.a;
foo.a[0] = "xyzzy";
String baz = foo.a[0];
}
}
That compiles without warnings, and as you can see in main, for whatever type you declare an instance of GenSet as, you can assign a to an array of that type, and you can assign an element from a to a variable of that type, meaning that the array and the values in the array are of the correct type.
It works by using class literals as runtime type tokens, as discussed in the Java Tutorials. Class literals are treated by the compiler as instances of java.lang.Class. To use one, simply follow the name of a class with .class. So, String.class acts as a Class object representing the class String. This also works for interfaces, enums, any-dimensional arrays (e.g. String[].class), primitives (e.g. int.class), and the keyword void (i.e. void.class).
Class itself is generic (declared as Class<T>, where T stands for the type that the Class object is representing), meaning that the type of String.class is Class<String>.
So, whenever you call the constructor for GenSet, you pass in a class literal for the first argument representing an array of the GenSet instance's declared type (e.g. String[].class for GenSet<String>). Note that you won't be able to get an array of primitives, since primitives can't be used for type variables.
Inside the constructor, calling the method cast returns the passed Object argument cast to the class represented by the Class object on which the method was called. Calling the static method newInstance in java.lang.reflect.Array returns as an Object an array of the type represented by the Class object passed as the first argument and of the length specified by the int passed as the second argument. Calling the method getComponentType returns a Class object representing the component type of the array represented by the Class object on which the method was called (e.g. String.class for String[].class, null if the Class object doesn't represent an array).
That last sentence isn't entirely accurate. Calling String[].class.getComponentType() returns a Class object representing the class String, but its type is Class<?>, not Class<String>, which is why you can't do something like the following.
String foo = String[].class.getComponentType().cast("bar"); // won't compile
Same goes for every method in Class that returns a Class object.
Regarding Joachim Sauer's comment on this answer (I don't have enough reputation to comment on it myself), the example using the cast to T[] will result in a warning because the compiler can't guarantee type safety in that case.
Edit regarding Ingo's comments:
public static <T> T[] newArray(Class<T[]> type, int size) {
return type.cast(Array.newInstance(type.getComponentType(), size));
}
This is the only answer that is type safe
E[] a;
a = newArray(size);
#SafeVarargs
static <E> E[] newArray(int length, E... array)
{
return Arrays.copyOf(array, length);
}
To extend to more dimensions, just add []'s and dimension parameters to newInstance() (T is a type parameter, cls is a Class<T>, d1 through d5 are integers):
T[] array = (T[])Array.newInstance(cls, d1);
T[][] array = (T[][])Array.newInstance(cls, d1, d2);
T[][][] array = (T[][][])Array.newInstance(cls, d1, d2, d3);
T[][][][] array = (T[][][][])Array.newInstance(cls, d1, d2, d3, d4);
T[][][][][] array = (T[][][][][])Array.newInstance(cls, d1, d2, d3, d4, d5);
See Array.newInstance() for details.
In Java 8, we can do a kind of generic array creation using a lambda or method reference. This is similar to the reflective approach (which passes a Class), but here we aren't using reflection.
#FunctionalInterface
interface ArraySupplier<E> {
E[] get(int length);
}
class GenericSet<E> {
private final ArraySupplier<E> supplier;
private E[] array;
GenericSet(ArraySupplier<E> supplier) {
this.supplier = supplier;
this.array = supplier.get(10);
}
public static void main(String[] args) {
GenericSet<String> ofString =
new GenericSet<>(String[]::new);
GenericSet<Double> ofDouble =
new GenericSet<>(Double[]::new);
}
}
For example, this is used by <A> A[] Stream.toArray(IntFunction<A[]>).
This could also be done pre-Java 8 using anonymous classes but it's more cumbersome.
You do not need to pass the Class argument to the constructor.
Try this.
public class GenSet<T> {
private final T[] array;
#SafeVarargs
public GenSet(int capacity, T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException(
"Do not provide values for dummy argument.");
this.array = Arrays.copyOf(dummy, capacity);
}
#Override
public String toString() {
return "GenSet of " + array.getClass().getComponentType().getName()
+ "[" + array.length + "]";
}
}
and
GenSet<Integer> intSet = new GenSet<>(3);
System.out.println(intSet);
System.out.println(new GenSet<String>(2));
result:
GenSet of java.lang.Integer[3]
GenSet of java.lang.String[2]
This is covered in Chapter 5 (Generics) of Effective Java, 2nd Edition, item 25...Prefer lists to arrays
Your code will work, although it will generate an unchecked warning (which you could suppress with the following annotation:
#SuppressWarnings({"unchecked"})
However, it would probably be better to use a List instead of an Array.
There's an interesting discussion of this bug/feature on the OpenJDK project site.
Java generics work by checking types at compile time and inserting appropriate casts, but erasing the types in the compiled files. This makes generic libraries usable by code which doesn't understand generics (which was a deliberate design decision) but which means you can't normally find out what the type is at run time.
The public Stack(Class<T> clazz,int capacity) constructor requires you to pass a Class object at run time, which means class information is available at runtime to code that needs it. And the Class<T> form means that the compiler will check that the Class object you pass is precisely the Class object for type T. Not a subclass of T, not a superclass of T, but precisely T.
This then means that you can create an array object of the appropriate type in your constructor, which means that the type of the objects you store in your collection will have their types checked at the point they are added to the collection.
Although the thread is dead, I would like to draw your attention to this.
Generics are used for type checking during compile time. Therefore, the purpose is to check
What comes in is what you need.
What you return is what the consumer needs.
Check this:
Don't worry about typecasting warnings when you are writing a generic class; worry when you are using it.
What about this solution?
#SafeVarargs
public static <T> T[] toGenericArray(T ... elems) {
return elems;
}
It works and looks too simple to be true. Is there any drawback?
The example is using Java reflection to create an array. Doing this is generally not recommended, since it isn't typesafe. Instead, what you should do is just use an internal List, and avoid the array at all.
Look also to this code:
public static <T> T[] toArray(final List<T> obj) {
if (obj == null || obj.isEmpty()) {
return null;
}
final T t = obj.get(0);
final T[] res = (T[]) Array.newInstance(t.getClass(), obj.size());
for (int i = 0; i < obj.size(); i++) {
res[i] = obj.get(i);
}
return res;
}
It converts a list of any kind of object to an array of the same type.
I have found a quick and easy way that works for me. Note that i have only used this on Java JDK 8. I don't know if it will work with previous versions.
Although we cannot instantiate a generic array of a specific type parameter, we can pass an already created array to a generic class constructor.
class GenArray <T> {
private T theArray[]; // reference array
// ...
GenArray(T[] arr) {
theArray = arr;
}
// Do whatever with the array...
}
Now in main we can create the array like so:
class GenArrayDemo {
public static void main(String[] args) {
int size = 10; // array size
// Here we can instantiate the array of the type we want, say Character (no primitive types allowed in generics)
Character[] ar = new Character[size];
GenArray<Character> = new Character<>(ar); // create the generic Array
// ...
}
}
For more flexibility with your arrays you can use a linked list eg. the ArrayList and other methods found in the Java.util.ArrayList class.
Passing a list of values...
public <T> T[] array(T... values) {
return values;
}
I made this code snippet to reflectively instantiate a class which is passed for a simple automated test utility.
Object attributeValue = null;
try {
if(clazz.isArray()){
Class<?> arrayType = clazz.getComponentType();
attributeValue = Array.newInstance(arrayType, 0);
}
else if(!clazz.isInterface()){
attributeValue = BeanUtils.instantiateClass(clazz);
}
} catch (Exception e) {
logger.debug("Cannot instanciate \"{}\"", new Object[]{clazz});
}
Note this segment:
if(clazz.isArray()){
Class<?> arrayType = clazz.getComponentType();
attributeValue = Array.newInstance(arrayType, 0);
}
for array initiating where Array.newInstance(class of array, size of array). Class can be both primitive (int.class) and object (Integer.class).
BeanUtils is part of Spring.
The forced cast suggested by other people did not work for me, throwing an exception of illegal casting.
However, this implicit cast worked fine:
Item<K>[] array = new Item[SIZE];
where Item is a class I defined containing the member:
private K value;
This way you get an array of type K (if the item only has the value) or any generic type you want defined in the class Item.
Actually an easier way to do so, is to create an array of objects and cast it to your desired type like the following example:
T[] array = (T[])new Object[SIZE];
where SIZE is a constant and T is a type identifier
No one else has answered the question of what is going on in the example you posted.
import java.lang.reflect.Array;
class Stack<T> {
public Stack(Class<T> clazz, int capacity) {
array = (T[])Array.newInstance(clazz, capacity);
}
private final T[] array;
}
As others have said generics are "erased" during compilation. So at runtime an instance of a generic doesn't know what its component type is. The reason for this is historical, Sun wanted to add generics without breaking the existing interface (both source and binary).
Arrays on the other hand do know their component type at runtime.
This example works around the problem by having the code that calls the constructor (which does know the type) pass a parameter telling the class the required type.
So the application would construct the class with something like
Stack<foo> = new Stack<foo>(foo.class,50)
and the constructor now knows (at runtime) what the component type is and can use that information to construct the array through the reflection API.
Array.newInstance(clazz, capacity);
Finally we have a type cast because the compiler has no way of knowing that the array returned by Array#newInstance() is the correct type (even though we know).
This style is a bit ugly but it can sometimes be the least bad solution to creating generic types that do need to know their component type at runtime for whatever reason (creating arrays, or creating instances of their component type, etc.).
I found a sort of a work around to this problem.
The line below throws generic array creation error
List<Person>[] personLists=new ArrayList<Person>()[10];
However if I encapsulate List<Person> in a separate class, it works.
import java.util.ArrayList;
import java.util.List;
public class PersonList {
List<Person> people;
public PersonList()
{
people=new ArrayList<Person>();
}
}
You can expose people in the class PersonList thru a getter. The line below will give you an array, that has a List<Person> in every element. In other words array of List<Person>.
PersonList[] personLists=new PersonList[10];
I needed something like this in some code I was working on and this is what I did to get it to work. So far no problems.
Generic array creation is disallowed in java but you can do it like
class Stack<T> {
private final T[] array;
public Stack(int capacity) {
array = (T[]) new Object[capacity];
}
}
According to vnportnoy the syntax
GenSet<Integer> intSet[] = new GenSet[3];
creates an array of null references, to be filled as
for (int i = 0; i < 3; i++)
{
intSet[i] = new GenSet<Integer>();
}
which is type safe.
You could create an Object array and cast it to E everywhere. Yeah, it's not very clean way to do it but it should at least work.
try this.
private int m = 0;
private int n = 0;
private Element<T>[][] elements = null;
public MatrixData(int m, int n)
{
this.m = m;
this.n = n;
this.elements = new Element[m][n];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
this.elements[i][j] = new Element<T>();
}
}
}
An easy, albeit messy workaround to this would be to nest a second "holder" class inside of your main class, and use it to hold your data.
public class Whatever<Thing>{
private class Holder<OtherThing>{
OtherThing thing;
}
public Holder<Thing>[] arrayOfHolders = new Holder<Thing>[10]
}
Maybe unrelated to this question but while I was getting the "generic array creation" error for using
Tuple<Long,String>[] tupleArray = new Tuple<Long,String>[10];
I find out the following works (and worked for me) with #SuppressWarnings({"unchecked"}):
Tuple<Long, String>[] tupleArray = new Tuple[10];
I'm wondering if this code would create an effective generic array?
public T [] createArray(int desiredSize){
ArrayList<T> builder = new ArrayList<T>();
for(int x=0;x<desiredSize;x++){
builder.add(null);
}
return builder.toArray(zeroArray());
}
//zeroArray should, in theory, create a zero-sized array of T
//when it is not given any parameters.
private T [] zeroArray(T... i){
return i;
}
Edit: Perhaps an alternate way of creating such an array, if the size you required was known and small, would be to simply feed the required number of "null"s into the zeroArray command?
Though obviously this isn't as versatile as using the createArray code.
You could use a cast:
public class GenSet<Item> {
private Item[] a;
public GenSet(int s) {
a = (Item[]) new Object[s];
}
}
I actually found a pretty unique solution to bypass the inability to initiate a generic array. What you have to do is create a class that takes in the generic variable T like so:
class GenericInvoker <T> {
T variable;
public GenericInvoker(T variable){
this.variable = variable;
}
}
and then in your array class just have it start like so:
GenericInvoker<T>[] array;
public MyArray(){
array = new GenericInvoker[];
}
starting a new Generic Invoker[] will cause an issue with unchecked but there shouldn't actually be any issues.
To get from the array you should call the array[i].variable like so:
public T get(int index){
return array[index].variable;
}
The rest, such as resizing the array can be done with Arrays.copyOf() like so:
public void resize(int newSize){
array = Arrays.copyOf(array, newSize);
}
And the add function can be added like so:
public boolean add(T element){
// the variable size below is equal to how many times the add function has been called
// and is used to keep track of where to put the next variable in the array
arrays[size] = new GenericInvoker(element);
size++;
}
If you really want to wrap a generic array of fixed size you will have a method to add data to that array, hence you can initialize properly the array there doing something like this:
import java.lang.reflect.Array;
class Stack<T> {
private T[] array = null;
private final int capacity = 10; // fixed or pass it in the constructor
private int pos = 0;
public void push(T value) {
if (value == null)
throw new IllegalArgumentException("Stack does not accept nulls");
if (array == null)
array = (T[]) Array.newInstance(value.getClass(), capacity);
// put logic: e.g.
if(pos == capacity)
throw new IllegalStateException("push on full stack");
array[pos++] = value;
}
public T pop() throws IllegalStateException {
if (pos == 0)
throw new IllegalStateException("pop on empty stack");
return array[--pos];
}
}
in this case you use a java.lang.reflect.Array.newInstance to create the array, and it will not be an Object[], but a real T[].
You should not worry of it not being final, since it is managed inside your class.
Note that you need a non null object on the push() to be able to get the type to use, so I added a check on the data you push and throw an exception there.
Still this is somewhat pointless: you store data via push and it is the signature of the method that guarantees only T elements will enter. So it is more or less irrelevant that the array is Object[] or T[].

Exception when using CompareTo with a generic Bag of objects [duplicate]

Due to the implementation of Java generics, you can't have code like this:
public class GenSet<E> {
private E a[];
public GenSet() {
a = new E[INITIAL_ARRAY_LENGTH]; // error: generic array creation
}
}
How can I implement this while maintaining type safety?
I saw a solution on the Java forums that goes like this:
import java.lang.reflect.Array;
class Stack<T> {
public Stack(Class<T> clazz, int capacity) {
array = (T[])Array.newInstance(clazz, capacity);
}
private final T[] array;
}
But I really don't get what's going on.
I have to ask a question in return: is your GenSet "checked" or "unchecked"?
What does that mean?
Checked: strong typing. GenSet knows explicitly what type of objects it contains (i.e. its constructor was explicitly called with a Class<E> argument, and methods will throw an exception when they are passed arguments that are not of type E. See Collections.checkedCollection.
-> in that case, you should write:
public class GenSet<E> {
private E[] a;
public GenSet(Class<E> c, int s) {
// Use Array native method to create array
// of a type only known at run time
#SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, s);
this.a = a;
}
E get(int i) {
return a[i];
}
}
Unchecked: weak typing. No type checking is actually done on any of the objects passed as argument.
-> in that case, you should write
public class GenSet<E> {
private Object[] a;
public GenSet(int s) {
a = new Object[s];
}
E get(int i) {
#SuppressWarnings("unchecked")
final E e = (E) a[i];
return e;
}
}
Note that the component type of the array should be the erasure of the type parameter:
public class GenSet<E extends Foo> { // E has an upper bound of Foo
private Foo[] a; // E erases to Foo, so use Foo[]
public GenSet(int s) {
a = new Foo[s];
}
...
}
All of this results from a known, and deliberate, weakness of generics in Java: it was implemented using erasure, so "generic" classes don't know what type argument they were created with at run time, and therefore can not provide type-safety unless some explicit mechanism (type-checking) is implemented.
You can do this:
E[] arr = (E[])new Object[INITIAL_ARRAY_LENGTH];
This is one of the suggested ways of implementing a generic collection in Effective Java; Item 26. No type errors, no need to cast the array repeatedly. However this triggers a warning because it is potentially dangerous, and should be used with caution. As detailed in the comments, this Object[] is now masquerading as our E[] type, and can cause unexpected errors or ClassCastExceptions if used unsafely.
As a rule of thumb, this behavior is safe as long as the cast array is used internally (e.g. to back a data structure), and not returned or exposed to client code. Should you need to return an array of a generic type to other code, the reflection Array class you mention is the right way to go.
Worth mentioning that wherever possible, you'll have a much happier time working with Lists rather than arrays if you're using generics. Certainly sometimes you don't have a choice, but using the collections framework is far more robust.
Here's how to use generics to get an array of precisely the type you’re looking for while preserving type safety (as opposed to the other answers, which will either give you back an Object array or result in warnings at compile time):
import java.lang.reflect.Array;
public class GenSet<E> {
private E[] a;
public GenSet(Class<E[]> clazz, int length) {
a = clazz.cast(Array.newInstance(clazz.getComponentType(), length));
}
public static void main(String[] args) {
GenSet<String> foo = new GenSet<String>(String[].class, 1);
String[] bar = foo.a;
foo.a[0] = "xyzzy";
String baz = foo.a[0];
}
}
That compiles without warnings, and as you can see in main, for whatever type you declare an instance of GenSet as, you can assign a to an array of that type, and you can assign an element from a to a variable of that type, meaning that the array and the values in the array are of the correct type.
It works by using class literals as runtime type tokens, as discussed in the Java Tutorials. Class literals are treated by the compiler as instances of java.lang.Class. To use one, simply follow the name of a class with .class. So, String.class acts as a Class object representing the class String. This also works for interfaces, enums, any-dimensional arrays (e.g. String[].class), primitives (e.g. int.class), and the keyword void (i.e. void.class).
Class itself is generic (declared as Class<T>, where T stands for the type that the Class object is representing), meaning that the type of String.class is Class<String>.
So, whenever you call the constructor for GenSet, you pass in a class literal for the first argument representing an array of the GenSet instance's declared type (e.g. String[].class for GenSet<String>). Note that you won't be able to get an array of primitives, since primitives can't be used for type variables.
Inside the constructor, calling the method cast returns the passed Object argument cast to the class represented by the Class object on which the method was called. Calling the static method newInstance in java.lang.reflect.Array returns as an Object an array of the type represented by the Class object passed as the first argument and of the length specified by the int passed as the second argument. Calling the method getComponentType returns a Class object representing the component type of the array represented by the Class object on which the method was called (e.g. String.class for String[].class, null if the Class object doesn't represent an array).
That last sentence isn't entirely accurate. Calling String[].class.getComponentType() returns a Class object representing the class String, but its type is Class<?>, not Class<String>, which is why you can't do something like the following.
String foo = String[].class.getComponentType().cast("bar"); // won't compile
Same goes for every method in Class that returns a Class object.
Regarding Joachim Sauer's comment on this answer (I don't have enough reputation to comment on it myself), the example using the cast to T[] will result in a warning because the compiler can't guarantee type safety in that case.
Edit regarding Ingo's comments:
public static <T> T[] newArray(Class<T[]> type, int size) {
return type.cast(Array.newInstance(type.getComponentType(), size));
}
This is the only answer that is type safe
E[] a;
a = newArray(size);
#SafeVarargs
static <E> E[] newArray(int length, E... array)
{
return Arrays.copyOf(array, length);
}
To extend to more dimensions, just add []'s and dimension parameters to newInstance() (T is a type parameter, cls is a Class<T>, d1 through d5 are integers):
T[] array = (T[])Array.newInstance(cls, d1);
T[][] array = (T[][])Array.newInstance(cls, d1, d2);
T[][][] array = (T[][][])Array.newInstance(cls, d1, d2, d3);
T[][][][] array = (T[][][][])Array.newInstance(cls, d1, d2, d3, d4);
T[][][][][] array = (T[][][][][])Array.newInstance(cls, d1, d2, d3, d4, d5);
See Array.newInstance() for details.
In Java 8, we can do a kind of generic array creation using a lambda or method reference. This is similar to the reflective approach (which passes a Class), but here we aren't using reflection.
#FunctionalInterface
interface ArraySupplier<E> {
E[] get(int length);
}
class GenericSet<E> {
private final ArraySupplier<E> supplier;
private E[] array;
GenericSet(ArraySupplier<E> supplier) {
this.supplier = supplier;
this.array = supplier.get(10);
}
public static void main(String[] args) {
GenericSet<String> ofString =
new GenericSet<>(String[]::new);
GenericSet<Double> ofDouble =
new GenericSet<>(Double[]::new);
}
}
For example, this is used by <A> A[] Stream.toArray(IntFunction<A[]>).
This could also be done pre-Java 8 using anonymous classes but it's more cumbersome.
You do not need to pass the Class argument to the constructor.
Try this.
public class GenSet<T> {
private final T[] array;
#SafeVarargs
public GenSet(int capacity, T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException(
"Do not provide values for dummy argument.");
this.array = Arrays.copyOf(dummy, capacity);
}
#Override
public String toString() {
return "GenSet of " + array.getClass().getComponentType().getName()
+ "[" + array.length + "]";
}
}
and
GenSet<Integer> intSet = new GenSet<>(3);
System.out.println(intSet);
System.out.println(new GenSet<String>(2));
result:
GenSet of java.lang.Integer[3]
GenSet of java.lang.String[2]
This is covered in Chapter 5 (Generics) of Effective Java, 2nd Edition, item 25...Prefer lists to arrays
Your code will work, although it will generate an unchecked warning (which you could suppress with the following annotation:
#SuppressWarnings({"unchecked"})
However, it would probably be better to use a List instead of an Array.
There's an interesting discussion of this bug/feature on the OpenJDK project site.
Java generics work by checking types at compile time and inserting appropriate casts, but erasing the types in the compiled files. This makes generic libraries usable by code which doesn't understand generics (which was a deliberate design decision) but which means you can't normally find out what the type is at run time.
The public Stack(Class<T> clazz,int capacity) constructor requires you to pass a Class object at run time, which means class information is available at runtime to code that needs it. And the Class<T> form means that the compiler will check that the Class object you pass is precisely the Class object for type T. Not a subclass of T, not a superclass of T, but precisely T.
This then means that you can create an array object of the appropriate type in your constructor, which means that the type of the objects you store in your collection will have their types checked at the point they are added to the collection.
Although the thread is dead, I would like to draw your attention to this.
Generics are used for type checking during compile time. Therefore, the purpose is to check
What comes in is what you need.
What you return is what the consumer needs.
Check this:
Don't worry about typecasting warnings when you are writing a generic class; worry when you are using it.
What about this solution?
#SafeVarargs
public static <T> T[] toGenericArray(T ... elems) {
return elems;
}
It works and looks too simple to be true. Is there any drawback?
The example is using Java reflection to create an array. Doing this is generally not recommended, since it isn't typesafe. Instead, what you should do is just use an internal List, and avoid the array at all.
Look also to this code:
public static <T> T[] toArray(final List<T> obj) {
if (obj == null || obj.isEmpty()) {
return null;
}
final T t = obj.get(0);
final T[] res = (T[]) Array.newInstance(t.getClass(), obj.size());
for (int i = 0; i < obj.size(); i++) {
res[i] = obj.get(i);
}
return res;
}
It converts a list of any kind of object to an array of the same type.
I have found a quick and easy way that works for me. Note that i have only used this on Java JDK 8. I don't know if it will work with previous versions.
Although we cannot instantiate a generic array of a specific type parameter, we can pass an already created array to a generic class constructor.
class GenArray <T> {
private T theArray[]; // reference array
// ...
GenArray(T[] arr) {
theArray = arr;
}
// Do whatever with the array...
}
Now in main we can create the array like so:
class GenArrayDemo {
public static void main(String[] args) {
int size = 10; // array size
// Here we can instantiate the array of the type we want, say Character (no primitive types allowed in generics)
Character[] ar = new Character[size];
GenArray<Character> = new Character<>(ar); // create the generic Array
// ...
}
}
For more flexibility with your arrays you can use a linked list eg. the ArrayList and other methods found in the Java.util.ArrayList class.
Passing a list of values...
public <T> T[] array(T... values) {
return values;
}
I made this code snippet to reflectively instantiate a class which is passed for a simple automated test utility.
Object attributeValue = null;
try {
if(clazz.isArray()){
Class<?> arrayType = clazz.getComponentType();
attributeValue = Array.newInstance(arrayType, 0);
}
else if(!clazz.isInterface()){
attributeValue = BeanUtils.instantiateClass(clazz);
}
} catch (Exception e) {
logger.debug("Cannot instanciate \"{}\"", new Object[]{clazz});
}
Note this segment:
if(clazz.isArray()){
Class<?> arrayType = clazz.getComponentType();
attributeValue = Array.newInstance(arrayType, 0);
}
for array initiating where Array.newInstance(class of array, size of array). Class can be both primitive (int.class) and object (Integer.class).
BeanUtils is part of Spring.
The forced cast suggested by other people did not work for me, throwing an exception of illegal casting.
However, this implicit cast worked fine:
Item<K>[] array = new Item[SIZE];
where Item is a class I defined containing the member:
private K value;
This way you get an array of type K (if the item only has the value) or any generic type you want defined in the class Item.
Actually an easier way to do so, is to create an array of objects and cast it to your desired type like the following example:
T[] array = (T[])new Object[SIZE];
where SIZE is a constant and T is a type identifier
No one else has answered the question of what is going on in the example you posted.
import java.lang.reflect.Array;
class Stack<T> {
public Stack(Class<T> clazz, int capacity) {
array = (T[])Array.newInstance(clazz, capacity);
}
private final T[] array;
}
As others have said generics are "erased" during compilation. So at runtime an instance of a generic doesn't know what its component type is. The reason for this is historical, Sun wanted to add generics without breaking the existing interface (both source and binary).
Arrays on the other hand do know their component type at runtime.
This example works around the problem by having the code that calls the constructor (which does know the type) pass a parameter telling the class the required type.
So the application would construct the class with something like
Stack<foo> = new Stack<foo>(foo.class,50)
and the constructor now knows (at runtime) what the component type is and can use that information to construct the array through the reflection API.
Array.newInstance(clazz, capacity);
Finally we have a type cast because the compiler has no way of knowing that the array returned by Array#newInstance() is the correct type (even though we know).
This style is a bit ugly but it can sometimes be the least bad solution to creating generic types that do need to know their component type at runtime for whatever reason (creating arrays, or creating instances of their component type, etc.).
I found a sort of a work around to this problem.
The line below throws generic array creation error
List<Person>[] personLists=new ArrayList<Person>()[10];
However if I encapsulate List<Person> in a separate class, it works.
import java.util.ArrayList;
import java.util.List;
public class PersonList {
List<Person> people;
public PersonList()
{
people=new ArrayList<Person>();
}
}
You can expose people in the class PersonList thru a getter. The line below will give you an array, that has a List<Person> in every element. In other words array of List<Person>.
PersonList[] personLists=new PersonList[10];
I needed something like this in some code I was working on and this is what I did to get it to work. So far no problems.
Generic array creation is disallowed in java but you can do it like
class Stack<T> {
private final T[] array;
public Stack(int capacity) {
array = (T[]) new Object[capacity];
}
}
According to vnportnoy the syntax
GenSet<Integer> intSet[] = new GenSet[3];
creates an array of null references, to be filled as
for (int i = 0; i < 3; i++)
{
intSet[i] = new GenSet<Integer>();
}
which is type safe.
You could create an Object array and cast it to E everywhere. Yeah, it's not very clean way to do it but it should at least work.
try this.
private int m = 0;
private int n = 0;
private Element<T>[][] elements = null;
public MatrixData(int m, int n)
{
this.m = m;
this.n = n;
this.elements = new Element[m][n];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
this.elements[i][j] = new Element<T>();
}
}
}
An easy, albeit messy workaround to this would be to nest a second "holder" class inside of your main class, and use it to hold your data.
public class Whatever<Thing>{
private class Holder<OtherThing>{
OtherThing thing;
}
public Holder<Thing>[] arrayOfHolders = new Holder<Thing>[10]
}
Maybe unrelated to this question but while I was getting the "generic array creation" error for using
Tuple<Long,String>[] tupleArray = new Tuple<Long,String>[10];
I find out the following works (and worked for me) with #SuppressWarnings({"unchecked"}):
Tuple<Long, String>[] tupleArray = new Tuple[10];
I'm wondering if this code would create an effective generic array?
public T [] createArray(int desiredSize){
ArrayList<T> builder = new ArrayList<T>();
for(int x=0;x<desiredSize;x++){
builder.add(null);
}
return builder.toArray(zeroArray());
}
//zeroArray should, in theory, create a zero-sized array of T
//when it is not given any parameters.
private T [] zeroArray(T... i){
return i;
}
Edit: Perhaps an alternate way of creating such an array, if the size you required was known and small, would be to simply feed the required number of "null"s into the zeroArray command?
Though obviously this isn't as versatile as using the createArray code.
You could use a cast:
public class GenSet<Item> {
private Item[] a;
public GenSet(int s) {
a = (Item[]) new Object[s];
}
}
I actually found a pretty unique solution to bypass the inability to initiate a generic array. What you have to do is create a class that takes in the generic variable T like so:
class GenericInvoker <T> {
T variable;
public GenericInvoker(T variable){
this.variable = variable;
}
}
and then in your array class just have it start like so:
GenericInvoker<T>[] array;
public MyArray(){
array = new GenericInvoker[];
}
starting a new Generic Invoker[] will cause an issue with unchecked but there shouldn't actually be any issues.
To get from the array you should call the array[i].variable like so:
public T get(int index){
return array[index].variable;
}
The rest, such as resizing the array can be done with Arrays.copyOf() like so:
public void resize(int newSize){
array = Arrays.copyOf(array, newSize);
}
And the add function can be added like so:
public boolean add(T element){
// the variable size below is equal to how many times the add function has been called
// and is used to keep track of where to put the next variable in the array
arrays[size] = new GenericInvoker(element);
size++;
}
If you really want to wrap a generic array of fixed size you will have a method to add data to that array, hence you can initialize properly the array there doing something like this:
import java.lang.reflect.Array;
class Stack<T> {
private T[] array = null;
private final int capacity = 10; // fixed or pass it in the constructor
private int pos = 0;
public void push(T value) {
if (value == null)
throw new IllegalArgumentException("Stack does not accept nulls");
if (array == null)
array = (T[]) Array.newInstance(value.getClass(), capacity);
// put logic: e.g.
if(pos == capacity)
throw new IllegalStateException("push on full stack");
array[pos++] = value;
}
public T pop() throws IllegalStateException {
if (pos == 0)
throw new IllegalStateException("pop on empty stack");
return array[--pos];
}
}
in this case you use a java.lang.reflect.Array.newInstance to create the array, and it will not be an Object[], but a real T[].
You should not worry of it not being final, since it is managed inside your class.
Note that you need a non null object on the push() to be able to get the type to use, so I added a check on the data you push and throw an exception there.
Still this is somewhat pointless: you store data via push and it is the signature of the method that guarantees only T elements will enter. So it is more or less irrelevant that the array is Object[] or T[].

Java Is there any way to initialize a generic array that's type safe?

I have the following code
public class Container<T> {
private T element;
private T[] tarray;
public T getElement() {
return element;
}
public void setElement(T element) {
this.element = element;
}
public void add(T element) {
tarray[0] = element;
}
public void CreateArray(int size) {
//Can this be cleaned up better?
tarray = (T[]) new Object[size];
}
public T get() {
return tarray[0];
}
public Container(T someElement) {
this.element = someElement;
}
public Container() {
}
public static void main(String[] args) {
Container<String> myContaier1 = new Container<String>();
myContaier1.setElement("Hello");
myContaier1.CreateArray(1);
myContaier1.add("GoodBye");
System.out.println(myContaier1.get());
}
}
Is there no way to initialize a type safe generic array?
There is no way unless you provide a reified T in the form of an actual Class<T> object that represents a specific value of T. This is because the array type is reified, whereas the Generic type isn't.
There are two problems here:
First of all, the actual type of your array will always be Object[]. You cast it to T[], but this works only because T[] erases to Object[]. If your class definition said, for example, <T extends Number>, then (T[])new Object[] would fail with a ClassCastException.
You could get around this by passing Class<T> to the constructor of your collection and keeping it in a field:
private Class<T> componentClass;
...
tarray = (T[]) Array.newInstance(componentClass, size);
Now the actual in-memory type of tarray is T[], but you still get an unchecked cast error. Even though you have the component class, as far as I know there is no equivalent of Class.cast() for doing a checked cast of an array instance.
You can do private T[] tarray;, But you cannot assign it to (T[]) new Object[size];. How can an array of Object be same an array of any other class.
T is not even there after compilation.
It is called type erasure. E.g if you do
List<Person> persons = new ArrayList<Person>();
It becomes List persons = new ArrayList() after compilation.
It is similar to ask "Is there a way to initialize a generic object: new T()?"
Of course it is impossible, as the compiler does not know what the type is of it.
Array is the same, its type relies on its elements. If the type of its elements is unknown, the type of itself is unknown.
Those classes which can take generic types like List, Set, Map, etc. are different. They have their own classes as types and they are dynamic, so you can initialize one like new ArrayList<T>().
You can try on this:
public class Test {
public static void main (String args[]) {
int[] i = new int[3];
short[] s = new short[4];
ArrayList<String> a = new ArrayList<String>();
System.out.println(i.getClass().getName());
System.out.println(s.getClass().getName());
System.out.println(args.getClass().getName());
System.out.println(a.getClass().getName());
}
}
You will see the types of elements are already combined with the arrays, while not combined with ArrayList.
There are way to do this on the JVM, but to do something like this in Java would require writing a lot of boiler plate code. In Scala, you can use Manifests to get around type erasure, and can instantiate generic arrays without casting.
An example:
class Container[T : Manifest]() {
def createArray(size:Int) = Array.ofDim[T](size)
}
scala> val f = new Container[String]
f: Container[String] = Container#12f3aa66
scala> f.createArray(5)
res7: Array[String] = Array(null, null, null, null, null)
Scala code compiles to the same bytecode class files as Java (implying that this should be possible in Java if you jumped through enough hoops and maybe wrote your own manifests). Scala classes can be imported into Java projects... though I'm not sure how hard it is to instantiate a class like this from Java.
If you often find yourself wanting to be able to handle more complicated type situations, have a look at Scala, you might like it.

Categories