3

Below is the code that defines class type:

package annotationtype;

public class Example {

    public static void main(String[] args){


    }
}

that gets functionally compiled by javac to:

public class annotationtype.Example{
    public static Class<annotationtype.Example> class;
    {
        class = Class.forName("annotationtype.Example")
    }
    public annotationtype.Example(){}
    public static void main(java.lang.String[] args){}
}

My major focus is on the Class<annotationtype.Example> class static member variable in the above code. In addition, this member variable Class<annotationtype.Example> class is actually pointing to an object of type class Class that maintains meta data of class Example after class Example gets loaded into memory.

Is my understanding correct?

overexchange
  • 11,586
  • 11
  • 75
  • 203
  • I am not sure if you should see `class` literal as field since just like `this` it is `keyword` which we can also use even with primitive types like `int.class`. But if you are asking about *idea* of `class` then yes, it can be somehow treated as static field declared in class. – Pshemo Jul 02 '15 at 12:58
  • @Pshemo, it's probably because you can always do `Example.class`, i.e. referring a `static` member, called `class`. :) – Konstantin Yovkov Jul 02 '15 at 13:00
  • Definitely no, `javac` does not compiles that way. Did you use an old decompiler to get that code? – Umberto Raimondi Jul 02 '15 at 13:16
  • I had been thru `javap -p` output. – overexchange Jul 02 '15 at 13:16
  • @my-thoughts Please do not dump the literal meaning of `Example.class` in byte code. Please provide the functional translation as shown in similar question [here](http://stackoverflow.com/questions/31039980/in-java-what-does-such-enum-type-compile-to). – overexchange Jul 02 '15 at 13:22
  • Nope, javap gives an output similar to what @dohaqatar7 shows below. There is no `.class` property. Adding a proper answer... – Umberto Raimondi Jul 02 '15 at 13:23

2 Answers2

4

Class literals are part of the language specification as noted in 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.

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>.

javac doesn't create a static class field for each class, but it will recognize a class literal expression and compile it correctly.

Take for example the class:

public class Hello {
        public static void main(String[] args){
                Class<?> myClass = Hello.class;
                System.out.println("Hello, " + myClass);
        }
}

This compiles to (only relevant sections of bytecode included):

public class Hello   minor version: 0   major version: 52   flags:
 ACC_PUBLIC, ACC_SUPER 
Constant pool:    
#1 = Methodref          #11.#20        // java/lang/Object."<init>":()V    
#2 = Class              #21            // Hello
......
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=3, locals=2, args_size=1
     0: ldc           #2                  // class Hello
     2: astore_1

You can see that javac has put a reference to the Hello class in the constant pool and then loaded that constant when I refer to it in main.

Community
  • 1
  • 1
Dev
  • 10,959
  • 3
  • 36
  • 50
  • @overexchange, that's the answer you want, +1. – Umberto Raimondi Jul 02 '15 at 13:29
  • You should quote the relevant section of the JLS in your answer. – ankh-morpork Jul 02 '15 at 13:29
  • 2
    @uraimo So, I am not suppose to go by the syntax of `Hello.class`, interpreting that `class` is a member of `class Hello`. I am suppose to interpret as, `javac` doing under the hood job of interpreting `Hello.class` syntax as special syntax and provide corresponding byte code to create object of type `class Class` and `myClass ` points to that object. Is that correct? – overexchange Jul 02 '15 at 14:30
  • 1
    Yes, correct. You see that `#2 = Class #21 // Hello` in the constant pool of the Hello class? That's the result of the work done by `javac`, that adds a class constant to the constant pool of the .class file and use it with the `ldc #2` bytecode ( ldc=load constant from constantpool). – Umberto Raimondi Jul 02 '15 at 14:43
  • @uraimo 1) Is it the same constant pool where `class String` literals are stored? 2) I did not get this: "that adds a class constant to the constant pool". what is class constant? – overexchange Jul 02 '15 at 15:20
  • 1
    1) If you mean interned Strings, no, that's the String Pool, if you mean string literals loaded from the .class file javac produces, yes. 2) I was referring to that `#2 = Class` you see above, learn more about the Constant Pool from this question: https://stackoverflow.com/questions/10209952/what-is-the-purpose-of-the-java-constant-pool – Umberto Raimondi Jul 02 '15 at 15:37
  • @uraimo within main method, is that byte equivalent to, 'myClass = Class.forName("Hello");'? – overexchange Jul 03 '15 at 01:49
  • @uraimo It isn't, the class literal expression is evaluated into a Class reference by the compiler. Class.forName() isn't evaluated until runtime. – Dev Jul 03 '15 at 02:40
  • @Dev am totally confused. Assume, I keep `main()` method empty in your answer and compile `Hello.java`. When is member `Class class` come into existence that gets pointed to an object that has meta data about `Hello`? Because when I type `Hello.` in eclipse, `class` member is already visible. – overexchange Jul 03 '15 at 10:43
  • @overexchange The expression `Hello.class` is not a reference to a `class` member (which doesn't exist) it is a ***literal*** reference to the class `Hello`. The expression is evaluated at compile time just all all other literals. – Dev Jul 03 '15 at 13:12
0

If by "functionally compiled" you mean that the class "field" is available to you without you explicitly declaring it, then you are correct. Of course, class isn't a field, it's a class literal in the java language.

Furthermore, if we compile javac Example.java then disasemble javap -c Example we are left with this:

Compiled from "Example.java"
public class Example {
  public Example();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: return
}

note that there is no reference to class in this dissembled code. On the other hand, the default constructor Example() does magically appear so, it is fair to say that

public class Example {
    public static void main(String[] args){
    }
}

compiles to

public class Example {
    public Example(){}
    public static void main(String[] args){
    }
}
ankh-morpork
  • 1,422
  • 1
  • 16
  • 27
  • If there is no member by name `class` in disassembled code, why does java allow you to say `Example.class`? – overexchange Jul 02 '15 at 13:18
  • 1
    @overexchange because class literals are part of the language spec [JLS 15.8.2](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.8.2) – Dev Jul 02 '15 at 13:21