00/ 知识回顾
上一节,学习了Scanner类的导入。
接着,创建了Scanner类的实例对象。
然后,学习了Scanner对象中用于接收各种输入数据的方法。
最后,我们学习了生成随机数的Random类及其方法。
01/ 先导课
之前我们学习1~3节是基础知识,4~10节是循环与判断,11~14节是数组,15~22节是类和对象,接下来进入高级语法阶段。
之前我们学习了方法重载,在同一个类中,创建多个同名方法,根据具体的数据类型,定义不同的参数列表。那我们可不可以进一步简化?用一个方法就可以接收不同的数据类型。
答案是有的,在java中使用泛型,接下来我们开始学习。
泛型概念理解:
在日常生活中,“泛”指广泛、普通或不特定。例如,"泛指"意味着不指某一个具体对象,而是指一个范围或类别。在编程中的泛型,也体现了类似的概念,它允许一个类或者方法,通过定义类型参数,能够处理不同类型的数据。

02/ 包装类
什么是包装类?
包装类是Java中的类,它们用于将基础类型的数据封装成对象。
这些对象具有一些额外的功能,例如提供了一些方法来操作基础类型的数据,支持面向对象编程的特性,以及允许处理null值等。
// int的包装类Integer,可以存储null值 Integer x = null;
// 使用包装类的equals方法判断x与y的值是否相等 Integer x = 10; Integer y = 20; System.out.print(x.equals(y)); // 输出结果 false
基础类型对应的包装类是什么?
基础类型对应的包装类如下表所示,包装类遵循“类名首字母大写”的约定。

基础类型和包装类之间的关系

基础类型和包装类的关系可以比作现金和银行卡:
基础类型是现金,它直接代表货币价值,使用方便、高效。
包装类是银行卡,它代表数字货币,除了用来消费外它提供了更多的功能,如转账、查询,但处理起来比现金更复杂。
自动装箱(了解即可)
自动装箱是Java中的一个特性,它是指在需要使用包装类的地方,可以自动地将基础数据类型的值转换为对应的包装类对象,而不需要显式地进行类型转换。
// 自动装箱,将int类型的值42转换为Integer对象 Integer num = 42;
02/ 在方法中使用泛型
方法重载的写法和泛型写法对比
方法重载的写法:
// 支持int类型的printArray方法,用来输出一个数组的每个元素
public static void printArray(int[] inputArray) {
// 遍历数组的每一个元素并输出
for (int element : inputArray) {
System.out.println(element);
}
}
// 支持char类型的printArray方法,用来输出一个数组的每个元素
public static void printArray(char[] inputArray) {
for (char element : inputArray) {
System.out.println(element);
}
}
// 支持double类型的printArray方法,用来输出一个数组的每个元素
public static void printArray(double[] inputArray) {
for (double element : inputArray) {
System.out.println(element);
}
}
// 支持String类型的printArray方法,用来输出一个数组的每个元素
public static void printArray(String[] inputArray) {
for (String element : inputArray) {
System.out.println(element);
}
}
使用泛型写法:
public static <T> void printArray(T[] inputArray) {
for (T element : inputArray) {
System.out.println(element);
}
}
-
void前面多了一个符号<T>,它是类型参数,一个占位符,表示方法可以操作任意数据类型,而不是固定在某一特定类型上。
-
printArray后的括号里面是泛型数组参数,表示该方法接受一个类型为T的数组。
-
T element是方法中的一个泛型变量,表示一个类型为T的变量。
调用泛型方法
当你调用printArray方法并传递参数时,T会自动识别实参的数据类型,并按照该类型执行方法中的代码。注意,当参数类型为基础类型时,必须替换为对应的包装类,如int替换为Integer
public static <T> void printArray(T[] inputArray) {
for (T element : inputArray) {
System.out.println(element);
}
}
// 传递int类型的数组,需要使用int的包装类Integer
Integer[] arr1 = {1, 2};
printArray(arr);
// 传递char类型的数组,需要使用char的包装类Character
Character[] arr2 = {'a', 'b'};
printArray(arr);
// 输出结果
1
2
a
b
可以为方法设置泛型返回值
firstElement设置了一个T类型的返回值
// firstElement方法:可以返回任意类型数组的第一个元素
public static <T> T firstElement(T[] inputArray) {
return inputArray[0];
}
// 传递int类型的数组,需要使用int的包装类Integer
Integer[] arr1 = {1, 2};
int firstNum = firstElement(arr1);
System.out.println(firstNum);
// 输出结果
1
练习题
编写一个Java程序,创建一个泛型方法 linearSearch,该方法接受一个泛型数组和一个目标元素,返回目标元素在数组中的索引位置(从0开始)。如果目标元素不存在于数组中,则返回 -1。
public class MyTest {
// 定义一个泛型方法linearSearch,用于在数组中搜索目标值
public static <T> int linearSearch(T[] inputArray, T target) {
// 遍历数组
for (int i = 0; i < inputArray.length; i++) {
// 使用equals方法比较目标值和当前数组元素是否相等
if (target.equals(inputArray[i])) {
// 如果相等,返回当前元素的索引位置
return i;
}
}
// 如果循环结束仍未找到目标值,返回 -1 表示目标值不存在于数组中
return -1;
}
// 这里是主方法
public static void main(String[] args) {
// 包装类
Integer[] nums = {7, 6, 2};
// 搜索目标值3
int index3 = linearSearch(nums, 3);
System.out.println(index3);
// 搜索目标值6
int index6 = linearSearch(nums, 6);
System.out.println(index6);
}
}
// 输出结果
-1
1
03/ 在类中使用泛型
为什么需要有泛型类?

假设你正在开发一个应用程序,需要编写一个通用的类来临时存储各种类型的数据,如用户信息、配置设置或临时计算结果。这些数据可能是字符串、整数、或者更复杂的对象(如自定义的用户类)。此时,你需要定义一个泛型类。
怎么定义泛型类
// 定义了一个TempData类,并为其设置类型参数T
class TempData<T> {
// 私有属性data用来存储任意类型的临时数据
private T data;
// 构造方法TempData为data属性赋值
public TempData(T data) {
this.data = data;
}
// 公共方法getData返回data属性当前存储的数据
public T getData() {
return data;
}
}
类型参数:与泛型方法类似,在定义泛型类时,我们可以在类名后添加类型参数<参数名>。其中 T 是一个类型参数,代表可以存储任何类型的数据。
泛型属性:借助类型参数T,你可以在泛型类中创建泛型属性。
泛型方法:借助类型参数T,你同样可以在泛型类中创建泛型方法。例如:构造方法,创建了一个T类型的参数data;公共方法,设置了返回值类型为T。
实例化对象
在声明泛型类的变量时,需要使用类名<数据类型包装类>的格式指定具体的类型。
注意,基础类型必须使用对应的包装类,例如int类就是TempData<Integer>
使用new关键字创建泛型类的对象时,需要在类名后添加一对空的尖括号,格式为:new 类名<>(实参);
int userId = 1314;
TempData<Integer> intData = new TempData<>(userId);
练习题
创建一个Box类用于模拟一个抽奖箱,其中包含了不同类型的奖品数据(它们使用任意类型的数组存储)。
该类型提供3个方法:
-
head() 方法:返回数组的第一个元素。
-
till() 方法:返回数组的最后一个元素。
-
search(T target) 方法:在数组中搜索是否包含某个特定元素,若存在返回true,不存在返回false。
// 按要求创建类BOX
class Box<T> {
// 创建一个私有的data属性,类型为泛型数组
private T[] data;
// 构造函数,接受泛型数组作为参数为data赋值
public Box(T[] data) {
this.data = data;
}
// head方法,返回数组的第一个元素
public T head() {
return this.data[0];
}
// till方法,返回数组的最后一个元素
public T till() {
return this.data[data.length - 1];
}
// search方法,搜索是否包含某个元素
// 若包含返回true,不包含返回false
public boolean search(T target) {
for (T t : data) {
if (t.equals(target)) {
return true;
}
}
return false;
}
}
public class MyTest {
public static void main(String[] args) {
// 调用box
String[] gifts = {"稀有", "传奇", "史诗", "金币10", "金币20", "金币30", "稀有"};
Box<String> gameBox = new Box<>(gifts); // 创建 Box 对象,并传入字符串数组
System.out.println("本次抽奖有史诗级奖品吗:" + gameBox.search("史诗")); // 检查是否包含 "史诗"
}
}
// 输出
本次抽奖有史诗级奖品吗:true
04/ 扩展


05/ 总结
-
理解包装类,了解自动装箱。
-
学习在方法中使用泛型,并调用泛型方法。
-
学习在类中使用泛型,在泛型类中创建泛型属性、泛型方法,并学习实例化泛型类的对象。
335

被折叠的 条评论
为什么被折叠?



