Error overriding shared sets in Java

When I try to override a method that takes a List<String> , I get the following compilation error .

Several markers on this line:
- The getname(List<Integer>) method of type child must override or implement the supertype method
- Name clash: getname(List<Integer>) method of type child has the same erasure as getname(List<String>) type parent , but does not override it

I got the impression that because of erasing, the method that takes the List<String> method and the subclass that takes the List<Integer> value are considered overridden, since the signature of both methods is the same after the erase.

Here is the definition of the method signature, which includes erasure.
I do not understand why this error occurs and what exactly it means.

My code is below:

 class parent { public void getname(List<String> num) { System.out.printf("parent class: %s",num); } } class child extends parent { @Override // here is the compile error public void getname(List<Integer> num) { System.out.printf("child class: %s",num); } } 
0
java override generics inheritance
source share
5 answers

List<String> and List<Integer> are different types, and getname(List<String> num) and getname(List<Integer> num) are methods with different signatures. Thus, the second does not cancel the first. Thus, child cannot extend parent with this method.

+3
source share

The error message is pretty clear: it has the same erasure, but the types do not match, so it is not considered an override. A List<Integer> not a List<String> ; it cannot refer to it as an override (for which it is necessary that the types match exactly), nor overload (which would require that the erasures be different).

+3
source share

Basically your impression is wrong, and it is impossible. JLS considers this illegal.

From 8.4.2 :

The signature of method m1 is a signature of the signature of method m2 if:

  • m2 has the same signature as m1, or

  • the signature m1 coincides with the erasure (Β§4.6) of the signature m2.

Two method signatures m1 and m2 are equivalent to overriding, if m1 is a sub-sticker of m2 or m2, is a sub-voltage of m1.

The bold bit is important because it does not say that β€œerasing m1 is the same as erasing m2”. This is actually allowed (and some more confusing examples):

 class A { void process(List<String> list) {} } class B extends A { @Override void process(List list) {} // |List| is erasure of List<T> } 

Since the signature of the B.process method is an erasure of A.process , this is an override.

According to 8.4.9, an example like the OP can be overload, because signatures do not override the equivalent:

If two methods of the class ... have the same name, but signatures are not equivalent to overriding, then the method name is considered overloaded.

Except that this is definitely a compile-time error ( 8.4.8.3 ):

This is a compile-time error if a declaration of type T has a member method m1 and there exists a method m2 declared in T, or a supertype T such that all of the following conditions are true:

  • m1 and m2 have the same name.

  • m2 is available from T.

  • The signature m1 is not a sub-label (Β§8.4.2) of the signature m2.

  • The signature of m1 or some redefinition of the m1 method (directly or indirectly) has the same erasure as the signature of m2 or some method of m2 redefines (directly or indirectly).

These restrictions are necessary because generic funds are realized through erasure. From the above rule it follows that methods declared in the same class with the same name must have different erasures ....

+2
source share

To add to the answers already here, I want to comment on the signature of the methods is the same after erasure ... but the compiler checks the type of the method before deleting it.

You can do something like creating a "different" Parent class, for example

 class Parent { public void getname(List<Integer> num) { System.out.printf("child class: %s",num); } } 

compile it, use it to compile the Child class, and then mix the original Parent.class and Child.class in the same JVM without problems, avoiding compiler checking and using type erasure.

But as long as the compiler notices that it is doing something similar β€œin one run”, it will fail for the reasons explained by Ashot and Louis.

0
source share

The indicated error is clearly related to the @Override annotation. When checking annotations (which, I believe, should happen at the very early stage of the compilation process), type deletion did not happen. Thus, the types of List are not the same as List, and you get a warning. But even without this annotation, I get an error message

  name clash: getname(java.util.List<java.lang.Integer>) in child and getname(java.util.List<java.lang.String>) in parent have the same erasure, yet neither overrides the other class child extends parent{`. 

This error clearly states that they have the same erasure, but still none of them pass. Therefore, Java, in principle, does not allow this. I can understand that this will lead to a lot of problems / embarrassment, if that is permissible. E.g. if someone calls new Child().get_name( new List<String> () ) , he cannot be allowed for the Child method, which violates the concept of riding. Therefore, it is right that it is prohibited.

0
source share

All Articles