Win a copy of TDD for a Shopping Website LiveProject this week in the Testing forum!
  • 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
  • Paul Clapham
  • Ron McLeod
  • Jeanne Boyarsky
  • Tim Cooke
Sheriffs:
  • Liutauras Vilda
  • paul wheaton
  • Henry Wong
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Frits Walraven
Bartenders:
  • Piet Souris
  • Himai Minh

static inner class question.

 
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Can someone explain and point me to where in the jls it explains why this happens.
Bar myBar = new Bar();
becomes Foo$Bar() = new Foo$Bar();

public class Foo
{
public static class Bar
{
private int num = 0;

public void doIt()
{
System.out.println( "My number: " + num );
}
}
}


public class Bar extends Foo
{
public void doIt()
{
System.out.println( "Hello!" );
}

public static void main( String[] args )
{
Bar myBar = new Bar();
myBar.doIt();
}
}
 
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Although $ is a perfectly valid Java letter which can be used in Java identifiers, it is reserved for use in machine (compiler) generated names. (That much is in the JLS). The names of nested classes are generated by the compiler and so these names can and do contain the $ character to separate the nested classname from the containing one. The character is also used in the filename used for these classes.
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Rules for the generated names of nested classes are given in JLS 13.1: "The binary name of a member type consists of the binary name of its immediately enclosing type, followed by $, followed by the simple name of the member."

As long as you're referring to the JLS, I should also point out that there is no such thing as a static inner class. Static nested classes are nested, but not inner, by definition.
[ December 03, 2005: Message edited by: Jim Yingst ]
 
simon valter
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok perhaps i didn't make this very clear. I'm wondering why the Bar myBar = new Bar();
gets to be the Foo$Bar and not just the Bar extending Foo.
One could say that thats just the way it is, but I'm more interested i knowing why it was designed to be that way instead of the other way around, and not forcing me to use Foo$Bar if i really meant to make a instance of that. And would like to know where in the jls that it says it should be implemented that way.
 
simon valter
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The way it is now is really just obfuscating what is really happening.
 
author
Posts: 23919
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Personally, I felt that the designers of Java painted themselves into a corner with inner classes.

They can't compile the inner class to Bar.class, because there may already be a Bar class. And they can't compile it to Foo.Bar, because there may be a conflicting Foo package.

What they did with the "$" is almost equivalent to what C libraries did with using the "_" character to represent private variables.

Oh well...
Henry
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[simon]: And would like to know where in the jls that it says it should be implemented that way.

I gave a link to the appropriate section - did you read it? In general the JLS does not explain why it does things, it just tells you how it is. That's the case here.

Henry addressed the why. Note that when Java was originally designed it did not have nested classes. When nested classes came out in 1.1, they tried to implement them with a minimum number of changes to the existing JDK. They chose to change the compiler to handle nested classes, but leave the JVM mostly unchanged. The strategy is that the JVM doesn't really understand what nested classes are - it sees only top-level classes. It's the compiler's job to take nested classes in source code and translate them into equivalent top-level classes in class file form.

[simon]: ...I'm more interested i knowing why it was designed to be that way instead of the other way around, and not forcing me to use Foo$Bar if i really meant to make a instance of that.

Ummm, you're really not forced to know about the Foo$Bar structure at all for most normal operations. In your source code you won't need to use a $ at all unless perhaps you're using reflection. Instead you usually refer to the class as Foo.Bar, and the compiler translate that. There are a few places where you might need to use the $, but they're pretty unorthodox. (The person recently calling a main method in a static nested class, that's a good example.) Most Java programmers can live happy, produtive lives without ever typing a $ as part of a class name.
[ December 03, 2005: Message edited by: Jim Yingst ]
 
simon valter
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hehe my english must be very bad since none of you seem to understand my question.

public static void main( String[] args )
{
Bar myBar = new Bar();
myBar.doIt();
}

becomes

public static void main( String[] args )
{
Bar myBar = new Foo$Bar();
myBar.doIt();
}


I never asked where the $ comes from. I understand that, its not the issue.

I'm not referring to the class as Foo.Bar but as Bar, But that is what i get.
the code will print "My number: 0" and not "Hello!"

I know that they both gets translated into top level classes. one will be Bar another will be Foo$Bar
when i extend the Foo class it happens if i don't extend Foo it doesn't happen. I still can't see where the jls says that.
 
Henry Wong
author
Posts: 23919
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

I know that they both gets translated into top level classes. one will be Bar another will be Foo$Bar
when i extend the Foo class it happens if i don't extend Foo it doesn't happen. I still can't see where the jls says that.



It will be compiled to Foo$Bar.class when Bar is an inner class of Foo. It will be compiled to Bar.class if Bar is not an inner class. I don't think whether or not it extends foo has anything to do with it. Everything else you said is correct.

Henry
 
simon valter
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
And i would never write code like that if thats what you think And if i really had to then i would of course write Foo.Bar. But this is a corner case, where i have a static nested class Bar and another class Bar and a problem that happens when Bar extends Foo that contains the nested static class.

Here you will assume unless you know this specific thing that when you write new Bar you will really get a instance of Bar and not Foo$Bar.

I'm only interested because i never meet anyone who could explain it.
[ December 03, 2005: Message edited by: simon valter ]
 
simon valter
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

It will be compiled to Foo$Bar.class when Bar is an inner class of Foo. It will be compiled to Bar.class if Bar is not an inner class. I don't think whether or not it extends foo has anything to do with it. Everything else you said is correct.



yes, but when you have both, then it will matter, try it yourself. when you extend you get a instance of the Foo$Bar class when you don't extend you get a instance of the Bar class
 
Henry Wong
author
Posts: 23919
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by simon valter:

yes, but when you have both, then it will matter, try it yourself. when you extend you get a instance of the Foo$Bar class when you don't extend you get a instance of the Bar class



Interesting... Could you show me code that does this?

In your two examples above, one is an inner class, the other is a subclass. Neither has both.

Henry
 
simon valter
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
sorry but now you got me confused, didn't you just tell me that static classes isn't inner classes, but nested classes.
But of course there is also a class Bar which is a subclass of Foo.

The "problem" is still the same, the code above will react differently depending on if the Bar class extends Foo or not.

I'm thinking that it have something to do with static nested classes, class scope but who knows
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ah, I see what you were getting at, Simon. (I haven't read the last few posts closely - I'm just addressing the questions in the first few posts.)

The relevant section of the JLS is in 6.3.1: "A declaration d of a type named n shadows the declarations of any other types named n that are in scope at the point where d occurs throughout the scope of d." In the top-level class Bar, the declaration of Foo.Bar is not in scope at the time that top-level Bar is declared. Therefore top-level Bar does not shadow Foo.Bar. However if we look inside the Foo class, top-level Bar is in scope at the time Foo.Bar is declared. (Bar is a public top-level class in the same package, so it's in scope.) Therefore by the rule quoted above, Foo.Bar shadows top-level Bar.

Normally, the way to access a shadowed name is by using a fully qualified name (i.e. include the packge name). Unfortunately in your example we can't do that, as the classes are in the default package, which has no name, which means that the qualified name is unfortunately identical to the simple name, which means there is no way to refer to the shadowed top-level Bar instead of Foo.Bar.

If you put these classes in a package, the problem is easily solved:

Here "simon.Bar" clearly can only refer to top-level Bar. And if we wanted Foo.Bar instead, we could say simon.Foo.Bar, Foo.Bar, or just Bar. (The last would of course be a horrible idea at this point - the compiler would understand, but humans most likely be very confused (as we all have been).)
[ December 03, 2005: Message edited by: Jim Yingst ]
 
simon valter
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok thank you very much that answers my question I actually know a guy who was asked about it during a job interview and have been wondering about it since. But i think it makes sense now.
[ December 03, 2005: Message edited by: simon valter ]
 
Henry Wong
author
Posts: 23919
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Okay, I *think* that I finally understand what you are asking... Here is the question... but I don't have an answer...

Basically, there are two Bar classes. There is a Bar class what is the inner class of the Foo class. There is a Bar class that is extending the Foo class.

In the main method, a Bar class is created. However, for some reason Java is choosing the inner class of the Foo class, even though it is the main() method of the Bar class that is creating the Bar method.

Is that is what you are asking?

[EDIT] Oops, beaten again. At least I don't think I wasted my time trying to figure this question out, as it was an obscure issue.

Henry
[ December 03, 2005: Message edited by: Henry Wong ]
 
simon valter
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Henry yes that was it, i think Jim figured it out but thank you for your time anyway
[ December 03, 2005: Message edited by: simon valter ]
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[Simon]: sorry but now you got me confused, didn't you just tell me that static classes isn't inner classes, but nested classes.

Well I was the one who said that. Henry is evidently a philistine who uses different terminology. Actually this is all Sun's fault because, when they first introduced nested/inner classes, they were rather inconsistent with how they defined and used the terms. Nowadays they are a lot more consistent than they were, and they mostly stick to the official definition: "An inner class is a nested class that is not explicitly or implicitly declared static." However there are a few people still using nested and inner as interchangeable. At least until we finish rounding them up for the reeducation camps.

[Henry]: At least I don't think I wasted my time trying to figure this question out, as it was an obscure issue.

Yeah, my head still hurts from that one. I was definitely glad to see Simon say he would never write code like this himself, or I would have had to add another paragraph ranting about that.
 
Henry Wong
author
Posts: 23919
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

However there are a few people still using nested and inner as interchangeable. At least until we finish rounding them up for the reeducation camps.



Yup, I am one of those people... who BTW, previously worked 13 years for Sun.

And I have to say there are still many (inside Sun) that don't make the distinction...

Henry
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[Henry]: Yup, I am one of those people... who BTW, previously worked 13 years for Sun.

Well, that explains how your mind got polluted.
 
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Boy.. that was really informative. Keep it up guys!!!
 
We're being followed by intergalactic spies! Quick! Take this tiny ad!
free, earth-friendly heat - a kickstarter for putting coin in your pocket while saving the earth
https://coderanch.com/t/751654/free-earth-friendly-heat-kickstarter
reply
    Bookmark Topic Watch Topic
  • New Topic