java异常 与 泛型<T>

文章目录

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

异常

认识异常

什么是异常?

异常代表程序出现的问题

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

Java的异常体系

java异常 与 泛型<T>_第1张图片
这也是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 list = new ArrayList(); 这可以让程序员自己选择类型。
        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 list = new MyArrayList();
        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 cars) 
    // 虽然Xiaomi和BYD是Car的子类,但是 ArrayList  ArrayList和 ArrayList 是没有半毛钱关系!
    // 也不能写public static void go(ArrayList 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 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

包装类

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

基本数据类型 对应的包装类(引用数据类型)
byte Byte
short Short
int Integer
long Long
char Character
float Float
double Double
boolean Boolean

为什么要引入包装类

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)

你可能感兴趣的:(java,java,开发语言)