Hos Computerworld it-jobbank er vi stolte af at fortsætte det gode partnerskab med folkene bag IT-DAY – efter vores mening Danmarks bedste karrieremesse for unge og erfarne it-kandidater.
I think that is how I think it works to. And in my opinion the output sholud be "Hello!".
Do you agree with me?
But may the reson be because Foo.Bar is static and there for only is located at one place in the memory. Is this a reson that extends and inner class does not apply to ordinary rules?
I changed the code to: public class Bar //extends Foo { public void doIt() { System.out.println( "Hello!" ); }
public static void main( String[] args ) { Bar myBar = new Bar(); myBar.doIt(); } } Of course the output now is "Hello!", since Foo is not involved at all.
I also changed the code to this (I removed the static from the inner class i Foo): public class Foo { public class Bar { private int myNum = 0;
public void doIt() { System.out.println( "My number: " + myNum ); } } }
And the Bar back to (with extends Foo):
public class Bar extends Foo { public void doIt() { System.out.println( "Hello!" ); }
public static void main( String[] args ) { Bar myBar = new Bar(); myBar.doIt(); } }
This gave me this compilation error: D:\Fredrik\Javalabb\Bar.java:10: non-static variable this cannot be referenced from a static context Bar myBar = new Bar(); ^ 1 error
Tool completed with exit code 1
Is this a clue??? How ever my opinion is that the code should be able to be compiled. I think the line "Bar myBar = new Bar();" just refers to Bar, not to Foo.Bar
So if any one could help me out please let me know!!!! I can not sleep well until i understand the explanation of this.
It is about static methods versus methods in an instance of the object
instance methods are always accessed from 'below' whatever supertype the object may be cast to the method you get is from the lowest subtype overrriding that method.
class A { void writeIt( String s ) { system.out.println( s ); } static void writeIt2( String s ) { system.out.println( "no I wont" ); } } class B extends A { void writeIt( String s ) { system.out.println( "no I wont" ); } static void writeIt2( String s ) { system.out.println( "no I wont" ); } } B bObj = new B(); A aObj = (A)bObj; // now aObj.writeIt( "x" ) and bObj.writeIt( "x" ) will give the same "no I wont" response. The object was created as a B and tat is where the search for the method start whatever it might be cast to.
But with the static methods it is different static methods are found through the table created for static class proberties when the class was defined. so: aObj.writeIt2( "x" ); // writes "x" as pr definition in A bObj.writeIt2( "x" ); // writes "no I wont" as pr definition in B
Insidentally this also apply to static variables. So general rule is to just not overwrite statics.
Boo hiss. answer abowe is not to your question at all.
It is about scopes.
the classname of the class you are defining is in the Outer scope to anything declared inside the class
class A { static String A = "something"; static String toString() { return "something else"; } // now inhere (and only here inside the class) 'A' is just a string // System.out.println( A ); will write "something" // and new A(); will give an error because A is a variable, not a classname. } but with the construct they use there actually is a class 'Bar' visible inside the class scope, so new Bar(); returns a reference to the static class Bar.
nasty bit of coding there. is there an 'obfusciated Java code' competition? A clear contender.
I have been trying to figure this one out myself but had to turn elsewhere to get the answer.
<paste> 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: code: package simon;
public class Foo { public static class Bar { private int num = 0;
public class Bar extends Foo { public void doIt() { System.out.println("Hello!"); }
public static void main(String[] args) { simon.Bar myBar = new simon.Bar(); myBar.doIt(); } }
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).) </paste>
Thanks for an very nice explanation but I still got a couple of questions.
If I am right your answer means that all that happens in this code is depending on the scope or in other words when each of the classes is declared!!
My question then is when does each of the class get declared, in what order does it happens?
My first thought would be in this order: Foo Foo.Bar Bar
Then I would guess Foo.Bar is over shadowed by Bar (in my oppinion Foo.Bar is in the scope of Bar since Bar extends Foo and Foo must exists before Bar)
How ever it must be the opposite around! When excuting the code I guess the declaration is taken place in this order: Foo Bar Foo.Bar
There for Bar is over shadowed by Foo.Bar
But I can not explain why!!!
JakobA wrote this interesting comment: but with the construct they use there actually is a class 'Bar' visible inside the class scope, so new Bar(); returns a reference to the static class Bar.
Perhaps you could explain why a bit further, cause I guess this is the key to everything? In what order, and why, is the scopes taken place?
Simonvalter wrote: In the top-level class Bar, the declaration of Foo.Bar is not in scope at the time that top-level Bar is declared.
How come? Even If I see it is wrong my guess would be: Foo Foo.Bar Bar
Simonvalter also wrote this interesting comment: 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.
How is it possible that the names is identical? Is it just in this particular scope in this code or is this a rule: A static member class inside an class in a package or the default package appears at the same "level" as an other top-level class in the same package or in the default package. CORRECT ME IF I AM WRONG HERE!!
So if you guys could explain why the order of the scopes are like they are it would be great!
Foo.Bar is inside the scope of top-level Bar Inside the scope of top-level Bar, Foo.Bar is named Bar or Foo.Bar There for Foo.Bar is initiated instead of top-level Bar because Foo.Bar is shadowing Bar.
The nearest/"most inner" definition of a class name is the valid class! The nearest/"most inner" definition always shadowing an outer class with the same name!
Then I guess the scope is taken place like: Bar-scope-start Foo-scope-start Foo.Bar-scope-start Foo.Bar-scope-end Foo-scope-end Bar-scope-end
>> Foo.Bar is inside the scope of top-level Bar true enough, but it sortof overcomplexifies the situation.
The thing is that the name 'Bar' of 'top-level Bar' is OUTSIDE of the scope it defines. Just like a method name is outside the local scope of the method.
public void faculty( // name of method is outside local scope int faculty // parameters to method are inside local scope ) { // basic scope rule is "first check local scope, if not found extend search to outer scope(s)" // so here in the methods local scope 'faculty' is the int parameter. not the method if ( faculty > 0 ) { //OK testing param value return faculty( faculty-1 ) * faculty; //ERROR method name is shadowed. We cannot see it from here } else { return 1; } }
and likewise in top-level Bar's local scope the 'Bar' visible is the one defined inside that scope.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.