I need to make cast from one type to another. Googled but stucked. Say I want to cast initObject to Casted class.
Object objInstance = initObject.getClass().newInstance();
Casted str=(Casted)objInstance;
Why it make ClassCastException?
Casting requires that Class Casted must be a subclass or subinterface of Class initObject. For example:
List<String> list = new ArrayList<String>();
ArrayList<String> castedList = (ArrayList<String>) list; //works
Integer int = (Integer) list; // throws ClassCastException
An alternative to casting could be a helper method that will convert related objects. Such an example is the Collections.toArray method.
Casting is usually discouraged as you are basically telling the compiler that you know what type the casted object is, and of course you could be wrong.
Related
we can achieve the output in two ways one is typecasting and one is without typecasting
A a=new B() // without typecaste
A a = (A)a// with Typecaste
in both ways we get same output.so, what is the use of typecasting
Let's assume that you have a list of Animals. and you have Tigers and Lions in it.
ArrayList<Animal> animals = new ArrayList<>();
//add some Tigers and some Lions
//sort so Tigers are at the beggining of the list
Tiger t = (Tiger)animals.get(0);
Without casting you will get type missmatch at compile time. With a cast you only risk ClassCastException which can be easy caught with a try-catch
It's just an example of a proper use of class casting in Java.
Casting is for "the opposite direction", i.e. for converting to a expression of a subtype of the original expression.
Example
Given
Object o = "Hello World";
String s = o;
does not compile, but
String s = (String) o;
compiles. This may yield a ClassCastException however, e.g. if a Integer was stored in o.
Casting has different uses. Unfortunately, your example doesn't exercise any useful example of casting since you create an instance of A (a) then cast it to an A.
What you need to understand is there are apparent types and actual types. An apparent type would be List<T> list;. Here we see that it's a list. But the actual type might be an ArrayList<T> (List<T> list = new ArrayList<>();). In this scenario we can, with care, cast the apparent type to the actual type. This would allow us to then use the functionality of the actual type. For example, let's look at some code; given:
List<Integer> list = new ArrayList<>();
ArrayList<Integer> aList;
LinkedList<Integer> lList = new LinkedList<>();
We can do this without issue (although dangerous in general)...
// Dangerous but OK with a cast
// list might not be an ArrayList
aList = (ArrayList<Integer>) list;
// Use ArrayList methods
aList.trimToSize();
list = lList;
LinkedList<Integer> danger = (LinkedList<Integer>) list;
...but it's also possible to do:
aList = (ArrayList<Integer) list;
// Use ArrayList methods
aList.trimToSize();
// list = lList;
LinkedList<Integer> danger = (LinkedList<Integer>) list;
The last snippet results in a ClassCastException because list isn't a LinkedList.
Casting goes beyond that though. Consider when you have two integers you want to divide. Without a cast you could end up with an integer result where a floating point is more appropriate. Consider:
int i = 2;
int j = 3;
System.out.println("No cast: " + i/j + " ;With cast: " + (double)i/j);
Output:
No cast: 0 ;With cast: 0.6666666666666666
So, it depends on the use case.
A a = new B();
will only works if B inherit from A.
If B inherit from A, the type cast is not required as B is a A. Type cast will be necessary if you need to type cast to a subclass:
A a = new B();
B b = (B) a;
While this would be illegal :
A a = new A();
B b = (B) a;
as a is not a B.
Java implicitly upcast with assignment, so in the code you've provided the casting operator is redundant; a is already of type A:
A a = new B(); // without typecast operator (implicit upcast)
A a = (A)a; // with redundant typecast operator
One reason to have a casting operator is that you may also wish to downcast (which is not done implicitly in Java). For instance, when a is a type A reference to an object of class B (e.g. when B is a subclass of A) one may need to downcast to access certain methods:
A a = new B(); // implicit upcast
C c = ((B)a).methodOfBOnly(); // explicit downcast
You may also want to check this question on why Java doesn't do implicit downcasting.
There can be times when upcasting needs to be done explicitly as well. For instance, if a class contains overloaded methods
C method(A x){/*does one thing*/}
C method(B x){/*does another*/}
and assuming b is of type B, the calls to method((A)b) and method(b) would behave differently.
A a=new B()
is applicable only when class B extends class A. In this way the extra methods that are available in class B other than class A will be available with reference a.
When you do this
A a = (A)a
Then actually you are down casting the object of class B into an object of class A. And it is true that child can be type cast to parent. After this statement the reference a will not be able to call any method of class B which were not in class A because now the reference a points to an object of class A.
It is useful in many scenarios.
For example, you want to have a collection of Objects that point to same base class. Instead of maintaining separate collections for each sub class, you maintain a single collection of base class. And then when you want to use any child object you type cast the base class object to child class object to do that.
ArrayList<Base> children = new ArrayList<Base>();
children.add(new Child1());
children.add(new Child2());
Console.WriteLine(((Child1)children.get(0)).getChildName());
Console.WriteLine(((Child2)children.get(1)).getChildName());
Now base class does not have any method named getChild1Name or getChild2Name. And you need to typecast object of base class to respective child class to do that.
Hello I have a few questions regarding type casting and inheritance. I have been doing some reading and I understand the point and basics of type casting. However, I don't fully understand where I can and can't use it.
Consider this class:
class A{
public A(){}
}
A temp = new A();
temp = (Object)temp;
This code gives me the error "Cannot convert from type Object to type A". However, wouldn't this be converting from type A to type Object? Can you not type cast up the hierarchy?
Now my second question regards inheritance and such.
When you type:
Object temp = new A();
what is really happening? Is temp an A or is it an Object?
Here the excerpt from JLS 8.1.3:
If the class declaration for any other
class has no extends clause, then the
class has the class Object as its
implicit direct superclass.
Of course, Object itself is a bit special (JLS):
Each class except Object is an
extension of (that is, a subclass of)
a single existing class (§8.1.3) and
may implement interfaces (§8.1.4).
Every Class is a descendant of Object.
In your case, you are trying store an object of A into a Class object called A. This isn't going to work. You need to do:
Object testObject = (Object)temp;
This will store the Object into testObject, which has the type Object that you casted to.
Here it is working on ideone.
It's just because you can't assign superclass object to the subclass reference.
So you can't do:
temp = (Object)temp;
because it's the same as:
Object newObject = new Object();
A temp = newObject;
You will get the same compile error here.
Of course you can do something like that:
Object newObject = new Object;
A temp = new A();
newObject = temp;
You can do it because you can assign subclass to the superclass reference
The problem is in the last line. First you promise Java that temp is of type Object by the statement:
(Object) temp
Afterwards you try to assign an object that the compiler thinks is of type Object to a variable that should be of type A. So to conclude, the part where you cast temp to type Object is fine, the problem is when you afterwards try to assign it to a variable expecting something of type A.
For your second question, temp is an A. When creating an object with the new keyword, the type of the object will always be whatever comes right after. In your case A. Afterwards you then assign temp to a variable of type Object, but that does not change the actual type of temp. Having a variable of some type X just tells you that whatever the variable is pointing to is a subtype of X.
A a = (Object)temp;
"Cannot convert from type Object to type A". However, wouldn't this be converting from type A to type Object? Can you not type cast up the hierarchy?
You are correct that
(Object)temp;
is converting temp, which is an A to an Object. However, that's not what the compiler is complaining about. Now that you have, effectively,
A a = anObjectNOTAnA
(A = ... is invalid code. I've changed it to A a = ....)
It's saying that you cannot convert an Object back to an A, unless you explicitely cast it and potentially suppress the unchecked-cast warning:
A a = (A)anObjectNOTAnA
or
#SuppressWarnings("unchecked")
A a = (A)anObjectNOTAnA
Regarding your other question:
Object temp = new A();
What is really happening? Is temp an A or is it an Object?
When you cast an object of any type, it never changes the actual type of the underlying object. A new A() is always an A, whether its
A a = new A();
or
Object objButReallyA = new A();
or
#SuppressWarnings("unchecked")
A a = (A)((Object)new A());
If an A is stored in an Object, it's just a different "view" of the same object. In order to use the A specific functions, however, you must first revert it back to the A view:
objButReallyA.getAOnlyField(); //compile error
((A)objButReallyA).getAOnlyField(); //Okay
I'm currently trying to populate an array of of objects of the type Stipulations which is a class which is an
public abstract interface
My method of populating this array is as follows where popStipAttr is a simple switch statement.
public static Stipulations[] popStipArr(ZASAllocation zasAlloc)
{
//ArrayList<String> s = new ArrayList<String>();
ArrayList<Stipulations> stipAL = new ArrayList<Stipulations>();
for(int i = 0; i < NoStip; i++)
{
stipAL.add(popStipAttr(i,zasAlloc));
}
Stipulations[] StipArr = (Stipulations[]) stipAL.toArray();
return StipArr;
}
However I get the error about casting:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Lc.Stipulations;
What exactly am I doing wrong here I created the arraylist of the same type, why would coverting it to an array of that type throw this?
ArrayList.toArray returns an Object[] (which, as stated in the message, can't be cast to Stipulations[]). ArrayList.toArray(T[] a) however, returns a T[]. Thus, change
Stipulations[] StipArr = (Stipulations[]) stipAL.toArray();
to
Stipulations[] StipArr = (Stipulations[]) stipAL.toArray(new Stipulations[0]);
^^^^^^^^^^^^^^^^^^^
Oh, right. Just realized what may have caused the confusion. The leading [ in [Ljava.lang.Object; indicates that it is an array. Same for [Lc.Stipulations;. Perhaps that's why you wrote Casting from type object to a class as title :-) Now you know anyway :-)
What you are doing in
Stipulations[] StipArr = (Stipulations[]) stipAL.toArray();
is calling the method on the java.util.List class
Object[] toArray();
which is returning you an Object[] which cant be cast to your Stipulations[]
What you want to be calling is the method on java.util.List
<T> T[] toArray(T[] a);
which will return you the array with your type.
So try
Stipulations[] StipArr = stipAL.toArray(new Stipulations[stipAL.size()]);
It is a strange syntax which tends to pollute the code and for this reason and a few others I always try to use Lists where possible and never convert to and from Arrays unless absolutely necessary like an external API not under my control requires it
Note: purely out of curiosity and not for any actual use case.
I'm wondering if there is a way to declare the Class Class object with valid type parameters:
Class cc1 = Class.class; //raw type
Class<Class> cc2 = Class.class; //now parameter is raw type
Class<Class<?>> cc3 = Class.class; //compile error: inconvertible types
If Class and Class<?> are interchangeable, why are Class<Class> and Class<Class<?>> not?
EDIT: the question can be generalized to an issue of nested raw type parameters. For example:
ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList>(); //same compile error
EDIT2: I should rephrase the question a little: I know that
Class<?> c = Class.class;
is valid but I'm wondering why Class<Class> is not the same as Class<Class<?>>
Generics have some pretty serious limitations. In this case you can't assign a type to the inner type of Class<Class> because you're actually referencing the raw type, not an implementation of the raw type. It will give you a warning, but you have no way to fix that warning.
Class<Class<?>> by itself isn't an inconvertible type, you just can't assign a class directly to it because it doesn't have the type Class<Class<T>>, it has the type Class<T>.
Think of it another way; try List<List<String>>. To create that, you need to create a List that takes a List of Strings. This works because lists can contain lists.
A Class is more like a primitive than a data object, so I don't think it'd be possible to create a Class that is of type Class of something else.
Edit: your extra question about ArrayList<ArrayList<?>> is a more obvious example of the inconvertible type issue you're having with Class<Class<?>>.
The rule here is that the generic type in the left side must match the generic type in the right side.
Class<?> means a class of any type.
Class<?> c = Class.class;
Works because Class of any type can be Class<Class>.
Class<Class<?>> cc3 = Class.class;
Do not work because Class.class type is Class<Class> which is not of type Class<Class<?>>
ArrayList<ArrayList<Integer>> lst = new ArrayList<ArrayList<Integer>>();
ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList<?>>();
Works because the two expressions match.
ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList>();
Don't match.
It's kind of difficult to see exactly what you're asking (or what you're trying to do).. but you can parametrize without raw types.
Class<? extends Object> cc4 = Class.class; // no raw types
Class<?> cc5 = Class.class; // also an option
As far as your last example is concerned, it makes no sense because it appears you want to make an array list of array lists that hold ?, but your declaration isn't declaring an array list of array lists that hold ?.
Properly written (but still not proper Java) would be:
ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList<Integer>>(); // Type mismatch
Which is expected. It doesn't work for the same reason something like the following doesn't work:
Object o = new Object();
Integer i = new Integer(3);
o = i;
i.floatValue();
o.floatValue(); // can't access that method, we need to specifically cast it to Integer
Java types aren't proactively inferred (even in an inheritance chain).
If you want to keep the wildcard in there, you're welcome to, though:
ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList<?>>(); // works!
I don't think I really understand Java generics. What's the difference between these two methods? And why does the second not compile, with the error shown below.
Thanks
static List<Integer> add2 (List<Integer> lst) throws Exception {
List<Integer> res = lst.getClass().newInstance();
for (Integer i : lst) res.add(i + 2);
return res;
}
.
static <T extends List<Integer>> T add2 (T lst) throws Exception {
T res = lst.getClass().newInstance();
for (Integer i : lst) res.add(i + 2);
return res;
}
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - incompatible types
required: T
found: capture#1 of ? extends java.util.List
For the second method to compile, you have to cast the result of newInstace() to T:
static <T extends List<Integer>> T add2 (T lst) throws Exception {
T res = (T) lst.getClass().newInstance();
for (Integer i : lst) res.add(i + 2);
return res;
}
Regarding the difference between the two methods, let's forget about the implementation, and consider only the signature.
After the code is compiled, both methods will have exactly the same signature (so the compiler would give an error if the have the same name). This happens because of what is called type erasure.
In Java, all the type parameters disappear after compilation. They are replaced by the most generic possible raw type. In this case, both methods will be compiled as List add2(List).
Now, this will show the difference between the two methods:
class Main {
static <T extends List<Integer>> T add1(T lst) { ... }
static List<Integer> add2(List<Integer> lst) { ... }
public static void main(String[] args) {
ArrayList<Integer> l = new ArrayList<Integer>();
ArrayList<Integer> l1 = add1(l);
ArrayList<Integer> l2 = add2(l); // ERROR!
}
}
The line marked as // ERROR! won't compile.
In the first method, add1, the compiler knows that it can assign the result to a variable of type ArrayList<Integer>, because the signature states that the return type of the method is exactly the same as that of the parameter. Since the parameter is of type ArrayList<Integer>, the compiler will infer T to be ArrayList<Integer>, which will allow you to assign the result to an ArrayList<Integer>.
In the second method, all the compiler knows is that it will return an instance of List<Integer>. It cannot be sure that it will be an ArrayList<Integer>, so you have to make an explicit cast, ArrayList<Integer> l2 = (ArrayList<Integer>) add2(l);. Note that this won't solve the problem: you are simply telling the compiler to stop whining and compile the code. You will still get an warning (unchecked cast), which can be silenced by annotating the method with #SuppressWarnings("unchecked"). Now the compiler will be quiet, but you might still get a ClassCastException at runtime!
The first one is specified to accept a List<Integer> and return a List<Integer>. List being an interface, the implication is that an instance of some concrete class that implements List is being passed as a parameter and an instance of some other concrete class that implements List is returned as a result, without any further relationship between these two classes other than that they both implement List.
The second one tightens that up: it is specified to accept some class that implements List<Integer> as a parameter, and return an instance of exactly that same class or a descendant class as the result.
So for example you could call the second one like so:
ArrayList list; // initialization etc not shown
ArrayList result = x.add2(list);
but not the first, unless you added a typecast.
What use that is is another question. ;-)
#Bruno Reis has explained the compile error.
And why does the second not compile, with the error shown below.
The error shown is actually reporting that you have tried to run code that failed to compile. It is a better idea to configure your IDE to not run code with compilation errors. Or if you insist on letting that happen, at least report the actual compilation error together with the line number, etc.
"I don't think I really understand Java generics."
Nobody does...
The issue is related to the interesting return type of getClass(). See its javadoc. And this recent thread.
In both of your examples, lst.getClass() returns Class<? extends List>, consequently, newInstance() returns ? extends List - or more formally, a new type parameter W introduced by javac where W extends List
In your first example, we need to assign W to List<Integer>. This is allowed by assignment conversion. First, W can be converted to List because List is a super type of W. Then since List is raw type, the optional unchecked conversion is allowed, which converts List to List<Integer>, with a mandatory compiler warning.
In the 2nd example, we need to assign W to T. We are out of luck here, there's no path to convert from W to T. It makes sense because as far as javac knows at this point, W and T could be two unrelated subclass of List.
Of course, we know W is T, the assignment would have been safe if allowed. The root problem here, is that getClass() loses type information. If x.getClass() returns Class<? extends X> without erasure, both of your examples will compile without even warning. They indeed are type safe.
Generics are a way to guarantee type safety.
Eg:
int[] arr = new int[4];
arr[0] = 4; //ok
arr[1] = 5; //ok
arr[2] = 9; //ok
arr[3] = "Hello world"; // you will get an exception saying incompatible
types.
By default arrays in Java are typeSafe. An integer array is only meant to
contain integer and nothing else.
Now:
ArrayList arr2 =new ArrayList();
arr2.add(4); //ok
arr2.add(5); //ok
arr2.(9); //ok
int a = arr2.get(0);
int b = arr2.get(1);
int c = arr3.get(2);
You willa gain get an exception like what it is not possible to cast Object
instance to integer.
The reason is that ArrayList stores object and not primitive like the
above array.
The correct way would be to explicitly cast to an integer.You have to do this
because type safety is not yet guaranteed.
eg:
int a = (int)arr2.get(0);
To employ type safety for collections, you simply specify the type of objects that your collection contains.
eg:
ArrayList<Integer> a = new ArrayList<Integer>();
After insertion into the data structure, you can simply retrieve it like you
would do with an array.
eg:
int a = arr2.get(0);