数据结构——(java版)包装类与泛型

文章目录

  • [一 包装类](#一 包装类)
    • [1.1 包装类的概念](#1.1 包装类的概念)
    • [1.2 装箱/装包](#1.2 装箱/装包)
    • [1.3 拆箱/拆包](#1.3 拆箱/拆包)
    • [1.4 一个面试题:](#1.4 一个面试题:)
  • [二 泛型](#二 泛型)
    • [2.1 什么是泛型?](#2.1 什么是泛型?)
    • [2.2 泛型的使用](#2.2 泛型的使用)
    • [2.3 泛型的上界](#2.3 泛型的上界)
    • [2.4 泛型实现Comparable接口](#2.4 泛型实现Comparable接口)
    • [2.5 擦除机制](#2.5 擦除机制)
    • 另外:

一 包装类

1.1 包装类的概念

在java中基本数据类型并不继承于Object,为了在泛型 代码中支持基本数据类型,对每一个基本数据类型都对应了一个包装类。

 如图所示,除int类型与char类型外,其余的包装类名均是数据类型名首字母大写!

1.2 装箱/装包

     装箱是指将基本数据类型的值转换成包装类类型
     进行装箱的方法:valueOf
java 复制代码
        int a = 10;
        //装箱成Integer类型
        Integer i = Integer.valueOf(a);
        System.out.println(i);
        Integer i2 = 10;    //隐式装箱
        System.out.println(i2);


隐式装箱的原理:

如图所示:第一个valueOf方法是我们自己调用的

而第二个valueOf方法是系统默认调用的,即在隐式装箱时,系统默认调用了valueOf方法!

 能否装箱成Double封装类?
java 复制代码
        int a = 10;
        Double double1 = Double.valueOf(a);
总结:即使不是对应的包装类,也可以进行装箱。

1.3 拆箱/拆包

 拆箱即将数据从包装类类型转换成基本数据类型
拆箱的方法:intValue()方法
java 复制代码
   Integer a3 = 10;
        int i1 =  a3.intValue();    //拆箱
        int i2 = a3;                //自动拆箱
// 观察本质实现,实际上是调用了intValue()方法.
        System.out.println(i1);
        System.out.println(i2);


隐式拆箱的原理:

第一个intValue方法是显式装箱,第二个intValue方法是隐式装箱,系统自动调用intValue方法!

1.4 一个面试题:

  判断下面两个布尔表达式的值是什么?
java 复制代码
        Integer a4  = 100;
        Integer a5  = 100;
        System.out.println(a4==a5);
        Integer a6  = 200;
        Integer a7 = 200;
        System.out.println(a6==a7);

为什么会出现这个结果?

要查看原理,就要看valueOf方法是怎样实现的!


代码解析:

如果传入的实参i值 在IntegerCache.low这个值与IntegerCache.high这个值范围之内,就返回

IntegerCache.cache这个数组中相应数组元素的内容。

如果不在这个范围之内,就新创建一个对象并返回。

二 泛型

2.1 什么是泛型?

对于一般的方法与变量,只能使用具体的类型:自定义类型与基本数据类型,但是如果要写适用于多种类型的代码,这种刻板的方式对代码的束缚就很大,我们可以通过泛型来解决这个问题,本质就是将类型参数化!

2.2 泛型的使用

举例:创建一个有数组成员的类:创建两个方法,一个为数组赋值,一个获取数组的值!

1 .我们似乎可以不使用泛型,通过Object类使用一段代码接收所有类型的数据!
java 复制代码
//普通类
class MyArray{

    public Object [] arrays = new Object[10];
    //为数组设置值!
    public void setValue(int pos, Object o ){
        arrays[pos] = o;
    }
    public Object getValue(int pos){
        return  arrays[pos];
    }
}
public class Test {

 public static void main(String[] args) {
  MyArray myArray = new MyArray();
        myArray.setValue(0,10);
        myArray.setValue(1,"hello");
        System.out.println(myArray.getValue(0));
        System.out.println(myArray.getValue(1));
    }
}
 但是这种一个数组中存储多种不同类型数据的方式太乱
 我们可以通过指定参数类型来限制数据类型。
  1. 通过泛型类使用泛型
java 复制代码
//泛型类:
//<E>可以看作一个占位符,代表将传入的类型
//在类名后面加<>,
class MyArray<E> {

    //创建一个数组
    public Object[] arrays = new Object[10];
    public E [] arrays2 = (E[])new Object[5] ;  //也可以这样创建一个数组!!!
    //不能直接实例化E!
    //为数组设置值!
    public void setValue(int pos, E o) {   //限定传入的参数类型
        arrays[pos] = o;
    }

    public Object getValue(int pos) {
        return (E) arrays[pos];                //将返回的数据强制转换成指定的数据类型
    }

}
public class Test {

    public static void main(String[] args) {
       MyArray<Integer> myArray = new MyArray<>();
        myArray.setValue(0,10);
       // myArray.setValue(1,"zhangsan");//只能传入整型值!
        System.out.println(myArray.getValue(0));

}

}


  1. 使用泛型方法而不是泛型类!
java 复制代码
class MyArray {

    //创建一个数组
    public  Object[] arrays = new Object[10];
    //为数组设置值!
    public  <E> void setValue(int pos, E o) {   //限定传入的参数类型
        arrays[pos] = o;
    }
    public   <E> Object getValue(int pos) {
        return (E) arrays[pos];                //将返回的数据强制转换成指定的数据类型
    }

}
public class Test {

    public static void main(String[] args) {
       MyArray myArray = new MyArray();
       //在将<>放在调用的方法名之前,进行传参
     myArray.<Integer>setValue(0,5);
        System.out.println(myArray.<Integer>getValue(0));
     }

}

3.2 使用静态方法,这样可以不创建对象也可以调用方法!

java 复制代码
class MyArray {

    //创建一个数组
    public  static  Object[] arrays = new Object[10];
    //为数组设置值!
    public  static <E> void setValue(int pos, E o) {   //限定传入的参数类型
        arrays[pos] = o;
    }
    public  static  <E> Object getValue(int pos) {
        return (E) arrays[pos];                //将返回的数据强制转换成指定的数据类型
    }

}
public class Test {

    public static void main(String[] args) {
      MyArray.<Integer>setValue(0,2);
     }

}

2.3 泛型的上界

//泛型的上界是指:泛型中指定的类型必须是一个类本身或者这个类的子类,此时这个类即泛型的上界。
java 复制代码
class Person<E extends Number>{  
}

此时E代表的类型,必须是Number类本身或者Number的子类。

如果E 继承的是接口,则E代表的类型必须实现了此接口!

2.4 泛型实现Comparable接口

1. 泛型类型的变量不能够直接相互用关系运算符进行比较,因为不能确定是什么类型,所以需要实现Comparable口的类型
   
2. Object类中并没有实现Comparable接口,所以自定义的类中必须自己去实现Comparable接口!
 
3. 包装类自己已经实现了自动类接口
java 复制代码
class Alg<E extends Comparable<E>> { 
    public E max(E[] arrays ){
          E max =  arrays[0];
        for (int i = 1; i < arrays.length ; i++) {
            if(max.compareTo(arrays[i])<0){
                max = arrays[i];
            }
        }
        return max;
    }
}
public class Test {
   public static void main(String[] args) {
        //泛型类实现Comparable接口:
        Integer [] arrays = {1,5,4,2,3,8,9,6};
   //Integer实现了comparable接口
        Alg<Integer> alg = new Alg<>();

        System.out.println(alg.max(arrays));

}

如果换成Person类:

此时报错:是因为Person类没有实现Comparable接口,不符合作为实参的条件!

2.5 擦除机制

另外:

在泛型类中,<>中的类型不参与类型的组成!

java 复制代码
        MyArray<Integer>myArray1 = new MyArray<>();
        MyArray<String> myArray2  = new MyArray<>();
        System.out.println(myArray1);
        System.out.println(myArray2);

结果表明,与并没有参与到类型的组成中去,myArray1与myArray2的类型依然是

MyArray类型!

相关推荐
LuckyLay17 分钟前
Spring学习笔记_27——@EnableLoadTimeWeaving
java·spring boot·spring
向阳121830 分钟前
Dubbo负载均衡
java·运维·负载均衡·dubbo
Gu Gu Study40 分钟前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言
WaaTong1 小时前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
m0_743048441 小时前
初识Java EE和Spring Boot
java·java-ee
AskHarries1 小时前
Java字节码增强库ByteBuddy
java·后端
泉崎1 小时前
11.7比赛总结
数据结构·算法
你好helloworld1 小时前
滑动窗口最大值
数据结构·算法·leetcode
小灰灰__1 小时前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭1 小时前
Java中的动态代理
java·开发语言·aop·动态代理