-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"?

5
  • 1
    @AndyBrown I would say that that question is related but doesn't answer OP's question since OP asks about class loading. Commented Aug 26, 2015 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, or this one, or ... Commented Aug 26, 2015 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, it is to help people find the right answer more easily, and two questions are generally considered duplicate if they have the same answer. Commented Aug 26, 2015 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 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 and ask about it. Commented Aug 26, 2015 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. Commented Aug 26, 2015 at 17:14

1 Answer 1

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
Sign up to request clarification or add additional context in comments.

9 Comments

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.
@AndyBrown I don't understand what's misleading by your comment.
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.
@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.
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.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.