He is a entrepreneur and a software architect from Tel Aviv, Israel. He is also a technology freak with about 20 years experience working with computers. He is currently working on his first private initiative in the area of software development tools. His vision is to maximize the abilities of software developers by providing pragmatic tools that enable them to get fast results. Zviki has posted 36 posts at DZone. You can read more from them at their website. View Full User Profile

Java Riddle: Static Members in Inner Classes?

  • submit to reddit

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.

Published at DZone with permission of its author, Zviki Cohen. (source)

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



Lemaire Raphael replied on Wed, 2008/07/23 - 6: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 ?

Ian Pomanitskiy replied on Wed, 2008/07/23 - 7: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!

Arseniy Sizov replied on Wed, 2008/07/23 - 7:08am

Zviki Cohen replied on Wed, 2008/07/23 - 7: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.


Lemaire Raphael replied on Wed, 2008/07/23 - 7: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 - 9: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 - 9: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 - 9:11pm



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.




Alen Vrecko replied on Wed, 2008/07/23 - 3: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.


Roger Crawfis replied on Sat, 2009/10/24 - 9:33pm

Looking for help as to why this was not allowed. Wanted to comment on the last two comments about needing an instance of the outer type in order to deal with the inner type. This is not necessary so. Static members are part of the type, not part of an instance. So: TestInnerStaticFinal.MyInner.Object_Const would easily tell the compiler what it is that we are after. In C# the rules for initializing types (aka calling the static constructor that every type has) are very clear and I am not sure there is this problem there. Not a Java expert, but I believe the real answer is because the language designers choose not to let you do this and either wanted to prohibit it or where just lazy in not wanted to implement it. Really no technical reason for it.

Comment viewing options

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