ArrayList的contains方法

来源:互联网 发布:怎样挑选淘宝剪标衣服 编辑:程序博客网 时间:2024/05/22 13:37

ArrayList的contains方法

先看代码

下边这段代码的输出应该是什么?

// 代码一public class ContainsMethod {public static void main(String[] args) {    ArrayList<String> codePool = new ArrayList<>();    codePool.add("1");    codePool.add("2");    int intCode = 1;    Integer integerCode = 2;    System.out.println(codePool.contains(intCode));    System.out.println(codePool.contains(integerCode));    }}

这段代码会报错吗?

其实,两个println语句的输出都是false,仔细看看会发现codePool是String类型的ArrayList,但是intCodeIntegerCode都不是String类型的,所以都返回了false。但是codePoolStirng类型的列表,却接收到了非String类型的参数,为什么没有报错呢?

源码分析(下载)

想要回答这个问题,就要看一下contains方法的具体实现。

// 代码二public boolean contains(Object o) {    return indexOf(o) >= 0;}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]))   //line 14                return i;    }    return -1;}
  1. 为什么没有报错?
    从代码中可以看到contains方法接受的是一个Object类型的参数,而Object是所有类型的父类,所以当integerCode被当做实参的时候,它被当做一个Object类型的对象,所以无论是编译器还是JVM都不会报错

    而之所以intCode在传入contains方法的时候也没有报错是因为Java的自动装箱和拆箱机制在intCode传入之前将其包装为了Integer类型的变量。

// 代码三:代码一的class文件反编译public class ContainsMethod {    public ContainsMethod() {        }    public static void main(String[] args) {        ArrayList<String> codePool = new ArrayList();        codePool.add("1");        codePool.add("2");        int intCode = 1;        Integer integerCode = Integer.valueOf(2);        System.out.println(codePool.contains(Integer.valueOf(intCode)));  //line 12        System.out.println(codePool.contains(integerCode));    }}

上边的代码是代码一经过编译后的样子,从第12行可以看到,实际传入的是个Integer类型的变量。

  1. 为什么返回false?
    代码二的第14行看到,在比较codePool中元素和要查找数据时调用的是obj对象的equals方法,这个方法在没有覆写的情况下采用的是Object类的默认实现,代码如下:
// 代码四:Object的equals方法默认实现public boolean equals(Object obj) {    return (this == obj);  // line 3}

可以看到,代码四第3行中使用了==进行判断,对于两个对象,这是在判断两个对象的引用是否相等,显然这里不相等。所以两个contains方法返回的都是false

其实IDEA的代码检查器已经检测到可能存在的问题并给出了提示,如下图:
IDEA的提示

总结

本文主要讨论了JDK源码中ArrayListcontains方法的实现,列举了一种可能被忽视的错误。

  • contains方法接受的是Object类型的参数
  • ==运算符左右两边都是对象的时候,比较的是两个对象的引用
原创粉丝点击