In Java, will using Class.forName in a cast result in the object being cast to a class or being cast to the cast found. As an example, if you did this
Object a;
String b = "testing";
a = (Class.forName("java.lang.Object")) b;
Would a be an instance of Class or an instance of Object?
Class.forName returns a Class instance. I'm fairly certain your code as quoted doesn't compile, you're trying to use a function call as a cast.
Update: Just had a thought: If you're asking how to use a dynamically-loaded class in a cast, you basically can't. Casting is (mostly) a compile-time thing. Have the dynamically-loaded class implement an interface you can compile into your code and then cast to that, or if you can't do that, use reflection to access the dynamically-loaded class' members.
You can cast with the class object's .cast method:
Object a;
String b = "testing";
a = Class.forName("java.lang.Object").cast(b);
But you seem to have wrong ideas about casting - in Java, casting does not change any object, it just tells the compiler that the object is of some type, and on runtime, the VM will test if this is really the case (if the compiler can't already prove it). If you "cheated", the VM will throw an ClassCastException here (it will not convert your object).
(It works a bit different if primitive types are involved.)
The Class object's cast method is a generic variant of this same mechanism. Since it has the return type T (from Class<T>), this allows generic code to cast an unknown object to some class type, where this class object corresponds to a type variable.
This will not help you here - the return type of Class.forName is Class<?>, which means that its cast method can only return Object.
And anyway, casting to java.lang.Object has no effect (it will always succeed), other than hiding the to the compiler that the value has some specialized type. (This might matter if you have overloaded methods.)
Simply writing
Object a;
String b = "testing";
a = b;
has the same effect here.
If it is required to cast an instance this is a way to do it
String className = "YourClass";
Class someClass = Class.forName( className );
Constructor constructor = (Constructor) someClass.getConstructor();
Object someInstance = constructor.newInstance();
// now you can cast as allways.
(YourClass) (someInstance)
Class.forName always returns the Class.
Related
I accidentally found that this works:
Class<?> a;
a = int.class;
System.out.println(a); // int
a = Integer.class;
System.out.println(a); // class java.lang.Integer
What does it really mean / do for primitives?
I tried and neither List<int> nor List<int.class> works (yeah, I know I have to use Integer). Also, obviously, I can't invoke getClass() on primitives, so it's useless for type checking of any sort.
In what situation would I use int.class and why is it even present in the language?
You would use it when you are trying to locate a method having an int argument via the reflection API.
From the specs:
The type of p.class, where p is the name of a primitive type
(§4.2), is Class<B>, where B is the type of an expression of
type p after boxing conversion (§5.1.7).
And
A class literal evaluates to the Class object for the named
type (or for void) as defined by the defining class loader
(§12.2) of the class of the current instance.
So how about
Class<Integer> a = int.class;
When to use: Lots of reflection use cases (for instance in argparse4j they use it to map from command line parameters to methods).
I am trying to cast an object to its superclass using Java.lang.Class.cast but I get the same object. What can be the reason?
This is the code I'm running:
public static void parse(Object obj)
{
// parse all super classes
Class<?> clazz = obj.getClass().getSuperclass();
if (!clazz.equals(prevClass))
{
prevClass = clazz;
Object castedObj = clazz.cast(obj);
parse(castedObj);
}
fillObject(obj);
}
but when passing to parse an object of dynamic type B, where B extends A, castedObj is equal to obj.
But I want castedObj to be a new object of dynamic type A because the parse method relies on that fact (iterates on the fields of the dynamic type class).
I am trying to cast an object to its superclass using Java.lang.Class.cast but I get the same object.
That is exactly what is supposed to happen.
For reference types, a cast is simply a type check. For example:
A a = (A) b;
This says to check that b is-a A and the assign the reference so that we can refer to it as an A using a.
There is no object conversion going on. No creation of new instances. The value assigned to a is identical in every respect to the value in b.
The same also applies when you use reflection to do the typecasting.
Or to put it another way, the value returned by getClass() for a given object is always going to be the same ... no matter how you cast is.
It is not clear what you are trying to do in your code, but it we assume that fillObject is filling in fields that relate to a particular class, then you most likely need to pass the Class as an explicit parameter. The true class of obj is always going to be the object's actual class ... irrespective of any casting.
I have been reading the answers to the question:
Create instance of generic type in Java?
I have implemented the approach suggested by Lars Bohl. I adapted his code as follows:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class ParameterizedTypeEg<E> {
public Class<E> getTypeParameterClass() {
Type type = getClass().getGenericSuperclass();
ParameterizedType paramType = (ParameterizedType) type;
return (Class<E>) paramType.getActualTypeArguments()[0];
}
private static class StringHome extends ParameterizedTypeEg<String> {
private String _string;
StringHome (String string) {
_string = string;
}
}
public static void main(String[] args)
throws InstantiationException, IllegalAccessException {
String str = new StringHome("my string").getTypeParameterClass().newInstance();
String str2 = new ParameterizedTypeEg<String>().getTypeParameterClass().newInstance();
}
}
This approach works fine for the str variable. Then str2 is created with what appears to me to be the same type (ParameterizedTypeEg < String >, which is basically the same thing as a StringHome). However, the approach does not work for str2, and a ClassCastException is thrown when I try to cast (ParameterizedType) type.
Even though for str2, I have parameterized ParameterizedTypeEg with a String, getGenericSuperclass() returns something very different than for str. Also, within methods str2 shows 'this' as a ParameterizedTypeEg, whereas for str, 'this' is a ParameterizedTypeEg$StringHome. I suppose that is the root of the problem. Why does Java not see that the generic type has been determined for str2 also?
I have had what appears to be the same problem when the parameterized type is passed through multiple levels of hierarchy? That is, class B< T > contains A< T > and I instantiate a B. Within A, I cannot create a String object by determining the parameterized type of A using the above approach. The approach produces an exception in the case of a containment hierarchy as well. And this causes me a problem because I want to be able to pass the parameterized type through multiple levels of containment and/or inheritance and have the same approach produce an instance of the generic type in all cases.
Thanks,
John
With the following change your code will work:
from
String str2 = new ParameterizedTypeEg<String>().getTypeParameterClass().newInstance();
to
String str2 = new ParameterizedTypeEg<String>(){}.getTypeParameterClass().newInstance();
This creates an anonymous subclass of ParameterizedTypeEg. When you call
getClass().getGenericSuperclass();
on StringHome, you get a ParameterizedTypeEg < java.lang.String>, which is what you want. If you create str2 as you did, that call simply returns Object, so the attempt to cast it to a paremeterized type fails:
Exception in thread "main" java.lang.ClassCastException:
java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
Creating an anonymous subclass makes this return ParameterizedTypeEg < java.lang.String>
This is the same trick that's used in the Type Token class in the Google Guice Guave libraries, btw. You write, for example
new TypeToken<List<String>>() {}
and not
new TypeToken<List<String>>()
However, the approach does not work for str2, and a ClassCastException
is thrown when I try to cast (ParameterizedType) type........... Why
does Java not see that the generic type has been determined for str2
also?
As specified in oracle doc for ParameterizedType:
ParameterizedType represents a parameterized type such as
Collection<String>
But, super class of ParameterizedTypeEg is Object , which is not Generic Type. So, the Type returned by getClass().getGenericSuperclass(); is Class of Object itself. And type casting of non parametrized type to the ParameterizedType is giving you ClassCastException for str.
Why does Java not see that the generic type has been determined for
str2 also?
An object at runtime does not have any type parameter information. Basically, for you to do .newInstance() to create an object, you need to have the class object at runtime, which means you have to store it somewhere in a way to get it.
The reason it works for str is exactly because the type String is stored somewhere -- in the class metadata. Classes have metadata which includes the superclass and superinterfaces, enclosing class if it's an inner class, and the types of fields and methods (return type and parameter types of methods). All this information is stored, with generics, in the bytecode at runtime (the reason for this is that files in Java can be compiled separately, so when compiling one file that uses a class from an already compiled file, the compiler must be able to look at the class file and see the generics information), and is available at runtime via reflection on the class object.
So basically, the StringHome class acts as a "storage" for the String class object, because String was hard-coded as the type parameter of its superclass at compile-time. So at runtime you can get it out of this "storage".
That is, class B< T > contains A< T > and I instantiate a B. Within A,
I cannot create a String object by determining the parameterized type
of A using the above approach.
From my discussion above, you probably picked up that the key thing is to somehow "get" at runtime the class object for the class that is T. Making a class that subclasses A<T> will not help, because the point of that was that the actual class was hard-coded at compile-time, which requires knowing the class at compile-time. We don't know what class T is at compile-time, so we can't put it into the metadata; we can only put "T", i.e. a type variable.
So, again, the problem goes back to needing to find some way to pass or transmit the class object for the class that the type parameter represents. You cannot rely on any compile-time based mechanisms anymore. So you have to pass it in in an extra parameter or something.
getClass().getGenericSuperclass(); gives you the details of the super class. Therefore it will only work if you subclass a parameterized super class. It won't work if you instantiate a parameterized super class given type parameters.
class Person { void f() {} }
class Student extends Person { void f() {} }
So when I execute the following code:
Person p = new Student();
((Person) p).f();
Why is the f() function in the Student class called when the variable is cast as a Person? I understand why the f() function is called when it is just p.f(), but I guess I'm just confused to what exactly the cast does.
This is one of the cornerstones of Object Oriented: Polymorphism. You have all kinds of Person entities each doing f() in its own way! It is the actual instance of the object and not what you cast it to that does f().
You can always convert subtypes to Type this casting is always allowed in java however because instance is of subtype subtype methods will get executed.
You can check Here for more information
In Java there are two types of reference variable casting:
Downcasting: If you have a reference variable that refers to a subtype object, you can assign it to a reference variable of the
subtype. You must make an explicit cast to do this, and the result is
that you can access the subtype's members with this new reference
variable.
Upcasting: You can assign a reference variable to a supertype reference variable explicitly or implicitly. This is an inherently
safe operation because the assignment restricts the access
capabilities of the new variable.
Yes, you need to implement the interface directly or indirectly to enable assigning your class object reference to the interface type.
When invoking methods, it will be always executed on object type, not reference type due to ploymorphsim.
The same method -- the one in Student -- will be called whether or not you've cast the Student to a Person.
Up-casting a reference (from subclass to superclass) serves no real function (and in fact will generally be a no-op internally). Down-casting, on the other hand, tells the JVM that you believe the superclass to be of the specified subclass, and if it's not a cast error will be raised.
(I'll give gefei credit for pointing out an omission above: The cast ALSO tells the compiler the type, and the compiler uses this information to know what methods and fields the object (supposedly) has. This is not strictly necessary to compile a Java program to bytecodes, but it does allow the compiler to do the usual compile time validity checks.)
The upcasting is irrelevant here. The overridden method will always be called if present.
The cast in your example is totally useless. The compiler knows that p is of type Person. More interesting would be a narrowing cast:
Person p = getPerson();
if (p instanceof Student) {
Student s = (Student) p;
// do something Student-specific with s
}
Casting reference types in Java does not change the nature of the object; it only tells the compiler what assumptions can be made about the object. At run time, the object's actual type is used to determine what method is called. (Note that this is not true of primitive types; casting an int to a byte will change the data.)
I've a method in which I'm passing a generic argument. To execute one required method I need the class instance of the same. How can I get it.
There is a workaround which I'm using but I want to know how can we get the Class instance.
The snippet I'm using is:
public <T> T readModelWithId(Class<T> c, Serializable pk) {
// Some code here.
T t = (T)session.get(c, pk);
// Some code here.
return t;
}
The problem is that I don't want to pass the Class instance in this method as it is same as the return type T which is of generic type.
There's no way you can get to something like T.class within that method, so you must pass the class argument since you need it to get your model object from the session.
Moreover, this adds a bit of extra "type-safety". You will force the caller to specify the return type as an argument, so the returned type will not just be "anything a caller may expect" (although I agree this makes it redundant).
You can't do it because Java implements Generics using "type erasure".
http://docs.oracle.com/javase/tutorial/java/generics/erasure.html
Looks like you are doing a generic DAO. I've done something similar here:
http://www.matthews-grout.co.uk/2012/01/my-generic-hibernate-dao.html
You cannot do anything with generics that you could not do with non-generics with casts. Consider the non-generic version of your code:
public Object readModelWithId(Class c, Serializable pk) {
// Some code here.
Object t = session.get(c, pk);
// Some code here.
return t;
}
Now ask the same question, can you get rid of the class instance argument c?
Generics are more for compile time type safety - you need class instance so compiler does not complain about missing cast. Alternatively you can ditch generics altogether and cast result