ClassCastException when using generic custom class - java

I was trying to construct a simple list class using generics.
However, it throws classcastexception when I was trying to print out the value. Is there any problem when I declare and initialize generic array?
class vector<E> {
static int MAX_LEN = 1234567;
E[] data;
int[] prv;
int to;
int size;
vector() {
data = (E[])new Object[MAX_LEN];
prv = new int[MAX_LEN];
to = -1;
size = 0;
for(int i = 0; i < MAX_LEN; ++i) {
prv[i] = -1;
}
}
void push_back(E e) {
data[size] = e;
prv[size] = to;
to = size;
++size;
}
}
public class Main {
public static void main(String[] args) throws Exception {
vector<Integer> v = new vector();
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
for(int i = v.to; i != -1; i = v.prv[i]) {
System.out.println(v.data[i]); //<- Exception here
}
}
}

There are a few things wrong with the code.
It looks like, you've missed a <> in the line vector<Integer> v = new vector();
A cast from Object[] to Integer[] will never succeed
Ex:
Integer[] a= (Integer[]) new Object[] {}; // this cast will never succeed
Infact you can only cast Object[] to Object or Object[].
currently when you are trying to access data in the main() method, the cast put in by the compiler for you Integer[] will fail at runtime. You don't need the data array, you just need the values from it, which you can get by adding the following method to the vector class.
E getData(int index) {
return data[index];
}
In this case, compiler will add the cast to individual elements and will provide you the correct values.

You really have two options here. Either use data array of Object[] type or create proper generic array. Here is how to create generic array.
vector(Class<E> clazz) {
data = (E[])Array.newInstance(clazz, MAX_LEN);

Related

Create array of object from an array of int

I'm not understanding something, obviously. I've got a primitive array of ints, and I need to convert that into an array of my own type. Here's what I've tried.
public class StupidInt {
#JsonProperty("ID")
private int id;
public StupidInt(int id) { this.id = id; }
public int getId() { return this.id; }
}
public static void main(String []args){
int[] ints = {1,2,4,67};
StupidInt[] myInts = IntStream.of(ints).map(StupidInt::new).collect(Collectors.toList());
}
As you might expect, myInts line has a problem and that problem is "cannot convert StupidInt to int". But I'm not sure what combination of map or foreach or whatever intermediate and terminal methods to use to convert that array of ints to an array of my object. What is the correct way to do this conversion?
You need to use mapToObj to create a new Stream of objects and toArray instead of collect to obtain the result as an array.
StupidInt[] myInts = IntStream.of(ints).mapToObj(StupidInt::new).toArray(StupidInt[]::new);
The answer from #hev1 is simple and the best answer for a terminal method for what you are trying to achieve.
I provide here two different options if you need a different solution. The first is just a for intermediate method to create the primitive array; and the second option is a wholesome different approach to the problem and does not create a primitive array but a "list" of the type Object that reflect the primitive type and will also work with any type or object:
Solution 1:
int[] ints = {1,2,4,67};
StupidInt[] myInts = new StupidInt[ints.length];
for (int i = 0; i < myInts.length; i++) {
myInts[i] = new StupidInt(ints[i]);
}
Solution 2:
public class StupidIntList {
private ArrayList<Integer> ids;
public StupidIntList() {
this.ids = new ArrayList<Integer>();
}
public void add(int id) {
this.ids.add(id);
}
public int get(int pos) {
return this.ids.get(pos);
}
public boolean findId(int i_d) {
for (Integer id : ids) {
if(id == i_d)
return true;
}
return false;
}
public String toString() {
String res = "[";
for (Integer id : ids) {
res += id+",";
}
return res.substring(0, res.lastIndexOf(","))+"]";
}
public static void main(String []args){
int[] ints = {1,2,4,67};
StupidIntList myInts = new StupidIntList();
for (int i = 0; i < ints.length; i++) {
myInts.add(ints[i]);
}
System.out.println(myInts);
}
}
In this case to add a new int you use the add method and to get one int you will use the get(position) method or the find method to look if it exists and get the position.
Or you could simply use the ArrayList class or if you want I can share with you a list structure that allows what you need to accomplish, has most methods you can think of, implements comparable, can be ordered, implements iterable and is very efficient.

Creating an Array List from scratch

I was wondering if anyone would be able to point me in the correct direction in regards to creating my own array list methods. For instance, the current project I am assigned to does not allow for me to use the methods given to me for free like in the following example.
package com.tutorialspoint;
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
// create an empty array list with an initial capacity
ArrayList<Integer> arrlist = new ArrayList<Integer>(5);
// use add() method to add elements in the list
arrlist.add(15);
arrlist.add(22);
arrlist.add(30);
arrlist.add(40);
// adding element 25 at third position
arrlist.add(2,25);
// let us print all the elements available in list
for (Integer number : arrlist) {
System.out.println("Number = " + number);
}
}
}
This example shows the add() method. For my project I have to create this method myself and call it from a different file within my package.
I find this as an interesting problem. I am always curious about how things work at the raw level.
If you think about it, an ArrayList is basically just an array that you can expand. So you can either have a really big array (which would take a lot of memory for one ArrayList) or every time you add something, you make a new bigger array and copy the contents and add the new item (which I think the performance is O(N)).
This is my attempt without using any libraries:
public class MyArrayList<T>
{
private T[] asArray;
#SuppressWarnings("unchecked")
public MyArrayList()
{
asArray = (T[]) new Object[0];
}
public void add(T t)
{
#SuppressWarnings("unchecked")
T[] temp = (T[]) new Object[asArray.length + 1];
// copy everything over to the new array
for (int i = 0; i < asArray.length; i++)
{
temp[i] = asArray[i];
}
// add the new element
temp[asArray.length] = t;
asArray = temp;
}
public void remove(int index)
{
if (index < 0 || index >= asArray.length) return;
#SuppressWarnings("unchecked")
T[] temp = (T[]) new Object[asArray.length - 1];
boolean found = false;
// copy everything over to the new element
for (int i = 0; i < asArray.length; i++)
{
// don't copy if the indices are the same
if (i == index)
{
found = true;
continue;
}
temp[i - (found ? 1 : 0)] = asArray[i]; // it's i - 1 after the removed object so then it doesn't leave a gap and it doesn't go over the array's length
}
asArray = temp;
}
public T get(int index)
{
return asArray[index];
}
}
I am quite proud of this code. :) I consider Short_Teeth's code cheating because the class is a subclass and, well, doesn't add anything. I hope I helped.
This is very easy to understand; However, I explained a little bit in comments.
public class MyArrayList<E extends Object> {
private static int initialCapacity = 5;
private static int currentSize;
private Object[] myArrayList = {}, temp = {};
private static int currentIndex = 0;
public static void main(String[] args) {
MyArrayList arrList = new MyArrayList();
arrList.add("123"); //add String
arrList.printAllElements();
arrList.add(new Integer(111)); //add Integer
arrList.printAllElements();
arrList.add(new Float("34.56")); //add Integer
arrList.printAllElements();
arrList.delete("123");
arrList.printAllElements();
arrList.delete(123);
arrList.printAllElements();
arrList.delete(123);
arrList.printAllElements();
}
public MyArrayList() { //creates default sized Array of Objects
myArrayList = new Object[initialCapacity]; //generic expression
/* everytime I cross my capacity,
I make double size of Object Array, copy all the elements from past myObject Array Object
*/
}
public MyArrayList(int size) { //creates custom sized Array of Objects
myArrayList = new Object[size];
}
public void add(Object anyObj) {
//add element directy
myArrayList[currentIndex] = anyObj;
currentSize = myArrayList.length;
currentIndex++;
if (currentIndex == currentSize) {
createDoubleSizedObjectArray(currentSize);
}
}
//print all elements
public void printAllElements() {
System.out.println("Displaying list : ");
for (int i = 0; i < currentIndex; i++) {
System.out.println(myArrayList[i].toString());
}
}
private void createDoubleSizedObjectArray(int currentSize) {
temp = myArrayList.clone();
myArrayList = new MyArrayList[2 * currentSize]; //myObject pointer big size data structure
// myObject = temp.clone(); //probably I can do this here as well. Need to check this
System.arraycopy(temp, 0, myArrayList, 0, currentSize);
}
void delete(Object object) {
//if already empty
if (currentIndex == 0) {
System.out.println("Already empty!");
return;
}
//you don't need to delete anything. I can simply override the storage
currentIndex--;
}
}
import java.util.ArrayList;
public class MyArrayList<E> extends ArrayList<E>{
private static final long serialVersionUID = -5164702379587769464L;
public void newMethod(){
// No implementation
}
}
This is a class which extends from ArrayList and a method called newMethod() was added to this class.
Below we are calling this newly created method in your case you must implement the add to this newly created method.
public class Hello {
public static void main(String args[]) {
MyArrayList<Integer> myList = new MyArrayList<Integer>();
// It has the ArrayList add() method as this new class extends from ArrayList (all the ArrayList methods are included)
myList.add(2);
// The newly created method in your case you need to implement the add yourself
myList.newMethod();
}
}
This could also be a good link for what you need.
http://www.java2novice.com/java-interview-programs/arraylist-implementation/
I also recomend that you try to implement and solve your problems first and then ask questions about a specific problem, and only after you done a good research about what may be causing this problem (There are lots of resources out there). If you done some research before you asked this question, I'm pretty sure that you would have been able to solve everything on your own.
Hope you find this information useful. Good luck.

ClassCastException Object cannot be cast to

I don't understand why I get ClassCastException on below code in line:
for(int i = 0; i < k.t.length; i++)
So problem is that in method addElement I make replacing of array elements by objects with type T. In my opinion in array should be objects with type T. And compiler doesn't protest for that.
But in run-time JVM cannot cast despite in array is really objects with type T (in case below String), why JVM cannot use polymorphism?
But when I change the T[] t; to Object[] t;
and remove cast in constructor it run correctly without any errors, why?
public class MyCollection<T> {
T[] t;
MyCollection( int size){
t = (T[]) new Object[size];
}
boolean addElement(T e, int i){
if(i < t.length){
t[i] = e;
return true;
}
return false;
}
public static void main(String[] ss){
MyCollection<String> k = new MyCollection<String>(3);
k.addElement("a",0);
k.addElement("b",1);
k.addElement("c",2);
for(int i = 0; i < k.t.length; i++)
System.out.println(k.t[i]);
//for(String s : (String[])k.t)
// System.out.println(s);
}
}
The problem is that you're casting Object[] to T[], and then you're exposing the underlying array. The only reason this works altogether is because the type erasure of T is Object. But since in our case T is being interpreted as String, when we access the array externally, we're trying to cast it to String[], which is incorrect. In order to avoid this issue, you should make the array private and provide accessor methods to retrieve elements. By doing that, you only cast individual elements to their correct type without making assumptions about the underlying array.
public class MyCollection<T> {
private T[] t;
MyCollection( int size){
t = (T[]) new Object[size];
}
boolean addElement(T e, int i){
if(i < t.length){
t[i] = e;
return true;
}
return false;
}
T getElement(int index) {
return t[index];
}
int getLength() {
return t.length;
}
public static void main(String[] ss){
MyCollection<String> k = new MyCollection<String>(3);
k.addElement("a",0);
k.addElement("b",1);
k.addElement("c",2);
for(int i = 0; i < k.getLength(); i++)
System.out.println(k.getElement(i));
//for(String s : (String[])k.t)
// System.out.println(s);
}
}
Note that Java's Collection interface demonstrates the same behavior. Collection.toArray() returns Object[] regardless of the type of E. The only available workaround is Collection.toArray(T[]), where you're forced to pass an array with a fixed type, which can then be either be populated or copied.
Check again the line of the problem. In my opinion the exception will be thrown because of:
for(String s : (String[])k.t)
You`re trying to cast to String[] here, while the array is defined as Object[]:
t = (T[]) new Object[size];
you can Create a new instance of array using the reflection to avoid ClassCastException
example:
import java.lang.reflect.Array;
public class MyCollection<T> {
T[] t;
MyCollection(Class<T> clazz, int size) {
t = (T[]) Array.newInstance(clazz, size);
}
boolean addElement(T e, int i) {
if (i < t.length - 1) {
t[i] = e;
return true;
}
return false;
}
public static void main(String[] ss) {
MyCollection<String> k = new MyCollection<String>(String.class, 3);
k.addElement("a", 0);
k.addElement("b", 1);
k.addElement("c", 2);
for (int i = 0; i < k.t.length; i++)
System.out.println(k.t[0]);
}
}

A polymorphic method for creating a list of new objects

What is the best way to write a method that given a type T and integer n, returns a list of n newly created objects of type T. Is it possible to pass a constructor as argument or will I have to accomplish this in some other way?
Was thinking something like this
public <T> ArrayList<Object> generate(T type, int amount){
ArrayList<Object> objects = new ArrayList();
for (int i = 0; i < amount; i ++){
objects.add(new bla bla)...
}
Use a generic method.
public <T> List<T> getList(Class<T> clazz, int size) throws InstantiationException, IllegalAccessException{
List<T> list = new ArrayList<T>();
for(int x = 0; x < size; x++){
list.add(clazz.newInstance());
}
return list;
}
NOTE: This will only work for objects with a default constructor. If you want to create a List of objects that do not contain a default constructor you must do so using reflection to pick the appropriate constructor.
public static <T> List<T> generate(Class<T> clazz, int amount) {
ArrayList<Object> objects = new ArrayList();
for (int i = 0; i < amount; i ++){
objects.add(clazz.newInstance());
}
return list;
}
The code above actually tries to use default constructor. You can pass a reflection reference to an appropriate constructor of your choice if you want. A list of constructors can be obtained by calling Class.getConstructors().
Then your code would look like this:
public static <T> List<T> generate(Constructor<T> constructor, int amount) {
ArrayList<Object> objects = new ArrayList();
for (int i = 0; i < amount; i ++){
objects.add(constructor.newInstance(param1, param2, ...)); // fill the arguments
}
return list;
}

Cast primitive type array into object array in java

Why I cannot do this in java?
Object[] o = (Object[])(new int[]{0,1,2,3.14,4});
I have a method that receives an object and then represents it as a string, but depending on his type (primitive, primitive wrapper, array, etc...). When I was creating a Unit test, I was passing an array as Object which is Ok, but when I perform cast of that object into Object[] I'm getting ClassCastException.
This is only happening with primitive type arrays. Is there any way to avoid this behavior? If not, could someone explain what is the reason of this behavior on Java Virtual Machine.
Any help is very appreciated.
Here is a simple one-liner:
Double[] objects = ArrayUtils.toObject(primitives);
You will need to import Apache commons-lang3:
import org.apache.commons.lang3.ArrayUtils;
In Java, primitive types and reference types are two distinct worlds. This reflects to arrays: A primitive array is not an object array, that's why you can't cast.
Here is a simpler version of your solution in the question:
private Object[] getArray(Object val){
if (val instanceof Object[])
return (Object[])val;
int arrlength = Array.getLength(val);
Object[] outputArray = new Object[arrlength];
for(int i = 0; i < arrlength; ++i){
outputArray[i] = Array.get(val, i);
}
return outputArray;
}
This will still work when they sometimes decide to add new primitive types to the VM.
Of course, you might want to do the copying always, not only in the primitive case, then it gets even simpler:
private Object[] getArray(Object val){
int arrlength = Array.getLength(val);
Object[] outputArray = new Object[arrlength];
for(int i = 0; i < arrlength; ++i){
outputArray[i] = Array.get(val, i);
}
return outputArray;
}
Of course, this is not casting, but converting.
Primitive type cannot be transformed in this way.
In your case, there is an array of double values, cause of 3.14.
This will work:
List<Object> objectList = new ArrayList<Object>();
objectList.addAll(Arrays.asList(0,1,2,3.14,4));
Even this works :
List<Object> objectList = new ArrayList<Object>();
objectList.addAll(Arrays.asList(0,"sfsd",2,3.14,new Regexp("Test")));
for(Object object:objectList)
{
System.out.println(object);
}
UPDATE
Ok, there as there was said, there is not direct way to cast a primitive array to an Object[].
If you want a method that transforms any array in String, I can suggest this way
public class CastArray {
public static void main(String[] args) {
CastArray test = new CastArray();
test.TestObj(new int[]{1, 2, 4});
test.TestObj(new char[]{'c', 'a', 'a'});
test.TestObj(new String[]{"fdsa", "fdafds"});
}
public void TestObj(Object obj) {
if (!(obj instanceof Object[])) {
if (obj instanceof int[]) {
for (int i : (int[]) obj) {
System.out.print(i + " ");
}
System.out.println("");
}
if (obj instanceof char[]) {
for (char c : (char[]) obj) {
System.out.print(c + " ");
}
System.out.println("");
}
//and so on, for every primitive type.
} else {
System.out.println(Arrays.asList((Object[]) obj));
}
}
}
Yes, it's annoying to write a loop for every primitive type, but there is no other way, IMHO.
Originally posted by the OP within the question itself, but pulled here as a separate answer.
After getting response from StKiller and other users
I was able to create a more generic method, which is located below:
private final Class<?>[] ARRAY_PRIMITIVE_TYPES = {
int[].class, float[].class, double[].class, boolean[].class,
byte[].class, short[].class, long[].class, char[].class };
private Object[] getArray(Object val){
Class<?> valKlass = val.getClass();
Object[] outputArray = null;
for(Class<?> arrKlass : ARRAY_PRIMITIVE_TYPES){
if(valKlass.isAssignableFrom(arrKlass)){
int arrlength = Array.getLength(val);
outputArray = new Object[arrlength];
for(int i = 0; i < arrlength; ++i){
outputArray[i] = Array.get(val, i);
}
break;
}
}
if(outputArray == null) // not primitive type array
outputArray = (Object[])val;
return outputArray;
}
You can pass kind of array into getArray method, which will return Object[] without throwing ClassCastException.
Thanks again for all your replies.
As the original poster first stated in his question:
I have a method that receives an object and then represents it as a string
While the intent was to output an Object's value in a friendly way, he was using Casting as a mean to that end. Therefore, expanding upon PaĆ­lo Ebermann's answer, here is my solution to make most objects toString() friendly.
The main problem being arrays, it will recursively transform any array X[] into its Object equivalent of List<X>, whether X is a primitive or not. The rest is be handled by each specific object's toString() if needed, as it should.
Important caveat: it is assumed that there are no circular references!
Given:
System.out.println(objectify(new double[][]{{65.5 * 15.9, 0}, {0.123456, 1}}))
The expected result is:
[[1041.45, 0.0], [0.123456, 1.0]]
The implementation:
public Object objectify(Object obj) {
if(obj == null)
return obj;
Object o = obj;
if(obj.getClass().isArray()) {
// array
if(obj instanceof Object[]) {
// array of Object
Object[] oI = (Object[])obj;
Object[] oO = new Object[oI.length];
for(int i = 0; i < oI.length; i++) {
// objectify elements
oO[i] = objectify(oI[i]);
}
o = Arrays.asList(oO);
} else {
// array of primitive
int len = Array.getLength(obj);
Object[] out = new Object[len];
for(int i = 0; i < len; i++)
out[i] = Array.get(obj, i);
o = Arrays.asList(out);
}
}
return o;
}
With Java 8 you could use Streams with a mapping function to turn the array into one of any other type like this:
Foo[] fooArray = ...;
Bar[] barArray = Arrays.stream(fooArray).map(object -> (Bar) object).toArray();
Assuming that the given object is assignable to the type you are casting it into. In your case you could turn an Integer array into an object array slightly differently as an integer stream has a different way of mapping objects:
Arrays.stream(intArray).mapToObj(i -> (Object) i).toArray();
Another implementation for the getArray function with flexible handling of primitive types :
public static Object[] createArrayFromArrayObject(Object o) throws XYZException {
if(!o.getClass().isArray())
throw new XYZException("parameter is not an array");
if(!o.getClass().getComponentType().isPrimitive())
return (Object[])o;
int element_count = Array.getLength(o);
Object elements[] = new Object[element_count];
for(int i = 0; i < element_count; i++){
elements[i] = Array.get(o, i);
}
return elements;
}
You could do:
int[] intArray = new int[]{0,1,2,3,14,4};
ArrayList<MyObject> myObjArray = new ArrayList<MyObject>;
for (int i = 0; i < intArray.length; i++) {
myObjArray.set(new MyObject(intArray[i]));
}
You'd need to define a class where the constructor sets the integer parameter to an instance field (in the MyObject class).
You can only cast an object of type derived type, which is handled and passed as base type. In the opposite direction, you can just assign a derived type to a base type:
Object o = new String ("simple assignment");
String s = (String) o;
There in no transformation of the Object going on - it is just demasked as what it is, what it always was.
Integer [] ia = new Integer [] {4, 2, 6};
Object [] oa = ia;
But primitive ints aren't Objects, hence they can't be assigned to an Object array. Casting, however, would, if possible, only play a role in the opposite direction.
None of the answers presented here work with multidimensional arrays, so here's my universal wrapper. It works with arrays of any type and any dimension, and also correctly handles null references (including deeply hidden ones).
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayWrapper {
private static Object[] deepWrap(Class<?> componentClass, Object a) {
if (a == null)
return null;
Object[] result = (Object[])Array.newInstance(componentClass, Array.getLength(a));
if (componentClass.isArray()) {
Class<?> innerCompClass = componentClass.getComponentType();
Object[] b = (Object[])a;
Arrays.parallelSetAll(result, i -> deepWrap(innerCompClass, b[i]));
} else
Arrays.setAll(result, i -> Array.get(a, i));
return result;
}
public static Object[] wrap(Object a) {
if (a == null)
return null;
Class<?> c = a.getClass();
if (!c.isArray())
throw new IllegalArgumentException("Not an array");
int dimension = 0;
do {
dimension++;
c = c.getComponentType();
} while (c.isArray());
if (!c.isPrimitive())
return (Object[])a;
c = Array.get(Array.newInstance(c, 1), 0).getClass();
while (--dimension > 0)
c = Array.newInstance(c, 0).getClass();
return deepWrap(c, a);
}
}
Usage demo:
public static void main(String[] args) {
final int size1 = 5;
final int size2 = 4;
int[][] b = new int[size1][size2];
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
b[i][j] = (i + 1) * (j + 1);
b[1] = new int[7];
b[1][4] = 4;
b[3] = null;
System.out.println(b.getClass().getCanonicalName());
System.out.println(Arrays.deepToString(b));
Integer[][] w = (Integer[][])wrap(b);
System.out.println(w.getClass().getCanonicalName());
System.out.println(Arrays.deepToString(w));
}
Primitive types are not Objects. There is no workaround, you can cast any arrays that contain objects to Object[], but not arrays that contain primitive types.

Categories

Resources