0

I have two classes as follows

class QueryResult:

public class QueryResult
{
...
public static List sortResults(boolean ascending, List<QueryResult> toSort)
    {   ...
    }
}

and class CaseResult:

public class CaseResult extends QueryResult
{
...
public static List sortResults(boolean ascending, List<CaseResult> toSort)
    {   ...
    }
}

I am getting the following error:

Name clash: The method sortResults(boolean, List) of type CaseResult has the same erasure as sortResults(boolean, List) of type QueryResult but does not hide it CaseResult.java

I tried answers under the similar question Java generics name clash , has the same erasure but got more errors. I think I may misunderstand something or those answers do not fit my case.

Could someone please provide any solutions or explain more to help me understand? Thank you all.

Smiley
  • 190
  • 1
  • 12
Catherine
  • 83
  • 1
  • 6
  • The solution is to use different names for the methods, the problem is that you are providing `static` methods which have same signature after type erasure so `CaseResult.sortResults(...)` implementation can't be chosen at compile time, or rather the compiler is not designed to find the correct implementation even if it would be possible, check: https://stackoverflow.com/questions/14002965/java-name-clash-have-the-same-erasure-neither-hides-the-other – Jack Jul 06 '17 at 03:36
  • try it using super() https://stackoverflow.com/questions/3767365/super-in-java – Kenry Sanchez Jul 06 '17 at 03:58
  • Thank you for your explanation, @Jack . It is a large open source framework downloaded from a website so rename a method may mess up the whole system in my case. I will try to rename if no other solution can be found. – Catherine Jul 07 '17 at 05:29
  • @KenrySanchez, I tried to add super() in sortResults function under CaseResult but it didn't work. Maybe I used it incorrectly. Could you please explain more? Thank you. – Catherine Jul 07 '17 at 05:35

2 Answers2

1

The reason for the error is covered in Darshit Chokshi's answer. However, since a solution/alternative has not been posted yet, try the following:

You are trying to override the sortResults() method in such a way so that you can sort lists with different elements. However, when overriding you need to have the same type signature. The signature looks similar in your case, but since the elements in the List differ - the compiler realises List< QueryResult> and List< CaseResult> is different, but due to type erasure in Java, it would be uncertain which method it should be calling - i.e. should it call the super class method or the subclass method.

Instead of overriding, rather change the original method in the super class (in your case, QueryResult) so that it can handle anytype of List element. You can use wildcard capturing to accomplish this:

public class QueryResult {
...
public <T> static List<T> sortResults(boolean ascending, List<T> toSort) {   
    ...
    }
}

This method receives a list and will infer the element type, assigning the element type to the generic type parameter T. Whenever you then want to refer to the element type in the body of the method, instead of using the element type name (previously either QueryResult or CaseResult), now you would use the generic type variable T instead.

You can also put further bounds on this variable if required (i.e. if the list element needs to be a subtype of QueryResult you can say < T extends QueryResult>), this will force Java to do a type check on the List and what type of elements it may have.

A further comment on your original code. Be very careful of using raw types in new generic code - you are returning a list as a raw type: List, without specifying what the element type of the list is i.e. a parameterised type: List< SomeActualType>. This can cause many problems and is not advised. The Java creators kept this form of coding in Java for backward compatibility of code that existed before generics, but it is strongly advised not to code in this manner for new written code.

You can read up more about the raw type vs parameterised type and the pitfalls of using raw types, as well as more information on wildcard capturing and bounds, in the textbook:

Effective Java, by Joshua Bloch
    Section: Generics
    Item 23: Don't use raw types in new code
    Item 28: Use bounded wildcards to increase API flexibility
Smiley
  • 190
  • 1
  • 12
  • Another alternative would be to create an interface Result< T>, with all the methods from QueryResult. Result class will have the method: public static List sortResults(boolean ascending, List toSort). Then have: QueryResult implement Result and CaseResult implement Result. Then you can keep your original code you posted. Using interfaces is often a better design choice than inheritance. – Smiley Oct 20 '17 at 15:01
0

As per Java Documentation,

If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.

The distinction between hiding a static method and overriding an instance method has important implications:

  • The version of the overridden instance method that gets invoked is the one in the subclass.
  • The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass
Darshit Chokshi
  • 589
  • 3
  • 13
  • Thank you. Your explanation helped. Do you have any detailed solutions to my case? – Catherine Jul 07 '17 at 05:38
  • @Catherine If you want to keep this structure and don't want to change your method name as well than you can create an interface, implement it and use it as type of list parameter in your method of both class. OR change the type of list parameter in your subclass as parent class. I hope got my point. – Darshit Chokshi Jul 07 '17 at 05:52
  • Got you. I'll have a try. Thank you. – Catherine Jul 07 '17 at 21:27