Win a copy of The Journey To Enterprise Agility this week in the Agile and Other Processes forum! And see the welcome thread for 20% off.
  • 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 all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Jeanne Boyarsky
  • Liutauras Vilda
  • Campbell Ritchie
  • Tim Cooke
  • Bear Bibeault
Sheriffs:
  • Paul Clapham
  • Junilu Lacar
  • Knute Snortum
Saloon Keepers:
  • Ron McLeod
  • Ganesh Patekar
  • Tim Moores
  • Pete Letkeman
  • Stephan van Hulst
Bartenders:
  • Carey Brown
  • Tim Holloway
  • Joe Ess

Static context is showing unfair preference for interface  RSS feed

 
Ranch Hand
Posts: 110
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello All,
Please, look at the newbie program below:

When compiled, I get the following error:

>Condo.java
..\rawcodes\Condo.java:18: error: non-static variable this cannot be referenced from a static context
                Arranger inOrder = new Arranger();
                                            ^


The inner class and the interface are both at the same level of visibility.  Why am I able to implement the interface in the static context and yet not able to instantiate the inner class? What does the static context think of the inner class?
Thanks.

 
Bartender
Posts: 1842
46
Eclipse IDE Google Web Toolkit Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hint: A nested class can be static
 
author
Sheriff
Posts: 23566
138
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Biniman Idugboe wrote:What does the static context think of the inner class?



Another hint. An instance of an inner class* requires access to its outer class instance. From a static context, how do you supposed that can happen? Can you do it via a this variable?

Henry

* to be pedantic, I mean an inner class that is not a method local or anonymous inner class...
 
Sheriff
Posts: 23640
48
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I fiddled around with that code for a bit and here's what I found: inner classes and inner interfaces ARE treated differently. Observe:



So here I have a class with an nested interface, which has a default method, and with an nested (abstract) class which looks a lot like the interface. There's also an instance variable in the class, and both the interface and the class have code which tries to use that instance variable. And what happens?

There are no compiler errors in the class. And therefore it's NOT a static context, otherwise it couldn't access the instance variable. But if you declare the class to be static, then it IS a static context and you get the compiler error "Cannot make a static reference to the non-static field testData".

But there IS a compiler error in the interface, the dreaded "Cannot make a static reference to the non-static field testData". And therefore the interface IS a static context, even though it isn't declared static.

I can see why the Java designers did it that way, now that you provide the example. A nested interface must be static, because if it weren't then how would you implement it? "public class What implements newCondoAgain().Test"?
 
Paul Clapham
Sheriff
Posts: 23640
48
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I gave you a cow for the interesting question... my thought process started out with "Well, of course" and proceeded through "Wait a minute" on the way to "That's interesting".
 
Marshal
Posts: 59715
187
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I went through the Java® Language Specification looking for differences between member classes and member interfaces and didn't find anything.
 
Biniman Idugboe
Ranch Hand
Posts: 110
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the cow and for the analysis.  Here's my understanding of your explanations:
An inner class must be declared static if there is a possibility that the inner class will be referenced from a static context.
Question: Is it not better to declare all inner classes static?

An interface that is nested inside a class, is implicitly static; otherwise the interface will not be accessible outside the enclosing class. 
Question:  If we can have implicitly static interface, why can't we have explicitly static interface?
 
Campbell Ritchie
Marshal
Posts: 59715
187
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Biniman Idugboe wrote:. . . Is it not better to declare all inner classes static?

No. If the class is intended to form part of an object, it is better to have it an instance member. If it is accessible outwith its enclosing type, then maybe it isn't intended to form part of the instance, and it can be marked static. Search for Bruce Eckel's book Thinking in Java; the 3rd edition used to be available free of charge on the net. That has a nice chapter about nested classes in. It also shows that public static nested classes are easy to use from other code. And that non‑private inner classes are awkward to use elsewhere because you have to write new twice.

By the way: when you mark a nested class static it is no longer called an inner class.

An interface that is nested inside a class, is implicitly static; otherwise the interface will not be accessible outside the enclosing class.

Have you found anything in the JLS (=Java® Language Specification) to support that statement? But once I got rid of the compiler errors in jshell, I managed to get such code to compile:-Let's correct the indentation:-That compiles and runs:

jshell> new Bar().f.foo(999);
999

Question:  If we can have implicitly static interface, why can't we have explicitly static interface?

How do you know that interface is implicitly static? Have you found anything in the JLS? How do you know there isn't another explanation? If you go through the Map interface and look for Map.Entry you will see it is marked

...static interface Map.Entry<K,V> A map entry (key-value pair)....

...even though the code doesn't have the keyword static. So the suggestion that nested interfaces are implicitly static is probably correct. It would just be nice to read it in the JLS.
As for explicitly making something static, look at this section about nested enums. It tells you that nested enums are implicitly static, but you are allowed to use the keyword static if you wish.

* * * * * * * * * * * * * * * * * * * * * * * * * *

Oh. I have found something. Look at this JLS section which tells you about nested interfaces.
 
Campbell Ritchie
Marshal
Posts: 59715
187
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Biniman Idugboe wrote:. . . a possibility that the inner class will be referenced from a static context. . . .

Stop thinking about static contexts. Think about instance context. Java® is an object language, so you should always think in terms of objects first.
 
Henry Wong
author
Sheriff
Posts: 23566
138
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Biniman Idugboe wrote:Thanks for the cow and for the analysis.  Here's my understanding of your explanations:
An inner class must be declared static if there is a possibility that the inner class will be referenced from a static context.
Question: Is it not better to declare all inner classes static?



That is because it is *not* true. You can access an inner class instance from an static context. You just have to provide the outer class instance, because the static context doesn't have access to the outer class.

For example, if you had provided something like this...  Arranger inOrder = new Condo().new Arranger(); ... it would have worked. Although, you probably wouldn't want a throwaway one-use outer class instance...

Henry

 
Henry Wong
author
Sheriff
Posts: 23566
138
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Modification of the OP's code, to provide an outer class instance while in static context, and hence, should compile.

Biniman Idugboe wrote:



Hope this helps,
Henry
 
Biniman Idugboe
Ranch Hand
Posts: 110
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks everybody.  Very useful suggestions and recommendations.  Resolved!
 
Campbell Ritchie
Marshal
Posts: 59715
187
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's a pleasure
 
Don't get me started about those stupid light bulbs.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!