英文:
bounded Generic Comparator for base and derived classes
问题
我试图理解如何为给定的类及其所有派生类构建一个通用的比较器。
public class Employee {
String name;
int id;
}
在我的主类中,我尝试了以下代码:
Comparator<T extends Employee> comp = Comparator.comparing(Employee::getName);
但是IDE给出了错误信息:
意外的边界
英文:
I am trying to understand how to build a generic Comparator for the a given class and all derived class.
public class Employee {
String name;
int id;
}
In my main class, I tried this
Comparator<T extends Employee> comp = new Comparator.comparing(Employee::getName);
and the IDE gives me the error
Unexpected bound
答案1
得分: 1
Maurice Perry's answer mungkin benar dalam hal memungkinkan baris itu untuk dikompilasi, tetapi itu tidak sangat berguna setelahnya: Anda tidak dapat memanggil comp.compare
dengan argumen lain selain literal null
.
Comparator<? extends Employee>
berarti bahwa komparator menerima subkelas yang spesifik, tetapi tidak diketahui dari Employee
: karena kompiler tidak tahu subkelas mana yang dimaksud, ia hanya akan memungkinkan Anda untuk melewatkan sesuatu yang pasti bisa dicasting dengan aman ke jenis yang tidak diketahui itu: yaitu, null
.
Jika Anda menginginkan komparator yang lebih generik daripada Comparator<Employee>
, Anda bisa menggunakan Comparator<? super Employee>
, yang berarti komparator dengan aman dapat menerima sebuah instansi dari Employee
(tetapi objek konkret mungkin dapat menerima sesuatu yang lebih umum).
Tetapi sebenarnya, Anda tidak ingin menggunakan wildcard jenis apa pun di sini. Wildcard hanya benar-benar berguna dalam parameter metode, agar metode dapat menerima objek yang lebih umum.
Anda seharusnya tidak menggunakannya dalam variabel atau tipe pengembalian (dll) karena Anda akan terjebak dengan tipe wildcard begitu Anda mendapatkannya - Anda tidak dapat (dengan aman) mencabut wildcard, jadi Anda terjebak dengan kerumitan ekstra dari ? extends
atau ? super
di mana-mana, yang sebenarnya hanya menyebabkan mata terasa tidak perlu.
Alasan mengapa Comparator<T extends Employee>
tidak berfungsi adalah mencoba mendeklarasikan variabel tipe, T
: Anda hanya bisa melakukannya pada kelas (atau antarmuka) atau pada tanda tangan metode. Tidak masuk akal untuk dapat mendeklarasikannya di dalam metode, karena Anda tidak dapat menggunakan jenis T
tersebut secara berikutnya.
英文:
Maurice Perry's answer might be right in terms of allowing that line to compile, but it's not very useful afterwards: you can't invoke comp.compare
with any other arguments than literal null
s.
Comparator<? extends Employee>
means that the comparator accepts a specific, but unknown subclass of Employee
: since the compiler does not know which subclass it is, it will only allow you to pass in something that it knows for sure can be safely cast to that unknown type: namely, null
.
If you want a comparator which is somehow more generic than a Comparator<Employee>
, you could use Comparator<? super Employee>
, which means the comparator can safely accept an instance of Employee
(but the concrete object may be able to safely accept a more general thing).
But really, you don't want to use any sort of wildcard here. Wildcards are only really useful in method parameters, in order to make a method able to accept more general objects.
You shouldn't use them in variables or return types (etc) because you're stuck with the wildcard type once you've got it - you can't (safely) cast away the wildcards, so you are stuck with the extra verbosity of the ? extends
or ? super
everywhere, which is really just unnecessary eye pain.
The reason why Comparator<T extends Employee>
doesn't work is that is attempting to declare a type variable, T
: you can only do that on a class (or interface) or on a method signature. It doesn't make sense to be able to declare it inside a method, since you can't subsequently use that type T
.
答案2
得分: 0
尝试这样做:
Comparator<? extends Employee> comp = Comparator.comparing(Employee::getName);
英文:
Try this:
Comparator<? extends Employee> comp = Comparator.comparing(Employee::getName);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论