Java 没有类型转换的编译器如何在子类中调用正确的 equals() 函数?
How is Java compiler without type casting calling a correct equals() function in subclass?
我有 ScheduledSessionViewModel
class 扩展 AbstractSessionViewModel
。这两个函数都实现了 equals() 函数。
class AbstractSessionViewModel {
@Override public boolean equals(Object o) {
return /* some logic */
}
}
class ScheduledSessionViewModel extends AbstractSessionViewModel {
@Override public boolean equals(Object o) {
if (!super.equals(o)) return false;
return /* some logic */;
}
}
因为我使用的是新的 Android ListAdapter
我正在实施 DiffUtil.ItemCallback<T>
并且我有下一个方法:
@Override public boolean areContentsTheSame(AbstractSessionViewModel oldItem, AbstractSessionViewModel newItem) {
if (oldItem instanceof ScheduledSessionViewModel && !(newItem instanceof ScheduledSessionViewModel)){
return false;
} else if (!(oldItem instanceof ScheduledSessionViewModel) && newItem instanceof ScheduledSessionViewModel){
return false;
} else if (oldItem instanceof ScheduledSessionViewModel){
return ((ScheduledSessionViewModel)oldItem).equals((ScheduledSessionViewModel)newItem);
} else {
return oldItem.equals(newItem);
}
}
奇怪的是,编译器在下一条语句中向我显示警告
((ScheduledSessionViewModel)oldItem).equals((ScheduledSessionViewModel)newItem);
不需要类型转换。
这怎么可能? Java 编译器如何检测到 oldItem
是 ScheduledSessionViewModel
类型?
How's Java compiler able to detect that oldItem
is of type ScheduledSessionViewModel
?
不,不是;编译器只知道 oldItem
是 AbstractSessionViewModel
.
类型
不过没关系。编译器知道 AbstractSessionViewModel
有 equals(Object)
方法,所以 actual 对象类型也有它。通过这种方式,编译器保证 equals(Object)
方法在运行时可用。
它是如何实现的 只有在运行时才知道。运行时根据 JLS 定义的一组规则搜索适当的方法。
旁注:经过上述说明后,我得出的结论是,通过正确实施 equals()
方法,下面是一个方法
@Override public boolean areContentsTheSame(AbstractSessionViewModel oldItem, AbstractSessionViewModel newItem) {
if (oldItem instanceof ScheduledSessionViewModel && !(newItem instanceof ScheduledSessionViewModel)){
return false;
} else if (!(oldItem instanceof ScheduledSessionViewModel) && newItem instanceof ScheduledSessionViewModel){
return false;
} else if (oldItem instanceof ScheduledSessionViewModel){
return ((ScheduledSessionViewModel)oldItem).equals((ScheduledSessionViewModel)newItem);
} else {
return oldItem.equals(newItem);
}
}
可以重构并且 if 语句是不必要的。 equals()
方法的实现应该处理所有事情。
最终结果:
@Override public boolean areContentsTheSame(AbstractSessionViewModel oldItem, AbstractSessionViewModel newItem) {
return oldItem.equals(newItem);
}
我有 ScheduledSessionViewModel
class 扩展 AbstractSessionViewModel
。这两个函数都实现了 equals() 函数。
class AbstractSessionViewModel {
@Override public boolean equals(Object o) {
return /* some logic */
}
}
class ScheduledSessionViewModel extends AbstractSessionViewModel {
@Override public boolean equals(Object o) {
if (!super.equals(o)) return false;
return /* some logic */;
}
}
因为我使用的是新的 Android ListAdapter
我正在实施 DiffUtil.ItemCallback<T>
并且我有下一个方法:
@Override public boolean areContentsTheSame(AbstractSessionViewModel oldItem, AbstractSessionViewModel newItem) {
if (oldItem instanceof ScheduledSessionViewModel && !(newItem instanceof ScheduledSessionViewModel)){
return false;
} else if (!(oldItem instanceof ScheduledSessionViewModel) && newItem instanceof ScheduledSessionViewModel){
return false;
} else if (oldItem instanceof ScheduledSessionViewModel){
return ((ScheduledSessionViewModel)oldItem).equals((ScheduledSessionViewModel)newItem);
} else {
return oldItem.equals(newItem);
}
}
奇怪的是,编译器在下一条语句中向我显示警告
((ScheduledSessionViewModel)oldItem).equals((ScheduledSessionViewModel)newItem);
不需要类型转换。
这怎么可能? Java 编译器如何检测到 oldItem
是 ScheduledSessionViewModel
类型?
How's Java compiler able to detect that
oldItem
is of typeScheduledSessionViewModel
?
不,不是;编译器只知道 oldItem
是 AbstractSessionViewModel
.
不过没关系。编译器知道 AbstractSessionViewModel
有 equals(Object)
方法,所以 actual 对象类型也有它。通过这种方式,编译器保证 equals(Object)
方法在运行时可用。
它是如何实现的 只有在运行时才知道。运行时根据 JLS 定义的一组规则搜索适当的方法。
旁注:经过上述说明后,我得出的结论是,通过正确实施 equals()
方法,下面是一个方法
@Override public boolean areContentsTheSame(AbstractSessionViewModel oldItem, AbstractSessionViewModel newItem) {
if (oldItem instanceof ScheduledSessionViewModel && !(newItem instanceof ScheduledSessionViewModel)){
return false;
} else if (!(oldItem instanceof ScheduledSessionViewModel) && newItem instanceof ScheduledSessionViewModel){
return false;
} else if (oldItem instanceof ScheduledSessionViewModel){
return ((ScheduledSessionViewModel)oldItem).equals((ScheduledSessionViewModel)newItem);
} else {
return oldItem.equals(newItem);
}
}
可以重构并且 if 语句是不必要的。 equals()
方法的实现应该处理所有事情。
最终结果:
@Override public boolean areContentsTheSame(AbstractSessionViewModel oldItem, AbstractSessionViewModel newItem) {
return oldItem.equals(newItem);
}