Every object in Java belongs to a certain class. That's why the Object class, which is inherited by all other classes, defines the getClass().
getClass() method returns the instance of Class class.
For example:
class Foo{}
class Sample{ class Foo instance = Foo(); Class obj = instance.getClass(); }
Another way of getting the instance of Class class is by saying Foo.class
My question:
I can see the definition of getClass() in Object class source code(File Object.java package java.lang). In which source file, can i see the member class which we are using as Foo.class?
No source file. class is a keyword (like this, instanceof, etc), not a member of any class, and is handled by the compiler, not in code.
If an instance of an object is available, then the simplest way to get its Class is to invoke Object.getClass()
Foo foo=new Foo();
Class c = foo.getClass();
If the type is available but there is no instance then it is possible to obtain a Class by appending .class to the name of the type. This is also the easiest way to obtain the Class for a primitive type.
boolean b;
Class c = boolean.class;
and this would produce compile-time error
Class c = b.getClass();
because a boolean is a primitive type and cannot be dereferenced
And for something like this
Foo foo=null;
note that you cannot use foo.getClass() in this case since it is not instantiated.
And finally for something like this
Foo foo=new FooChild();
Class c= foo.getClass(); //returns FooChild, evaluates at runtime
Class c= Foo.class;// returns Foo , evaluates statistically at compile-time.
Edit:- For .class its a static field inside every primitive type, static Class<Integer> ,The Class instance representing the Integer. you can see it here for Integer , here for Boolean. boolean, byte, char, short, int, long, float, and double all of them have a Class static field because like i said its always going to stay same and primitive types cannot be cannot be dereferenced. To see the source, if you see source of Integer you can see the class field as public static final Class<Integer> TYPE = (Class<Integer>) VMClassLoader.getPrimitiveClass('I'); , see here line 82. You can search and see for others too.
Related
Test test1 = new Test();
here, new Test() means create new instance of class Test and assign it
to reference test1.
Class<Test> test2 = Test.class;
Test test2Instance = test2.newInstance();
I am not able to define (in words) 1st statement. On the other hand 2nd statement it pretty clear to me.
EDIT
String is an instance of the class Class.
A string literal (e.g. "I am a string.") is an instance of the class
String.
class literal (e.g. Hashtable.class) is an instance of the class
Class.
Class<Test> test2 = Test.class;
This statement declares a variable named test2, of type Class<Test>. It initializes this variable with the unique instance of this type, using the class literal expression Test.class which refers to the class Test.
Class<Test> test2 = Test.class;
means "give me the Class object representing the Test class and store it in the variable test2.
Aside from Class being generic, this has little to do with generics. It's about class objects.
Class<Test> is a specific type of a generic type. Literally you are defining a variable test2 which is of type Class<T> with T == Test.
Class<T> is a parametric type, it depends on T, if you add the constraint T == Test then you are talking about a variable of Class<Test> (which is a specific different type).
It's orthogonal compared to polymorphism by subtype. If you have
class Base { .. }
class Derived extends Base { .. }
and you write
Derived derived = ...
You have no problems in stating that you are declaring a variable named derived of type Derived. This is the same thing, but Class<Test> is not a subtype of Class<T> but a specialization of it.
I'm wondering what specifically allows an object of one class to be cast as another class. Looking at the Class.isInstance(Object obj) javadoc, it suggests that an object has to be 'assignment-compatible' with another class in order to be cast to that class. But what constitutes 'assignment-compatible'?
I'm trying to figure out how the following returned a ClassCastException:
public class A
{
multiple private attributes
No constructor
multiple public methods
}
public class B extends A
{
blank default constructor
2 additional private attributes
4 additional public getter / setter methods for these attributes
}
The line
B b = (B)variable.getA() // where getA() returned an instance of class A
returns a ClassCastException A cannot be cast as B. I know that casting from a parent class to a subclass is a bad idea. I did not write the code in question, I'm just looking at it in a production support capacity.
Class B is the only class in the codebase that extends from A. So the result of getA() is not an object of another subclass of A (say C) cast to A.
So why in this instance can Java not cast an object of class A to the seemingly compatible class B?
Consider these two cases:
A a = new B();
B b = (B)a; <-- Ok.
A a = new A();
B b = (B)a; <-- ClassCastException
So in order to cast an object to B it must be an instance of B (or a subclass of B).
In your case it is however an instance of A.
The javadoc for Class.isInstance(Object obj) gives the definition of assignment compatible:
Specifically, if this Class object represents a declared class, this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses); it returns false otherwise. If this Class object represents an array class, this method returns true if the specified Object argument can be converted to an object of the array class by an identity conversion or by a widening reference conversion; it returns false otherwise. If this Class object represents an interface, this method returns true if the class or any superclass of the specified Object argument implements this interface; it returns false otherwise. If this Class object represents a primitive type, this method returns false.
Basically, you can assign an object of type A to variable of type B if type A extends or implements type B.
Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance. For example, the following code generates a ClassCastException:
Object x = new Integer(0);
System.out.println((String)x);
more info here and here.
If we replaced A and B with meaningful names that help us think about the problem, then the answer becomes clearer. If A becomes Mammal and B is Dog, then we can reasonably say that all Dogs are Mammals, but we cannot say that all Mammals are Dogs. Even if they superficially shared the same attributes, there is no guarantee that all Mammals would fulfill the contract of being a Dog, and the compiler shouldn't try to assume so.
Just wanted to add the official specification to support
Ricardo's correct answer that "you can assign an object of type A to variable of type B if type A extends or implements type B":
The JLS defines assignment-compatibility as follows:
5.2. Assignment Contexts
If the type of an expression can be converted to the type of a variable by assignment conversion, we say the expression (or its value) is assignable to the variable or, equivalently, that the type of the expression is assignment compatible with the type of the variable.
The term "assingment conversion" is only defined as applying the appropriate conversion from the list given in the "Assignment Contexts"-chapter:
The term "conversion" is also used to describe, without being specific, any conversions allowed in a particular context. For example, we say that an expression that is the initializer of a local variable is subject to "assignment conversion", meaning that a specific conversion will be implicitly chosen for that expression according to the rules for the assignment context.
The most relevant for reference types being
5.1.5. Widening Reference Conversion
A widening reference conversion exists from any reference type S to any reference type T, provided S is a subtype of T (§4.10).
Subtypes include implemented interfaces (see 4.10.2. Subtyping among Class and Interface Types ).
There are additional rules for numeric and generic types, but they are not relevant for the example given in the question.
Consider sample code below
public class Test {
public static void main(String args[]) {
Test t = new Test();
Class c2 = Test.class;
System.out.println(c2);
}
}
Test.class statically evaluates and returns compile time Class object. Looking at the Test.class syntax it looks like the variable class is of type java.lang.Class and is static and public. My question is where is this variable defined? It is not present in Test class (because I don't declare it) neither it is in the java.lang.Object class.
I saw an analogous method public final native Class<?> getClass();. This is present in java.lang.Object and is a native java method. This method returns the runtime Class of an object.
So my question is where is this public & static class variable defined?(Please correct me if I have mistaken) Is it again some native implementation? This is set at compile time and being static needs no class instance to be created. So if even this is some native implementation is it initialized by registerNatives() method in java.lang.Object?
These are called class literals and are defined by the language itself as per JLS §15.8.2 (there is no "class member"):
A class literal is an expression consisting of the name of a class, interface, array, or primitive type, or the pseudo-type void, followed by a '.' and the token class.
The type of C.class, where C is the name of a class, interface, or array type (§4.3), is Class<C>.
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).
The type of void.class (§8.4.5) is Class<Void>.
One indication that these constructs are intrinsically built into the language is that they even work with primitives!
System.out.println(int.class);
System.out.println(double.class);
// etc.
class is not normal static variable. It's a language construct which is replaced at compilation time.
Because class is a keyword it wouldn't even be possible to declare a variable with that name.
Your assumption that class is a static field of class Class is not exact. Assume that this is correct. In this case the value of this field will be exactly the same for all classes that is wrong.
Although MyClass.class syntactically looks like access to static field it is just a special syntax of language. Think about this as a kind of operator.
Probably JVM creates some kind of synthetic class that wraps real class and has such field but it is just an assumption about internal representation of classes in JVM.
In my textbook I can read:
If T is any Java type, then T.class is the matching class object. For example:
Class cl1 = Date.class; // if you import java.util.*;
Class cl2 = int.class;
Class cl3 = Double[].class;
Later on I'm reading:
The virtual machine manages a unique Class object for each type. Therefore, you can use the == operator to compare class objects. For example:
if (e.getClass() == Employee.class)
Could you help me find anything about this .class field in the documentation.
And another qutstion - I can't understand whether the e.getClass() == Employee.class is the same as e.class == Employee.class. I mean, if it is the same, why the author of the textbook used getClass here in the lefthand expression.
From JLS §15.8.2 - Class Literals:
A class literal is an expression consisting of the name of a class, interface, array, or primitive type, or the pseudo-type void, followed by a '.' and the token class.
The type of C.class, where C is the name of a class, interface, or array type (§4.3), is Class.
So, Date.class, int.class are nothing but class literals, which give appropriate Class objects for a class type.
I can't understand whether the e.getClass() == Employee.class is the same as e.class == Employee.class
No, they are not the same. In fact, e.class won't even compile. As per the definition of class literal above, since e is not a type but an object of Employee (I assume that), e.class is not a valid class literal. To get the Class object of a class, using it's instance, you need to use Object#getClass() method.
So, e.getClass() and Employee.class are two different ways to obtain the Class object for Employee class. Both to be used in different circumstances. When you know the class type, use 2nd version, and when you have an instance of your class, use the 1st version.
However, note that in case of inheritance, e.getClass() might not return the same Class object as Employee.class. The former would return the Class object of the actual subclass object, referred by the reference e, whereas the later would always give you Class<Employee>.
If you neither have the instance, nor the class type available, then you can also get the Class object for a class name in String form, using - Class#forName(String) method.
How you get a Class object depends on what you already know. If you have an object referenced by x, you can obtain the Class object for its class by x.getClass(). If you know, when you are writing your code, the name of a type T, you can use T.class to get the class object. There is a third approach, less convenient, that only requires run time access to the class name.
The getClass method is described as one of the Object methods, in the Object API documentation.
Class literals, the T.class form, are described in the Java Language Specification.
The third approach uses one of the static forName methods defined the API documentation for java.lang.Class.
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.