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

相关文章
|
18小时前
|
存储 Java 编译器
【用Java学习数据结构系列】初识泛型
【用Java学习数据结构系列】初识泛型
13 2
|
1月前
|
安全 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版)
|
27天前
|
存储 安全 搜索推荐
Java中的泛型
【9月更文挑战第15天】在 Java 中,泛型是一种编译时类型检查机制,通过使用类型参数提升代码的安全性和重用性。其主要作用包括类型安全,避免运行时类型转换错误,以及代码重用,允许编写通用逻辑。泛型通过尖括号 `&lt;&gt;` 定义类型参数,并支持上界和下界限定,以及无界和有界通配符。使用泛型需注意类型擦除、无法创建泛型数组及基本数据类型的限制。泛型显著提高了代码的安全性和灵活性。
|
17小时前
|
Java 语音技术 容器
java数据结构泛型
java数据结构泛型
14 5
|
4天前
|
Java
【Java】什么是泛型?什么是包装类
【Java】什么是泛型?什么是包装类
12 0
|
1月前
|
存储 Java 测试技术
Java零基础教学(10):包装类
【9月更文挑战第1天】Java零基础教学篇,手把手实践教学!
30 1
|
2月前
|
安全 Java Go
Java&Go泛型对比
总的来说,Java和Go在泛型的实现和使用上各有特点,Java的泛型更注重于类型安全和兼容性,而Go的泛型在保持类型安全的同时,提供了更灵活的类型参数和类型集的概念,同时避免了运行时的性能开销。开发者在使用时可以根据自己的需求和语言特性来选择使用哪种语言的泛型特性。
41 7
|
2月前
|
存储 安全 Java
如何理解java的泛型这个概念
理解java的泛型这个概念
|
2月前
|
存储 缓存 Java
|
Java
JAVA包装类及自动封包解包示例代码
在学习上是一个知识点,但不知如何与实际串起来。。。 悲哀,真是悲哀!!! 代码: 1 public class Wrapper { 2 public static void main(String[] args) { 3 int i = 500; 4 ...
1094 0