java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java异常、泛型、Collection单列集合与List集合

Java零基础之异常处理、泛型、Collection单列集合与List集合详解

作者:季夏124

这篇文章主要介绍了Java零基础之异常处理、泛型、Collection单列集合与List集合的相关资料,文中通过代码深入解析try-catch、自定义异常、通配符使用方法,并全面梳理Collection与List集合遍历方式,需要的朋友可以参考下

异常

异常的概念与结构

索引越界异常

public class Test{
	public static void main(String[] args) {
        int[] arr = {1,2,3};
        System.out.println(arr[3]); //ArrayIndexOutOfBoundsException
	}
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
	at com.bit.ExceptionDemo.Test.main(Test.java:6)

算数异常

public class Test{
	public static void main(String[] args) {
	System.out.println(10 / 0);//ArithmeticException
		}
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.bit.ExceptionDemo.Test.main(Test.java:7)

空指针异常

public class Test{
	public static void main(String[] args) {
		int[] array = null;
		System.out.println(array.length);//NullPointerException
	}
}
Exception in thread "main" java.lang.NullPointerException: Cannot read the array length because "array" is null
	at com.bit.ExceptionDemo.Test.main(Test.java:9)

编译时异常:编译阶段就会出现错误提醒(一般不会遇到)

public class Test{
	public static void main(String[] args) {
        System.out.println("程序开始====");
        String str = "2026-07-13";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf.parse(str);
        // parse方法会抛出编译时异常ParseException,编译器直接报错标红
        //原因:parse()方法声明抛出ParseException,属于编译时异常,Java 强制开发者处理。
        System.out.println(date);
        System.out.println("程序结束====");
    }
}

异常的处理

public class Test {
    public static void main(String[] args) throws Exception {
        System.out.println("程序开始");
        System.out.println(div(10, 0));
        System.out.println("程序结束");
    }
    public static int div(int a, int b) throws Exception {
        if(b == 0){
            System.out.println("除数不能为0");
            throw new Exception("除数不能为0"); // 抛出异常,程序会终止
        }
        return a / b;
    }
}

程序开始
除数不能为0
Exception in thread "main" java.lang.Exception: 除数不能为0
	at com.bit.ExceptionDemo.Test.div(Test.java:15)
	at com.bit.ExceptionDemo.Test.main(Test.java:9)

try{
// 将可能出现异常的代码放在这⾥
}catch(要捕获的异常类型 e){
// 如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型⼀致时,或者是try中抛出异常的基类时,就会被捕获到
// 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执⾏后序代码
}
public class Test {
    public static void main(String[] args) {
        System.out.println("程序开始");
        try {
            System.out.println(div(10, 0));
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("出现异常");
        }
        System.out.println("程序结束");
    }
    public static int div(int a, int b) throws Exception {
        if(b == 0){
            System.out.println("除数不能为0");
            throw new Exception("除数不能为0"); // 抛出异常,程序会终止
        }
        return a / b;
    }
}

自定义异常

实现⾃定义异常

具体⽅式:

  1. ⾃定义异常类,然后继承⾃Exception 或者 RunTimeException
    继承 Exception:自定义编译时(受检)异常,调用方法时必须手动 try-catch 或 throws 抛出,否则编译报错;
    继承 RuntimeException:自定义运行时(非受检)异常,编译器不强制处理,代码更简洁,现代开发推荐优先使用。
  2. 实现⼀个带有String类型参数的构造⽅法
public class Test{
	public static void main(String[] args) {
        System.out.println("程序开始");
        try {
            Age(130);
        } catch (BitAgeIegalException e) {
            e.printStackTrace();
            System.out.println("出现异常");
        }
        System.out.println("程序结束");
    }
    public static void Age(int age) throws BitAgeIegalException {
        if(age < 0 || age > 120) {
            throw new BitAgeIegalException("年龄不合法,年龄不能为负数或大于120");
        } else {
            System.out.println("年龄合法");
            System.out.println("年龄是:" + age);
        }
    }
}
 /*
 * 自定义异常类,继承Exception类
 * 重写Exception类的构造方法,添加一个参数为String类型的构造方法,用于传入异常信息
 * 创建一个测试类,演示如何抛出和捕获自定义异常
 * 哪里需要判断年龄是否合法,就抛出这个异常,哪里需要处理异常,就捕获这个异常
 */
public class BitAgeIegalException extends Exception{
    public BitAgeIegalException(String message) {
        super(message);
    }
}

在定义编译时异常和运行时异常时看程度定义

1.如果这个错误程序员容易出现或者问题严重时定义为编译时异常

2.如果这个问题程序员不容易出现定义为运行时异常

现在Java全面摒弃编译时异常,今后尽量定义运行时异常

异常的处理方案

常见处理方式:最外层捕获异常后,尝试重新修复

核心思路:外层 while 死循环 + try-catch 捕获异常

以用户输入正确价格为例

import java.util.Scanner;
public class Test{
	public static void main(String[] args) {
        System.out.println("程序开始");
        // 死循环,输入格式错误时会重新走循环,直到输入合法数字跳出循环
        while (true) {
            try{
                double price = UserInputPrice();
                System.out.println("用户输入的价格是:" + price);
                // 调用方法获取用户输入的价格,若输入非数字会抛出输入不匹配异常
                break;
                // 输入合法,跳出while死循环,结束输入流程
            } catch (Exception e) {
            // 捕获所有类型异常,提示用户重新输入正确数字
                System.out.println("请输入正确的价格:");
            }
        }
        System.out.println("程序结束");
    }

    public static double UserInputPrice() {
    // 创建Scanner扫描器对象,用于读取控制台输入
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入价格:");
        double price = scanner.nextDouble();
        return price;
    }
}

Ctrl + alt + T:快速生成 try-catch、while 等代码包裹结构

泛型

泛型类

public class GenericDemo {
    //目标:学会自定义泛型类
    public static void main(String[] args) {
        MyArrayList<String> list = new MyArrayList<>();
        list.add("hello");
        list.add("world");
        //list.add(555);  //报错,因为它不属于String类型
        list.add("java");
        list.add("python");
        list.remove("world");
        System.out.println(list.toString());
    }
}

public class MyArrayList<E> {
    public boolean add(E e) {
        return true; // 临时返回值,表示添加成功
    }
    public boolean remove(E e) {
        return true; // 临时返回值,表示删除成功
    }
    @Override
    public String toString() {
        return "MyArrayList{" + "自定义泛型集合" + '}';
    }
}

泛型接口

public class GenericDemo1 {
    public static void main(String[] args) {
        // 标准多态(推荐,贴合泛型接口学习)
        Data<Student> student = new Student();
        student.add(new Student());
        student.query(1);

        Data<Teacher> teacher = new Teacher();
        teacher.add(new Teacher());
        teacher.query(2);
    }
}

// 泛型接口,定义通用增查方法
interface Data<T>{
    void add(T t);
    T query(int id);
}

// 重点:实现接口时必须指定泛型<Student>
class Student implements Data<Student> {
    @Override
    public void add(Student student) {
        System.out.println("添加学生数据");
    }

    @Override
    public Student query(int id) {
        System.out.println("查询id=" + id + "学生");
        return null;
    }
}

// 重点:实现接口时必须指定泛型<Teacher>
class Teacher implements Data<Teacher> {
    @Override
    public void add(Teacher teacher) {
        System.out.println("添加教师数据");
    }

    @Override
    public Teacher query(int id) {
        System.out.println("查询id=" + id + "教师");
        return null;
    }
}

泛型方法

泛型方法:在方法返回值前声明类型参数,整个方法内都可以使用T代表任意引用类型。

语法格式:修饰符 返回值类型 方法名(T 参数){}

核心优势:一个方法可以接收、处理任意引用类型数据,不用为每种类型单独重载方法,实现代码复用,同时编译期做类型校验。

public class GenericDemo2 {
    //目标:学会定义泛型方法,搞清楚作用
    //需求:打印任意数组的内容
    public static void main(String[] args) {
        String[] arr = {"hello","world","java"};
        printArray(arr);
        Student[] arr2 = new Student[2];
        printArray(arr2);
    }

    public static <T> void printArray(T[] array){
        
    }
}

注意事项

泛型方法使用总结

通配符和上下限

public class GenericDemo {
    public static void main(String[] args) {
        ArrayList<XiaoMi> xiaomis = new ArrayList<>();
        xiaomis.add(new XiaoMi());
        xiaomis.add(new XiaoMi());
        xiaomis.add(new XiaoMi());
        go(xiaomis);

        ArrayList<Byd> byds = new ArrayList<>();
        byds.add(new Byd());
        byds.add(new Byd());
        byds.add(new Byd());
        go(byds);
        
//        ArrayList<Dog> dogs = new ArrayList<>();
//        dogs.add(new Dog());
//        dogs.add(new Dog());
//        go(dogs); // Error: dogs is not a subclass of Car
    }
    public static void go(ArrayList<? extends Car> cars){
    }
}

public class Car {
}

public class XiaoMi extends Car {
}

public class Byd extends Car {
}

public class Dog {
}

包装类

基本数据类型对应包装类(应用数据类型)
byteByte
shortShort
intInteger
longLong
charCharacter
floatFloat
doubleDouble
booleanBoolean
import java.util.ArrayList;
public class GenericDemo3 {
    //目标:搞清楚泛型和集合不支持基本数据类型,只支持引用数据类型
    //把基本数据类型包装成对象
    public static void main(String[] args) {
        //手工装箱
        Integer i1 = Integer.valueOf(10);
        Integer i2 = Integer.valueOf(10);
        System.out.println(i1 == i2);
        //自动装箱:基本数据类型的数据可以直接变成包装对象的数据
        Integer i3 = 10;
        Integer i4 = 10;
        System.out.println(i3 == i4);
        //自动拆箱:包装对象的数据可以直接变成基本数据类型的数据
        int i5 = i3;
        System.out.println(i5);

        ArrayList<Integer> list = new ArrayList<>();
        list.add(10);
        list.add(20);
        list.add(30);
        int it = list.get(1);
        System.out.println(it);

        System.out.println("============================================");

        //包装类新增方法
        int i = 23;
        String s = Integer.toString(i);
        System.out.println(s + 1);//231

        //2.把字符串数值转换成基本数据类型
        String s1 = "123";
        //int i6 = Integer.parseInt(s1);
        int i6 = Integer.valueOf(s1);
        System.out.println(i6 + 1);//124

        String s2 = "123.45";
        double d = Double.valueOf(s2);
        System.out.println(d + 1);//124.45
    }
}

集合

单列集合体系结构

Collection 集合特点

List 系列集合:添加的元素是有序、可重复、有索引。
ArrayList、LinkedList:有序、可重复、有索引。
Set 系列集合:添加的元素是无序、不重复、无索引。
HashSet:无序、不重复、无索引;
LinkedHashSet:有序、不重复、无索引。
TreeSet:按照大小默认升序排序、不重复、无索引。

了解Collection集合的常用功能

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

public class Collection1 {
    public static void main(String[] args) {
        //搞清楚Collection提供的通用集合功能
        Collection<String> list = new ArrayList<String>();
        //添加元素
        list.add("hello");
        list.add("world");
        list.add("bit");
        System.out.println(list);
        //获取集合元素个数
        System.out.println(list.size());
        //删除元素
        list.remove("hello");
        System.out.println(list);
        //判断集合是否为空
        System.out.println(list.isEmpty());
        //判断集合是否包含某个元素
        System.out.println(list.contains("world"));
//        //清空集合
//        list.clear();
//        System.out.println(list);
        //把集合转换成数组
        Object[] array = list.toArray();
        System.out.println(Arrays.toString(array));
    }
}

Collection的遍历方式

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

public class Collection2 {
    public static void main(String[] args) {
        //掌握Collection的遍历方式一:迭代器遍历
        //创建一个Collection对象
        Collection<String> names = new ArrayList<String>();
        names.add("张三");
        names.add("李四");
        names.add("王五");
        names.add("赵六");
        System.out.println(names);//[张三, 李四, 王五, 赵六]

        //使用迭代器遍历
        Iterator<String> it = names.iterator();
        //使用while循环遍历
        while (it.hasNext()) {
            String name = it.next();
            System.out.println(name);
        }
    }
}
import java.util.ArrayList;
import java.util.Collection;

public class Collection3 {
    public static void main(String[] args) {
        //掌握Collection的遍历方式一:增强for循环
        //创建一个Collection对象
        Collection<String> names = new ArrayList<String>();
        names.add("张三");
        names.add("李四");
        names.add("王五");
        names.add("赵六");

        //使用增强for循环遍历
        for (String name : names) {
            System.out.println(name);
        }

        String[] users = {"张三", "李四", "王五", "赵六"};
        for (String user : users) {
            System.out.println(user);
        }
    }
}
import java.util.ArrayList;
import java.util.Collection;

public class Collection4 {
    public static void main(String[] args) {
        //掌握Collection的遍历方式一:Lambda表达式
        //创建一个Collection对象
        Collection<String> names = new ArrayList<String>();
        names.add("张三");
        names.add("李四");
        names.add("王五");
        names.add("赵六");

        //使用Lambda表达式遍历
//        names.forEach(new Consumer<String>() {
//            @Override
//            public void accept(String s) {
//                System.out.println(s);
//            }
//        });
        names.forEach(s -> System.out.println(s));
    }
}

认识并发修改异常问题

import java.util.ArrayList;

public class Collection5 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");
        list.add("C#");
        list.add("Java");
        //删除全部Java
        for(int i = 0; i < list.size(); i++) {
            String names = list.get(i);
            if(names.contains("Java")) {
                list.remove(names);
                i--;
            }
        }
        System.out.println(list);
    }
}
import java.util.ArrayList;
import java.util.Iterator;

public class Collection5 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");
        list.add("C#");
        list.add("Java");
        //删除全部Java
        //迭代器遍历并删除默认也存在并发修改异常,需要使用迭代器的remove方法
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            String name = it.next();
            if (name.contains("Java")) {
                it.remove();
            }
        }
        System.out.println(list);
    }

解决并发修改异常问题的方案
① 如果集合支持索引,可以使用 for 循环遍历,每删除数据后做 i–;或者可以倒着遍历
② 可以使用迭代器遍历,并用迭代器提供的删除方法删除数据。
注意:增强 for 循环 / Lambda 遍历均不能解决并发修改异常问题,因此它们只适合做数据的遍历,不适合同时做增删操作。

List集合系列

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Collection6 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");
        System.out.println(list);
        //给第三个位置插入一个数据
        list.add(2,"JavaScript");
        System.out.println(list);
        //删除Python
        list.remove("Python");
        System.out.println(list);
        //把C++改成C#
        list.set(2,"C#");
        System.out.println(list);
        //获取C#
        System.out.println(list.get(2));
        //1.for循环
        for(int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        //2.迭代器
        Iterator<String> it = list.iterator();
        while(it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }
        //3.增强for循环
        for(String s : list) {
            System.out.println(s);
        }
        //4.Lambda表达式
        list.forEach(s -> System.out.println(s));

    }
}

四种遍历方式

LinkedList 实现队列、栈

核心方法

import java.util.LinkedList;

public class Collection7 {
    public static void main(String[] args) {
        LinkedList<String> queue = new LinkedList<>();
        //入队
        queue.addLast("Java");
        queue.addLast("Python");
        queue.addLast("C++");
        queue.addLast("JavaScript");
        queue.addLast("C#");
        System.out.println(queue);

        //出队
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue);
        //做一个栈,后进先出
    }
}

模拟栈:后进先出 LIFO

核心方法

import java.util.LinkedList;

public class Collection7 {
    public static void main(String[] args) {
        //做一个栈,后进先出
        LinkedList<String> stack = new LinkedList<>();
        stack.push("Java");
        stack.push("Python");
        stack.push("C++");
        stack.push("JavaScript");
        stack.push("C#");
        System.out.println(stack);//[C#, JavaScript, C++, Python, Java]
        //出栈
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack);
    }
}

总结 

到此这篇关于Java零基础之异常处理、泛型、Collection单列集合与List集合的文章就介绍到这了,更多相关Java异常、泛型、Collection单列集合与List集合内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文