2010-04-27 40 views
185

Tại sao generics trong Java làm việc với các lớp học nhưng không phải với các kiểu nguyên thủy?Tại sao Java Generics không hỗ trợ các kiểu nguyên thủy?

Ví dụ, điều này hoạt động tốt:

List<Integer> foo = new ArrayList<Integer>(); 

nhưng điều này là không được phép:

List<int> bar = new ArrayList<int>(); 
+0

int i = (int) new Object(); biên dịch tốt mặc dù. –

Trả lời

194

Generics trong Java là một hoàn toàn thời gian biên dịch xây dựng - trình biên dịch chuyển tất cả sử dụng chung vào dàn diễn viên đúng loại. Điều này là để duy trì khả năng tương thích ngược với các thời gian chạy JVM trước đó.

này:

List<ClassA> list = new ArrayList<ClassA>(); 
list.add(new ClassA()); 
ClassA a = list.get(0); 

bị biến thành (khoảng):

List list = new ArrayList(); 
list.add(new ClassA()); 
ClassA a = (ClassA)list.get(0); 

Vì vậy, bất cứ điều gì mà được sử dụng như thuốc generic có được convertable vào Object (trong ví dụ này get(0) trả về một Object) và các kiểu nguyên thủy thì không. Vì vậy, chúng không thể được sử dụng trong Generics.

+0

Làm rõ rằng đây chỉ dành cho Java. – ChaosPandion

+31

Trong C# không có vấn đề với các kiểu nguyên thủy. – Danvil

+0

@ChaosPandion: thực hiện – thecoop

30

Trong Java, generics làm việc theo cách mà chúng làm ... ít nhất là một phần ... bởi vì chúng được thêm vào ngôn ngữ một số năm sau khi ngôn ngữ được thiết kế . Các nhà thiết kế ngôn ngữ được hạn chế trong các tùy chọn của họ cho generics bằng cách phải đưa ra một thiết kế tương thích ngược với ngôn ngữ hiện có và thư viện lớp Java.

Các ngôn ngữ lập trình khác (ví dụ: C++, C#, Ada) cho phép các kiểu nguyên thủy được sử dụng làm loại tham số cho generics. Nhưng mặt trái của việc này là việc triển khai các generic (các kiểu mẫu) của các ngôn ngữ như vậy thường đòi hỏi phải tạo ra một bản sao riêng biệt của kiểu generic cho mỗi kiểu tham số hóa.


1 - Lý do generics không được bao gồm trong Java 1.0 là do áp lực thời gian. Họ cảm thấy rằng họ đã có được ngôn ngữ Java phát hành nhanh chóng để lấp đầy cơ hội thị trường mới được trình duyệt web trình bày. James Gosling đã tuyên bố rằng ông muốn bao gồm Generics nếu họ có thời gian. Ngôn ngữ Java sẽ trông như thế nào nếu điều này xảy ra là dự đoán của bất kỳ ai.

5

Các bộ sưu tập được xác định để yêu cầu loại có nguồn gốc từ java.lang.Object. Các basetypes chỉ đơn giản là không làm điều đó.

+21

Tôi nghĩ câu hỏi ở đây là "tại sao". Tại sao generics yêu cầu Object? Sự đồng thuận dường như là nó ít của một sự lựa chọn thiết kế và nhiều hang động trong khả năng tương thích ngược. Trong mắt tôi, nếu generics không thể xử lý nguyên thủy, đó là một thiếu hụt chức năng.Vì nó là viết tắt, mọi thứ liên quan đến nguyên thủy phải được viết cho mỗi nguyên thủy: thay vì Comparator , chúng ta có Integer.compare (int a, int b), Byte.compare (byte a, byte b), vv Đó không phải là giải pháp ! –

+0

Vâng generics trên các loại nguyên thủy sẽ là một tính năng phải có. Đây là một liên kết đến một đề xuất cho nó http://openjdk.java.net/jeps/218 – crow

1

Theo Java Documentation, các biến loại chung chỉ có thể được khởi tạo với các loại tham chiếu, không phải kiểu nguyên thủy.

Điều này được cho là có trong Java 10 dưới Project Valhalla.

Trong Brian Goetz giấy trên State of the Specialization

Có một excellent explanation về lý do mà chung không được hỗ trợ cho nguyên thủy. Và, how it will be implemented trong các phiên bản tương lai của Java.

Thực thi xóa hiện tại của Java tạo ra một lớp cho tất cả các cảnh báo tham chiếu và không hỗ trợ cho các cảnh báo nguyên thủy. (Đây là một bản dịch đồng nhất, và sự hạn chế mà các generics của Java chỉ có thể nằm trong các kiểu tham chiếu đến từ các giới hạn của bản dịch đồng nhất đối với tập hợp bytecode của JVM, sử dụng các bytecode khác nhau cho các hoạt động trên các kiểu tham chiếu so với các kiểu nguyên thủy.) Tuy nhiên, generics xoá hoàn toàn bằng Java cung cấp cả parametricity hành vi (phương pháp chung chung) và parametricity dữ liệu (instantiations liệu và ký tự đại diện của các kiểu generic.)

...

một chiến lược dịch đồng nhất đã được lựa chọn, nơi biến kiểu generic được xóa theo giới hạn của chúng khi chúng được tích hợp vào bytecode. Điều này có nghĩa rằng cho dù một lớp là chung hay không, nó vẫn biên dịch thành một lớp duy nhất, có cùng tên và chữ ký thành viên của nó giống nhau. Loại an toàn được xác minh tại thời gian biên dịch và thời gian chạy không bị hệ thống loại chung loại bỏ. Đổi lại, điều này áp đặt hạn chế rằng generics chỉ có thể làm việc trên các kiểu tham chiếu, vì Object là kiểu chung nhất có sẵn, và nó không mở rộng đến các kiểu nguyên thủy.

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