2011-08-29 24 views
8

Nếu bạn không sử dụng Java Generics, tôi tin rằng không thể có hai phương thức trong cùng một lớp chỉ khác nhau về kiểu trả về của chúng.Bạn có thể thực hiện phương thức nạp chồng bằng generics và chỉ thay đổi kiểu generic của chữ ký phương thức?

Nói cách khác, đây sẽ là bất hợp pháp:

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

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

là giống nhau đúng khi quá tải phương pháp mà trả về một kiểu chung chung mà có thể thực hiện các giao diện khác nhau, chẳng hạn như nếu hai phương pháp sau đây đã có mặt tại định nghĩa cùng một lớp:

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

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

Điều này có bất hợp pháp không?

+2

Bạn đã cố gắng biên dịch nó chưa? Trình biên dịch (tuân thủ) sẽ nhanh chóng cho bạn biết những gì là hợp pháp và những gì là bất hợp pháp. Một câu hỏi hay hơn sẽ là 'tại sao ... bất hợp pháp?' nếu bạn không hiểu lý do. –

Trả lời

5

này là hợp pháp kể từ khi thông số đầu vào quá khác dựa trên loại ..

Vì lý do này, sau đây là hợp pháp,

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

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

Nhưng đây không phải là,

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

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

Cảm ơn ...

2

Điều này đã chạy tốt.

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; 
    } 
} 
2

Nó sẽ biên dịch, nhưng khi bạn gặp vấn đề là nếu Happy hoặc Sad là lớp cha của người kia.

Ví dụ, sau đây biên dịch:

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

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

Tuy nhiên, bạn gặp vấn đề khi bạn cố gắng để biên dịch như sau:

Integer test = sayHi(); 

Trong trường hợp này, bạn chỉ đơn giản là không thể thêm <Integer> đến phía trước bởi vì Integer vẫn là một số và một số nguyên.

Tuy nhiên sau biên dịch

Double test2 = <Double>sayHi(); 

nên về cơ bản miễn là một đối tượng Sad không thể là một thể hiện của một đối tượng hạnh phúc và lại visa, mã của bạn nên làm việc miễn là bạn gọi nó với hoặc ở phía trước của tên phương thức.

+0

làm thế nào bạn có thể viết hai phương pháp có cùng một chữ ký phương thức, nhưng các kiểu trả về khác nhau và nói rằng nó biên dịch, nó hoàn toàn vi phạm khái niệm về nạp chồng phương thức –

1

Bạn có thể sử dụng chung để phân biệt phương thức trong Java. JVM không nhìn thấy kiểu này, tuy nhiên cung cấp đối số hoặc kiểu trả về là khác nhau nhưng nó vẫn sẽ biên dịch trong trình biên dịch Sun/Oracle. Điều này không biên dịch cho trình biên dịch IBM/eclipse.

Điều này cho thấy bạn muốn xảy ra ở cấp mã byte. http://vanillajava.blogspot.com/2011/02/with-generics-return-type-is-part-of.html

1

Điều này là hợp pháp, như những người khác đã nói. Tuy nhiên, tôi muốn chỉ ra điều gì xảy ra khi các loại mở rộng lẫn nhau.

Hãy nói rằng chúng tôi có hai giao diện (chỉ hoạt động cho các lớp học cũng chỉ cần thay đổi chữ ký):

interface Emotion {} 
interface Happy extends Emotion {} 

Và hai chức năng:

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

Nếu một đối tượng phù hợp với Emotion JVM sẽ chọn foo1. Nếu một đối tượng phù hợp với Happy JVM sẽ chọn foo2 và không foo1. Lưu ý thứ tự ưu tiên. Đó là cách JVM giải quyết sự mơ hồ. Tuy nhiên, điều này chỉ hợp lệ khi bạn chuyển tham số chung làm đối số.

Các vấn đề liên quan