This week's book giveaway is in the Mac OS forum.
We're giving away four copies of a choice of "Take Control of Upgrading to Yosemite" or "Take Control of Automating Your Mac" and have Joe Kissell on-line!
See this thread for details.
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Question of the day Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Question of the day" Watch "Question of the day" New topic
Author

Question of the day

Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Do interfaces inherit from Object?
if no, then why can I run toString() against a pointer to an interface?
if yes, then how can an interface inherit an implementation?
[ changed the "if, no..."]
[ April 15, 2003: Message edited by: Thomas Paul ]

Associate Instructor - Hofstra University
Amazon Top 750 reviewer - Blog - Unresolved References - Book Review Blog
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Thank you Thomas. This question is very interesting.
Cloneable.class.getSuperclass();
null
An interface does not extends from Object
Object.class.isAssignableFrom(Cloneable.class);
true
However the VM has taken actions to ensure a n interface is castable to Object

Object.class.getMethods().length;
9
There are nine public methods declared in Object class
Cloneable.class.getMethods().length);
0
However an interface inherits none of them

Test.class.getMethods().length);
10
But our class it does inherits them, and also adds main.
Cloneable.class.getMethod("toString", null);
NoSuchMethodException
Because an interface does not inherit from Object

new Cloneable(){}.getClass().getMethod("toString", null);
public java.lang.String java.lang.Object.toString()
However such method is found on an object implementing the interface because getMethod searches first the proper class of the object, then its superclasses and later the superinterfaces.

[ April 12, 2003: Message edited by: Jose Botella ]

SCJP2. Please Indent your code using UBB Code
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
if interfaces don't inherit the methods of the Object class then I shouldn't be able to do this:

Since I does not inherit the methods of Object, the compile should fail. However...
The JLS specifies that interfaces must declare a public abstract method for all public methods in the Object class.
But it isn't that simple. Take this case:

This should compile if interfaces don't inherit the Object class clone() method which is protected (Bug Id 4479715). Prior to the 1.4.1 release of java this would give a compile error saying that the interface could not override the clone() method. Fixed? Not really. All that was done is that non-public methods are filtered from the interface. Look at this example:

This should give the message "cannot resolve sysmbol" since the Set interface doesn't inherit the clone() method. Instead it gives this message: "clone() has protected access in java.lang.Object". This is Bug Id 4644627.
As stated in the evaluation of Bug Id 4479715:

The root of the problem is that javac represents an interface using the same representation that it will put it into the class file; that is, an
interface extends Object. That doesn't agree with the specification in 9.2, which says that the public members of Object are inserted directly into the interface but the interface doesn't extend Object.

So the answer is that interfaces do inherit from Object but it is a bug and they shouldn't.
[ April 15, 2003: Message edited by: Thomas Paul ]
John Zoetebier
Ranch Hand

Joined: Mar 28, 2003
Posts: 76
interface I {}
public class A implements I {}
public class B {
public static void main(String[] args) {
I i = new A();
i.toString();
}
}

This is polymorphism at work.
i is a reference of type I that points to an actual object of type A.
At runtime the method of the actual object is invoked, not the method of the reference type !
This rule applies only to instance methods.
Instance fields use shadowing and static methods use hiding.
The effect is the same.
A reference to a class field or static method is resolved at compile time. A field reference and a static method are both derived from the reference type, not the actual object at runtime.
John Zoetebier
Ranch Hand

Joined: Mar 28, 2003
Posts: 76
Forget about my previous posting.
I now realize it misses the point.
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Originally posted by John Zoetebier:
Forget about my previous posting.
I now realize it misses the point.

Great! I guess my explanation made sense after all!
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
if no, then why does reflection on an interface find toString()?
I don't find toString().
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Originally posted by Marlene Miller:
I don't find toString().

I used the wrong example. If an interface doesn't inherit the methods of the Object class then I shouldn't be able to compile this:

If the toString() method isn't part of the interface then the above should give a compile error.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
The JLS specifies that interfaces must inherit the public interfaces of all methods in the Object class.
As I understand the JLS, an interface with no direct superinterfaces implicitly declares abstract methods corresponding to those methods in Object. It does not inherit the methods from Object. JLS 9.2
[ April 15, 2003: Message edited by: Marlene Miller ]
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Originally posted by Marlene Miller:
As I understand the JLS, an interface with no direct superinterfaces implicitly declares abstract methods corresponding to those methods in Object. It does not inherit the methods from Object. JLS 9.2
[ April 15, 2003: Message edited by: Marlene Miller ]

You are correct, Marlene. I have corrected my wording so others won't be led astray.
This doesn't change the fact that interfaces do inherit all the methods of Object no matter what the JLS says. None of the compilers (including Sun's) are following JLS 9.2.
[ April 15, 2003: Message edited by: Thomas Paul ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Thomas, do you see how the following example captures the same issues as your example? (Or do I still misunderstand the question?)
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Originally posted by Marlene Miller:
Thomas, do you see how the following example captures the same issues as your example? (Or do I still misunderstand the question?

It's a different problem. Your interface I contains method m(). The compiler can look and say that yes, any I object must cointain method m(). But does it contain method toString()? Why? Where did it get it from? The JLS tells us that every interface without a superinterface must contain an abstract representation of the public methods (and only the public methods) of the Object class. But this isn't the case based on the two examples from my post above. The way the java compilers are implemented, interfaces are inheriting (not having an abstract representation inserted in them) not just the public methods but all of the methods of the Object class. This causes some strange bugs, most of them esoteric and not really a problem. You can go to the Bug parade to see the bugs listed in my post above.
[ April 15, 2003: Message edited by: Thomas Paul ]
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12792
    
    5

I used the wrong example. If an interface doesn't inherit the methods of the Object class then I shouldn't be able to compile this:

--------------------------------------------------------------------------------
If the toString() method isn't part of the interface then the above should give a compile error.

I am trying to figure out what error you expect to see. Seems to me you have an object created with new A() which naturally has a toString() inherited from Object.
Bill
[ April 15, 2003: Message edited by: William Brogden ]
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Bill, the compiler shouldn't be looking at A. The compiler sees that I am trying to run the toString() method of I. But I doesn't have a toString() method.
Look at this:

Compiling this gives me an error because even though p is a Child object, the compiler looks in Parent for the m1() method and doesn't find it.
Now change p.m1() to p.toString() and it compiles. Why is toString() a method of the interface? If the interface doesn't extend Object, shouldn't I get a compile error?
***See the posts above for the explantion as to why you don't get a compile error.***
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12792
    
    5
Seems to me this is just another case of the compiler assuming you know what you are doing. How could there ever be a toString() call that can't be resolved?
Bill
[ April 16, 2003: Message edited by: William Brogden ]
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
The compiler never assumes anything. The JLS specifies that when an interface is compiled, an abstract representation of every public method in the Object class must be copied into the interface. That means if I do something like this, I get a compiler error:

I get this error:
I.java:2: toString() in I cannot override toString() in java.lang.Object; attempting to use incompatible return type
But I should be able to do this:

This interface could never actually be used, of course.
I'm running Java 1.4.0 so I get the same compile error that I get when I try to override toString(). This is a reported bug that has been corrected in Java 1.4.1. But the correction was to mask the non-public methods inherited by the interface, not to correct the fundamental disagreement with the JLS. The problem is that what the JLS says and what actually is happening are two different things.
Here is the comment from Sun on bug 4526026:

A compiler bug. javac implements the rules using inheritance instead of by explicitly inserting the members as per JLS2 9.2 bullet 3. This subtle and generally innocuous bug is the only known symptom (well, see also 4479715) of this compiler shortcut. Implementing the JLS2 directly would require making special cases in many places in the compiler for very little benefit. We are more likely to fix this by filtering out protected members that were inherited into an interface. [ TP-this is what they did ]
The JLS2 is correct as it stands, as it is hard to imagine a more concise specification that has the desired effect.

So as to the question, does an interface inherit from Object? The JLS says no but in fact they do.
Francis Siu
Ranch Hand

Joined: Jan 04, 2003
Posts: 867
hi Thomas,William,Marlene,John and Jose
Let me summarize the point to let people easy to trace what the problem is Thomas found out.
Jose found out
Cloneable.class.getSuperclass();
null
An interface does not extends from Object
Object.class.getMethods().length;
9
There are nine public methods declared in Object class
Cloneable.class.getMethods().length);
0
However an interface inherits none of them
Cloneable.class.getMethod("toString", null);
NoSuchMethodException
Because an interface does not inherit from Object

Thomas said
if interfaces don't inherit the methods of the Object class then I shouldn't be able to do this:

Thomas point out

Since I does not inherit the methods of Object, the compile should fail.
If the toString() method isn't part of the interface then the above should give a compile error.

So as to the question, does an interface inherit from Object? The JLS says no but in fact they do.

Originally posted by Marlene Miller:
An interface with no direct superinterfaces implicitly declares abstract methods corresponding to those methods in Object. It does not inherit the methods from Object. JLS 9.2

So, it is easy to trace what the problem is Thomas found out.


Francis Siu
SCJP, MCDBA
 
GeeCON Prague 2014
 
subject: Question of the day