fro*_*tto 1 java arraylist indexof
请考虑以下代码(非常简单)
public class Main {
public static class A{
int id;
public A(final int id){
this.id = id;
}
@Override
public boolean equals(final Object obj) {
if(obj instanceof A){
final A a = (A) obj;
return id == a.id;
}
return false;
}
}
public static void main(final String[] args) {
final List<A> items = new ArrayList<A>();
items.add(new A(0));
items.add(new A(1));
final Object obj = new A(1);
System.out.println(items.indexOf(obj));
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行此代码时,1将在控制台中登录.在我看来,它应该是1应该的-1.我查看了indexOf 源代码.从那里完全复制/粘贴:
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
Run Code Online (Sandbox Code Playgroud)
正如我们所知,当我的代码想要运行else时,上面代码的片段开始执行.正如你在那里看到的,语句o.equals(elementData[i])将被执行.到目前为止一切都还可以,我没有问题
我的问题
变量的类型o在上述方法是Object当我们调用equals的方法就可以了,在我看来equals通用Object的方法将被执行,在另一边,我已经看equals的对象方法的源代码.我在这里复制/粘贴它:
public boolean equals(Object obj) {
return (this == obj);
}
Run Code Online (Sandbox Code Playgroud)
现在,在for循环indexOf方法中,它不应该与o对象匹配任何项,因为数组中没有项等于oobject,在==视图中
现在我想知道我的代码的输出是如何等于的1.谁能帮帮我吗?
谢谢
在静态类型obj的Object,但运行时类型A.
由于Java中的所有方法都是虚拟的,因此静态类型无关紧要.它是被调用者的运行时类型,它将决定调用哪个方法.在这种情况下运行时类型被A因而A.equals被调用.
类似于下面的代码段调用String.toString而不是Object.toString因为运行时类型o是String.
Object o = "Hello";
System.out.println(o.toString());
// Prints "Hello" and not something like "java.lang.String@15db9742"
Run Code Online (Sandbox Code Playgroud)
您将变量的编译时类型与其值的执行时类型混淆.
A.equals将调用该方法而不是Object.equals因为覆盖 - 执行时类型用于确定使用哪个方法覆盖.如果不是这种情况,则永远不会使用自定义相等覆盖ArrayList.indexOf.不要忘记代码obj完全不知道声明的类型ArrayList.indexOf.所有它是值的的o参数-这是一个实例的引用A.
区分编译时类型(用于重载,检查可用成员等)和执行时的值(用于覆盖instanceof等)非常重要.