Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

K&B7 Chapter 6 Self-Test Q14 - Compile time constant

 
Jain Amit
Greenhorn
Posts: 16
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

I am quite perplexed with K&B7 Chapter 6 Self-Test Q14. Following is the code:-



And given that the numbered lines will all be tested by un-commenting one switch statement and one case statement together, which line(s) will FAIL to compile? Line 1/2/3/4/5/6 or ALL.

As per K&B7 the case constant must be a compile-time constant and only a final variable can be used. This implies s is not a compile time constant but s2 is.

But why "ann" (line 4) is a compile-time constant? I got this wrong but more than the correct answer I am interested in understanding this concept. I don't have behind the scene knowledge of Java.

Thanks
Amit
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jain Amit wrote:As per K&B7 the case constant must be a compile-time constant and only a final variable can be used. This implies s is not a compile time constant but s2 is.

Spot-on!

Jain Amit wrote:But why "ann" (line 4) is a compile-time constant? I got this wrong but more than the correct answer I am interested in understanding this concept. I don't have behind the scene knowledge of Java.

"ann" is a String literal. Any literal (int, String, short,...) is inherently (by definition) a compile-time constant!

So it's similar with a switch with intsline2 and line4 compile successfully, because on line2 an int literal (and thus a compile-time constant by definition) is used and i2 is a compile-time constant as well. i is not a final variable, so line3 gives a compiler error.

Hope it helps!
Kind regards,
Roel
 
Jain Amit
Greenhorn
Posts: 16
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Roel,

I guess a String literal "ann" is still created in the heap but the reference is stored in the String pool. So, will the compiler create String object "ann" in heap in this case?

Thanks
Amit
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jain Amit wrote:I guess a String literal "ann" is still created in the heap but the reference is stored in the String pool. So, will the compiler create String object "ann" in heap in this case?

Have you already read this excellent article about String literals and the String Literal Pool? It's definitely a must read!
 
Jain Amit
Greenhorn
Posts: 16
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, I read it few times before posting the query to understand it though it seems I haven't completely. I am actually confused between compile time and run time for String literals as referred below. Since, the JVM is creating a String instance on the heap (if String not present) isn't it run time? If no what actually defines run time for Java.

When a .java file is compiled into a .class file, any String literals are noted in a special way, just as all constants are. When a class is loaded (note that loading happens prior to initialization), the JVM goes through the code for the class and looks for String literals. When it finds one, it checks to see if an equivalent String is already referenced from the heap. If not, it creates a String instance on the heap and stores a reference to that object in the constant table. Once a reference is made to that String object, any references to that String literal throughout your program are simply replaced with the reference to the object referenced from the String Literal Pool.


I am trying to figure out Java's behind the scene policies but it's tough for me right now.

Regards
Amit
 
Liutauras Vilda
Bartender
Pie
Posts: 2792
112
BSD VI Editor
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jain Amit wrote:I guess a String literal "ann" is still created in the heap but the reference is stored in the String pool. So, will the compiler create String object "ann" in heap in this case?
Sorry if I'm out of context, a bit difficult to follow since I see references to book and other code snippets.

I'll try in simple way, someone hopefully will correct me if I'll overshoot.

1. Every time you create a String object by using "new" keyword - every time you create new object on Java Heap.

2. Every time you declare and initialize String object by using "=", Java first search its value in String constant pool, if finds - makes reference variable to refer to that found string, if not - creates new one in string pool.

3. String constant pool is possible, because as Roel mentioned, String is immutable, so, Java can look for the same already existing String and re-use it, in order to manage memory more efficiently.


 
nick woodward
Ranch Hand
Posts: 370
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
(i think) most methods on strings implicitly call 'new' too so the pool doesn't get checked either

had me scratching my head for a bit.

 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jain Amit wrote:I am trying to figure out Java's behind the scene policies but it's tough for me right now.

Let's try to clear some doubts

Only String literals (and compile time constants) will be added to the String Literal Pool (hence its name). The compiler doesn't execute any code, but can flag any String literal in some special way. Then at runtime the JVM goes through the code for the class and looks for String literals. If it finds one, it checks if that String is already in the String Literal Pool or not. If it is not, the String instance is created on the heap and a reference to that object is stored in the constant table. Any String literals which are equal to that String will be replaced with the reference to that String (retrieved from the constant table).
So let's assume in your application, the String literal "Roel" occurs 1000 times. Thanks to the String Literal Pool (and String immutability), the String "Roel" will exist just once on the heap (and not a 1000 times) and in the String Literal pool a reference to that String is stored, let's say 1979. All occurences of "Roel" in your application will be replaced with 1979 (the reference to the String object "Roel" on the heap).

You wanted to know some behind the scenes stuff as well... Fasten your seatbelt, here we go!

Let's have a look at this code"Test" is clearly a String literal, so when this code is compiled, both literals (on line1 and line2) get a special mark. Then at runtime, the JVM sees the String literal on line1, checks the empty String Literal Pool, creates "Test" on the heap and stores the reference (e.g. 123) in the constant table. Then this reference is assigned to s1. Then the JVM notices another String literal on line2, checks the String Literal Pool again and because "Test" is already in the String Literal Pool, its reference (123) is returned and assigned to s2. Because s1 and s2 have the same value (123) and thus refer to the same object, line3 prints true.
On line4 and line5 two new String objects are created at runtime. But these strings are not String literals, because they were created at runtime. So although both String objects have the same value ("test"), the reference variables refer to two different objects (with the same character sequence). And that's why line6 prints false.

The intern method does all this magic and is invoked by the JVM. If you want to add a String created at runtime to the String Literal Pool, you could use this intern method. A code snippet to illustratelineA stores "test" to the String Literal Pool and assign and stores the reference (e.g. 456) in the constant table. Then this reference is assigned to s1. s2 is still refering to its own String object (with the same character sequence as the - on the previous line - interned String). So both reference variables refer to different objects and lineB prints false. On lineD the intern method is invoked on the String object "test" (refered by s2). Because "test" is already in the String Literal Pool (remember lineA), its reference is returned; this reference and s1 refer to the same (interned) String object, so lineC prints true. lineD prints false for the same reason as lineB (remember that the reference of s2.intern() was not assigned to s2, so s2 is still refering to the String object created at runtime on line5).

Hope it helps!
Kind regards,
Roel

(Disclaimer: you don't need to know the intern method for the OCA exam, I just mentioned it for completeness)
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
nick woodward wrote:(i think) most methods on strings implicitly call 'new' too so the pool doesn't get checked either

Indeed! If you invoke a method (with a String return type) on a String object, you are always creating a runtime exception. So you'll never create a String literal or a compile-time constant and the String Literal Pool will not be checked to see if the resulting String already exists. One exception: the intern method, which is already discussed heavily in my previous post). And the toString method of the String class can be tricky as well. Why? You'll read it here!
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Liutauras Vilda wrote:

Just want to nitpick a little bit about this comment. I think everybody understand the gist of this comment, but it's not 100% correct.

obj1 is a reference variable and reference variables don't live on the heap. The actual object (to which obj1 refers) is living on the heap. And similar for s1: s1 is a reference variable which is not in the String Literal Pool. The actual object (to which s1 refers) is living on the heap and the reference to that object is stored in the constant table. This reference is assigned to s1.

Just my two cents.
 
Jain Amit
Greenhorn
Posts: 16
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Roel,

Thanks for the nice explanation.

It's kind of confusing to differentiate between stuff so I will summarize below:-

1. "str" - is a string literal and compile time constant.
2. final String s1 = "bob"; s1 is a compile time constant.
3. String s2 = "bob"; s2 is NOT a compile time constant as it is not declared final.
4. final String s3; s3 is NOT a compile time constant since s3 is not initialised while declaring.
s3 = "bob"

Thanks
Amit
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jain Amit wrote:1. "str" - is a string literal and compile time constant.
2. final String s1 = "bob"; s1 is a compile time constant.

Correct! So "str" and s1 can be used as a case label in a switch statement.

Jain Amit wrote:3. String s2 = "bob"; s2 is NOT a compile time constant as it is not declared final.
4. final String s3; s3 is NOT a compile time constant since s3 is not initialised while declaring.
s3 = "bob";

That's true as well! So s2 and s3 can not be used as a case label in a switch statement.

And just for completeness I like to add this little note: although s2 and s3 are not compile-time constants, the String they both are refering to is String literal and will thus exist in the String Literal Pool. That's proven with this little code snippet

Hope it helps!
Kind regards,
Roel
 
Jain Amit
Greenhorn
Posts: 16
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Roel.

It certainly helps.

Thanks
Amit
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic