13

So, I have this bit of wild, crazy code, that is making the compiler spit in my face for some hours the following error:

The inherited method Object.clone() cannot hide the public abstract method in IOrderable<T>

The culprit classes are the following (the error appears right in the T of the generic):

public class MyInterval<T extends Xpto & Successorable<T>> implements Cloneable {
    public MyInterval<T> clone(){
        MyInterval<T> it = null;
        try {
            it = (MyInterval<T>) super.clone();
            it.max = it.max.clone();
            it.min = (T) it.min.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return it;
    }
}

public interface Xpto {}

public interface Successorable<Y> extends IOrderable<Y> {
    Y suc();    
}   

interface IOrderable<J> extends Rankable<J>, Cloneable {
    boolean greaterEq(J e);
    J clone();
}

public interface Rankable<P> {
    int rank(P e);
}

Yes, they seem kinda random. They solely exist to test some weird things in a compiler/java_byte_code_instrumentation-like project I am doing. How can I make this work while keeping the logic intact?

Thanks

devoured elysium
  • 101,373
  • 131
  • 340
  • 557

5 Answers5

7

I encountered the same compilation error, and as far as I can tell, this is an edge case in the specification for intersection types (multiply-bound generic types), and there is no solution possible.

A small test case:

public interface InterfaceA {
    public Object clone();
}

public interface InterfaceB {}

public class ClassA<T extends InterfaceA> {} // ok

public class ClassB<T extends InterfaceA & InterfaceB> {} //not ok

You can't have an intersection type containing any interfaces containing any method whose signature matches a non-public method on the base class (in this case, implicitly Object). This is not specific to Object or clone, however:

public abstract class Base {
    protected abstract void m();
}

public interface Interface {
    public void m();
}

public class Class<T extends Base & Interface> {} // not ok

Here's the relevant Oracle bug, marked as "Not a defect".

Here's the relevant Eclipse bug, where the compiler was modified to produce the same error to match javac. This appears to have been a change for Indigo 3.7, which explains why some people could reproduce and others couldn't.

paraquat
  • 641
  • 6
  • 9
3

I think this tutorial explains the problem and you should be able to figue out a solution. The problem is when a type parameter has several bounds.

The below code replicates the error.

interface Xpto
{
}

interface Xable < T >
{
    T clone ( ) ;
}

class MyStuff < S extends Xpto & Xable < S > >
{
}

However the below code is basically the same but without the compiler error.

interface Xpto
{
}

interface Xable < T > extends Xpto
{
    T clone ( ) ;
}

class MyStuff < S extends Xable < S > >
{
}
emory
  • 10,725
  • 2
  • 30
  • 58
  • I'm getting a different error with this: `clone() in java.lang.Object cannot implement clone() in Xable; attempting to assign weaker access privileges; was public`. Also, FWIW, making `Xable` an abstract class with an abstract `clone` method fixes it. – trutheality Jul 27 '11 at 03:20
0

I got this error too, however I think I came to it a bit differently....

the following code works fine: (it is nested within another class, so the interface did not need to have public methods).

interface A{}
class B{
    class C extends B implements A{ }
}

the problem occurs when you add a non-public method into interface A, and implement it non-publically in class B.

interface A{
    void doeet();

}

class B{
    void doeet(){};
    class C extends B implements A{
    }
}

Looking at your code, it seems to be similar in that some of the methods in the interfaces haven't been declared public.

Liang
  • 383
  • 4
  • 13
  • You said: "the problem occurs when you add a non-public method into interface A, and implement it non-publically in class B." Can I ask you a question for I'm new to Java. As far as I know, all methods in an interface must be marked as "public" or "abstract". Even if , we don't marked them as "public" , it is implicitly declared as public in order to be visible for the implementing classes. So how can we "add a non-public method in interface A" as you said? Do I misunderstand anything? Thank you! – Huy Than Mar 20 '13 at 06:51
0

I had the same error.

In my case I forgot the public keyword in front of a method that had to be implemented as the class containing it implemented an interface defining it.

Piet Hein
  • 184
  • 2
  • 16
0

I solve this problem implementing clone as public

Matias
  • 1