【Java】什么是泛型?什么是包装类

简介: 【Java】什么是泛型?什么是包装类

包装类

基本类型对应的包装类

Java是一个面向对象的编程语言,但其基本数据类型(如int、char、boolean等)并不直接支持面向对象的特性。为了弥补这一不足,Java为每种基本数据类型设计了一个对应的类,这些类统称为包装类(Wrapper Class)。包装类均位于java.lang包中。


装箱和拆箱

装箱(Boxing)和拆箱(Unboxing)是Java语言中关于基本数据类型(primitive types)和它们对应的包装类(wrapper classes)之间转换的两个重要概念。


装箱

  • 装箱是指将基本数据类型转换为对应的包装类对象的过程。
  • 例如,将 int 类型转换为 Integer 类型。
int a = 10;
Integer ii = Integer.valueOf(a);  //显示装箱 or 手动装箱
Integer jj = a;   //隐式装箱 or 自动装箱

我们查看这段代码的汇编代码可以发现,两种装箱底层都是调用的 valueOf() 方法


拆箱

  • 拆箱是指将包装类对象转换为对应的基本数据类型的过程。
  • 例如,将 Integer 类型转换为 int 类型。
Integer ii = 10;
int a = ii;   //自动拆箱
int b = ii.intValue(a); //手动拆箱

我们查看这段代码的汇编代码可以发现,两种拆箱底层都是调用的 intValue() 方法


阿里笔试题【Integer的比较】

//判断两次输出分别是什么
Integer a = 100;
Integer b = 100;
System.out.println(a==b);
Integer c = 200;
Integer d = 200;
System.out.println(c==d)

答案:true false

解析:

  • 这些赋值的过程都是在进行装箱,所以都调用了 valueOf() 方法
  • if 判断条件可知,i 如果是在 [-128, 127] 之间,就是返回一个数组的值
  • 相反,若不在这个范围,就会随机实例化一个对象进行返回

  • 看题可知,100在范围之内,所以 a 和 b 都是返回 IntegerCache.cache[100-(-128)] = IntegerCache.cache[228],故 a == btrue
  • 而200不在范围内,所以 c 和 d 均随机实例化两个不同的对象,会占用内存中不同的位置,一定不会相等,故 c == dfalse

泛型

  • 属于一个语法
  • 简单来说就是适用于许多类型
  • 主要功能是把类型参数化,意味着可以传指定的类型参数

为什么要有泛型

举例:

  • 实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中控某个下标的值

  1. 实现这个类,我们先定义一个 Object[] 数组,Object 使得这个数组可以放下任何类型的数据
  2. 然后创建一个 setArray(int pos, Object obj) 方法,用来在第 pos 位上存放数据 obj
  3. 再创建一个 Object getArray(int pos) 方法,用来返回第 pos 位的值
  4. 可是在当你在 pos = 1 的地方,传入一个 obj = 10 之后,当准备创建一个 int a 来接收 array[1] 这个值的时候,程序确保错了
  • 这是由于 getArray() 方法为了可以让数组能返回任意类型的数据,返回类型设置成了 Object
  • 而在要以 int 类型取出这个数据的时候,由于类型不匹配,导致报错
  • 若要成功接收,就需要强制类型转换,将 Object 的类型转化为 int

  • 因为这样操作下来非常麻烦,所以泛型就出现了

  • 上面例子的代码为:
public class MyArray {  
    public Object[] array = new Object[10];  
  
    public void setArray(int pos, Object obj) {  
        array[pos] = obj;  
    }  
    public Object getArray(int pos) {  
        return array[pos];  
    }  
    public static void main(String[] args) {  
        MyArray myArray = new MyArray();  
        myArray.setArray(1,3);  
        int a = (int) myArray.getArray(1);  
    }
}

泛型语法

class 泛型类名称<类型形参列表> {    // 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> { }
class 泛型类名称<类型形参列表> extends 继承类 { }
class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> { }

  • 上面例子用泛型来写:
public class MyArray<T> {  
    public Object[] array = new Object[10];  
  
    public void setArray(int pos, T obj) {  
        array[pos] = obj;  
    }  
    public T getArray(int pos) {  
        return (T) array[pos];  
    }  
    public static void main(String[] args) {  
        MyArray<Integer> myArray = new MyArray<>();  
        myArray.setArray(1,3);  
        Integer a = myArray.getArray(1);  
    }
}
  • 这里面存放数据的时候都是按照 T类型 来存放的,最后取出的时候是按照 Integer类型 来检查的,若索取出的值和实例化中 <> 内的类型一直,则可取出,反之报错

< >

  • 八种基本类型不能写在里面
  • 只能写包装类类型或者类类型,包装类可以,自己定义的类也可以

  • 小结:
  1. 泛型是讲数据类型参数化,进行传递
  2. 使用 表示当前类是一个泛型
  3. 泛型目前为止的优点:数据类型参数化、编译时自动进行类型检查和转换

泛型的上界

  • 在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束
  • 在泛型编程中,上界通过 extends 关键字(在Java中)来指定,用于声明一个类型参数必须是某个特定类或接口(或其子类/实现类)的实例。这允许在编译时进行更严格的类型检查,防止类型不匹配的错误

public class MyArray<E extends Number> {   //只接受Number的子类型或Number本身作为E的类型实参
  ... 
}
public class MyArray<E extends Comparable<E>> {  //E必须是实现了Comparable接口的
  ... 
}

泛型方法

  • 泛型方法,顾名思义,就是在定义方法时引入了类型参数的方法。这些类型参数在调用方法时会被具体的类型所实例化,从而允许同一个方法接受不同类型的参数并返回相应类型的结果。泛型方法的类型参数通常放在方法返回类型之前,并使用尖括号 <> 包围。

public <T extends Comparable<T>> T findMax(T[] array){  
    T max = array[0];  
    for(int i = 1; i < array.length; i++){  
        if(array[i].compareTo(max) > 0){  
            max = array[i];  
        }    
    }    
  return max;  
}


相关文章
|
8月前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
190 4
|
10月前
|
Java 编译器 容器
Java——包装类和泛型
包装类是Java中一种特殊类,用于将基本数据类型(如 `int`、`double`、`char` 等)封装成对象。这样做可以利用对象的特性和方法。Java 提供了八种基本数据类型的包装类:`Integer` (`int`)、`Double` (`double`)、`Byte` (`byte`)、`Short` (`short`)、`Long` (`long`)、`Float` (`float`)、`Character` (`char`) 和 `Boolean` (`boolean`)。包装类可以通过 `valueOf()` 方法或自动装箱/拆箱机制创建。
115 9
Java——包装类和泛型
|
10月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
9月前
|
存储 安全 Java
🌱Java零基础 - 泛型详解
【10月更文挑战第7天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
82 1
|
9月前
|
Java 语音技术 容器
java数据结构泛型
java数据结构泛型
76 5
|
9月前
|
存储 Java 编译器
Java集合定义其泛型
Java集合定义其泛型
54 1
|
9月前
|
存储 Java 编译器
【用Java学习数据结构系列】初识泛型
【用Java学习数据结构系列】初识泛型
63 2
|
10月前
|
存储 安全 搜索推荐
Java中的泛型
【9月更文挑战第15天】在 Java 中,泛型是一种编译时类型检查机制,通过使用类型参数提升代码的安全性和重用性。其主要作用包括类型安全,避免运行时类型转换错误,以及代码重用,允许编写通用逻辑。泛型通过尖括号 `&lt;&gt;` 定义类型参数,并支持上界和下界限定,以及无界和有界通配符。使用泛型需注意类型擦除、无法创建泛型数组及基本数据类型的限制。泛型显著提高了代码的安全性和灵活性。
108 8
|
9月前
|
安全 Java 编译器
Java基础-泛型机制
Java基础-泛型机制
75 0
|
Java API 容器
Java泛型的继承和通配符
Java泛型的继承和通配符
75 1