当前位置: 首页 > news >正文

java异常 与 泛型<T>

文章目录

  • 异常
    • 认识异常
      • 什么是异常?
      • Java的异常体系
      • 异常的基本处理
      • 异常的作用?
    • 自定义异常
      • 编译时异常
      • 自定义运行时异常
    • 异常的处理方案
  • 泛型
    • 认识泛型
    • 泛型类
    • 泛型接口
    • 泛型方法、通配符、上下限
    • 泛型支持的类型
      • 包装类
      • 包装类具备的其他功能
      • 总结

异常

认识异常

什么是异常?

异常代表程序出现的问题

int[] arr = {10, 20, 30};
System.out.println(arr[3]);
// 没有下标为3的元素
System.out.println(10 / 0);
// 除数不能为0
// 读取的文件不存在了
// 读取网络数据,断网了

Java的异常体系

在这里插入图片描述
这也是java帮我们写好的我们直接调用就好。
Java.lang.Throwable 这是所有异常的父级

  • Error:代表的系统级别错误(属于严重问题),也就是说系统一旦出现问题,sun公司会把这些问题封装成Error对象给出来
    ( 说白了,Error是给sun公司自己用的,不是给我们程序员用的,因此我们开发人员不用管它)
  • Exception:叫异常,它代表的才是我们程序可能出现的问题,所以,我们程序员通常会用Exception以及它的孩子来封装程序出现的问题。
    1. 运行时异常:RuntimeException及其子类,编译阶段不会出现错误提醒,运行时出现的异常(如:数组索引越界异常)
    2. 编译时异常:编译阶段就会出现错误提醒的。(如:日期解析异常,这里是提示你这里的程序很容易出错。就算你写的是对的也会提示你。)

运行时异常

import java.io.FileInputStream;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo1 {
    public static void main(String[] args) {
        // 目标:认识异常的体系,搞清楚异常的基本作用。
         show();
    }
    // 定义一个方法认识运行时异常。
    public static void show(){
        System.out.println("==程序开始。。。。==");
        // 运行时异常的特点:编译阶段不报错,运行时出现的异常,继承自 RuntimeException。
        int[] arr = {1,2,3};
        // System.out.println(arr[3]); 
        // ArrayIndexOutOfBoundsException 数组越界异常

        // System.out.println(10/0); 
        // ArithmeticException  计算异常

        // 空指针异常
        String str = null;
        System.out.println(str);
        System.out.println(str.length()); 
        // NullPointerException  空指针异常。
        // 表示程序试图在需要对象的地方使用 null 值进行操作。
        System.out.println("==程序结束。。。。==");
    }
}

编译时异常: 即使你写的代码是对的也会报错。
下面演示你的代码是正确的但是还会报错的情况。

import java.io.FileInputStream;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionDemo1 {
    public static void main(String[] args) {
        // 目标:认识异常的体系,搞清楚异常的基本作用。
		try {
            // 监视代码,出现异常,会被catch拦截住这个异常
            show2();
            // ==程序开始。。。。==
			// Tue Jul 09 11:12:13 CST 2024
			// ==程序结束。。。。==
        } catch (Exception e) {
            e.printStackTrace(); // 打印这个异常信息
        }
    }
    // 定义一个方法认识编译异常。
    public static void show2() throws ParseException {
        System.out.println("==程序开始。。。。==");
        // 编译异常:编译阶段报错,编译不通过。
        String str = "2024-07-09 11:12:13";
        // 把字符串时间解析成Java中的一个日期对象。
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 虽然上面的正确但是我们还是报错加一个throws或者try...catch解决
		

        Date date = sdf.parse(str); 
        // 这里编译时异常。提醒程序员仔细检查这里。
        // 编译时异常,提醒程序员这里的程序很容易出错,请您注意!
        // 这就很恶心了明明我们的代码是对的但是还提示异常。这时候就需要使用throws抛出异常
        // 说明,你不要管我。我已经知道这里容易出错,
        // 但是我已经百分百确定我写的是对的。你直接跑就行了。
        System.out.println(date);
        System.out.println("==程序结束。。。。==");
    }
}

下面演示你的代码是不正确的。但你认为你写对了直接加个throws或者try…catch让程序跑。

import java.io.FileInputStream;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo1 {
    public static void main(String[] args) {
        try {
            // 监视代码,出现异常,会被catch拦截住这个异常
            show2();
        } catch (Exception e) {
            e.printStackTrace(); // 打印这个异常信息
            // 提示千万别写错,但是你还是写错了hhhh~~~
            // java.text.ParseException
        }
    }

    // 定义一个方法认识编译异常。
    public static void show2() throws ParseException {
        System.out.println("==程序开始。。。。==");
        // 编译异常:编译阶段报错,编译不通过。
        String str = "2024-07-09 11:12:13";
        // 把字符串时间解析成Java中的一个日期对象。
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date = sdf.parse(str); // 编译时异常,提醒程序员这里的程序很容易出错,请您注意!
        System.out.println(date);
        System.out.println("==程序结束。。。。==");
    }
    
}

异常的基本处理

两种方式

  • 抛出异常(throws)
  • 捕获异常(try…catch)

快捷键
Alt+Enter:编译时异常调用 throws或者try…catch
Ctrl+Alt+T : throws / try…catch / if / for …

// 抛出异常(throws)
// 在方法上使用throws关键字,可以将方法内部出现的异常抛出去给调用者处理。
方法 throws 异常1 ,异常2 ,异常3 ..{}

// 捕获异常(try…catch)
//直接捕获程序出现的异常。
...
try{
 // 监视可能出现异常的代码!
 }catch(异常类型1 变量){
    // 处理异常
}catch(异常类型2 变量){
      // 处理异常
}
...

实例在上一小节不再过多叙述。

异常的作用?

  • 异常是用来定位程序bug的关键信息。

  • 可以作为方法内部的一种特殊返回值,以便通知上层调用者,方法的执行问题。

public class ExceptionDemo2 {
    public static void main(String[] args) {
        // 目标:搞清楚异常的作用。
        System.out.println("程序开始执行...");
        try {
            System.out.println(div(10, 0));
            System.out.println("底层方法执行成功了~~~");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("底层方法执行失败了~~");
        }
        System.out.println("程序结束执行...");
        // 程序开始执行...
		// 除数不能为0,您的参数有问题!
		// 底层方法执行失败了~~
		// 程序结束执行...
		// java.lang.Exception: 除数不能为0,您的参数有问题!
		// 下面定位信息
		// at com.itheima.demo1exception.ExceptionDemo2.div(ExceptionDemo2.java:28)
		// at com.itheima.demo1exception.ExceptionDemo2.main(ExceptionDemo2.java:8)
    }
   	// 需求:求2个数的除的结果,并返回这个结果。
    public static int div(int a, int b) throws Exception {
        if(b == 0){
            System.out.println("除数不能为0,您的参数有问题!");
            // 可以返回一个异常给上层调用者,返回的异常还能告知上层底层是执行成功了还是执行失败了!!
            throw new Exception("除数不能为0,您的参数有问题!");
        }
        int result = a / b;
        return result;
    }
}

自定义异常

Java无法为这个世界上全部的问题都提供异常类来代表, 如果企业自己的某种问题,想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了。
我们可以使用编译时异常也可以使用运行时异常

编译时异常

/**
 * 自定义的运行时异常
 * 1、继承RuntimeException做爸爸。
 * 2、重写RuntimeException的构造器。
 * 3、哪里需要用这个异常返回,哪里就throw
 */
public class ItheimaAgeIllegalRuntimeException extends RuntimeException{
    public ItheimaAgeIllegalRuntimeException() {

    }

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

public class ExceptionDemo3 {
    public static void main(String[] args) {
        // 目标:认识自定义异常。
        System.out.println("程序开始。。。。");
        try {
            saveAge(300);
            System.out.println("成功了!");
        } catch (ItheimaAgeIllegalException e) {
            e.printStackTrace();
            System.out.println("失败了!");
        }
        System.out.println("程序结束。。。。");
        // 程序开始。。。。
        // 失败了!
        // 程序结束。。。。
        // com.itheima.demo1exception.ItheimaAgeIllegalException: 年龄非法 age 不能低于1岁不能高于200岁
	    // at com.itheima.demo1exception.ExceptionDemo3.saveAge(ExceptionDemo3.java:21)
	    // at com.itheima.demo1exception.ExceptionDemo3.main(ExceptionDemo3.java:8)
    }

    // 需求:我们公司的系统只要收到了年龄小于1岁或者大于200岁就是一个年龄非法异常。
    public static void saveAge(int age) throws ItheimaAgeIllegalException {
        if(age < 1 || age > 200){
            // 年龄非法;抛出去一个异常。
            throw new ItheimaAgeIllegalException("年龄非法 age 不能低于1岁不能高于200岁");
        }else {
            System.out.println("年龄合法");
            System.out.println("保存年龄:" + age);
        }
    }
}

自定义运行时异常

  • 定义一个异常类继承RuntimeException.
  • 重写构造器。
  • 通过throw new 异常类(xxx)来创建异常对象并抛出。
    特点:编译阶段不报错,运行时才可能出现!提醒不属于激进型。
/**
 * 自定义的运行时异常
 * 1、继承RuntimeException做爸爸。
 * 2、重写RuntimeException的构造器。
 * 3、哪里需要用这个异常返回,哪里就throw
 */
public class ItheimaAgeIllegalRuntimeException extends RuntimeException{
    public ItheimaAgeIllegalRuntimeException() {

    }

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

public class ExceptionDemo4 {
    public static void main(String[] args) {
        // 目标:认识自定义异常-运行时异常
        System.out.println("程序开始。。。。");
        try {
            saveAge(300);
            System.out.println("成功了~");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("失败了");
        }
        System.out.println("程序结束。。。。");
        // 程序开始。。。。
        // 失败了
        // 程序结束。。。。
        // com.itheima.demo1exception.ItheimaAgeIllegalRuntimeException: 年龄非法 age 不能低于1岁不能高于200岁
        // at com.itheima.demo1exception.ExceptionDemo4.saveAge(ExceptionDemo4.java:21)
        // at com.itheima.demo1exception.ExceptionDemo4.main(ExceptionDemo4.java:8)
    }

    // 需求:我们公司的系统只要收到了年龄小于1岁或者大于200岁就是一个年龄非法异常。
    public static void saveAge(int age) {
        if(age < 1 || age > 200){
            // 年龄非法;抛出去一个异常。
            throw new ItheimaAgeIllegalRuntimeException("年龄非法 age 不能低于1岁不能高于200岁");
        }else {
            System.out.println("年龄合法");
            System.out.println("保存年龄:" + age);
        }
    }
}

自定义编译时异常

  • 定义一个异常类继承Exception.
  • 重写构造器。
  • 通过throw new 异常类(xxx) 创建异常对象并抛出。
    特点:编译阶段就报错,提醒比较激进
/**
 * 自定义的编译时异常
 * 1、继承Exception做爸爸。
 * 2、重写Exception的构造器。
 * 3、哪里需要用这个异常返回,哪里就throw
 */
public class ItheimaAgeIllegalException extends Exception{
    public ItheimaAgeIllegalException() {

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

public class ExceptionDemo3 {
    public static void main(String[] args) {
        // 目标:认识自定义异常。
        System.out.println("程序开始。。。。");
        try {
            saveAge(300);
            System.out.println("成功了!");
        } catch (ItheimaAgeIllegalException e) {
            e.printStackTrace();
            System.out.println("失败了!");
        }
        System.out.println("程序结束。。。。");
    }

    // 需求:我们公司的系统只要收到了年龄小于1岁或者大于200岁就是一个年龄非法异常。
    public static void saveAge(int age) throws ItheimaAgeIllegalException {
        if(age < 1 || age > 200){
            // 年龄非法;抛出去一个异常。
            throw new ItheimaAgeIllegalException("年龄非法 age 不能低于1岁不能高于200岁");
        }else {
            System.out.println("年龄合法");
            System.out.println("保存年龄:" + age);
        }
    }
}

注意:开发时一般使用运行时异常

异常的处理方案

方案1
1、底层异常层层往上抛出,最外层捕获异常,记录下异常信息,并响应适合用户观看的信息进行提示

方案2
2、最外层捕获异常后,尝试重新修复

抛出异常(throws)
在方法上使用throws关键字,可以将方法内部出现的异常抛出去给调用者处理。

方法 throws 异常1 ,异常2 ,异常3 ..{}
// 推荐方式
方法 throws Exception{
}
// Exception代表可以捕获一切异常

捕获异常(try…catch)
直接捕获程序出现的异常。

try{
// 监视可能出现异常的代码!
}catch(异常类型1 变量){
// 处理异常
}catch(异常类型2 变量){
 // 处理异常
 }...

// 推荐方式
try{
    // 可能出现异常的代码!
}catch (Exception e){
        e.printStackTrace(); 
        // 直接打印异常对象的信息
}
// Exception代表可以捕获一切异常
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo5 {
    public static void main(String[] args) {
        // 目标:掌握异常的处理方案1: 底层异常都抛出去给最外层调用者,最外层捕获异常,记录异常,响应合适信息给用户观看。
        System.out.println("==程序开始。。。。==");
        try {
            show();
            System.out.println("这次操作成功了~~~");
        } catch (Exception e) {
            e.printStackTrace();// 捕获异常,记录异常,打印错误给程序员观看。
            System.out.println("这次操作失败了~~~");// 捕获异常,记录异常,响应合适信息给用户观看。
        }
        System.out.println("==程序结束。。。。==");
        // ==程序开始。。。。==
        // java.text.ParseException: Unparseable date: "2024-07-09 11:12:13"
        // at java.base/java.text.DateFormat.parse(DateFormat.java:399)
        // at com.itheima.demo1exception.ExceptionDemo5.show(ExceptionDemo5.java:29)
        // at com.itheima.demo1exception.ExceptionDemo5.main(ExceptionDemo5.java:15)
        // 这次操作失败了~~~
        // ==程序结束。。。。==
    }

    public static void show() throws Exception {
        // 编译异常:编译阶段报错,编译不通过。
        String str = "2024-07-09 11:12:13";
        // 把字符串时间解析成Java中的一个日期对象。
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date = sdf.parse(str); // 编译时异常,提醒程序员这里的程序很容易出错,请您注意!
        System.out.println(date);

        InputStream is = new FileInputStream("D:/meinv.png");
    }
}

import java.util.Scanner;
public class ExceptionDemo6 {
    public static void main(String[] args) {
        // 目标:掌握异常的处理方案2:捕获异常对象,尝试重新修复。
        // 接收用户的一个定价
        System.out.println("程序开始。。。。");

        while (true) {
            try {
                double price = userInputPrice();
                System.out.println("用户成功设置了商品定价:" + price);
                break;
            } catch (Exception e) {
                System.out.println("您输入的数据是瞎搞的,请不要瞎输入价格!");
            }
        }

        // System.out.println("程序结束。。。。");
        // 程序开始。。。。
        // 请您输入商品定价:
        // qw
        // 您输入的数据是瞎搞的,请不要瞎输入价格!
        // 请您输入商品定价:
        // 1
        // 用户成功设置了商品定价:1.0
        // 程序结束。。。。
    }
    public static double userInputPrice(){
        Scanner sc = new Scanner(System.in);
        System.out.println("请您输入商品定价:");
        double price = sc.nextDouble();
        return price;
    }
}

泛型

认识泛型

定义类、接口、方法时,同时声明了一个或者多个类型变量(如:)
称为泛型类、泛型接口,泛型方法、它们统称为泛型。

public class ArrayList<E>{
    . . .
}
ArrayList<String> list = new ArrayList<String>();
MyArrayList<String> mlist = new MyArrayList<>(); // JDK 7开始支持的后面类型可以不写

作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力!这样可以避免强制类型转换,及其可能出现的异常。

泛型的本质:把具体的数据类型作为参数传给类型变量。

import java.util.ArrayList;
public class GenericDemo1 {
    public static void main(String[] args) {
        // 目标:认识泛型,搞清楚使用泛型的好处。
        // ArrayList<T> list = new ArrayList<T>(); 这可以让程序员自己选择类型。
        ArrayList<String> list = new ArrayList<>();
        list.add("java");
        list.add("php");
        // 获取数据。
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }
    }
}

泛型类

类名后面跟

// 修饰符 class 类名<类型变量,类型变量,…> { }
public class ArrayList<E>{  ...  }
// 注意:类型变量建议用大写的英文字母,常用的有:E、T、K、V 等
import java.util.ArrayList;
// 自定义泛型类
public class MyArrayList<E> {
    private ArrayList list = new ArrayList();
    public boolean add(E e){
        list.add(e);
        return true;
    }
    public boolean remove(E e){
        return list.remove(e);
    }
    @Override
    public String toString() {
        return list.toString();
    }
}
public class GenericDemo2 {
    public static void main(String[] args) {
        // 需求:请您模拟ArrayList集合自定义一个集合MyArrayList.
        // MyArrayList<String> list = new MyArrayList<String>();
        MyArrayList<String> mlist = new MyArrayList<>(); // JDK 7开始支持的后面类型可以不写
        mlist.add("hello");
        mlist.add("world");
        mlist.add("java");
        mlist.add("前端");

        System.out.println(mlist.remove("world"));// true

        System.out.println(mlist);// [hello, java, 前端]
    }
}

泛型接口

// 修饰符 interface 接口名<类型变量,类型变量,…> {   . ..  }
public interface A<E>{ ... }
注意:类型变量建议用大写的英文字母,常用的有:ETKV

演示

public class Teacher {  }
public class Student {  }
package com.itheima.demo3genericity;
// 自定义泛型接口
public interface Data<T> {
    void add(T t);
    void delete(T t);
    void update(T t);
    T query(int id);
}
public class StudentData implements Data<Student>{
    @Override
    public void add(Student student) {  }
    @Override
    public void delete(Student student) {  }
    @Override
    public void update(Student student) { }
    @Override
    public Student query(int id) {
        return new Student();
    }
}
public class TeacherData implements Data<Teacher>{
    @Override
    public void add(Teacher teacher) { }
    @Override
    public void delete(Teacher teacher) { }
    @Override
    public void update(Teacher teacher) { }
    @Override
    public Teacher query(int id) {
        return new Teacher();
    }
}
public class GenericDemo3 {
    public static void main(String[] args) {
        // 需求:项目需要对学生数据/老师数据都要进行增删改查操作
        StudentData studentData = new StudentData();
        studentData.add(new Student());
        studentData.delete(new Student());
        Student s = studentData.query(1);
    }
}

泛型方法、通配符、上下限

// 修饰符 <类型变量,类型变量,…>  返回值类型 方法名(形参列表) {  }
// 正确写法
// 修饰符     <泛型> 返回值 方法名
public static <T>     void test(T t){   }
// 错误写法
public E get(int index){
	return (E) arr[index];
}
// 这才上面的正确写法
public <T> T get(int index) {
    return (T) arr[index];
}
public class Student {   }
public class GenericDemo4 {
    public static void main(String[] args) {
        // 需求:打印任意数组的内容。
        String[] names = {"赵敏", "张无忌", "周芷若", "小昭"};
        printArray(names);

        Student[] stus = new Student[3];
        printArray(stus);

        Student max = getMax(stus);
        String max2 = getMax(names);
    }

    public static <T> void printArray(T[] names){ }
    public static <T> T getMax(T[] names){
        return null;
    }
}

通配符
就是 “?” ,可以在“使用泛型”的时候代表一切类型; E T K V 是在定义泛型的时候使用。

public class Car {  }
public class BYD extends Car{  }
public class LX extends Car{  }
public class Xiaomi extends Car{  }
// GenericDemo5.java
import java.util.ArrayList;
public class GenericDemo5 {
    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);
    }

    // 需求:开发一个极品飞车的游戏。
    // 不能写public static void go(ArrayList<Car> cars) 
    // 虽然Xiaomi和BYD是Car的子类,但是 ArrayList<Xiaomi>  ArrayList<BYD>和 ArrayList<Car> 是没有半毛钱关系!
    // 也不能写public static void go(ArrayList<T> cars)  因为T只能在定义的时候使用。
    // 所以只能另外开发一个用来使用泛型的符号。于是有了?
    public static void go(ArrayList<?> cars) {
    }
}

泛型的上下限:

  • 泛型上限: ? extends Car: ? 能接收的必须是Car或者其子类 。(常用)
  • 泛型下限: ? super Car : ? 能接收的必须是Car或者其父类。
public class Car {  }
public class BYD extends Car{  }
public class LX extends Car{  }
public class Xiaomi extends Car{  }
// GenericDemo5.java
import java.util.ArrayList;
public class GenericDemo5 {
    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());
//        dogs.add(new Dog());
//        go(dogs);
    }

    // 需求:开发一个极品飞车的游戏。
    // 对于public static void go(ArrayList<?> cars) 来说我们不仅仅可以传进来一只车对象,还可以传进来其他的比如狗这显然不是我们要的。
    // 于是发明了给这个?加指定范围。
    // 泛型上限:    ? extends Car:   ? 能接收的必须是Car或者其子类 。这样再来加个狗对象就会报错
    public static void go(ArrayList<? extends Car> cars) {
    }
}

泛型支持的类型

泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。

基本类型的数据
byte
short
int
long
char
float
double
boolean

包装类

包装类就是把基本类型的数据包装成对象的类型。

基本数据类型对应的包装类(引用数据类型)
byteByte
shortShort
intInteger
longLong
charCharacter
floatFloat
doubleDouble
booleanBoolean

为什么要引入包装类

import java.util.ArrayList;
public class GenericDemo6 {
    public static void main(String[] args) {
        // 目标:搞清楚泛型和集合不支持基本数据类型,只能支持对象类型(引用数据类型)。
         ArrayList<int> list = new ArrayList<>();
         list.add(12)
        // 泛型擦除:泛型工作在编译阶段,等编译后泛型就没用了,所以泛型在编译后都会被擦除。所有类型会恢复成Object类型
        // 于是有了 Object o = 12。 但是12并不是一个对象
        // 为了实现万物皆对象,于是有了基本数据类型的包装类。
    }
}

基本类型的数据包装成对象的方案
public Integer(int value):已过时
public static Integer valueOf(int i)

为什么第一种方法过时了。

import java.util.ArrayList;
public class GenericDemo6 {
    public static void main(String[] args) {
        // 把基本数据类型变成包装类对象。
        // 手工包装:
        // Integer i = new Integer(100); // 过时
        Integer it1 = Integer.valueOf(100);  // 推荐的
        // 缓存了好多已经封装好的对象,最低的-128最高的127
        // valueof方法已经提前在数组里封装好了-128-127的所有对象,这些对象已经new好了。
        // 因为-128-127在编程中出现的比较多。他并不希望每次使用都去创建新的对象。
        // 创建新的对象占内存
        Integer it2 = Integer.valueOf(100);  // 推荐的
        System.out.println(it1 == it2);// true是同一个地址
        Integer it3 = Integer.valueOf(130);
        Integer it4 = Integer.valueOf(130);
        System.out.println(it3 == it4);// false不是同一个地址
    }
}

自动装箱:基本数据类型可以自动转换为包装类型。
自动拆箱:包装类型可以自动转换为基本数据类型。

import java.util.ArrayList;
public class GenericDemo6 {
    public static void main(String[] args) {
        // 自动装箱成对象:基本数据类型的数据可以直接变成包装对象的数据,不需要额外做任何事情
        Integer it11 = 130;
        Integer it22 = 130;
        System.out.println(it11 == it22);

        // 自动拆箱:把包装类型的对象直接给基本类型的数据
        int i = it11;
        System.out.println(i);

        ArrayList<Integer> list = new ArrayList<>();
        list.add(130);  // 自动装箱
        list.add(120);  // 自动装箱
        int rs = list.get(1); // 自动拆箱
    }
}

包装类具备的其他功能

可以把基本类型的数据转换成字符串类型。

public static String toString(double d)
public String toString()

可以把字符串类型的数值转换成数值本身对应的真实数据类型。

public static int parseInt(String s)
public static Integer valueOf(String s)
import java.util.ArrayList;
public class GenericDemo6 {
    public static void main(String[] args) {
        // 包装类新增的功能:
        // 1、把基本类型的数据转换成字符串。
        int j = 23;
        String rs1 = Integer.toString(j);   // "23"
        System.out.println(rs1 + 1); // 231

        Integer i2 = j;
        String rs2 = i2.toString(); // "23"
        System.out.println(rs2 + 1 ); // 231

        String rs3 = j + "";
        System.out.println(rs3 + 1 ); // 231

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

        // 2、把字符串数值转换成对应的基本数据类型(很有用)。
        String str = "98";
        // int i1 = Integer.parseInt(str);
        int i1 = Integer.valueOf(str);
        System.out.println(i1 + 2);

        String str2 = "98.8";
//        double d = Double.parseDouble(str2);
        double d = Double.valueOf(str2);
        System.out.println(d + 2);
    }
}

总结

为什么要有包装类,包装类有哪些?

  • 为了万物皆对象,并且泛型和集合都不支持基本类型,支持包装类
  • 8种,int -> Integer , char -> Character,其他的都是首字母大写

包装类提供了哪些常用的功能?
可以把基本类型的数据转换成字符串类型。

public static String toString(double d)
public String toString()

可以把字符串类型的数值转换成真实的数据类型。

public static int parseInt(String s)
public static Integer valueOf(String s)

相关文章:

  • 使用python获取电脑硬盘信息
  • GO语言-数据类型
  • 一种基于学习的多尺度方法及其在非弹性碰撞问题中的应用
  • 单双线程的理解 和 lua基础语法
  • C语言中冒泡排序和快速排序的区别
  • 输出流-----超级详细的在程序中向文件.txt中写入内容
  • 【挠头写算法系列】质疑分治,理解分治,到分治真香
  • STL之迭代器(iterator)
  • case客户续保预测中用到的特征工程、回归分析和决策树分析的总结
  • 监控相关信息 - 留档备查
  • 计算机体系结构之指令体系结构
  • Ubuntu虚拟机Linux系统入门
  • 从能量守恒的角度理解自然现象与社会现象
  • 【C语言】结构体 (深入)
  • python | tracemalloc模块,跟踪内存分配情况
  • 【时时三省】(C语言基础)选择结构程序综合举例2
  • 浅淡红黑树以及其在Java中的实际应用
  • 【ACM MM会议-2024工业异常检测】FiLo++:融合细粒度描述和形变定位的零样本/少样本异常检测
  • IO多路复用沉浸式体验
  • OpenAI Gym 提供了丰富的强化学习测试环境
  • 美国明尼苏达州发生山火,过火面积超80平方公里
  • 国务院关税税则委:调整对原产于美国的进口商品加征关税措施
  • 北京今日白天超30℃晚间下冰雹,市民称“没见过这么大颗的”
  • 75万买299元路由器后续:重庆市纪委、财政局、教委联合调查
  • 耗资10亿潮汕豪宅“英之园”将强拆?区政府:非法占用集体土地
  • 国家林草局原党组成员、副局长李春良接受审查调查