mogli
mogli

Reputation: 1609

what is MyClass.class?

following is the code listed in MainClass.java.

public class MainClass {

    public static void main(String[] args) {

        System.out.println("main started...");

        Class c = MyClass.class ;
                        //this class variable seems to be public static.
                        //But, as it is clearly visible in the MyClass,
                        //no reference variable is declared.
                        //My problem is that from where this class variable
                        //came from.
                        //i also check out the Object.java file, but it also don't
                        //have any public static class variable of Class class
                        //like there is
                        //out (instance of PrintStream class) in System class.
                        //Hope all u mindoverflow guys help me to sort out
                        //this probz.

        try {
            Class.forName( c.getName() ) ;

            System.out.println("classloader of MyClass : " + MyClass.class.getClassLoader());

            System.out.println("classloader of MyClass : " + String.class.getClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println("main ended...");
    }
}

class MyClass{
    static{
        System.out.println("static block of MyClass class.");
    }
}

thnx coobird... i found the article quite useful. :)

But, about litereals my knowledge is only limited to:

int i = 5 ;  //here 5 is an integer literal

float f = 5.6f ;  //here 5.6f is a float literal

the only non-primitive litereal, i know is

String str = "java" ;   //"java" is a String litereal

and class literal, which u and Jon Skeet make clear to me very well.

are there more literals found in java???


agreed... so as per the discussion, total literals are categorized as:-

are there some more literals (to make the list a little longer :) )


when i decompile the MainClass.class using decomipler, two Class type static variables (may be coz, i have used class literal 2 times) are found to be automatically added, but never found to be used in the code. Also, both the class literals are directly replaced from the class file where i have used them in the java file.

My code :-

public class MainClass {

    public static void main(String[] args) {

        System.out.println("main started...");

        Class c = MyClass.class ;

        try {
            Class.forName( c.getName() ) ;

            System.out.println("classloader of MyClass : " + MyClass.class.getClassLoader());

            System.out.println("classloader of MyClass : " + String.class.getClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println("main ended...");
    }
}

Decompiler generated code :-

import java.io.PrintStream;

public class MainClass
{

    public MainClass()
    {
    }

    public static void main(String args[])
    {
        System.out.println("main started...");
        Class c = MyClass;
        try
        {
            Class.forName(c.getName());
            System.out.println((new StringBuilder("classloader of MyClass : ")).append(MyClass.getClassLoader()).toString());
            System.out.println((new StringBuilder("classloader of MyClass : ")).append(java/lang/String.getClassLoader()).toString());
        }
        catch(ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        System.out.println("main ended...");
    }

    static Class class$0;
    static Class class$1;
}

Upvotes: 0

Views: 8275

Answers (4)

skaffman
skaffman

Reputation: 403581

To add to what others have already said, "MyClass.class" is semantically identical to:

Class.forName("MyClass", false, classloader);

where "classloader" is the ClassLoader instance of the calling class.

The main difference is in exception handling - with the above code fragment throws ClassNotFoundException, but I don't believe that MyClass.class can throw that (it may throw ClassDefNotFoundError, however, but that's a more general issue). Also, MyClass.class works with import statements, whereas Class.forname() requires you to pass in the fully-qualified class name.


As I was reminded, MyClass.class does not initialize MyClass, so the static initializer won't be called.

Upvotes: 0

Chet
Chet

Reputation: 22105

Right, there's no "class" instance variable so to speak. It exists in every class, actually. MyClass.class gets the Class instance directly for MyClass. I'm not sure how familiar you are with reflection, but this allows you start working with that. You might check out this tutorial for some examples of what you can do: http://www.ibm.com/developerworks/library/j-dyn0603/

Reflection allows programs to view and modify their own behavior at runtime. Its a type of "metaprogramming."

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503220

It's "class literal" - a simple way of getting the Class<T> for a particular type.

See section 15.8.2 of the Java Language Specification for more details.

Note that it's not a "field" of the class, it's a special piece of syntactic sugar.

Due to type erasure, you may run into interesting restrictions around generics. The TypeLiteral introduced in Guice gives more information and a workaround.

In terms of implementation, it depends on which bytecode version you're targeting. If you use -target 1.4 (or below), a call to Class.forName() is inserted into your code in a static method which is called during type initialization. If you use -target 1.5 (or above) the constant pool gets a "class" entry. I don't know the details of how this is handled though.

Upvotes: 9

coobird
coobird

Reputation: 161022

Writing MyClass.class gives an object of the type Class<MyClass>.

So, in the above code, if one is to use generics correctly, it should rather say:

Class<MyClass> c = MyClass.class;

or

Class<?> c = MyClass.class;

The class keyword will give the Class object that models the class.

As mentioned by Jon Skeet, Section 15.8.2: Class Literals of The Java Language Specification says the following about the class literal:

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 a class literal, C.Class, where C is the name of a class, interface or array type, is Class<C>.

A class literal evaluates to the Class object for the named type (or for void) as defined by the defining class loader of the class of the current instance.

Upvotes: 3

Related Questions