24

I have the following code and it doesn't work: the error both methods have same erasure appears.

public class Foo<V>  {
    public static void main(String[] args)  {
    }

    public void Bar(V value)  {
    }

    public void Bar(Object value)  {
    } 
}

Also I have this code:

public class Foo<V>  {
    public static void main(String[] args)  {
    }

    public void Bar(B value)  {
    }

    public void Bar(A value)  {
    }
}

class A  {
}

class B extends A  {
}

And this works. In the first case V is a child of Object, just like in the second case B is a child of A. Then why the first case results in error, while the second compiles successfully?

EDIT: What should I do to achieve method overloading, without raising an error?

parsecer
  • 4,758
  • 13
  • 71
  • 140
  • 2
    Because [type erasure](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html) affects the first, but not the second. – Oliver Charlesworth Apr 16 '17 at 21:51
  • 1
    [Type erasure](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html). When the generic is erased, it changes from `Bar(V value)` to `Bar(Object value)`. – Elliott Frisch Apr 16 '17 at 21:51
  • 1
    Possible duplicate of [Method has the same erasure as another method in type](http://stackoverflow.com/questions/1998544/method-has-the-same-erasure-as-another-method-in-type) – Mike Nakis Apr 16 '17 at 21:51
  • 1
    *"`V` is a child of `Object`"*. No. `V` is a type parameter that can be any subclass of `Object`, but also `Object` itself. So as far as compiler is concerned, `V` could be an `Object` and hence there is no difference between the two methods. – Andreas Apr 16 '17 at 22:00
  • The proposed duplicate gives the best explanation of why the rules are the way they are--it's for backward compatibility with raw generic types. If it weren't for that, Java could have allowed this kind of syntax pretty easily, and only generated an error if you use it on a `Foo` but not on `Foo`. – ajb Apr 16 '17 at 22:21

2 Answers2

34

What should I do to achieve method overloading, without raising an error?

Simple: don't try to overload the method with parameters with the same erasure.

A few options:

  1. Just give the methods different names (i.e. don't try to use overloading)
  2. Add further parameters to one of the overloads, to allow disambiguation (ideally only do this if you actually need those parameters; but there are examples in the Java API where there are junk parameters simply to avoid overloading issues).
  3. Bound the type variable, as suggested by @Kayaman:

    <V extends SomethingOtherThanObject>
    
Community
  • 1
  • 1
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • 5
    I vote for #1... Overloading is a convenience. There's never any _need_ to provide method overloading (except perhaps some complex cases involving reflection to look up methods by name). – ajb Apr 16 '17 at 22:19
  • 1
    @ajb indeed. Languages like [go](https://golang.org/) simply don't allow overloading at all, demonstrating that it's entirely workable to avoid it. – Andy Turner Apr 16 '17 at 22:23
6

V isn't "a child of Object". V is an unbounded generic type that erases to Object, resulting in the error. If the generic type were bounded, such as <V extends Comparable<V>>, it would erase to Comparable and you wouldn't get the error.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
Kayaman
  • 72,141
  • 5
  • 83
  • 121