Java:异常,包装类,泛型

本文详细讲解了Java异常的基础语法,如何使用try-catch-finally结构处理异常,以及throw和throws的区别。还介绍了异常体系、包装类和泛型在编程中的角色。特别关注了自定义异常和集合框架的使用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

异常:

包装类: 

泛型: 


异常:

异常:程序没有按照预计的结果运行,在运行的过程中发生了"错误"

异常的基本语法:

 try{

     //可能产生异常的代码,算术异常,数组越界,空指针

}catch(异常类型){

    //出现异常后如何处理

}finally{

     //无论如何都会执行的代码

}

1.使用try...catch...处理异常 

 一旦try中的代码出现异常,那么就不会继续往下执行,而是交给catch中的代码执行,catch执行完毕继续往下执行

public static void main(String[] args) {

        int[] data = {1,2,3};
        System.out.println("before...");
        try {
            System.out.println(data[100]);
            System.out.println("try中的代码");
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("异常产生了");
        }

        System.out.println("after...");
    }

before...
异常产生了
after...
2.异常也是类catch只能铺货相应的类型

 Exception是所有异常的父类

catch块中捕获的是exception这个类型,就可以接收所有的异常类型(不推荐)

若知道可能产生的异常类型(数组越界,空指针)catch捕获明确的类型

若不清楚异常类型就是用exception,所有的异常子类都会向上转型为exception引用

3. finally代码块:无论如何都会执行

 资源的释放,方法的关闭,关闭数据库的连接,关闭文件操作都在finally代码块中,保证资源会正确释放

不要在finally代码快中写返回值!!! 

 public static int test(){
        try{
            int[] data = {1,2,3};
            data[100] = 10;
            return 10;
        }catch (ArrayIndexOutOfBoundsException e){
              e.printStackTrace();
              return 20;
        }finally {
            System.out.println("finally代码块");
            return 30;
        }
     }


结果:
java.lang.ArrayIndexOutOfBoundsException: 100
	at www.bit.se.Try.TryTest.test(TryTest.java:9)
	at www.bit.se.Try.TryTest.main(TryTest.java:33)
finally代码块
30

3.异常的处理流程

1. 程序会先执行try中的代码

2.如果try中的代码出现异常,就会结束try中的代码,看和catch中的异常类型是否匹配

3.如果找到匹配的代码就会执行catch中的代码

4.如果没有找到匹配的异常类型就会将异常向上传递到上层调用者

5.无论是否找到异常匹配类型,finally代码都会执行

6.如果上层调用者也没有处理异常,就继续向上传递

7.一直到主方法,也没有处理异常就会交给JVM来进行处理,这时程序就会异常终止

4.throw和throws:人为抛出异常 

throws:用在方法的声明上,表示该方法可能会产生异常,但是本方法不处理,将异常抛给调用者 

  public static void fun()throws ArrayIndexOutOfBoundsException{
        int[] arr = {1,2,3};
        System.out.println(arr[100]);
    }

 throw:用在方法内部,表示人为产生异常对象并抛出

异常对象的产生是发生异常后由JVM产生的,若需要人为产生,就要使用throw关键字!!!

 public static void fun(){
        int[] arr = {1,2,3};
        throw new NullPointerException("抛出一个异常");
    }

5.异常体系:JDK内部异常继承关系 

Java中的异常分为两大类,一类是"受查异常",另一类是"非受查异常"

非受查异常:

RuntimeException及其子类,包括Error称之为"非受查异常",编译阶段可以不显示异常处理(try...catch/throws抛出) 下图中蓝色部分

RuntimeException(运行异常,编译阶段不报错,运行时出错,数组越界异常/空指针异常/类型转换异常)

Error - 程序内部错误,出现这个错误,程序没法正常执行下去,只能推出程序

堆内存溢出错误/栈溢出错误

受查异常:

下图红色为受查异常,必须在编译阶段进行异常处理,否则就会编译出错

 a.使用try...catch处理

 b.throws向上抛出

  

6.自定义异常 

JDK内部已经帮我们定义好了很多异常类,但在某些业务场景下,出现的错误需要我们自定义异常类(用户登录,用户名不对,密码不对,这种错误需要我们自定义异常)

自定义异常需要继承相关的两个父类

若希望这个异常必须显示处理-继承Exception父类

若这个异常不需要显示处理-RuntimeException

public class RuntimeExceptionText {
    private static final String USER_NAME = "zs";
    private static final String PASSWORD = "123";

    public static void main(String[] args) {

        System.out.println("请输入用户名:");
        Scanner sc = new Scanner(System.in);
        String userName = sc.nextLine();
        System.out.println("请输入密码");
        String passWord = sc.nextLine();

        if(!USER_NAME.equals(userName)){
              throw new UserNameException("用户名错误");
        }
        if(!PASSWORD.equals(passWord)){
            throw new PasswordException("密码错误");
        }
    }
}
class UserNameException extends RuntimeException{

    public UserNameException(String msg) {
        super(msg);
    }
}
class PasswordException extends RuntimeException{

    public PasswordException(String msg) {
        super(msg);
    }
}

包装类: 

就是把8大基本类型封装到类中

a.Object类可以接收所有引用数据类型(数组,类,接口),为了让Object类可以接收Java中一切内容,引入包装类,就是把基本类型封装到类的对象之中就产生了包装类

b.包装类的默认值是null

包装类类型:

    整形:(Byte,Shot,Integer,Long);

    浮点型:(Float,Double);

    char类型包装类:Character

    boolean类型的包装类:Boolean

 装箱:将基本类型的数组保存到包装类对象中

 int val = 10;

 Integer i1 = new Integer(val);

 拆箱:将包装类对象中的数值还原为基本类型

 int ret  = i1.Value();

自动拆装箱:使用包装类就和基本类型一样  

 public static void main(String[] args) {
        //自动装箱
        Integer i2 = 10;
        //自动拆箱
        i2 += 20;
        System.out.println(i2);
    }

 a.默认值不同,包装类的默认值都是null,基本类型的默认值就是其基本类型的默认值

 b.比较相等,仍然使用equals方法比较,所有类对象的比较都使用equas方法!!!

同字符串常量池

当使用整形包装类的自动拆装箱时,JVM会缓冲相应的数值

Integer常量池,默认在-128-127之间,都会缓冲到常量池中 

        Integer i1 = 130;
        Integer i2 = 130;
        System.out.println(i1 == i2);//false
        i1 = 120;
        i2 = 120;
        System.out.println(i1 == i2);//true

 阿里编码规范:所有POJO(普通类)的所有成员变量一律使用包装类替代基本类型

泛型: 

 定义泛型对象时,只能使用类

 基本类型不能保存到泛型中,必须使用包装类

   当用户不小心输入的x和y是不同类型时,编译没问题,但取出x和y的值时,强制类型转换就会报错,运行时异常

   一般来说,我们要求把所有的错误都提前暴露在编译阶段,程序还没跑起来就能发现错误!

 泛型:相当于守门员,编译阶段检测类型是否一致的手段

 泛型就是在类定义时不明确类型,在使用时明确类型

定义泛型使用"<>"操作符

<T>:称之为类型参数,可以使用任何字符,中文也可以,规范是单个的大写字母

T:表示任意类型

K:键值对,key值

V:value值

E:单个元素

public class MyPoint <T>{

    //此时X的类型不确定,在产生这个对象时确定类型
    private T x;
    private T y;

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }

    public static void main(String[] args) {
        MyPoint<String> myPoint = new MyPoint<>();
        //类型不一致报错
        myPoint.setY(10);
        myPoint.setX("北纬20度");
        System.out.println(myPoint.getX());
    }
}

若泛型类中存在多个类型参数,成员变量的类型不一定一致

产生对象时,T和E的类型可以相同也可以不同 

public class MypointNew <T,E>{

    private T x;
    private E y;

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public E getY() {
        return y;
    }

    public void setY(E y) {
        this.y = y;
    }

    public static void main(String[] args) {
        MypointNew<String,Integer> mypointNew = new MypointNew<>();
        mypointNew.setX("hello");
        mypointNew.setY(10);
    }
}

集合框架初识:所谓的集合,就是用来保存和操作数据的一些类 

List:线性表的父接口

常用子类: 

    ArrayList(底层是一个动态数组实现的线性表) 

    LinkedList(底层是一个双向链表实现的线性表)

public class ListTest {
    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        List<String> list1 = new LinkedList<>();
        list.add("1");
        list.add("2");
        list.add("2");
        list.add("3");
        list.add(1,"6");//16223
        list.remove(1);//1223
        list.remove("2");//123
        System.out.println(list.get(1));//2
        System.out.println(list.set(1,"6"));//2
        System.out.println(list.contains("3"));//true
        System.out.println(list);//[1,6,3]
    }
}

 相当于二维数组

      List<List<Integer>> list = new ArrayList<>();

        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(3);
        list1.add(5);
        List<Integer> list2 = new ArrayList<>();
        list2.add(2);
        list2.add(4);
        list2.add(6);

        list.add(list1);
        list.add(list2);
        System.out.println(list);//[[1, 3, 5], [2, 4, 6]]
public class MyPoint <T>{

    //此时X的类型不确定,在产生这个对象时确定类型
    private T x;
    private T y;

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }

    public static void main(String[] args) {
        MyPoint<Integer> myPoint = new MyPoint<>();
        myPoint.setY(10);
        myPoint.setX(20);
        System.out.println(myPoint.getX());
    }
}
public class MypointNew <T,E>{

    private T x;
    private E y;

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public E getY() {
        return y;
    }

    public void setY(E y) {
        this.y = y;
    }

    public static void main(String[] args) {
        MypointNew<String,Integer> mypointNew = new MypointNew<>();
        mypointNew.setX("hello");
        mypointNew.setY(10);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值