From the JLS (§15.8.2):
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.
This makes sense, but what if there is no 'current instance'? (i.e. the expression is in a class method, aka 'static method')
My intuition tells me to use the same rule, swapping out 'class of the current instance' for something like 'class of the class method'. However, I cannot find any such rule in the JLS, which in my experience tends to be very explicit. This makes me uncertain about my intuition.
The alternative is that my assumption that there is no 'current instance' when in a class method, is incorrect. If so - what are the rules for determining the 'current instance' when in a class method?
Class of the current instance indicates the instance of java.lang.Class whose type is T. Even if the class in consideration has static method, It is always an instance of java.lang.Class.
You can get related explanation in Java Documentation for java.lang.Class:
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.
The following example uses a Class object to print the class name of an object:
void printClassName(Object obj) {
System.out.println("The class of " + obj +
" is " + obj.getClass().getName());
}
It is also possible to get the Class object for a named type (or for void) using a class literal. See Section 15.8.2 of The Java™ Language Specification. For example:
System.out.println("The name of class Foo is: "+Foo.class.getName());
I believe "instance" in this case refers to the instance of the class itself, i.e., the class definition, and not an object instance of that class. This is difficult to articulate, so let's consider an example:
class A {}
class B {
Class<A> a = A.class;
}
Here, the expression A.class executes within a class B. However, it is possible that class B might be loaded into the runtime more than once using different class loaders. So, when the documentation says, "as defined by the defining class loader (§12.2) of the class of the current instance", I believe it is referring to whichever class loader loaded the copy ("instance") of the B class that is currently executing.
In short, the Class<A> instance assigned to a will be loaded from the same class loader that loaded B.
In practice, this isn't the sort of thing you're likely to have to have to worry about. Most Java developers don't have to deal with multiple class loaders in their day-to-day work.
The class literal can never appear alone, it must always be qualified by either a class name or a primitive type name. class should be used when you need to access a class object statically. someObject.getClass() should be used when you need to access an objects class at runtime.
Thus:
public class Foo {
public static String getMyFooClassNameStatic_good() {
return Foo.class.getName(); // ok
}
public static String getBarClassName() {
// the Bar class will be looked up in the same class loader as
// the one that the the Foo CLASS instance was loaded from that
// is executing this method. So if there are multiple versions
// of Bar floating around, the one you will get is the one that
// was loaded from the same class loader as the loaded Foo. That's
// what the language about "current instance" in the spec is
// getting at.
return Bar.class.getName();
}
public static String getMyFooClassNameStatic_bad() {
return class.getName(); // syntax error -
// use one of:
// Foo.class.getName()
// (new Foo()).getClass().getName()
// Class.forName("Foo").getName()
}
public static String getIntClassName() {
return int.class.getName(); // ok
}
}
Related
There are 2 ways to get a class's Class object.
Statically:
Class cls = Object.class;
From an instance:
Object ob = new Object();
Class cls = ob.getClass();
Now my question is getClass() is a method present in the Object class,
but what is .class? Is it a variable? If so then where is it defined in Java?
That's implemented internally and called a class literal which is handled by the JVM.
The Java Language Specification specifically mentions the term "token" for it.
So .class is more than a variable, to be frank it is not a variable at all. At a broader level you can consider it as a keyword or token.
https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.8.2
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.
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.
That information resides in the class 'file', although classes need not have a physical .class file in the file system. The JVM takes care of making it available from the class definition, as the other answer states.
See also:
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html
I try to understand what the Object.getClass() method does.
The documentation says that it "returns the runtime class of an object." That explanation doesn't help me understanding the term.
Has someone a simple description of what a "runtime class" is and what getClass() does?
Just understand it as "an object that has all the metadata of the object's type". In that object, you can find the methods declared in the class, the fields, the type hierarchy, etc.
This information will be typically used by code that uses reflection to either inspect objects/types or to run method without the need to have the class defined and compiled when they, themselves are being coded.
"Runtime" may be emphasized because the class definition may change over time, or the object may be declared as a supertype while it actually is an instance of a subtype of the one declared. When a certain class is loaded, it's that information, as loaded during that instance, that will be returned by the getClass() method.
In short, when your code runs, the VM will have a definition of your class in a different way than the "source" form that you type in a .java file. That information, of course after being compiled, will be loaded and all the metadata (as said above) will constitute what they call the "runtime class". It's just a fancy way to say "an object with all the metadata about a class loaded when the program is running"
It means "the class of the instance the variable refers to at runtime" (sorry if that's not actually clearer).
If you have a reference to an Object, it could refer to an Object, a String, an Integer... you get that class, not Object.
Object obj1 = new Object();
System.out.println(obj1.getClass()); // java.lang.Object
String obj2 = "";
System.out.println(obj2.getClass()); // java.lang.String
obj1 = obj2;
System.out.println(obj1.getClass()); // java.lang.String, not Object.
Every class you write has a lot of metadata. That metadata consists of the class name, its fields, its methods, its base classes, the interfaces it implements, and so on.
Sometimes you may need to access that metadata from your code at runtime.
In order to do so, you can take any object and call its getClass() method. You will receive a Class object that will contain the above metadata.
The class of an object can change at runtime. Consider following example:
package demo;
public class Main {
public static class A {
public int a=0;
}
public static class B extends A {
public int b=1;
}
public static void main(String[] args) {
Main.A b=new Main.A();
System.out.println(b.getClass().toString());
b=new Main.B();
System.out.println(b.getClass().toString());
}
}
The output of b.getClass() changed at runtime.
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.
Let's say we have a class name Home. What is the difference between Home.this and Home.class? What do they refer to?
Home.this
Home.this refers to the current instance of the Home class.
The formal term for this expression appears to be the Qualified this, as referenced in Section 15.8.4 of the Java Language Specification.
In a simple class, saying Home.this and this will be equivalent. This expression is only used in cases where there is an inner class, and one needs to refer to the enclosing class.
For example:
class Hello {
class World {
public void doSomething() {
Hello.this.doAnotherThing();
// Here, "this" alone would refer to the instance of
// the World class, so one needs to specify that the
// instance of the Hello class is what is being
// referred to.
}
}
public void doAnotherThing() {
}
}
Home.class
Home.class will return the representation of the Home class as a Class object.
The formal term for this expression is the class literal, as referenced in Section 15.8.2 of the Java Language Specification.
In most cases, this expression is used when one is using reflection, and needs a way to refer to the class itself rather than an instance of the class.
Home.class returns the instance of java.lang.Class<Home> that corresponds to the class Home. This object allows you to reflect over the class (find out which methods and variables it has, what its parent class is etc.) and to create instances of the class.
Home.this is only meaningful if you're inside a nested class of Home. Here Home.this will return the object of class Home that the object of the nested class is nested in.
What is the java class type used for? I am confused about what it means and how it is different than declaring an object type:
Class className;
Thanks
There are several uses for a Class object. For example, say I want to create an instance of a class based on some class name stored in a config file.
String className = config.myClass;
Class clazz = Class.forName(className);
Object myClassInstance = clazz.newInstance();
It represents the runtime type of the object. The actual programmatic use of the Class type is often found in reflection and generics.
For example, loading a JDBC driver abstractly with help of Class#forName():
String jdbcDriverClassName = getItFromSomeExternalConfigurationFile();
Class.forName(jdbcDriverClassName);
Or typecasting an generic Object to a beforeknown type:
public static <T> T findAttribute(String key, Class<T> type) {
return type.cast(attributeMap.get(key)); // It's a Map<String, Object>.
}
...which can be used as
SomeType instance = findAttribute("someKey", SomeType.class);
A more extended example can be found here in flavor of a "generic object converter".
Actually, reading the java.lang.Class javadoc, including all of the available methods, should give you an idea what it can be used for.
Class is a special type of Object, i.e Class is a sub class of Object. Every class you define has its own Class object. You can access this as MyObject.class or myInstance.getClass(). In another word, any class you define has a Class attribute where as any class is an Object. I agree it is slightly confusing to a newbie.
javadoc says:
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.
You can use it when checking the type of some variable or check for inheritance runtime.
It's also used in reflection, to load dynamically types and execute methods on them.
From the book Thinking in Java:
The Class object
To understand how Run Time Type Information (RTTI) works in Java, you must first know how type information is represented at run time. This is accomplished through a
special kind of object called the Class object, which contains information
about the class. In fact, the Class object is used to create all of the
'regular' objects of your class.