Java Riddle: Static Members in Inner Classes?

Tags:

Here's something that can annoy the most experienced Java developers and is guaranteed to make people to mumble in job interviews (if that's your thing).


Consider the following piece of code:


Java Riddle

On the face of it, the two variables are identical, but of a different type. So what's the problem here? 

Hint 1: This will work with a String. It will not work with an int array.

Hint 2:  This is the error you'll be getting (at least in Eclipse):

The field OBJECT_CONST cannot be declared static; static fields can only be declared in static or top level types

This hint is only more confusing. The error seems to apply to the integer field as well. So, what's the deal here?

If you know the answer, leave a comment.

0

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Raphael_Lemaire replied on Wed, 2008/07/23 - 7:51am

Wow, really confusing. I tried to use javac, and have a similar error whith the second constant :

Main.java:6: inner classes cannot have static declarations 
 But not with the int nor with a String.  

Does someone have an explanation ?

rygel replied on Wed, 2008/07/23 - 8:03am

Hi! This is not so confusing. Specification say that inner class may declare only compile-time conatant fields. So, constants is primitive types and String literals, String litarals because compiler create a pool of this literals during compiling. This is valid also for case in switch. Only compile-time constants!

Arsius replied on Wed, 2008/07/23 - 8:08am

Zviki Cohen replied on Wed, 2008/07/23 - 8:12am

Yes, that is correct.

 It is confusing because many Java developers are not aware of the difference between a compile-time constant and a regular constant. Probably because Java has high abstraction level over the underlying compiler and machine.

Well done.

 

Raphael_Lemaire replied on Wed, 2008/07/23 - 8:13am

Ok. This is logical, but lacks consistency, they could have disabled constants even for primitives to have the same behaviour for all types.

(Suppress primitives in java would be harder than I thought)

Aaron Digulla replied on Wed, 2008/07/23 - 10:31am

Simple: The inner type isn't static, so you can't attach static object instances to it (as opposed to static primitives). Just as the Eclipse compiler says: "The field OBJECT_CONST cannot be declared static; static fields can only be declared in static or top level types"

Osvaldo Doederlein replied on Wed, 2008/07/23 - 10:58am

This allows be to bitch, once again, about the classfile's poor constant pools. We should be able to define "compile-time literals" of ANY type; the only restriction should be that initialization should depend only on trivial constructors (i.e., constructors that only initialize fields with values that are compile-time constants, or derived from compile-time constants wothout invoking any external method - e.g. "this.x = 10 * xParameter") so the compiler could easily evaluate the constructor code at compilation time. This would cover >90% of all constructors out there. Notice that this optimization is easy and implemented in many anguages. Java's strong portability makes it easy, for example you could even evaluate at compile time an API calls like java.lang.Math.cos(), because its behavior is portable so a result generated at compile time in platform X is acceptable when the code is ran on platform Y, which makes safe to move evaluation from runtime to compile time. And of course, the constant pool should also support arays properly, so array initialization expressions don't need to be encoded as a horribly inefficient stream of bytecodes that assign each index. These limitations hurt startup time, and also data sharing: if we get smarter constant pools that can also guarantee deep immutability (which is a separated RFE), all that data could be easily shared among processes.

Slava Imeshev replied on Wed, 2008/07/23 - 10:11pm

 

Guys,

you are missing the fact that the static block is executed during the class initialization, and you cannot initialize a non-static inner class without having an instance of the enclosing class. That's it.

 

Slava

 

Alen Vrecko replied on Wed, 2008/07/23 - 4:46pm

I'd never tought anybody would want to write code like that.

Let us not forget how one instantiates an inner class

new TestInnerStaticFinal().new MyInner();

this might give a hint. An inner class can only live within an outer class, but if statics were allowed it could live outside the outer class which would defeat the purpuse of inner class at least this is how I see it.

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.