1

Question: Need to understand why in case of Program 1 getting this misleading error, but in Program 2 it gives correct error? Also why unlike toString(), equals(Object), and hashCode(), overriding clone() and finalize() inside interface is allowed?

Program 1

For below program getting misleading error:

FOO.java:10: error: finalize() in Object cannot implement finalize() in ClonerFinalizer

public class FOO implements ClonerFinalizer {
             ^
attempting to assign weaker access privileges; was public


interface ClonerFinalizer {
    default Object clone() {
        System.out.println("default clone"); return this;
    }
    default void finalize() {
        System.out.println("default finalize");
    }
}
    
public class FOO implements ClonerFinalizer {
//  @Override
//  public Object clone() {
//      return ClonerFinalizer.super.clone();
//  }
//  @Override
//  public void finalize() {
//      ClonerFinalizer.super.finalize();
//     }
    public static void main(String... args) {
        new FOO().clone();
        new FOO().finalize();
    }
}

But if uncommenting above commented code then it gives correct output.

Program 2

Unlike above program in below program clear/correct error

FOO.java:2: error: default method toString in interface ToStringer overrides a member of java.lang.Object

    default String toString() {
                   ^

1 error

interface ToStringer {
    default String toString() {
        System.out.println("default clone"); return "HI";
    }
}
            
public class FOO implements ToStringer {
    @Override
    public String toString() {
        return ToStringer.super.toString();
    }
            
    public static void main(String... args) {
        new FOO().toString();
    }
}
user207421
  • 305,947
  • 44
  • 307
  • 483
PANKAJ DUBEY
  • 173
  • 1
  • 1
  • 8
  • Followed this link: https://stackoverflow.com/questions/24016962/java8-why-is-it-forbidden-to-define-a-default-method-for-a-method-from-java-lan – PANKAJ DUBEY May 16 '23 at 18:50
  • 1
    It looks like a compiler error in java 8. I suppose it gets confused by the fact that `Object.finalize()` is declared as `protected`. – Mike Nakis May 16 '23 at 19:08
  • @MikeNakis Seems same to me. But why unlike toString(), ovrriding clone() and finalize() inside iterface is allowed? – PANKAJ DUBEY May 16 '23 at 20:04
  • 1
    According to Brian Goetz on the answer that you linked to, the only methods they disallow in interfaces are `equals()`, `hashCode()`, and `toString()`. This list of methods does not contain `clone()` and `finalize()`. You might ask okay, so, why? I do not know. – Mike Nakis May 16 '23 at 20:11
  • 2
    The compiler is correct and I wouldn’t even call the error message misleading. A few more clarifying words would be helpful, though. – Holger May 17 '23 at 07:32

1 Answers1

2

When a class inherits a method from an interface and from its superclass, the superclass method has precedence. This is regardless of whether any of the methods is abstract.

Therefore, when your FOO class does not declare the clone() and finalize() methods, it will inherit the protected methods from its superclass. The fact that the interface’s methods are default does not matter here. But the fact that these interface methods are implicitly public does matter, as the inherited protected methods are incompatible with the interface’s public declarations.

That’s exactly what the error message tells you, the inherited protected “finalize() in Object” cannot implement the public interface method “finalize() in ClonerFinalizer” because that would “assign weaker access privileges”.

The fact that superclass methods have precedence implies that you can never override a class’s method with an interface’s default method and therefore, it is impossible to provide an implementation for any of the methods of java.lang.Object without redeclaring the method in the implementation class.

The additional rule that you can’t override methods of Object with default methods is not necessary to enforce this. It’s just there to keep you from trying, so you don’t waste your time.

The reason why this doesn’t prevent you from declaring a clone() or finalize() method is simple: these declarations do not override a method.

Interfaces can’t have protected methods, hence, these protected methods do not exist in the interface in the first place and your declaration is not overriding them. You can check this by adding an @Override annotation—it will cause a compiler error as the method does not override a method.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • The additional rule that you can’t override methods of Object with default methods is not necessary to enforce this.--- You mean is a rule for public methods of Object class only right? Because in case of above Program 2, ToStringer interface it isn't allowing to override. Please correct me if I am wrong. – PANKAJ DUBEY May 18 '23 at 18:36
  • 1
    I think, you mean the correct thing. This sentence refers to the rule that prevents you from compiling the interface in the second example. As explained in the answer, it affects public methods only, because you can only override public methods in the interface in the first place. So we can say that it applies to *all* methods from java.lang.Object an interface can override, which is a better way to express the intention. But for non-public methods, this statement is [vacuously true](https://en.wikipedia.org/wiki/Vacuous_truth). – Holger May 22 '23 at 14:37