0

I agree that without extending class B the output is "1233" but why if extending class B with A the code doesn't compile ?

public class SomeClass {

    public static class A {

        public void f(int x){
            System.out.print("1");
        }

        public void f(Object x){
            System.out.print("2");
        }
    }

    public static class B // extends A {

        public <T> void f(T x){
             System.out.print("3");
        }
    }

    public static void main( String[] args){
        A a=new A();
        B b=new B();
        a.f(3);
        a.f("hello");
        b.f(3);
        b.f("hello");
    }
}
akash
  • 22,664
  • 11
  • 59
  • 87
tami
  • 45
  • 6

5 Answers5

3

The method signatures results in name clash, following two method signatures are having the problem of name clash as generic method is not actually overriding the former one. After type erasure both will have the same signature.

public <T> void f(T x){...}
public void f(Object x){...}

Method which is declared in B is not overriding the method of A as method is said to be overridden if,

JLS 8.4.8.1. Overriding (by Instance Methods)

An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true:

  • A is a superclass of C.
  • C does not inherit mA.
  • The signature of mC is a subsignature (§8.4.2) of the signature of mA.
    ....

Here following is valid and compiles fine,

public static class A {

    public <T> void f(T x) {
        System.out.print("3");
    }
}

public static class B extends A {

    @Override
    public void f(Object x) {
        System.out.print("2");
    }

}
akash
  • 22,664
  • 11
  • 59
  • 87
  • Is it correct to say that: method can't be overridden by generic method (in other words parent can be generic but not it's descendant)? – tami Aug 16 '16 at 05:26
  • @tami Not exactly. Same signature as the base method is also valid and some other signatures are also valid in case of generic method. – akash Aug 16 '16 at 05:31
  • 1
    "Same signature as the base method is also valid" , does it mean that to write "public void f(T x)" in both classes ( A and B) will be correct? Is it also be an override if I put "public void f(int x)" (not only "public void f(Object x)")? – tami Aug 16 '16 at 08:38
1

You cannot compile the above classes because of the type erasure problem.

The method that you have in your base class is generic and matches f(Object x) in your parent class. This will happen at compile time.

public void f(Object x){}
public <T> void f(T x){}

See this Oracle documentation about Type Erasures.


However, you can keep int method and it will compile fine:

class A {
      public void f(int x){
         System.out.print("1");
      }
}

public class B extends A
{
      public <T> void f(T x){
         System.out.print("3");
      }
}
Raman Sahasi
  • 30,180
  • 9
  • 58
  • 71
1

Java generics uses type erasure. javac will have clash while resolving

public <T> void f(T x);
public void f(Object x);

Both are same with respect to compiler javac.

Adding another example:

class Test{
   void add(Set<Integer> ii){}
   void add(Set<String> ss){}
}

This limitation is part of the language syntax, not the Java runtime itself. Essentially, this rule is intended to avoid conflicts in legacy code that still uses raw types.

Please refer to the above answer.

Community
  • 1
  • 1
Vinay Veluri
  • 6,671
  • 5
  • 32
  • 56
0

A method can only be overridden in derived class if the argument list are exactly same as that of the overridden method and the return type should be the same or a subtype of the return type of overridden method (in parent class).

You can override following method

public <T> void f(T x) {
          System.out.print("3");
      }

You can find more information on Overriding and Hiding Methods

ravthiru
  • 8,878
  • 2
  • 43
  • 52
0

The Problem because of The method f(String) is ambiguous for the type B in SomeClass, you can fix it like this

public class SomeClass {
    public static class A {
        public void f(int x) {
            System.out.print("1");
        }

        public void f(Object x) {
            System.out.print("2");
        }
    }

    public static class B extends A {
        public void f(Object x) {
            System.out.print("3");
        }
    }

    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        a.f(3);
        a.f("hello");
        b.f(3);
        b.f("hello");
    }
}

And will work, hope that help.

MaJiD
  • 74
  • 1
  • 8