网小鱼Java的bug小集锦0014

本文探讨了在使用Java ArrayList的remove方法时遇到的问题。通过示例代码展示了因传入错误类型导致的异常及解决方法。分析了remove方法的内部逻辑,包括对null和非null对象的处理步骤,强调了参数类型与集合元素类型一致的重要性。
摘要由CSDN通过智能技术生成

这个bug是在学习Collection集合当中的ArrayList集合时,在关于remove方法时候,遇到的一个问题,记录一下下~
首先,贴一下报错的源代码:

package day14;

import java.util.ArrayList;
import java.util.Collection;

public class Test3_Collection {
    public static void main(String[] args) {
//        Collection collection = new Collection<>();
        //Collection是接口不能直接实例化
        ArrayList<Integer> c = new ArrayList<>();
        c.add(100);
        c.add(200);
        c.add(300);
        c.add(400);
        c.add(500);
        System.out.println(c);
       // c.clear();清除c中所有元素
       // System.out.println(c);

        System.out.println(c.contains(100));
        System.out.println(c.isEmpty());
        System.out.println(c.remove(200));
        System.out.println(c);

    }
}

在控制台打印的结果如下:
在这里插入图片描述
错误提示:IndexOutOfBoundsException
错误原因:在上面代码中想要移去这个"200"这个元素,但是,remove方法是用的下标法来查找内容的,所以数组越界现象发生

再来看另一个测试的小版本:

package day14;

import java.util.ArrayList;
import java.util.Collection;

public class Test3_Collection {
    public static void main(String[] args) {
//        Collection collection = new Collection<>();
        //Collection是接口不能直接实例化
        ArrayList<Integer> c = new ArrayList<>();
        c.add(100);
        c.add(200);
        c.add(300);
        c.add(400);
        c.add(500);
        System.out.println(c);
       // c.clear();清除c中所有元素
       // System.out.println(c);

        System.out.println(c.contains(100));
        System.out.println(c.isEmpty());
        System.out.println(c.remove("200"));
        System.out.println(c);

    }
}

这里面运行结果图片贴一下,如下图:
在这里插入图片描述
程序运行到时没有报错,但是显然没有实现想要把“200”这个元素移除的目的,在回到代码中看一下编译器给的提示是什么,为什么会出现这种情况呢?
在这里插入图片描述
这里提示写到:‘ArrayList’ may not contain objects of type ‘String’

很明显:我们创建的这个集合是用来装Integer类型的,现在放了一个“String”类型的元素进去,编译器翻译不了这个内容,所以remove这个方法执行的结果就是false,我们再点击进去后面的三个小点点看一下提示:

‘ArrayList’ may not contain objects of type ‘String’
Inspection info: Reports method calls to parameterized collections, where actual argument type does not correspond to the collection’s elements type. For example if you have the following code:
//检查信息:提示下集合的方法调用,其中实际参数类型必须要对应于集合的元素类型。例如,如果你有以下代码:
List list = getListOfElements();
list.remove("");

  • the call to remove() will be highlighted. The option ‘Report suspicious but possibly correct method calls’ makes it possible to ignore potentially correct code, like this:
    Number number = new Integer(0);
    list.remove(number));

根据上面的提示:明确告诉一个信息:remove()的调用将突出显示。“报告可疑但可能正确的方法调用”选项可以忽略可能正确的代码。在调用remove这个方法的时候,执行的操作实际是按照下标来进行操作的,而不是按照这个里面的number俩进行操作的。

根据提示我来修改一下做法:

`package day14;

import java.util.ArrayList;
import java.util.Collection;

public class Test3_Collection {
    public static void main(String[] args) {
//        Collection collection = new Collection<>();
        //Collection是接口不能直接实例化
        ArrayList<Integer> c = new ArrayList<>();
        c.add(100);
        c.add(200);
        c.add(300);
        c.add(400);
        c.add(500);
        System.out.println(c);
       // c.clear();清除c中所有元素
       // System.out.println(c);

        System.out.println(c.contains(100));
        System.out.println(c.isEmpty());
        System.out.println(c.remove(1));
        System.out.println(c);

    }
}
`

运行结果如下图
在这里插入图片描述

这里面在remove()方法上面按住ctrl进去看一下它里面的源码的代码是怎么写的:

public boolean remove(Object o) {
        if (o == null) {//如果要移除的元素为null
            for (int index = 0; index < size; index++)//从0开始循环,每次往后+1,循环到小于目标对象的长度时停止
                if (elementData[index] == null) {//如果元素中下标==null
                    fastRemove(index);//快速移除这个元素
                    return true;//返回true
                }
        } else {//如果要移除的元素不为null
            for (int index = 0; index < size; index++)//从0开始循环,每次往后+1,循环到小于目标对象的长度时停止
                if (o.equals(elementData[index])) {//对象等于元素下标值对应的数据
                    fastRemove(index);//快速移除这个元素
                    return true;//返回true
                }
        }
        return false;//如果要移除的元素不为null,且没有找到这个对象等于元素下标值对应的数据
    }

所以就非常清楚了,源码当中的判断逻辑分了3步走:

  1. 先判断,要移除的这个元素是不是null,如果是null,按照下标寻找对应元素,并快速移除,返回true;
  2. 再根据上一步,要移除的这个元素不是null,按照下标寻找对应元素,并快速移除,返回true;
  3. 再根据上两步,要移除的这个元素不是null,且没有找到这个对象等于元素下标值对应的数据,返回false。
以下是一个简单的大鱼吃小鱼Java 小游戏,你可以在控制台中运行它: ```java import java.util.*; public class FishGame { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("欢迎来到大鱼吃小鱼游戏!"); System.out.println("请输入大鱼的初始体力值:"); int bigFish = sc.nextInt(); System.out.println("请输入小鱼的数量:"); int n = sc.nextInt(); System.out.println("请依次输入每只小鱼的体力值:"); int[] smallFish = new int[n]; for (int i = 0; i < n; i++) { smallFish[i] = sc.nextInt(); } Arrays.sort(smallFish); int i = 0; while (i < n && bigFish > smallFish[i]) { bigFish += smallFish[i]; i++; } System.out.println("大鱼最多能吃" + i + "只小鱼!"); System.out.println("游戏开始!"); while (i < n) { System.out.println("当前大鱼体力值为:" + bigFish); System.out.println("小鱼的体力值为:" + smallFish[i]); System.out.println("是否吃掉这只小鱼?(y/n)"); String choice = sc.next(); if (choice.equalsIgnoreCase("y")) { bigFish += smallFish[i]; System.out.println("恭喜你,成功吃掉了一只小鱼!"); i++; } else { System.out.println("你选择了不吃掉这只小鱼!"); } if (i == n) { System.out.println("恭喜你,你已经吃掉了所有小鱼!"); } else if (bigFish <= smallFish[i]) { System.out.println("很遗憾,你的大鱼没能吃掉这只小鱼!"); break; } } System.out.println("游戏结束!"); } } ``` 运行游戏后,你需要输入大鱼的初始体力值和小鱼的数量,以及每只小鱼的体力值。程序会自动计算出大鱼最多能吃掉的小鱼数量,并开始游戏。在游戏中,程序会依次显示每只小鱼的体力值,你需要选择是否吃掉这只小鱼。如果你选择吃掉它,大鱼的体力值会增加这只小鱼的体力值,并显示成功吃掉一只小鱼的提示。如果你选择不吃掉这只小鱼,程序会继续显示下一只小鱼的体力值。如果你的大鱼没能吃掉某只小鱼或者已经吃掉了所有小鱼,游戏结束。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值