• 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
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Question of the day

 
mister krabs
Posts: 13974
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Thomas Paul
mister krabs
Posts: 13974
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Ranch Hand
Posts: 76
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 76
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Forget about my previous posting.
I now realize it misses the point.
 
Thomas Paul
mister krabs
Posts: 13974
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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!
 
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

if no, then why does reflection on an interface find toString()?

I don't find toString().
 
Thomas Paul
mister krabs
Posts: 13974
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 13974
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 13974
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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 ]
 
Author and all-around good cowpoke
Posts: 13078
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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
Posts: 13974
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 13078
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 13974
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 867
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
reply
    Bookmark Topic Watch Topic
  • New Topic