2014-04-30 15 views
7

tôi chạy vào một thất bại biên soạn trong khi viết một số mã Java, mà tôi cất xuống test sau:lỗi Compilation với Generics và điều hành ternary trong JDK 7

import java.util.Collections; 
import java.util.List; 

public class TernaryFailure { 
    public static List<String> thisWorks() { 
     return Collections.emptyList(); 
    } 

    public static List<String> thisFailsToCompile() { 
     return true ? Collections.emptyList() : Collections.emptyList(); 
    } 
} 

Đoạn mã trên không biên dịch với javac với JDK 1.7.0_45:

$ javac TernaryFailure.java 
TernaryFailure.java:10: error: incompatible types 
     return true ? Collections.emptyList() : Collections.emptyList(); 
        ^
    required: List<String> 
    found: List<Object> 
1 error 

Tuy nhiên, nó biên dịch mà không cần bất kỳ lỗi với JDK 1.8.0_05.

Đó có phải là lỗi trong triển khai Java 7 không? Hoặc đã có một sự nâng cao về Đặc tả Ngôn ngữ Java trong Java 8 để bắt đầu cho phép điều này - và nếu có, thay đổi đó là gì?

+0

http://stackoverflow.com/questions/21258160/why-is-javas-type-inference-so-weak – assylias

+0

Toán tử bậc ba có vấn đề kết hợp với trả về chung, điều đó được biết rõ. Chỉ định thông số loại một cách rõ ràng. – qqilihq

Trả lời

4

Các JLS SE 8 nói tại (§15.2):

Khi một số thành ngữ xuất hiện trong những bối cảnh nhất định, họ được coi là biểu poly. Các hình thức sau các biểu thức có thể biểu poly:

  • biểu thức trong ngoặc đơn (§15.8.5)

  • biểu thức tạo dụ Class (§15.9)

  • biểu Phương pháp gọi (§15.12)

  • Biểu thức tham chiếu phương thức (§15.13)

  • biểu thức có điều kiện (§15.25)

  • Lambda biểu thức (§15.27)

Vì vậy, từ phần này của spec rõ ràng là biểu thức có điều kiện, các nhà điều hành ternary, có thể được coi biểu poly. Nhưng không phải tất cả các biểu thức có điều kiện đều có thể được coi là biểu thức poly, chỉ tham chiếu biểu thức có điều kiện theo (§15.25). Điều kiện mà một biểu thức điều kiện tham khảo có thể được coi là một biểu hiện nhiều được làm rõ tại (§15.25.3):

Một tài liệu tham khảo biểu thức điều kiện là một biểu thức nhiều nếu nó xuất hiện trong bối cảnh chuyển nhượng hoặc một bối cảnh gọi (§5.2 §5.3.). Nếu không, nó là một biểu thức độc lập.

Trong trường hợp biểu thức điều kiện nhiều tài liệu tham khảo xuất hiện trong một bối cảnh của một loại đặc biệt với loại mục tiêu T, biểu thức toán hạng thứ hai và thứ ba của nó tương tự xuất hiện trong một bối cảnh cùng loại với loại mục tiêu T.

Loại một biểu thức điều kiện tham chiếu poly là giống như kiểu đích của nó.

Kiểm tra xem trong ví dụ của bạn biểu thức điều kiện xuất hiện trong một bối cảnh chuyển nhượng vì theo (§14.17):

Khi một tuyên bố trở lại với một biểu thức xuất hiện trong một tuyên bố phương pháp, khái niệm phải được chuyển nhượng (§ 5.2) cho kiểu trả về đã khai báo của phương thức, hoặc xảy ra lỗi biên dịch.

Vì vậy, vào cuối ngày, điều này có nghĩa là gì? Điều này ngụ ý rằng khi các biểu thức có điều kiện là các biểu thức poly, kiểu đích được "đẩy xuống" cho mỗi toán hạng. Bằng cách này trình biên dịch có thể thuộc tính từng phần của điều kiện, so với mục tiêu. Trong trường hợp của bạn, mục tiêu là List<String>. Nếu chúng tôi kiểm tra định nghĩa của phương pháp emptyList() ta có:

@SuppressWarnings("unchecked") 
public static final <T> List<T> emptyList() { 
    return (List<T>) EMPTY_LIST; 
} 

Vì vậy, với mục tiêu List<String>, trình biên dịch có thể suy ra rằng T == String và mã được chấp nhận.

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