Tuy nhiên, một người mới, cố gắng để hiểu Java Generics. Tôi đã quan sát tất cả các chủ đề, tôi đã tìm thấy, nhưng tôi vẫn có những câu hỏi rất lớn. Ông có thể giải thích cho tôi những điều sau đây:<? mở rộng Class> và <? Super Class> trong Java - tại sao nó hoạt động theo cách này?
<? extends SomeClass>
phương tiện, mà?
là "bất kỳ loại", vàextends SomeClass
phương tiện, điều này bất kỳ loại có thể chỉ là một lớp con củaSomeClass
. OK, tôi viết hai lớp tiểu học:
abstract class Person {
private String name;
public Person(String name) {
this.name = name;
}
}
class Student extends Person {
public Student(String name) {
super(name);
}
}
Lớp Student
sẽ ?
trong ví dụ của chúng tôi. ? extends Person
, chính xác. Sau đó, tôi đang cố gắng để thêm học sinh mới đến ArrayList, mà, như tôi hiểu từ viết ở trên, áp dụng tất cả các lớp học, đó là lớp con của Person:
Student clarissa = new Student("Clarissa Starling");
List<? extends Person> list = new ArrayList<>();
list.add(clarissa); //Does not compile
Eclipse nói:
"Các phương thức add (capture # 3-of? mở rộng Person) trong các loại Danh sách không áp dụng cho các đối số (sinh viên)"
Làm thế nào lớp Student
có thể không áp dụng , khi chúng tôi khai báo Danh sách, được thông báo bởi <? extends Person>
và Student
chính xác mở rộng lớp Person
?
Tuy nhiên, đoạn mã sau:
List<? super Person> list = new ArrayList<>();
list.add(clarissa);
biên dịch và hoạt động tốt (list.get(0)
, truyền cho println phương pháp, chỉ cho tôi đúng kết quả của toString
gọi). Như tôi đã hiểu, List<? super Person>
có nghĩa là tôi có thể chuyển sang danh sách này bất kỳ loại nào, đó là loại siêu cho lớp học Person
của chúng tôi (trong trường hợp của chúng tôi là Object
chỉ lớp học). Nhưng chúng ta thấy rằng, trái với logic, chúng ta có thể dễ dàng thêm Học sinh lớp con vào số List<? super Person>
của chúng ta!
OK, gạt sang một bên cảm xúc của mình, và xem nào, điều gì có thể xảy ra với Clarissa Starling trong bộ sưu tập của chúng tôi. Chúng ta hãy cùng lớp của chúng tôi Student
, và thêm một vài phương pháp để nó:
class Student extends Person {
private int grant;
public Student(String name) {
super(name);
}
public void setGrant(int grant) {
this.grant = grant;
}
public int getGrant() {
return this.grant;
}
}
Sau đó, chúng tôi vượt qua một đối tượng, khởi tạo từ lớp đầy mới mẻ này (đối tượng của chúng tôi "Clarissa", ví dụ), để List<? extends Person>
. Làm điều này, chúng tôi có nghĩa là, chúng ta có thể lưu trữ phân lớp trong bộ sưu tập của các siêu lớp của nó. Có lẽ, tôi không hiểu một số ý tưởng cơ bản, nhưng ở giai đoạn này tôi không thấy bất kỳ sự khác biệt nào giữa việc thêm phân lớp vào tập hợp các siêu lớp của nó và việc gán tham chiếu đến đối tượng "clarissa" vào biến, đánh máy. Chúng ta có cùng phương pháp giảm các phương thức invokable, khi chúng ta muốn đối xử với một trong số chúng, sử dụng biến superclass của chúng ta. Vì vậy, tại sao List<? extends SomeClass>
không hoạt động theo cùng một cách, trong đó List<? super SomeClass>
hoạt động ngược lại?
- Tôi không hiểu sự khác biệt giữa fundamenthal
<T>
(hoặc<E>
, hoặc bất kỳ lá thư khác từ phần thích hợp của JLS) và<?>
.Cả hai<T>
và<?>
là loại chủ, vậy tại sao chúng tôi có hai "từ khóa" (ký hiệu này KHÔNG phải từ khóa, tôi vừa sử dụng từ này để nhấn mạnh ý nghĩa nặng nề của cả hai ký hiệu bằng ngôn ngữ Java).
Giả sử bạn có hai lớp 'Student' &' Teacher' mở rộng 'Person'. Bây giờ, bạn đã tạo danh sách 'List mở rộng Person> 'và giả sử bạn đã thêm' Student' vào nó rồi làm thế nào bạn sẽ chắc chắn rằng 'list.get (0)' sẽ trả về bạn chỉ 'Student' chứ không phải' Teacher'? Để ngăn chặn sự mơ hồ này, nó không được phép. – user2004685
Đọc http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs –
Tôi mong đợi, list.get (0) đó sẽ trả về một đối tượng, nó sẽ được đưa vào kiểu siêu lớp, và tôi ' sẽ chỉ có thể gọi các phương thức, được khai báo trong superclass (Person). –