I am trying to create an array of the generic class "DataStruct".
The code is the following:
public class DataArray<T> {
DataStruct<T>[] array;
int index;
public DataArray(int capacity) {
array = (DataStruct<T>[]) new Object[capacity]; // !!!
this.index = 0;
}
}
I get a java.lang.ClassCastException (Ljava.lang.Object; cannot be cast to [LArrayBased.DataStruct;) at the line marked with three exclamation marksat the end, while testing it.
Can you please tell me the correct way to create it?
Why not declare
array = new DataStruct[capacity];
Object[] can not be cast to DataStruct[].
Because arrays are refiable in nature that means arrays know their type at runtime so If you convert it to Object [] like below you will again run in to problems
Object[] array = new DataStruct[capacity];
array[0] = 10;//Array Store exception
So it is wise to declare it as DataStruct[capacity]
Related
I've got a generic array class and I want to return an array in the main so I can use the sort method that I have ready in the main. I understand that the constructor has an array in it so I'm wondering if I can use that. Or do I need to set up a new method to return this.array ? Also it returns a generic array, how do I choose the type in main?
public class dynamicArray <T>{
private int index;
private T[] array;
public dynamicArray() {
array = (T[])new Object[10];
this.index = 0;
}
public T [] populate() {
return this.array;
}
Here I chose the integer type for the class. I'm not sure how can I extract the
array from the constructor.
public static void main(String[] args) {
dynamicArray<Integer>array = new<Integer>dynamicArray();
array.add(10);
array.add(5);
array.add(6);
array.add(11);
array.add(13);
array.add(20);
int [] arr = array.populate();
mergeSort(arr);
System.out.println(array.toString());
}
Unfortunately, arrays and generics don't work well together. Take a look at the source code of java's ArrayList - it is implemented with an Object[] and not a T[] - then every method will cast to T (which costs literally zero, it's just ugly and causes compiler warnings). I advise you do the same here: Arrays actually KNOW their component type (unlike a list of Ts, which does not, there is no method on a java.util.List that you can invoke to get the component type), and therefore casting Object[] to T[] is just wrong; java allows this solely for backwards compatibility reasons.
Basically, you can't work with T[] without things being subtly wrong and a lot of compiler errors.
In this specific case? I would strenuously advise you to use a private List<T> array; field instead of a T[] field.
Your call to array.populate() (that seems like a bizarre name for this method!) IS retrieving the array you created in the constructor. You are doing what you're asking for: "Extracting the array from the constructor" - invoking populate() on the object returned by the new dynamicArray<Integer>() is doing exactly that.
NB: You have a typo in your source code. it's new dynamicArray<Integer>();, not new<Integer>dynamicArray();. Perhaps that's causing some issues?
NB2: Java conventions dictate it's DynamicArray, and something like getBackingArray (instead of populate).
I think you ask two question :
How to set Integer type of that array object.
How to get Integer[] to int[]
Here is the code :
private int index;
private T[] array;
public dynamicArray() {
array = (T[])new Object[10];
this.index = 0;
}
public T [] populate() {
return this.array;
}
public void add(T x) {
array[++index] = x;
}
public static void main(String[] args) {
dynamicArray<Integer>array = new<Integer>dynamicArray();
array.add(10);
array.add(5);
array.add(6);
array.add(11);
array.add(13);
array.add(20);
int[] arr = Arrays.stream(array.populate())
.mapToInt(i -> i)
.toArray();
System.out.println(array.toString());
}
Answer for 1st question is you can not set Integer type because there wasn't any add method in your class. Answer for 2nd question is you try to convert Integer[] to int[] but there is no direct way to cast this. you just need to change Integer -> Object then Object -> int. This can be done easily using streams which is in Java 8 and i have used lambda here for showing power of lambda function.
Here is a possible alternative. Pass the type of array to the constructor. But essentially you are creating a limited form of ArrayList so you may just as well use that. Note that this still has the limitation that you can't use primitive arrays as the array type.
dynamicArray<Integer> array = new dynamicArray<>(new Integer[0]);
array.add(10);
array.add(5);
array.add(6);
array.add(11);
array.add(13);
array.add(20);
Integer[] a = array.getArray();
System.out.println(Arrays.toString(a));
}
class dynamicArray<T> {
private int size = 0;
private T[] array;
public dynamicArray(T[] a) {
array = a;
}
public void add(T value) {
if (array.length == size) {
array = Arrays.copyOf(array, size == 0 ? 10 : size*2);
}
array[size++] = value;
}
#SuppressWarnings("unchecked")
public T[] getArray() {
// need to copy the array since the length and size could be different.
T[] arrayCopy = (T[]) Array.newInstance(array.getClass().getComponentType(), size);
System.arraycopy(array, 0, arrayCopy, 0, size);
return arrayCopy;
}
}
I'm implementing a Quicksort class in Java. For sorting to work, the items that are to be sorted need to be comparable, for example by implementing the Comparable interface. However, implementing Comparable gives me problems when casting at runtime in a method that returns array slices:
public class QuickSorter<T extends Comparable<T>> {
...
private T[] sliceOfArray(T[] arr, int start, int end) {
Object[] slice = new Object[end - start];
for (int i = start; i < end; i++) {
slice[i] = arr[i];
}
return (T[]) slice; // Throws exception at runtime.
}
}
The exception is:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
at com.sortingalgos.QuickSorter.sliceOfArray(QuickSorter.java:55)
at com.sortingalgos.QuickSorter.sort(QuickSorter.java:11)
at com.sortingalgos.MainApp.main(MainApp.java:11)
How can I get around this?
The simple fix is to change this line
Object[] slice = new Object[end - start];
to
Comparable[] slice = new Comparable[end - start];
The business of casting to T[] is a hack. It doesn't actually change tbe type of the array. You don't want to be passing it around pretending that it really is correctly typed. It may be clearer to use Object[] (or Comparable[]) or just plain old List<T>.
You can't even do the following:
Object[] a = new Object[] {1,3,4,5};
Integer[] b = (Integer[])a;
System.out.println(Arrays.toString(b));
This is because there is no guarantee that Object[] a doesn't really look like the following:
Object[] a = new Object[]{1,3,4,5.7}
Which clearly is not an array of Integer. But you could do this.
Object[] a = new Integer[] {1,3,4,5};
Integer[] b = (Integer[])a;
System.out.println(Arrays.toString(b));
The problem is that an array of Object isn't an array of Comparable. You need the slice array to have the same element type as the arr array. You can achieve this by changing
Object[] slice = new Object[end - start];
to
T[] slice = java.lang.reflect.Array.newInstance(arr.class.getComponentType(), end - start);
In other words, use reflection to determine at runtime the element type, and create slice arrays of the same type.
Using reflection is likely to be less performant, however. For an in-place sort algorithm like QuickSort, you shouldn't need to create any new arrays at all, you could just use the input array. (Or clone it, if you aren't allowed to modify the input.)
I am trying do something like this:-
public static ArrayList<myObject>[] a = new ArrayList<myObject>[2];
myObject is a class. I am getting this error:- Generic array creation (arrow is pointing to new.)
You can't have arrays of generic classes. Java simply doesn't support it.
You should consider using a collection instead of an array. For instance,
public static ArrayList<List<MyObject>> a = new ArrayList<List<MyObject>();
Another "workaround" is to create an auxilliary class like this
class MyObjectArrayList extends ArrayList<MyObject> { }
and then create an array of MyObjectArrayList.
Here is a good article on why this is not allowed in the language. The article gives the following example of what could happen if it was allowed:
List<String>[] lsa = new List<String>[10]; // illegal
Object[] oa = lsa; // OK because List<String> is a subtype of Object
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[0] = li;
String s = lsa[0].get(0);
There is a easier way to create generic arrays than using List.
First, let
public static ArrayList<myObject>[] a = new ArrayList[2];
Then initialize
for(int i = 0; i < a.length; i++) {
a[i] = new ArrayList<myObject>();
}
You can do
public static ArrayList<myObject>[] a = (ArrayList<myObject>[])new ArrayList<?>[2];
or
public static ArrayList<myObject>[] a = (ArrayList<myObject>[])new ArrayList[2];
(The former is probably better.) Both will cause unchecked warnings, which you can pretty much ignore or suppress by using: #SuppressWarnings("unchecked")
if you are trying to declare an arraylist of your generic class you can try:
public static ArrayList<MyObject> a = new ArrayList<MyObject>();
this will give you an arraylist of myobject (size 10), or if u only need an arraylist of size 2 you can do:
public static ArrayList<MyObject> a = new ArrayList<MyObject>(2);
or you may be trying to make an arraylist of arraylists:
public static ArrayList<ArrayList<MyObject>> a = new ArrayList<ArrayList<MyObject>>();
although im not sure if the last this i said is correct...
It seems to me that you use the wrong type of parenthesis. The reason why you can't define an array of generic is type erasure.
Plus, declaration of you variable "a" is fragile, it should look this way:
List<myObject>[] a;
Do not use a concrete class when you can use an interface.
I am trying do something like this:-
public static ArrayList<myObject>[] a = new ArrayList<myObject>[2];
myObject is a class. I am getting this error:- Generic array creation (arrow is pointing to new.)
You can't have arrays of generic classes. Java simply doesn't support it.
You should consider using a collection instead of an array. For instance,
public static ArrayList<List<MyObject>> a = new ArrayList<List<MyObject>();
Another "workaround" is to create an auxilliary class like this
class MyObjectArrayList extends ArrayList<MyObject> { }
and then create an array of MyObjectArrayList.
Here is a good article on why this is not allowed in the language. The article gives the following example of what could happen if it was allowed:
List<String>[] lsa = new List<String>[10]; // illegal
Object[] oa = lsa; // OK because List<String> is a subtype of Object
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[0] = li;
String s = lsa[0].get(0);
There is a easier way to create generic arrays than using List.
First, let
public static ArrayList<myObject>[] a = new ArrayList[2];
Then initialize
for(int i = 0; i < a.length; i++) {
a[i] = new ArrayList<myObject>();
}
You can do
public static ArrayList<myObject>[] a = (ArrayList<myObject>[])new ArrayList<?>[2];
or
public static ArrayList<myObject>[] a = (ArrayList<myObject>[])new ArrayList[2];
(The former is probably better.) Both will cause unchecked warnings, which you can pretty much ignore or suppress by using: #SuppressWarnings("unchecked")
if you are trying to declare an arraylist of your generic class you can try:
public static ArrayList<MyObject> a = new ArrayList<MyObject>();
this will give you an arraylist of myobject (size 10), or if u only need an arraylist of size 2 you can do:
public static ArrayList<MyObject> a = new ArrayList<MyObject>(2);
or you may be trying to make an arraylist of arraylists:
public static ArrayList<ArrayList<MyObject>> a = new ArrayList<ArrayList<MyObject>>();
although im not sure if the last this i said is correct...
It seems to me that you use the wrong type of parenthesis. The reason why you can't define an array of generic is type erasure.
Plus, declaration of you variable "a" is fragile, it should look this way:
List<myObject>[] a;
Do not use a concrete class when you can use an interface.
I am creating a list data structure and am having trouble with the generics syntax for actually using it. All I am trying to do is create an instance of ArrayLinearList<String> and of size 2 and put some strings in it. I have been trying to figure out why setting the first slot to "one" is not correct. This is the error and my code snippet.
myList[0] = "one";
The error message is: error: incompatible types: String cannot be converted to ArrayLinearList<String>
public class ArrayLinearList<E> implements LinearListADT<E> {
private Object[] array;
int currentSize = 0;
//Constructor (no arguments)
public ArrayLinearList() {
currentSize = 2;
// array = (ArrayLinearList[]) new Object[2]; //Start with a container of size 2
array = new Object[2];
}
public static void main(String[] var0) {
ArrayLinearList<String>[] myList;
myList = new ArrayLinearList[2];
myList[0] = "one";
}
}
I am having quite a bit of trouble with the syntax with using generics in java. In my mind I have an array of size 2 where I am going to be placing strings. I will add more methods later but I want to understand why my current syntax is incorrect for placing this string in the array.
Here:
ArrayLinearList<String>[] myList;
you define an array that holds ArrayLinearList<String> elements, not Strings, this is why you get the error message.
Your code here
ArrayLinearList<String>[] myList;
myList = new ArrayLinearList[2];//you have defining array myList of type ArrayLinearList
myList[0] = "one";//you are trying to store String to array which can hold ArrayLinearList
Here ArrayLinearList<String> means that your list will hold values of type String (provided we define it correctly in the code). But ArrayLinearList<String>[] will hold only reference of type ArrayLinearList and not String itself.
You need to use
myList.array[0] = "one";
Because myList is not an array. It's an object which you use to store an array within.