【用Java学习数据结构系列】初识泛型

简介: 【用Java学习数据结构系列】初识泛型

看到这句话的时候证明:此刻你我都在努力

加油陌生人 2.png

前言


好久没有更新文章了,大概断更了20天,想着今天就写一下文章吧!最近也是又温习了一下数据结构,其实之前我写过关于数据结构的一个专栏那个专栏是写了顺序表,链表,栈和队列,但是那时是用C语言实现的,虽然数据结构不局限于语言,但是总归在语言的使用上有所不同,毕竟面向不同,一个是面向过程的C语言,一个是面向对象的Java。所以这次我打算起一个数据结构的Java专栏,当然由于之前已经写过有些地方会写得简洁一点,模糊的话大家可以去看一下前面得文章哦。今天是关于泛型的哦!只是简单的认识一下基础,为了更好的理解后面Java使用数据结构的代码。

认识包装类

Java中,包装类(Wrapper Classes)是用来包装原始数据类型的类。Java是一种面向对象的语言,所有的对象都是类的实例,包括基本数据类型。但是基本数据类型并不是对象,它们是Java语言的一部分,而不是Java类。为了将基本数据类型当作对象来处理,Java提供了对应的包装类。

以下是Java中的基本数据类型及其对应的包装类:boolean - Boolean

byte - Byte

short - Short

int - Integer

long - Long

float - Floa

double - Double

char - Characte

很容易看出来除了int和char的包装类有些特殊其它基本数据的包装类就是大写其第一个字幕。

包装类的主要作用包括:

自动装箱和拆箱:Java 5 引入了自动装箱(Autoboxing)和拆箱(Unboxing)的概念,允许自动将基本数据类型转换为对应的包装类对象,反之亦然。

使用对象的方法:包装类提供了一些有用的方法,比如toString()、equals()、hashCode()等,这些在基本数据类型中是不可用的。

集合框架:Java的集合框架只能存储对象,不能直接存储基本数据类型。通过包装类,可以将基本数据类型作为对象存储在集合中。

方法参数:在定义方法时,如果需要一个可变参数,可以使用包装类,因为基本数据类型是不可变的。

在数据结构中我们主要运用第三点集合框架,集合框架,后面的文章会给大家讲到。

自动装箱和拆箱的使用

以下就是自动装箱和拆箱的使用方法:

如果将num1和num2打印出来,都是一样的值----5。

public class Test {

    public static void main(String[] args) {
        Integer num1 = 5; // 自动装箱
        int num2 = num1; // 自动拆箱
        
        System.out.println(num1);
        System.out.println(num2);
    }
}



包装类还提供了一些静态方法,比如Integer.valueOf(int i)用于将基本类型转换为包装类对象,

Integer.parseInt(String s)用于将字符串转换为基本类型。这些方法在处理数值与字符串之间的转换时非常有用。将字符串转化为整形其实我们前面在讲字符串时也是讲过的。

了解完包装类接下来就是我们的泛型学习了。

泛型的概念

泛型是Java中一种强大的特性,它允许程序员在编写代码时指定类型参数,从而使得代码更加灵活和可重用。泛型提供了一种方式,使得编译器可以在编译时检查类型安全,避免了类型转换的错误和运行时的类型检查。


当当看概念可能比较抽象,下面我们引出一个情境:


我们以前学过的数组,只能存放指定类型的元素,例如:int[] array = new int[10]; String[] strs = new

String[10];

那么如果我想要一个什么类型都能储存的数组可以吗?

其实这是可以实现的,那么我们这里就要提到object类了。

所有类的父类,默认为Object类。数组是否可以创建为Object?

答案是可以的,如下代码,在自己定义了一个MyArray后,我们就可以在里面储存各种类型的数据了。

class MyArray {
    Object[] array = new Object[10];

    public void setVal(int pos, Object val) {
        array[pos] = val;

    }

    public Object getVal(int pos) {

        return array[pos];

    }


}


    public class Test {




        public static void main(String[] args) {
            MyArray myArray=new MyArray();
            myArray.setVal(0,2);
            myArray.setVal(1,"hello world");

            int ret1=(int)myArray.getVal(0);        //注意这里必须进行强制类型转换
            String ret2=(String)myArray.getVal(1);   //注意这里必须进行强制类型转换

            System.out.println(ret1);
            System.out.println(ret2);

        }
        }


但是数组的定义本来就是用来储存同种类型数据的一种集合。像上面这种却又不像是数组呢。

下面我们在引入一个情境:

我在定义一个容器时暂时不知道用什么数据类型怎么办,我在用到时才知道这个容器要用什么类型的数据,这时我们该怎么办呢?这时我们的主角泛型就该出场了。


泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译 器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。

那么下面就来细看泛型的使用

语法:

class 泛型类名称<类型形参列表> {

// 这里可以使用类型参数

}


那么类型参数列表是什么呢?

其实我们可以理解为一个占位符,我们用一个字母来代表他是一个类型的数据,至于这具体是什么我们定义这个类时是不知道的,但是这时我们可以在这个类中先使用这个未知的类型进行一系列操作,当我们在实例化new一个对象出来时才可以传入自己想要使用的参数类型。

泛型的使用如下代码:

class Box<T> {
    private T t;

    public void set(T t) {
        this.t = t;
    }
    public T get() {
        return t;
    }
}




    public class Test {


        public static void main(String[] args) {
            Box<Integer> box=new Box<>();
            box.set(6);
            System.out.println(box.get());
        }
        }


在上面代码中我们定义一个泛型类Box,在实例化时我们需要如上 Box box=new Box<>();那么这个类中的T,那么全部转化为Integer了,所以在传入类型实参时通常是一个类,即:这里的Integer不能是int,这就是我们为什么要先学习包装类。

这个泛型类就是我们数据结构最常用的泛型知识点。


泛型的上界

首先我们先了解什么是泛型上界

泛型上界是泛型编程中的一个重要概念,它用于指定泛型参数可以继承或实现的类或接口的类型范围。在Java等支持泛型的语言中,上界允许你限制泛型参数必须是某个类或接口的子类或实现。

其语法为:

class 泛型类名称<类型形参 extends 类型边界> {

······

}代码例子

public class MyArray<E extends Number> {
...
}

那么这时我们的传入的类型变量就必须为Number的子类

MyArray n1; // 正常,因为 Integer 是 Number 的子类型

MyArray n2; // 编译错误,因为 String 不是 Number 的子类型


泛型方法

语法形式:

方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) {

}

代码示例:

 public class Util { 
//静态的泛型方法 需要在static后用<>声明泛型类型参数 
public static<E>  void swap(E[] array, int i, int j) { 
E t = array[i];
 array[i] = array[j]; 
array[j] = t;
 } 
} 

那么这时我们使用泛型方法时通常有两种方式:
一、可以自动进行类型推导:

 Integer[] a = { ... }; 
swap(a, 0, 9); 

String[] b = { ... };
 swap(b, 0, 9);  


二、 不使用类型推导

 Integer[] a = { ... }; 
Util.<Integer>swap(a, 0, 9); 

String[] b = { ... }; 
Util.<String>swap(b, 0, 9) 


以上就是泛型的简单介绍,泛型的知识还有很多,但是我们这次只学习一些基础唔。主要是为了后面数据类型的打基础铺垫。

目录
相关文章
|
29天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
|
20天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
40 6
|
26天前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
22天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
29天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习(8)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
29天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
29天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
29天前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
29天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
29天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明