7

When creating a default method in Java 8, certain Object methods are not callable from within the default method. For example:

interface I {
    default void m() {
        this.toString(); // works.
        this.clone(); // compile-time error, "The method clone() is undefined for the type I"
        this.finalize(); // same error as above.
    }
}

It seems that clone() and finalize() are the only methods from Object that are not allowed. Coincidently, these are the only methods of Object that are protected, but this question is in particular regard to default methods, as they will be inherited by classes that do extend java.lang.Object. What is the reason for this?

Raffi Khatchadourian
  • 3,042
  • 3
  • 31
  • 37
  • 1
    Possible duplicate of [Why is the clone() method protected in java.lang.Object?](http://stackoverflow.com/questions/1138769/why-is-the-clone-method-protected-in-java-lang-object) – Sean Apr 27 '16 at 15:42
  • 1
    @SPrashad I disagree. That question has nothing to do with why it's not callable in an interface's default method. – rgettman Apr 27 '16 at 17:09

1 Answers1

8

It's not a coincidence that the protected methods from Object are not available in a default method in an interface.

Section 9.2 of the JLS states:

If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.

An interface will not inherit anything from Object, but it will implicitly declare all public Object methods. This does not include any protected methods. This explains why clone and finalize can't be called; they are not declared in an interface.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • Interesting. I wasn't aware that interfaces do not inherit from `Object` when they declare `default` method. However, you cannot call a `default` method directly; it must be called on an object whose class directly or indirectly implements the interface. That class will no doubt inherit from `Object`. Thus, it should be safe to allow for this. Interesting design decision. – Raffi Khatchadourian Apr 27 '16 at 15:51
  • 2
    @RaffiKhatchadourian Just to clarify, interfaces **never** inherit from `Object`, regardless of whether there is a default method or not. They simply don't. The problem with inheriting from `Object` is that for example the `toString()` method could be overridden by any class implementing `I`, so which implementation should be chosen then? The one inherited by the interface or the one in the class that implements the interface? – biziclop Apr 27 '16 at 16:04
  • @biziclop If it's the case that interfaces **never** inherit from `Object`, then why is `Object o = i;` where `i` has a compile-time type of an interface legal? Actually, this seems related to http://stackoverflow.com/questions/6056124/do-interfaces-inherit-from-object-class-in-java. – Raffi Khatchadourian Feb 07 '17 at 18:54
  • It is legal due to this specific clause: [`The type Object, if C is an interface type with no direct superinterfaces (§9.1.3).`](https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.10.2). But this has no relevance as to inheritance, that is controlled by superclass/superinterface relationships. Interface types still don't inherit methods from `Object`. It only implicitly declares the same methods. The difference is rather subtle and seems unnecessary, but it exists. – biziclop Feb 07 '17 at 19:34