• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Enum constants| Static initializers | OCP 17

 
Ranch Foreman
Posts: 38
5
MySQL Database Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Hi everyone

As far as I've understood class initialization process during class loading phase, at runtime as per JLS "Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class."

As per JLS section  12.4.1. When Initialization Occurs
A class or interface T will be initialized immediately before the first occurrence of any one of the following:

T is a class and an instance of T is created.

A static method declared by T is invoked.

A static field declared by T is assigned.

A static field declared by T is used and the field is not a constant variable



My question is regarding the last point mentioned above and Enums in java.

Suppose I've the following code:





I believe for compiler above enum definition is like below representing each enum constant as public static final field referring to a singleton object



since all the enum values internally are public , static and final constants, so as per the fourth point mentioned above  using the enum field NOKIA for the first time shouldn't trigger the execution of static block in enum Phone during the class loading of Demo2 by JVM.

In other words, I'm not able to understand why explicitily declared static block is being exceuted here?
Are enum classes treated special by classloaders as compared to "regular" java classes in this aspect ?
Is fourth point of JLS section  12.4.1 of class initialization isn't applicable to enum classes?

I believe it would've made sense in the following case:





Please provide your guidance on this and where I'm having a gap in the understanding of enum concepts.

Thanks
 
Saloon Keeper
Posts: 10929
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Line 5 invokes the enum and thereby causes the enum to be loaded which causes the static block to run.
 
MyExamCloud Software Support
Posts: 753
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The rule for static initializers is same for both enum and regular class.

https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-8.9
8.9.2. Enum Body Declarations
"The body of an enum declaration may contain constructor and member declarations as well as instance and static initializers."
"Any constructor or member declarations in the body of an enum declaration apply to the enum type exactly as if they had been present in the body of a normal class declaration, unless explicitly stated otherwise."

Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class.

The static initializer for a class or enum gets run when the class or enum is first accessed, either to create an instance (in the case of regular class), or to access a static method or field.

When an enum type is referenced for the first time, the enum constants are initialized by creating a corresponding enum object. This initialization triggers the static block to execute, as it is part of the initialization process for the enum constants. In your code Phone.NOKIA is referenced for the first time and hence static initializers is executed.
 
Master Rancher
Posts: 5060
81
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Dalvir Singh Bains wrote:since all the enum values internally are public , static and final constants, so as per the fourth point mentioned above  using the enum field NOKIA for the first time shouldn't trigger the execution of static block in enum Phone during the class loading of Demo2 by JVM.


Note that the term “constant variable”  is precisely defined in JLS 4.12.4

A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.29). Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1), reachability (§14.22), and definite assignment (§16.1.1).


This wording does not include enum constants, since they are not primitive type and not Strings.  So using an enum constant for the first time can, indeed, trigger class initialization.
 
Dalvir Singh Bains
Ranch Foreman
Posts: 38
5
MySQL Database Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks @Carey and @Jhonson for your inputs. I appreciate.

and to @Mike thanks for pointing out what I believe completes this answer.
 
Marshal
Posts: 79956
396
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:. . . using an enum constant for the first time can, indeed, trigger class initialization.

And a static field used as a public constant, which is indeed a constant expression (sometimes called, “a compile‑time constant”), would cause the class to be initialised similarly because it would be used by the print statement.
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No.  The definitions of constant variable and constant expression are linked, and an enum constant is neither.  If it had been a constant variable and thus a constant expression, it would not trigger class initialization.  That is the whole point of Dalvir’s question, why is it triggering class initialization when the rule he quoted seems to say it doesn’t?  Answer, because that rule doesn’t apply, because it’s not a constant variable or constant expression.
 
Campbell Ritchie
Marshal
Posts: 79956
396
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:. . . .  If it had been a constant variable . . . it would not trigger class initialization. . . . .

Aaaaaaaaaaaaaaaaaaaaaaaaah!
 
Saloon Keeper
Posts: 28319
210
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I haven't checked recently, but I think a good rule of thumb is that a class is "initialized" when it becomes necessary to know something about what's defined inside the class.

Specifically when a class is located by a classloader, then queried about some characteristic(s). Which can be access of a class property/method, instantiation of the class, and so forth.

Now an interesting case is where you call classForName() on a class. That would probably initialize the class, because the class has to be located and a reference returned, and to use the reference, you'd have to have an (initialized) instance of the class's Class object.
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If only there were some place where they documented what Class.forName() did, they might tell us clearly whether or not it triggers initialization.  If only…
 
Campbell Ritchie
Marshal
Posts: 79956
396
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Does it matter when initialisation occurs?
Agree: the documentation for Class#forName(...) is by no means easy to understand, but by not saying anything about initialisation, it passes the buck back to the JLS, as previously discussed in this thread.
 
Tim Holloway
Saloon Keeper
Posts: 28319
210
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:If only there were some place where they documented what Class.forName() did, they might tell us clearly whether or not it triggers initialization.  If only…


Silly rabbits. Class.forName takes a string representing a class name (fully-qualified)  and searches the current classpath. Recall that a classloader can load from virtually anywhere, given the proper implementation. Local files, JARs, URs, database BLOBS, even build a class completely on the fly.

But, having searched the classpath, the returned result will either be a class reference or throws an Exception if the classname does not resolve.

I suppose that the "class" could simply be a proxy that will convert itself to an actual instance of Class when needed, but I suspect it's not likely to bother.

And, I should point out that if it's really important to know, that the source for java.lang.Class#forName() is available for the OpenJDK implementation. But its Javadoc does explicitly say it returns a Class, not anything more esoteric.

 
Tim Holloway
Saloon Keeper
Posts: 28319
210
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Oh, wait:

javadoc wrote:
    * @throws    ExceptionInInitializerError if the initialization provoked
    *            by this method fails


So yes, there's your answer. Initialisation must have been done before this method can successfully return!
 
Campbell Ritchie
Marshal
Posts: 79956
396
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:. . . Initialisation must have been done before this method can successfully return!

That goes with the old usage of Class.forName() to set up a database connection; the class has a static initialiser which must run when the class is initialised.
 
Sheriff
Posts: 28325
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:Oh, wait:

javadoc wrote:
    * @throws    ExceptionInInitializerError if the initialization provoked
    *            by this method fails


So yes, there's your answer. Initialisation must have been done before this method can successfully return!



Java 23 docs wrote:A call to forName("X") causes the class named X to be initialized.

 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you, Paul C.

Dalvir has shown how this can be easily tested, as well.  Note that the API also documents a way to avoid initialization, if desired.  The ExceptionInInitializer text doesn’t show that it must happen, only that it may happen.  

I don’t know why they were so obsessed with this, but they did document it carefully from the very beginning.  I think they were concerned with “write once, run anywhere” and didn’t want different platforms to behave differently.
 
Tim Holloway
Saloon Keeper
Posts: 28319
210
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Thank you, Paul C.

Dalvir has shown how this can be easily tested, as well.  Note that the API also documents a way to avoid initialization, if desired.  The ExceptionInInitializer text doesn’t show that it must happen, only that it may happen.  

I don’t know why they were so obsessed with this, but they did document it carefully from the very beginning.  I think they were concerned with “write once, run anywhere” and didn’t want different platforms to behave differently.

Yeah, you might want to avoid initialization if the class in question used a lot of resources in the process of initialization, but you wanted be assured it was then for when you needed it.

As a general rule, language designers do want to lock down details with potential consequences. Remember, every program is just a deal with the devil to begin with.
 
What are you doing in my house? Get 'em tiny ad!
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic