wood burning stoves 2.0*
The moose likes Java in General and the fly likes Error in the java language? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Java 8 in Action this week in the Java 8 forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Error in the java language?" Watch "Error in the java language?" New topic
Author

Error in the java language?

johnny zee
Greenhorn

Joined: Sep 28, 2002
Posts: 7
I am doing the Programmer certification and just went through the objects and classes part.
Now, the certification study guide (Complete Java 2 Certification Study Guide, published by Sybex) states quite clearly that:
"... anonymous inner classes are unique to member scopes; you cannot have anonymity with a member class."
I understand this to mean that an anonymous class may not be a class member. However, testing it, I wrote the following piece of code:
1:public class OuterClass {
2:public Object memberObject = new Object() { public String toString() { return "I override toString"; } };
3:
4:public static void main(String[] args) {
5:OuterClass instance = new OuterClass();
6:System.out.println(instance.memberObject);
7:}
8:}
The memberObject member is an anonymous inner class extending Object, which, according to the study guide, would not be legal. However, not only does the code compile, when run it invokes the overridden toString method, outputting "I override toString".
As a twist, whenever the anonymous inner class definition contains method or member declarations, these do not seem to be visible to the rest of the code, which seems inconsistent with the fact that methods can be overridden.
Am I missing something? Did I stumble upon an error in the Java 2 implementation (unlikely)? Is the certification study guide in error? And what's with the seeming disparity which allows me to override methods in the child class but not introduce new members?
I'd appreciate it if anyone could shed light on any of these topics.
Joel McNary
Bartender

Joined: Aug 20, 2001
Posts: 1815
I can't answer the question about whether the sutdy guide is right or wrong, but I can address:

As a twist, whenever the anonymous inner class definition contains method or member declarations, these do not seem to be visible to the rest of the code, which seems inconsistent with the fact that methods can be overridden.

There's a difference between overriding methods and creating new methods. When you create a new (anonymous) Object, the reference to that object is of type Object. Therefore, you can only be certain that the methods available to it are those provided by Object. (This holds true for any type T, but we'll just use Object here)
This is the same as if you extended a class. Look at:

While this is legal in weakly-typed languages (like Objective-C), in Java the compiler will complain because, even though the actual object is of type String, the reference to the object is of type Object, which does not have a .charAt() method.
Note that if you used relection on your anonymous class you would be able to run the additionally-defined methods.

Result:
C:\user\java\sources>java Test
This is a String
myString


Piscis Babelis est parvus, flavus, et hiridicus, et est probabiliter insolitissima raritas in toto mundo.
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
The memberObject member is an anonymous inner class extending Object, which, according to the study guide, would not be legal. However, not only does the code compile, when run it invokes the overridden toString method, outputting "I override toString".
memberObject is not an anonymous inner class. It is a reference to an object of an anonymous inner class. Your example still has member scope because the instantiation occurs in the OuterClass constructor that is generated for you. To prove that, here is the decompilation of your code:

Am I missing something? Did I stumble upon an error in the Java 2 implementation (unlikely)? Is the certification study guide in error?
Yes, No, No.
And what's with the seeming disparity which allows me to override methods in the child class but not introduce new members?
I'm not sure what you're getting at here, but if you are referring to the anonymous inner class, as Joey pointed out, you can access it thru reflection.


Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius - and a lot of courage - to move in the opposite direction. - Ernst F. Schumacher
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
I understand this to mean that an anonymous class may not be a class member.
Correct - the class may not be a member class. However an instance of the class may be assigned to a member variable. Not the same thing, though I can see how confusion can occur here...
However, testing it, I wrote the following piece of code:
In your code, memberObject is member variable. The class created by new Object() { ... } is an anonymous class whose scope is limited to the instance initializer in which it occurs (the latter part of one line). This may sound strange, since obviously the object created exists and can be used after that line. But when I say the class scope is limited to one line, that means that the compiler will not let you refer to any attributes of the class which were not part of its superclass - Object in this case. Consider Joel's example - if the new String() {...} class were in scope outside the line in which it was created, then the compiler would let you use the myString() method. But no, the compiler complains that it can't find a myString() method to access - it's not in scope.
If you want to make a member class (as opposed to member object which is initialized with an anonymous class), you would have to use the word "class" in the declaration, e.g.

Here MemberClass is a member class, in scope anywhere inside the Test class. So you can now access the myString() method from within test(), for exaqmple.
Note that "scope" is a concept enforced by the compiler, not the JVM. If you look at the class files, you get a different perspective. For example OuterClass$1 looks like a full-fledged class which you could access from anywhere, as far as the JVM is concerned. (If you use the right syntax.) The idea that its scope was limited is something that the compiler enforced. Once we're past the compiler, things look different. You can also violate scope using reflection, as noted previously. This doesn't mean that the class was really in scope; it means that reflection does not obey rules of scope. Reflection can be used to circumvent several of Java's rules (like the private modifier) - doesn't mean they're not rules, it just means they're not absolute. Reflection is a special case, independent of the rules enforced by the compiler.


"I'm not back." - Bill Harding, Twister
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Error in the java language?
 
Similar Threads
anonymous classes
Accessing methods in an anonymous inner class
How to Contruct an Inner Class Instance
Anonymous Inner Class
Anonym. inner class extending its enclosing class