一、包装类

1、什么是包装类?

  • 在进行类型转换时,有一种特殊的转换:将int这样的基本数据类型转换为对象
  • 包装类是基本数据类型对应的类,每个基本数据类型对应一个包装类
  • 基本数据类型不能直接参与引用类型的使用或计算,使用包装类将基本数据类型转换为引用数据类型,可以参与到其他引用类型的使用
  • 包装类是不可变类,在构造了包装类对象后,不允许更改包装在其中的值
  • 包装类是final的,不能继承

2、包装类赋值实例

Integer.valueOf()、 Double.valueOf()将基本数据类型转换为包装类对象。

/**
 * @document: 基本数据类型包装类
 * @Author:SmallG
 * @CreateTime:2023/8/1+16:19
 */

public class Demo01 {
    public static void main(String[] args) {
        //创建基本数据类型包装类对象
        Integer i1 = new Integer(128); //已经过时,不推荐使用
        //通过基本数据类型转换为包装类对象
        Integer i2 = Integer.valueOf(128); //推荐使用
        System.out.println(i1 == i2); //false 对象的引用指向的是地址
        System.out.println(i1.equals(i2)); //true

        Double d1 = Double.valueOf(130.76);
        Double d2 = Double.valueOf(130.76);
        System.out.println(d1 == d2);      //false
        System.out.println(d1.equals(d2)); //true

        //包装类转基本数据类型 转换的时候要符合基本数据类型的表示范围
        int i11 = i1.intValue();
        int i21 = i2.intValue();
        System.out.println(i11 == i21); //true

        double d = d1.doubleValue();
        System.out.println(d); //130.76
    }
}

3、Number及其主要方法

  • 抽象类Number是Byte、Double、Float、Integer、Long和Short类的父类
  • Number类本身是一个抽象类,不能直接实例化,而是作其他数值类的基类
  • 使用Number类及其子类,可以执行各种数值计算和转换操作,根据具体的需求将数值对象转换为不同的数据类型

4、自动拆装箱

对象------>基本数据类型(拆箱)

基本数据类型------>对象(装箱)

/**
 * @document: 自动拆装箱
 * @Author:SmallG
 * @CreateTime:2023/8/1+16:52
 * Java自动拆箱 有数据范围:-128~127
 * Java自动装箱 没有数据范围
 */

public class Demo03 {
    public static void main(String[] args) {
        //
        Integer i1 = 127; //自动装箱(将基本数据类型转换为对象) 装箱没有范围
        Integer i2 = 127;
        System.out.println(i1 == i2);   //true (一个字节内)-128~127之间的数字Java完成自动拆箱(把对象转换为基本数据类型)
        System.out.println(i1.equals(i2)); //true

        Integer i3 = Integer.valueOf(127);
        Integer i4 = Integer.valueOf(127);
        System.out.println(i3 == i4); //true

        Integer i5 = 128;
        Integer i6 = 128;
        System.out.println(i5 == i6); //false
        System.out.println(i5.equals(i6));//true
    }
}

5、大数类

  • 在Java中,存储的数据可能超过基本数据类型中整型最大范围,所以提供了BigInteger类来表示任意大小的整数,提供了BigDecimal类来表示任意大小且精度完全准确的浮点数
  • BigInteger和BigDecimal被称为Java中的大数字类,位于java.math包下,两个类均为Number类的子类

整数型大数类示例:

/**
 * @document: 大数字类
 * @Author:SmallG
 * @CreateTime:2023/8/1+17:23
 */

public class Demo04 {
    public static void main(String[] args) {
        //创建BigInteger对象 需要用字符串的形式传递数值
        BigInteger i1 = new BigInteger(String.valueOf(121231313));
        BigInteger i2 = new BigInteger("12313131313131313131313133134141414545151525");
        System.out.println(i1.add(i2)); //加
        System.out.println(i1.multiply(i2)); //乘
        System.out.println(i1.subtract(i2)); //减
        System.out.println(i1.divide(i2));  //除
        
        i2.longValueExact();//超long的范围会抛异常
    }
}

浮点型大数字类示例:

/**
 * @document: 浮点型大数字类
 * @Author:SmallG
 * @CreateTime:2023/8/1+17:38
 */

public class Demo05 {
    public static void main(String[] args) {
        BigDecimal d1 = new BigDecimal("1234.1414141");
        BigDecimal d2 = d1.multiply(d1);
        System.out.println(d2);

        //BigDecimal使用scale()计算小数位数
        BigDecimal d3 = new BigDecimal("12.34");
        BigDecimal d4 = new BigDecimal("12.3400");
        BigDecimal d5 = new BigDecimal("123400");

        System.out.println(d3.scale()); //2
        System.out.println(d4.scale()); //4
        System.out.println(d5.scale()); //0

        //BigDecimal可以使用setScale设置精度
        BigDecimal d6 = d1.setScale(2, RoundingMode.HALF_UP); //四舍五入保留两位
        BigDecimal d7 = d1.setScale(2, RoundingMode.DOWN); //只舍不入保留两位
        System.out.println(d6);
        System.out.println(d7);

        //判断两个值的数据是否相等
        BigDecimal d8 = new BigDecimal("123.456");
        BigDecimal d9 = new BigDecimal("123.45600");
        System.out.println(d8.equals(d9)); //false 精度不一样,equals在比较的时候要求数值和精度都要相等
        //compareTo()比较数值是否相等
        System.out.println(d8.compareTo(d9));// 0表示相等 1表示不相等
    }
}

二、异常

1、异常概述

让一个没有任何指向的引用去执行操作,会报异常。

异常概述

异常类型继承关系

  • 异常对象的类型之间存在继承关系,异常类都是从Throwable类派生而来
  • Throwable是Java异常类层次结构的根类,它分为两个主要的子类:Error和Exception,Exception又分为两种类型:检查异常(Checked Exception)和非检查异常(Unchecked Exception)。
  • (1)检查异常在编译时需要进行处理,否则编译器会报错。
  • (2)非检查异常在编译时不需要进行处理,因为他们通常表示程序内部错误、逻辑错误或者编程错误。也称运行时异常,它们可以在代码中捕获和处理,但也可以选择不处理。常见的非检查异常包括空指针异常、数组越界异常等。

Throwable类的API

  • getMessage():获取异常的详细描述信息。返回一个字符串,描述异常的原因或相关信息。
  • getCause():获取导致当前异常的原因。返回一个Throwable对象,表示导致当前异常的异常或错误。
  • printStackTrace():打印异常的堆栈跟踪信息。将异常的堆栈跟踪信息输出到标准错误流,用于调试和错误诊断。
  • getStackTrace():获取异常的堆栈跟踪信息。返回一个StackTraceElement数组,包含异常发生时方法的调用链信息。
  • toString():返回异常对象的字符串表示。通常返回异常类的名称,以及异常的详细描述信息。

2、处理异常

(1)try-catch语句块

将可能出现异常的语句放在try里面,如果出现异常会跳过try执行catch语句。

/**
 * @document: try-catch处理异常
 * @Author:SmallG
 * @CreateTime:2023/8/2+9:33
 */

public class Demo07 {
    public static void main(String[] args) {
        System.out.println("程序开始了");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str = scanner.nextLine(); // 接收一行内容
        //输入null 表示什么都没输
        str = str.equals("null") ? null : str;
        try {
            System.out.println(str.length());
            System.out.println(str.charAt(1));
            //转换为整型 当字符串不是数字 会出现NumberFormatException(数字格式化异常)
            System.out.println(Integer.parseInt(str));
            //当出现异常之后 在try语句以下部分代码都不会执行
            System.out.println("!!!!!!!!!!!!!");

        } catch (NullPointerException e1) {
            //获取异常信息
            System.out.println(e1.getMessage());
            System.out.println("出现空指针异常!");
        } catch (StringIndexOutOfBoundsException e2) {
            //获取字符串的一个位置,超过了字符串的长度 会出现下标越界异常
            System.out.println(e2.getMessage());
            System.out.println("出现字符串下标越界异常!");
        } catch (NumberFormatException e3) {
            System.out.println(e3.getMessage());
            System.out.println("出现了数字格式化异常!");
        }
       /* catch (Exception e){
            //最大捕获异常
            System.out.println("出现了异常");
        }*/
        System.out.println("程序结束了!");
    }
}

(2)finally语句块

finally语句块在try或catch语句块之后,不论try语句块中是否出现异常。finally语句块中的代码均会被执行,主要用于执行释放资源的逻辑。

/**
 * @document: finally语句块
 * @Author:SmallG
 * @CreateTime:2023/8/2+10:17
 */

public class Demo08 {
    public static void main(String[] args) {
        System.out.println("程序开始");
        String str1 = null;
        try {
            System.out.println(str1.length());
        } catch (Exception e) {
            System.out.println("出现了空指针异常");
        } finally {
            //无论try语句块中的代码是否出现异常 finally语句块都会执行
            System.out.println("finally执行了");
        }
        System.out.println("程序结束了!");
    }
}

(3)**finally代码中的执行时机(面试会问)

情况一:先将finally里的代码执行完毕后,再返回方法中的数值。

/**
 * @document: finally代码的执行时机
 * @Author:SmallG
 * @CreateTime:2023/8/2+10:24
 */

public class Demo09 {
    public static void main(String[] args) {
        System.out.println(get()); // 3  2
    }

    public static int get() {
        int a = 1;
        try {
            return a + 1; //return结果已经返回
        } finally {
            a = 3;
            System.out.println(a);
        }
    }
}

情况二:如果finally里面有return,则返回值以finally里面的return为准。

/**
 * @document: finally代码的执行时机
 * @Author:SmallG
 * @CreateTime:2023/8/2+10:24
 */

public class Demo09 {
    public static void main(String[] args) {
        System.out.println(get2()); //3
    }

    //以最后一次return为准
    public static int get2() {
        int a = 1;
        try {
            return a + 1;
        } finally {
            a = 3;
            return a;
        }
    }
}

情况三:如果在try-catch中JVM突然中断,强制退出,那么终止以下的代码不会被执行。或者try-catch存在死循环、进程被杀死等都不会执行。

/**
 * @document: finally代码的执行时机
 * @Author:SmallG
 * @CreateTime:2023/8/2+10:24
 */

public class Demo09 {
    public static void main(String[] args) {
        System.out.println(get3()); //不会输出任何内容
    }
    public static int get3() {
        int a = 1;
        try {
            System.exit(0); //强制退出程序
            return a + 1;
        } finally {
            a = 3;
            return a;
        }
    }
}

3、抛出异常

当出现异常的时候,由当前代码主动创建并抛出一个异常对象,抛出异常的目的是通知上层调用者或异常处理机制,表明当前代码无法正常处理某个特定情况,需要由上层调用者或异常处理机制来处理。

(1)throw

在代码中显式的抛出一个异常,在代码块中声明。

/**
 * @document: throw抛出异常
 * @Author:SmallG
 * @CreateTime:2023/8/2+10:44
 */

public class Demo10 {
    public static void main(String[] args) {
        String str = null;
        try {
            print(str);
        } catch (NullPointerException e) {
            System.out.println(e.getMessage());
        }
    }

    public static void print(String str) {
        if (str == null) {
            //程序满足抛出异常条件 ,余下代码就会终止
            //把异常抛给了调用者
            throw new NullPointerException("对象为空");
        }
        System.out.println(str.length());
    }
}

(2)throws

在方法签名中声明

/**
 * @document: throws抛出异常
 * @Author:SmallG
 * @CreateTime:2023/8/2+10:44
 */

public class Demo10 {
    public static void main(String[] args) {
        String str = null;
        try {
            hello(str);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        System.out.println("hello");
    }

    public static void hello(String str) throws NullPointerException, RuntimeException {
        if (str == null) {
            throw new NullPointerException("对象为空");
        }
        if (str.length() < 6) {
            throw new RuntimeException("字符串长度不足6位");
        }
        System.out.println(str);
    }
}

(3)*子类重写父类方法 throws规则

/**
 * @document: 子类重写父类方法 throws规则
 * @Author:SmallG
 * @CreateTime:2023/8/2+11:18
 */

public class Demo11 {

}

class Person {
    //父类的方法抛出的异常
    public void print(String str) throws RuntimeException {
        if (str == null) {
            throw new NullPointerException("对象为空");
        }
        System.out.println(str);
    }
}

class Student extends Person {
    //子类重写父类方法时,可以抛父类的异常或者时父类异常的子类,不能大于父类抛出的异常范围
    public void print(String str) throws NullPointerException {

    }
}

4、自定义异常

开发者自己定义的异常,创建自定义异常的步骤:

  1. 创建一个继承Exception或RuntimeException的子类,如果希望自定义异常是受检异常继承Exception,如果希望自定义异常是非受检异继承RuntimeException类
  2. 在自定义异常类中,给类起名见名知意,以Exception结尾
  3. 在自定义异常类中,通常需要显式声明构造函数

创建自定义异常

/**
 * @document: 自定义异常
 * 1、命名遵守见名知意 以Exception结尾
 * 2、继承Exception(受检异常/编译型异常)或者RuntimeException(非受检异常/运行时异常)
 * 3、重写父类的构造方法(5个)
 * @Author:SmallG
 * @CreateTime:2023/8/2+11:34
 */

public class PasswordLengthLittleException extends RuntimeException {
    public PasswordLengthLittleException() {
        super();
    }

    public PasswordLengthLittleException(String message) {
        super(message);
    }

    public PasswordLengthLittleException(String message, Throwable cause) {
        super(message, cause);
    }

    public PasswordLengthLittleException(Throwable cause) {
        super(cause);
    }

    protected PasswordLengthLittleException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

使用自定义异常

/**
 * @document: 使用自定义异常
 * @Author:SmallG
 * @CreateTime:2023/8/2+11:40
 */

public class Demo12 {
    public static void main(String[] args) {
        String password = "123";

        try {
            print(password);
        } catch (NullPointerException e) {
            System.out.println(e.getMessage());
        } catch (PasswordLengthLittleException e) {
            System.out.println(e.getMessage());
        }
    }

    public static void print(String password) throws NullPointerException, PasswordLengthLittleException {
        if (password == null) {
            //抛出异常
            throw new NullPointerException("密码为空");
        }
        if (password.length() < 6) {
            //抛出自定义异常
            throw new PasswordLengthLittleException("密码长度不足6位");
        }
        System.out.println("密码是:" + password);
    }
}

三、练习

1 输入数字字符串,转换为整数或浮点数

用户从控制台接收一个字符串,通过程序判断该字符串是整数,还是小数。如果是整数,将该字符串转换成int类型并输出结果;如果是小数,将该字符串转换成double类型并输出结果;如果既不是整数也不是小数,程序输出“数字格式不正确”。

提示:请使用正则表达式而不是异常来实现类型判断。

程序交互过程如下所示:

1、用户输入整数字符串的情况,如下图所示:

练习1

2、用户输入为小数的情况,如下图所示:

练习2

3、用户输入的既不是整数也不是小数的情况,如下图所示:

练习3

/**
 * @document: 输入数字字符串,转换为整数或浮点数
 * @Author:SmallG
 * @CreateTime:2023/8/1+16:51
 */

public class StringToIOrF {
    public static void main(String[] args) {
        String isInt = "^[0-9]+$";
        String isDouble = "^[0-9]+\\.[0-9]+$";
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个数字:");
        //输入数字字符串
        String s = scanner.next();
        if (s.matches(isInt)){
            int i = Integer.parseInt(s);
            System.out.println("这是一个整数:"+i);
        }else if (s.matches(isDouble)){
            double d = Double.parseDouble(s);
            System.out.println("这是一个小数:"+d);
        }else{
            System.out.println("数字格式不正确!");
        }
    }
}

2 输入数字字符串,转换为整数或浮点数

本题整体需求与第一题相同,但是要求使用异常处理机制而非正则表达式来实现第一题的需求。

/**
 * @document: 输入数字字符串,转换为整数或浮点数
 * @Author:SmallG
 * @CreateTime:2023/8/1+16:51
 */

public class StringToIOrF2 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个数字:");
        //输入数字字符串
        String s = scanner.next();
        try {
                int i = Integer.parseInt(s);
                System.out.println("这是一个整数:"+i);
        }catch (NumberFormatException e1){
            try {
                double d = Double.parseDouble(s);
                System.out.println("这是一个小数:"+d);
            }catch (NumberFormatException e2){
                System.out.println("数字格式不正确!");
            }
        }
    }
}

3 计算数字乘积

已知有一个整型数组{1280, 2560, 5120, 10240, 20480, 40960},现需要计算其中元素的乘积。计算规则为,按顺序逐一选出数组中的一个元素,计算它与数组中前面所有元素的乘积并输出。

程序运行结果如下所示:

练习4

/**
 * @document: 数字乘积
 * @Author:SmallG
 * @CreateTime:2023/8/1+17:19
 */

public class productNum {
    public static void main(String[] args) {
        int[] arr = {1280, 2560, 5120, 10240, 20480, 40960};
        BigInteger sum = new BigInteger(String.valueOf(arr[0]));
        for (int i = 0; i < arr.length; i++) {
            if (i!=0){
                sum = sum.multiply(BigInteger.valueOf(arr[i]));
            }
            System.out.println(sum);
        }
    }
}
最后修改:2023 年 08 月 02 日
如果觉得我的文章对你有用,请随意赞赏