-1

If I have a class with constants for example AppConstants and use public static final variable from there like AppConstants.MY_STRING it would recreate this class all the time or it creates it during runtime because the fields in the class is static? So is it better to define file in constants or "at the place"?

Kirill Zotov
  • 561
  • 3
  • 7
  • 18
  • 1
    @AndyBrown I would say that that question is related but doesn't answer OP's question since OP asks about class loading. – Luiggi Mendoza Aug 26 '15 at 15:52
  • @LuiggiMendoza - first answer to that question says : "*one per ClassLoader*". Seems like it directly answers this question, but if not that duplicate there are several other answers over the last 6 years, maybe [this one](http://stackoverflow.com/questions/10712897/whats-the-scope-of-a-static-field), or [this one](http://stackoverflow.com/questions/797964/what-is-the-exact-meaning-of-static-fields-in-java), or ... – Andy Brown Aug 26 '15 at 15:54
  • I'm sorry if you think I'm being nasty, I am genuinely not. [Closing as duplicate is not a personal attack](http://stackoverflow.com/help/duplicates), it is to help people find the right answer more easily, and two questions are generally [considered duplicate if they have the same answer](http://meta.stackexchange.com/a/10844/221930). – Andy Brown Aug 26 '15 at 15:57
  • @AndyBrown those links you're providing talk about `static` members. Please understand that OP's inquiry is not 100% related to `static` members, is more about class loading. While [the answer to this question](http://stackoverflow.com/q/10712897/1065197) explains the concepts to answer this question, it doesn't do it directly. Hence OP raises a question and gets a direct answer. If you're still against this, then raise a question on [meta](http://meta.stackoverflow.com/) and ask about it. – Luiggi Mendoza Aug 26 '15 at 16:12
  • I recommend you review my answer again in order to have a better understanding of what it means that the class will be loaded *when needed*. – Luiggi Mendoza Aug 26 '15 at 17:14

1 Answers1

3

Classes are loaded once by the class loader, usually when needed1. When a class is loaded, all its static members are loaded as well and "live with the class", not with a specific object reference of that class. Using a static field of the class several times won't fire a reload of the class. The only way to reload the class is using a custom class loader.

is it better to define file in constants or "at the place"?

Define them once as static final fields on a class or use enums.


1 Definition of when needed:

If you declare primitive or String constants like this:

public class AppConstants {
    public static final int ONE = 1;
    public static final int TWO = 2;
    public static final int TEN = 10;
}

public class ClientTest {
    public static void main(String[] args) {
        System.out.println(AppConstants.ONE);
        System.out.println(AppConstants.TWO);
        System.out.println(AppConstants.TEN);
    }
}

When compiling both classes and executing ClientTest, AppConstants class won't be loaded (tested using HotSpot) because the constants will be inlined by the compiler. In order to evaluate the results, do this:

> javac -cp:. AppConstants.java ClientTest.java
> javap -c ClientTest //you can see the generated bytecode
> java -verbose:class ClientTest //shows you the classes loaded to execute this app

And you will see this.

From javap -c ClientTest (proper code):

public static void main(java.lang.String[]);
  Code:
   0:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   iconst_1 //My Comment: constant with value 1
   4:   invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
   7:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  iconst_2 //My Comment: constant with value 2
   11:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
   14:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   17:  bipush  10 //My Comment: constant with value 10
   19:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
   22:  return

}

From java -verbose:class ClientTest:

[Opened C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
// Lots of classes from rt.jar
[Loaded java.security.UnresolvedPermission from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.security.BasicPermissionCollection from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded ClientTest from file:/D:/tmp/] //<-- Class being executed
[Loaded sun.launcher.LauncherHelper$FXHelper from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Class$MethodArray from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Void from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
1
2
10
[Loaded java.lang.Shutdown from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]

There's no trace of AppConstants class being loaded, only ClientTest.

But if you add a constant that refers to an object reference e.g. a List, then the class will be loaded. From the example above:

public class AppConstants {
    public static final int ONE = 1;
    public static final int TWO = 2;
    public static final int TEN = 10;
    public static final List<String> NAMES = Collections.unmodifiableList(Arrays.asList("Luiggi", "Andy"));
}

public class ClientTest {
    public static void main(String[] args) {
        System.out.println(AppConstants.ONE);
        System.out.println(AppConstants.TWO);
        System.out.println(AppConstants.TEN);
        System.out.println(Foo.NAMES);
    }
}

Now providing the relevant output of java -verbose:class ClientTest:

//...
[Loaded ClientTest from file:/D:/tmp/] //our class being executed
[Loaded sun.launcher.LauncherHelper$FXHelper from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Class$MethodArray from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.lang.Void from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
1  //output of constants
2
10
[Loaded AppConstants from file:/D:/tmp/] //loads AppConstants class here because it's needed
[Loaded java.util.Arrays$ArrayList from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Loaded java.util.AbstractList$Itr from C:\Program Files\Java\jre1.8.0_51\lib\rt.jar]
[Luiggi, Andy] //output of AppConstants#NAMES
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Aside from the duplicate discussion, this is a bit misleading. AFAIK `public static final` variable uses are actually inlined by the compiler where possible, and the respective class is therefore not loaded at all by such references. – Andy Brown Aug 26 '15 at 16:28
  • @AndyBrown I don't understand what's misleading by your comment. – Luiggi Mendoza Aug 26 '15 at 16:29
  • OP says: "*If I have a class with constants ... and use ... from there like AppConstants.MY_STRING it would recreate this class all the time or it creates it during runtime because the fields in the class is static?*" In his specific case it would not create that class at all - the constant would be inlined. In your answer you say "*loaded ... when needed*" but don't explain that in this case it won't be loaded as it isn't needed. – Andy Brown Aug 26 '15 at 16:31
  • @AndyBrown if you have a class `AppConstants` and you don't use it, then it won't be loaded. If you have such a line `String s = AppConstants.MY_STRING` and this line is executed, then `AppConstants` class is used, thus it will be loaded once because that class is needed. – Luiggi Mendoza Aug 26 '15 at 16:34
  • That's my exact point - if that is all you do, that class will not be loaded. The constant is inlined and the class is not therefore loaded by the classloader. Try it out - I can send you come code if you like. – Andy Brown Aug 26 '15 at 16:34
  • You said "*If you have such a line String s = AppConstants.MY_STRING and this line is executed, then AppConstants class is used, thus it will be loaded*": I am saying this is incorrect. `AppConstants` will not be loaded in this case. The value of `MY_STRING` will be inlined and thus `AppConstants` will not be loaded. You do not note this in your explanation. – Andy Brown Aug 26 '15 at 16:41
  • @AndyBrown ok I got your point. I'll evaluate this. – Luiggi Mendoza Aug 26 '15 at 16:45
  • See [Java static final values replaced in code when compiling?](http://stackoverflow.com/q/5173372/1945631) and [In Java, is it possible to know whether a class has already been loaded?](http://stackoverflow.com/q/482633/1945631) – Andy Brown Aug 26 '15 at 16:50
  • @AndyBrown thanks, but I prefer to see by myself :) And I've done it, I've posted the (basic) results of this. – Luiggi Mendoza Aug 26 '15 at 17:00