【用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) 


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

目录
相关文章
|
17天前
|
Java
Java基础学习day08-作业
本作业涵盖Java中Lambda表达式的应用,包括Runnable与Comparator接口的简化实现、自定义函数式接口NumberProcessor进行加减乘及最大值操作,以及通过IntProcessor处理整数数组,实现遍历、平方和奇偶判断等功能,强化函数式编程实践。
41 5
|
17天前
|
Java API 容器
Java基础学习day08-2
本节讲解Java方法引用与常用API,包括静态、实例、特定类型方法及构造器引用的格式与使用场景,并结合代码示例深入解析。同时介绍String和ArrayList的核心方法及其实际应用。
93 1
|
4天前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(一):认识Python、Py解释器作用;编写第一个Python程序;Python中的基本数据结构
认识Python 前提安装好Python,这里使用3.13版本 如今Python作为变成姐最炙手可热的编程语言,它的使用途径涵盖绝大部分生活中需要的开发需要。 许多大型网站就是用Python开发的,例如YouTube、Instagram,还有国内的豆瓣。很多大公司,包括Google、Yahoo等,甚至NASA都大量地使用Python。
108 1
|
14天前
|
安全 Java
Java之泛型使用教程
Java之泛型使用教程
122 10
|
18天前
|
Java 程序员
Java基础学习day08
本节讲解Java中的代码块(静态与实例)及其作用,深入介绍内部类(成员、静态、局部及匿名)的定义与使用,并引入函数式编程思想,重点阐述Lambda表达式及其在简化匿名内部类中的应用。
94 5
|
18天前
|
Java
Java基础学习day07-作业
本作业包含六个Java编程案例:1)动物类继承与多态;2)加油卡支付系统;3)员工管理类设计;4)学生信息统计接口;5)USB设备控制;6)家电智能控制。综合运用抽象类、接口、继承、多态等面向对象技术,强化Java基础编程能力。
131 3
|
18天前
|
Java
Java基础学习day06-作业
本内容为Java基础学习作业,涵盖两个案例:一是通过Card类及其子类GoldenCard、SilverCard实现加油卡系统,体现封装与继承;二是通过Shape类及子类Circle、Rectangle演示多态与方法重写,强化面向对象编程理解。
44 1
|
18天前
|
设计模式 存储 Java
Java基础学习day07
本节讲解Java中的final关键字、单例设计模式、枚举类、抽象类与接口。涵盖常量定义、单例写法(饿汉式/懒汉式)、枚举特点及应用场景,以及抽象类与接口的使用与区别,助力掌握核心面向对象编程思想。
91 1
|
23天前
|
Java
Java基础学习day05-作业
本文为Java基础学习第五天作业,通过五个案例练习类与对象的定义、构造方法、set/get方法及成员方法的应用。涵盖女友、学生、教师、手机和电影等类的设计与测试,强化面向对象编程基础。
52 2
|
23天前
|
安全 Java 编译器
Java基础学习day06
本节学习Java继承与多态核心概念:继承通过extends实现,子类可复用父类非私有成员,支持单继承与多层继承,遵循就近原则并可用super调用父类成员;方法重写需满足权限与返回值约束,常用于重写toString等。多态基于继承,实现父类引用指向子类对象,提升扩展性但无法直接访问子类独有方法,可通过instanceof安全类型转换。
86 2

热门文章

最新文章