Java——包装类和泛型

简介: 包装类是Java中一种特殊类,用于将基本数据类型(如 `int`、`double`、`char` 等)封装成对象。这样做可以利用对象的特性和方法。Java 提供了八种基本数据类型的包装类:`Integer` (`int`)、`Double` (`double`)、`Byte` (`byte`)、`Short` (`short`)、`Long` (`long`)、`Float` (`float`)、`Character` (`char`) 和 `Boolean` (`boolean`)。包装类可以通过 `valueOf()` 方法或自动装箱/拆箱机制创建。

包装类

包装类是Java提供的一种特殊类,它们将Java的基本数据类型(如int、double、char等)封装成对象。这样做的好处是可以将基本数据类型作为对象来处理,使用对象所特有的属性和方法。

Java提供了8种基本数据类型的包装类:
Integer → int
Double → double
Byte → byte
Short → short
Long → long
Float → float
Character → char
Boolean → boolean

获取包装类对象的方式

使用valueOf()创建

以Integer为例,直接通过调用valueOf方法,把值传入到方法中

Integer i1 = Integer.valueOf(127);

下面看一个特殊的例子:

Integer i1 = Integer.valueOf(127);
        Integer i2 = Integer.valueOf(127);
        System.out.println(i1 == i2); // true
        Integer i3 = Integer.valueOf(128);
        Integer i4 = Integer.valueOf(128);
        System.out.println(i3 == i4); // false

对于引用数据类型,因为" == " 是比较地址值的,i3 , i4不是同一个对象可以理解,但是为什么 i1 和 i2 是一样的呢?
在实际开发中,-128~127之间的数字用的比较多,为了节省内存,Java提前创建好了这些对象,用的时候直接调取,不会再创建新的对象

直接赋值

自动装箱和自动拆箱
当使用包装类的时候,该怎么去进行计算呢,首先要把对象转化为基本数据类型,再进行计算,再转化为引用数据类型,这样手动的去转化就非常麻烦,所以在JDK5的时候就出现了自动装箱和自动拆箱的机制
自动装箱:把基本数据类型变为对应的包装类
自动拆箱:把包装类转化为对应的基本数据类型

//自动拆箱
        Integer i = 1;
        //自动装箱
        int j = i;
        System.out.println(i);
        System.out.println(j);
        System.out.println(i + j);

Integer成员方法


返回值为String类型

//进制转换
        System.out.println(Integer.toBinaryString(10));//1010
        System.out.println(Integer.toOctalString(10));//12
        System.out.println(Integer.toHexString(10));//a

类型转换:

Integer i5 = Integer.parseInt("123");
        System.out.println(i5 + 1);
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();//键盘录入一行,遇到空格不会停止
        System.out.println(s);
        System.out.println(Integer.parseInt(s) + 1);

除了 Character,都有对应的转换方法

泛型

在Java编程中,泛型是一个强大的工具,它允许我们在编写代码时定义灵活的、可重用的结构,而无需关心具体的数据类型。

引出泛型

问题:实现一个类,类中包含一个数组成员,使得数组中可以存放任意类型的数据,也可以根据成员方法访问返回数组中下标的值
如果是任意类型的话,可以考虑Object,因为它是所有类型的父类,接着试着实现一下这个问题

class MyArray{
    private Object[] arr = new Object[10];
    public void set(int index,Object value){
        arr[index] = value;
    }
    public Object get(int index){
        return arr[index];
    }
}
public class Demo1 {
    public static void main(String[] args) {
        MyArray myArray = new MyArray();
        myArray.set(0,"AA");
        myArray.set(1,1);
        String s = (String) myArray.get(0);//因为返回的是Object类型,所以需要强制类型转换
        int i = (int)myArray.get(1);
        System.out.println(s+" "+i);
    }
}

上面的代码就实现了这个要求,但是此时发现一个弊端,如果数据过多的话就显得特别杂乱,各种类型都有,都需要强制类型转换
泛型的主要目的就是:指定当前容器要持有什么类型的对象,接着让编译器去检查类型,此时就是把类型作为参数传递,需要什么类型就传入什么类型
格式: <数据类型>
注意: 泛型只能支持引用数据类型

泛型的擦除:
类型擦除是Java编译器在编译泛型代码时的一个步骤。在编译过程中,编译器会将泛型信息从代码中擦除,并在需要的地方插入类型转换和类型检查代码。这样,运行时的字节码不包含任何泛型类型信息,只包含原始类型和必要的类型转换。

ArrayList<Integer> arrayList = new ArrayList<>();

例如在创建集合时,当数据真正的添加到集合里边的时候,集合还是会把它们当作Object类处理,只不过往外获取时会进行相应的强制类型转换

泛型类

当一个类中,某个变量的类型不确定,就可以定义带有泛型的类

格式:
修饰符 class 类名 <类型>{
}

class MyArray <E>{
    private Object[] arr = new Object[10];
    public void set(int index,E value){
        arr[index] = value;
    }
    public E get(int index){
        return (E) arr[index];//
    }
}
public class Demo1 {
    public static void main(String[] args) {
        MyArray<Integer> myArray = new MyArray<>(); //已经确定好类型了
        //myArray.set(0,"Str");  自动类型检查,要与上面的类型一致
        myArray.set(0,1);
        int i = myArray.get(0);
        System.out.println(i);
        //创建String类型
        MyArray<String> myArray2 = new MyArray<>();
        myArray2.set(0,"hello");
        String str = myArray2.get(0);
        System.out.println(str);
    }
}

上面的MyArray就是一个泛型类,通过使用泛型,就对传入的数据类型进行了约束,同时,也实现了可以传入不同的类型参数

泛型方法

当一个类中只有一个方法中要用到不确定的类型,就只需要把这个方法定义为泛型方法即可

格式:
修饰符 <类型> 返回值类型 方法名(类型 变量名){
}

class ListUtil{
    public void show(){
        System.out.println("其他方法···");
    }
    public static <E> void addAll(ArrayList<E> list,E e1,E e2,E e3){
        list.add(e1);
        list.add(e2);
        list.add(e3);
    }
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        addAll(list,"a","b","c");
        System.out.println(list);
        
        ArrayList<Integer> list2 = new ArrayList<>();
        addAll(list2,1,2,3);
        System.out.println(list2);
    }
}

泛型接口

格式:
修饰符 interface 接口名<类型>{
}

例如Java中的List接口就是一个泛型接口:

泛型接口的使用方法:
1.实现类给出具体类型


2.实现类延续泛型,创建对象时再确定类型

泛型的继承和通配符

泛型不具备继承性,但数据具备继承性
什么意思呢

首先定义了两个具有继承关系的类,method方法里边所限定的类型是Fu 类型,它的子类型所创建的对象并不能使用该方法,如果想要子类型也能使用,就需要把方法定义为泛型方法,但是如果是其他类型也可以使用,怎么去限定只有这种具有继承关系的类才能使用
这时就可以使用通配符来实现

通配符:?
也表示不确定类型,但是可以限定类型,
? extend E: 表示可以传递E 或 E所有的子类类型
? super E: 表示可以传递E 或 E 所有的父类类型

泛型的上界

上面介绍的通过extend进行类型限制就是指定了泛型的上界,下面还有一种复杂的示例

例如:
写一个泛型类,定义一个方法,可以求数组的最大值


这时候就需要用到compareTo方法,就要实现comparable接口

public class Alg<E extends Comparable<E>> { //对泛型进行了限制,必须实现Comparable接口的类型才能传入
    public E findMax(E[] array){
        E max = array[0];
        for(int i = 0;i < array.length;i++){
            if(max.compareTo(array[i]) < 0){
                max = array[i];
            }
        }
        return max;
    }
    public static void main(String[] args) {
        Integer[] arr = {1,2,3,4,5};
        Alg<Integer> alg = new Alg<>();
        int a = alg.findMax(arr);
        System.out.println(a); //5
    }
}

比如再定义一个Person类,因为它没有实现Comparable接口,所以泛型里边不能传入Student

相关文章
|
9天前
|
Java API
[Java]泛型
本文详细介绍了Java泛型的相关概念和使用方法,包括类型判断、继承泛型类或实现泛型接口、泛型通配符、泛型方法、泛型上下边界、静态方法中使用泛型等内容。作者通过多个示例和测试代码,深入浅出地解释了泛型的原理和应用场景,帮助读者更好地理解和掌握Java泛型的使用技巧。文章还探讨了一些常见的疑惑和误区,如泛型擦除和基本数据类型数组的使用限制。最后,作者强调了泛型在实际开发中的重要性和应用价值。
12 0
[Java]泛型
|
18天前
|
存储 安全 Java
🌱Java零基础 - 泛型详解
【10月更文挑战第7天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
10 1
|
25天前
|
Java 语音技术 容器
java数据结构泛型
java数据结构泛型
26 5
|
23天前
|
存储 Java 编译器
Java集合定义其泛型
Java集合定义其泛型
17 1
|
25天前
|
存储 Java 编译器
【用Java学习数据结构系列】初识泛型
【用Java学习数据结构系列】初识泛型
18 2
|
22天前
|
安全 Java 编译器
Java基础-泛型机制
Java基础-泛型机制
12 0
|
2月前
|
存储 安全 搜索推荐
Java中的泛型
【9月更文挑战第15天】在 Java 中,泛型是一种编译时类型检查机制,通过使用类型参数提升代码的安全性和重用性。其主要作用包括类型安全,避免运行时类型转换错误,以及代码重用,允许编写通用逻辑。泛型通过尖括号 `&lt;&gt;` 定义类型参数,并支持上界和下界限定,以及无界和有界通配符。使用泛型需注意类型擦除、无法创建泛型数组及基本数据类型的限制。泛型显著提高了代码的安全性和灵活性。
|
29天前
|
Java
【Java】什么是泛型?什么是包装类
【Java】什么是泛型?什么是包装类
15 0
|
5月前
|
Java API 容器
Java泛型的继承和通配符
Java泛型的继承和通配符
32 1
|
6月前
|
安全 Java API
Java一分钟之-泛型通配符:上限与下限野蛮类型
【5月更文挑战第19天】Java中的泛型通配符用于增强方法参数和变量的灵活性。通配符上限`? extends T`允许读取`T`或其子类型的列表,而通配符下限`? super T`允许向`T`或其父类型的列表写入。野蛮类型不指定泛型,可能引发运行时异常。注意,不能创建泛型通配符实例,也无法同时指定上下限。理解和适度使用这些概念能提升代码的通用性和安全性,但也需兼顾可读性。
64 3