学习任务:

视频学习

阅读文档理解需求

动手定义泛型类

动手使用泛型类

小结

攀博课堂课程服务类提供课程的服务接口,其中使用数组存储课程的信息,提供了添加课程、删除课程、查询课程列表等接口方法,下边是部分代码:

PbCourseService类实现了添加课程、查询课程等服务方法。

/**
 * 
 */
package com.pbteach.javase.oop.generictypes;

/**
 * 课程服务类
 * 
 * @author 攀博课堂
 * @version v1.0
 */
public class PbCourseService {

	// 课程列表
	private PbCourse[] courseList;

	
	public PbCourseService(int size) {
		courseList = new PbCourse[size];
	}

	// 添加
	public int addCourse(PbCourse course) {
		//从数组的第0个元素开始放pbCourse对象
		for(int i=0;i<courseList.length;i++) {
			if(courseList[i] == null) {
				//向courses存储课程信息
				courseList[i] = course;
				return 1;
			}
		}
		return 0;
		
	}

	// 根据索引查询课程信息
	public PbCourse getCourseByIndex(int index) {
		if(index>=0 && index<courseList.length) {
			return courseList[index];
		}
		return null;
	}

	public static void main(String[] args) {
		PbCourseService courseService = new PbCourseService(10);
		courseService.addCourse(new PbCourse(101L, "攀博课堂 java面向对象编程高级篇v1.0", 20F));
		courseService.addCourse(new PbCourse(102L, "攀博课堂 Spring Cloud 微服务开发v1.0", 50F));
		PbCourse course = courseService.getCourseByIndex(1);
		System.out.println(course.getCourseName());
	}

}

PbStudentService实现了添加学生、查询学生等服务方法。

/**
 * 
 */
package com.pbteach.javase.oop.generictypes;

/**
 * 学生服务类
 * 
 * @author 攀博课堂
 * @version v1.0
 */
public class PbStudentService {

	// 学生列表
	private PbStudent[] studentList;

	
	public PbStudentService(int size) {
		studentList = new PbStudent[size];
	}

	// 添加
	public int addStudent(PbStudent student) {
		//从数组的第0个元素开始放pbCourse对象
		for(int i=0;i<studentList.length;i++) {
			if(studentList[i] == null) {
				//向courses存储课程信息
				studentList[i] = student;
				return 1;
			}
		}
		return 0;
		
	}

	// 根据索引查询学生信息
	public PbStudent getStudentById(int index) {
		if(index>=0 && index<studentList.length) {
			return studentList[index];
		}
		return null;
	}

	public static void main(String[] args) {
		PbStudentService studentService = new PbStudentService(10);
		studentService.addStudent(new PbStudent(101L, "传智燕青", "1759102882@qq.com"));
		studentService.addStudent(new PbStudent(102L, "攀博", "pbteach@126.com"));
		PbStudent student = studentService.getStudentById(1);
		System.out.println(student.getNickName());
	}

}

在系统中还有很多类似的接口方法 ,比如:学生信息服务类提供了添加学生、删除学生、查询学生列表等方法,学生信息、选课信息等都可以用数组来存储。

如果开发一个面对数组的通用的服务接口就可以将其应用于学生信息、课程信息、选课信息等多种信息的管理业务上,服务接口包括添加元素、查询元素、删除元素等方法。

下边我们先创建一个类测试下,如果测试通过再抽取接口,暂时先定义添加元素和根据索引查询元素两个方法进行测试。

代码如下:

package com.pbteach.javase.oop.generictypes;

/**
 * 数组操作通用类
 * @author 攀博课堂
 * @version v1.0
 */
public class PbArrayListV1 {
	
	//数组用于存储各种对象
	private static Object[] objects;

	public PbArrayListV1(int size){
		objects = new Object[size];
	}
	
	//添加元素
	public int add(Object obj) {
		for(int i=0;i<objects.length;i++) {
			if(objects[i] == null) {
				//向courses存储课程信息
				objects[i] = obj;
				return 1;
			}
		}
		return 0;
		
	}
	
	//根据id获取元素
	public Object getByIndex(int index) {
		if(index>=0 && index<objects.length) {
			return objects[index];
		}
		return null;
	}
	
	public static void main(String[] args) {
		PbArrayListV1 arrayList = new PbArrayListV1(10);
		arrayList.add(new PbCourse(101L, "攀博课堂 java面向对象编程高级篇v1.0", 20F));
		arrayList.add(new PbCourse(102L, "攀博课堂 Spring Cloud 微服务开发v1.0", 50F));
		//由于getByIndex方法返回Object所以需要强制转换
		PbCourse course = (PbCourse) arrayList.getByIndex(1);
		System.out.println(course.getCourseName());
	}
}

通过测试,两个方法可以正常使用,不过存在如下问题:

1、向数组列表中添加元素,方法的参数为Object类型,只要是Object及它的子类都可以添加,如果能限制类型就可以在编译阶段防止添加错误的元素类型发生。比如:限制只能添加PbCourse类型,当添加PbStudent类时编译不通过。

2、由于数组类型为Object[],调用get方法从数组获取元素,需要将元素强制转换为指定类型,如果取出的元素类型与转换的类型不匹配在编译阶段不会报错,在使用时则报错,如果调用get方法取出的元素不用转换直接是目标类型这样即可省去强制转换,避免后期类型错误的问题。

上边两个问题有个共同的点就是类型的问题,由于要做成可以存储多种类型元素所以添加元素方法 的参数定义为Object,get方法取出的也是Object,所以要经过强制转换,虽然这两个问题不影响使用,但是风险很大,很容易由于元素类型错误些引发一些错误。

以上问题可用泛型来解决,泛型即参数化类型,即可将类型作为参数传入类的定义中。

之前学习调用一个方法可以传参,泛型可以理解为向定义的类中传参。

在类的定义中使用泛型(参数化类型)的类叫泛型类,它的定义格式如下:

public class 类名<T>  {

}

T是一个泛型标识符,可以理解为定义的形参,在尖括号中写上泛型标识符就是泛型的定义方法 ,格式如下:

<泛型标识符1,泛型标识符2...>
通常泛型标识符用单个大写字母表示,如:<T,E>,多个泛型标识符中间用逗号分隔。

定义PbArrayList泛型类代码如下:

public class PbArrayList<T>  {

}

泛型标识符是可以在类的定义中当类型来使用的,下边PbArrayList泛型类中,在接口的get方法 和add方法 中就可以将Object换成了T泛型标识符。

package com.pbteach.javase.oop.generictypes;

/**
 * 数组操作通用类,使用泛型实现
 * @author 攀博课堂
 * @version v1.0
 */
public class PbArrayListV2<T> {
	
	//数组用于存储各种对象
	private static Object[] objects;

	public PbArrayListV2(int size){
		objects = new Object[size];
	}
	
	//添加元素
	public int add(T obj) {
		for(int i=0;i<objects.length;i++) {
			if(objects[i] == null) {
				//向objects存储元素
				objects[i] = obj;
				return 1;
			}
		}
		return 0;
		
	}
	
	//根据id获取元素
	public T getByIndex(int index) {
		if(index>=0 && index<objects.length) {
			return (T) objects[index];
		}
		return null;
	}
	
	public static void main(String[] args) {
		PbArrayListV2<PbCourse> arrayList = new PbArrayListV2<PbCourse>(10);
		arrayList.add(new PbCourse(101L, "攀博课堂 java面向对象编程高级篇v1.0", 20F));
		arrayList.add(new PbCourse(102L, "攀博课堂 Spring Cloud 微服务开发v1.0", 50F));
		//由于getByIndex方法返回Object所以需要强制转换
		PbCourse course = arrayList.getByIndex(1);
		System.out.println(course.getCourseName());
	}
}

上边代码中add方法可以限定为添加PbCourse类型的对象,get方法获取的元素对象不用经过强制转换即可赋值给PbCourse。

测试代码中,arrayList为泛型类的对象,与定义普通类对象定义的格式差不多,只不过在new一个对象时需要传入具体的类型,定义泛型类对象的格式如下:

类名<传入实际类型> 对象名= new 类名<传入实际类型>(构造参数);

既然在创建泛型类的对象时需要传入具体的类型,如果在数组中准备填充学生类就可以在创建对象时传入学生类型,代码如下:

//传入学生类型
PbArrayListV2<PbStudent> studentList = new PbArrayListV2<PbStudent>(10);
studentList.add(new PbStudent(101L, "传智燕青", "1759102882@qq.com"));
studentList.add(new PbStudent(102L, "攀博", "pbteach@126.com"));
PbStudent student = studentList.getByIndex(1);
System.out.println(student.getNickName());

泛型是什么 ?

泛型即参数化类型,就是将类型当作参数。

在类中、接口、方法中都可以使用泛型。

泛型如何定义?

泛型是在尖括号中加入变量名,通常单个大写字母作为变量名,多个变量名中间用逗号分隔,当有多个变量名时说明可以传入多个类型。

具体泛型在接口、类及方法中应用时定义时有不同:

泛型类定义方法 :

public class 类名<T>  {

}

如何创建泛型类的对象?

与定义普通类对象格式差不多,只不过需要传入具体的类型,定义泛型类对象的格式如下:

类名<传入类型> 对象名= new 类名<传入类型>(构造参数);
提问-攀博课堂
我要提问 不会就问,有效沟通
关注公众号,加入微信群交流提问。 攀博课堂官方公众号
问答列表,查看本知识点所有问题