开发者

Can you do method overloading with generics and only change the generic type of the method signature?

开发者 https://www.devze.com 2023-03-31 15:26 出处:网络
If you don\'t use Jav开发者_如何学编程a Generics, I believe it\'s not possible to have two methods in the same class that differ only in their return type.

If you don't use Jav开发者_如何学编程a Generics, I believe it's not possible to have two methods in the same class that differ only in their return type.

In other words, this would be illegal:

public HappyEmotion foo(T emotion) {
    // do something
}   

public SadEmotion foo(T emotion) {
    // do something else
}   

Is the same true when overloading methods that return a generic type that may implement different interfaces, such as if the following two methods were present in the same class definition:

public <T extends Happy> T foo(T emotion) {
    // do something
}   

public <T extends Sad> T foo(T emotion) {
    // do something else
}   

Would this be illegal?


This is legal since the input parameter too differs based on the type..

For this reason, following is legal,

public <T extends Happy> T foo(T emotion) {
    // do something
}   

public <T extends Sad> T foo(T emotion) {
    // do something else
}

But following is not,

public <T extends Happy> String foo(T emotion) {
    // do something
}   

public <T extends Happy> T foo(T emotion) {
    // do something else
} 

Thanks...


This ran just fine.

public class Main {
    public static void main(String[] args){
        Main main = new Main();
        main.foo("hello");
        main.foo(new Integer(5));
    }

    public <T extends String> T foo(T emotion) {
        return (T) "test";
    }

    public <T extends Integer> T foo(T emotion) {
        Integer integer = 5;
        return (T) integer;
    } 
}


It will compile, but where you get into problems is if either Happy or Sad is a superclass of the other.

For instance, the following compiles:

public <T extends Number> T sayHi() {
    System.out.println("number");
    return null;
}

public <T extends Integer> T sayHi() {
    System.out.println("integer");
    return null;
}

However, you run into problems when you try to compile the following:

Integer test = sayHi();

In this case, you simply cannot add <Integer> to the front because Integer is still both a Number and an Integer.

However the following compiles

Double test2 = <Double>sayHi();

so basically as long as a Sad object cannot be an instance of a Happy object and visa versa, your code should work as long as you call it with the or in front of the method name.


You can use generic to distinguish the method in Java. The JVM doesn't see this type however provided the argument or return type is different it will still compile in the Sun/Oracle compiler. This doesn't compile for the IBM/eclipse compiler.

This shows you want is happening at the byte code level. http://vanillajava.blogspot.com/2011/02/with-generics-return-type-is-part-of.html


This is legal, as others have said. However, I want to point out what happens when types extend each other.

Let's say we have two interfaces (works for classes as well just change the signature):

interface Emotion {}
interface Happy extends Emotion {}

And two functions:

<T extends Emotion> void foo(T obj) {} // Referred as foo1
<T extends Happy> void foo(T obj) {} // Referred as foo2

If an object conforms to Emotion the JVM will choose foo1. If an object conforms to Happy the JVM will choose foo2 and not foo1. Notice the order of precedence. That is how the JVM resolves the ambiguity. However, this is only valid when you pass the generic parameter as an argument.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号