泛型
为什么要使用泛型?
集合不使用泛型的时候,存的时候什么类型都能存(Object)。但是取的时候(Object)就懵逼了。取出来啥也不是。
使用泛型在编译期直接对类型作出了控制,只能存储泛型定义的数据
泛型: 定义的时候表示一种未知的数据类型,在使用的时候确定其具体的数据类型。
泛型的作用是在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。
定义和使用含有泛型的类
定义格式:
修饰符 class 类名<代表泛型的变量> { }
代表泛型的变量: 可以是任意字母 例如: T,E...
泛型在定义的时候不具体类型,使用的时候才具体类型。在使用的时候确定泛型的具体数据类型。
// 泛型类
class ArrayList<E>{
// 参数是泛型
public boolean add(E e){ }
// 返回值是泛型
public E get(int index){ }
....
}
确定泛型具体类型
在创建对象的时候确定泛型
例如,ArrayList<String> list = new ArrayList<String>();
此时,变量E的值就是String类型,那么我们的类型就可以理解为
class ArrayList<String>{
public boolean add(String e){ }
public String get(int index){ }
...
}
定义含有泛型的类
public class MyList<E>{
E e;
public E func(E e){
return e;
}
public static void main(String[] args) {
MyList<String> myList = new MyList<>();
// 属性赋值
myList.e = "哈哈";
System.out.println(myList.e );
System.out.println(myList.func("呵呵"));
MyList<Integer> myList2 = new MyList<>();
// 属性赋值
myList2.e = 666;
System.out.println(myList2.e );
System.out.println(myList2.func(888));
}
}
定义和使用含有泛型的方法
格式
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
- 调用方法时,确定泛型的类型
public class Test {
// 修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
public static <T> T func1(T t){
return t;
}
public static void main(String[] args) {
Integer i = func1(100);
System.out.println(i);
String s = func1("2222");
System.out.println(s);
}
}
定义含有泛型的接口
修饰符 interface接口名<代表泛型的变量> { }
public interface IA <E>{
public abstract void m1(E e);
public default E m2(E e){
return e;
}
}
public class ImplA<E> implements IA<E>{
@Override
public void m1(E e) {
}
@Override
public E m2(E e) {
return e;
}
public static void main(String[] args) {
// 使用时确定泛型
ImplA<String> implA = new ImplA<>();
implA.m1("哈哈");
System.out.println(implA.m2("嘻嘻"));
}
}
好案例
package com.company.day13.fanxing;
import java.util.Scanner;
/**
* @ Author :Eric Lee
* @ Date :Created in 18:20 2021/8/23
* @ Description:
* @ Modified By:
* @ Version : 1.0
*/
public class LinearSearch {
// 构造函数私有 不能实例化(new) 只能通过静态方法调用
private LinearSearch(){};
// 泛型方法
public static <E> int search(E[] arr, E target){
for (int i = 0; i < arr.length; i++) {
if (arr[i].equals(target))
return i;
}
return -1;
}
public static void main(String[] args) {
Integer[] arr = {11, 2, 33, 55, 66, 88, 99};
String[] arr2 = {"hello", "hai", "xixi", "dada"};
// 编写线性查找目标数组元素, 返回元素的索引, 没找到返回 -1
// System.out.println(search(arr, 88)); // 5
// System.out.println(search(arr, 100)); //-1
// System.out.println(search(arr2, "hello")); //-1
// System.out.println(search(arr2, "100")); //-1
Car[] cars = new Car[5];
cars[0] = new Car("辽A8888", "雅迪");
cars[1] = new Car("吉A8888", "雅迪");
cars[2] = new Car("黑A8888", "雅迪");
cars[3] = new Car("京A8888", "雅迪");
cars[4] = new Car("鲁A8888", "雅迪");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入您的车牌号");
String chePai = scanner.next();
Car target = new Car(chePai, null);
int index = search(cars, target);
if ( index!= -1)
System.out.println("你的爱车在" + index +"位置");
else
System.out.println("你的车丢啦");
}
}
Car类
package com.company.day13.fanxing;
import java.util.Objects;
/**
* @ Author :Eric Lee
* @ Date :Created in 18:53 2021/8/23
* @ Description:
* @ Modified By:
* @ Version : 1.0
*/
public class Car {
// 车牌号
private String ID;
private String brand;
public Car(String ID, String brand) {
this.ID = ID;
this.brand = brand;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return Objects.equals(ID, car.ID) ;
}
@Override
public int hashCode() {
return Objects.hash(ID, brand);
}
@Override
public String toString() {
return "Car{" +
"ID='" + ID + '\'' +
", brand='" + brand + '\'' +
'}';
}
}
通配符高级使用----受限泛型
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限
泛型的上限:
- 格式:
类型名称 <? extends 类 > 对象名称
- 意义:
只能接收该类型及其子类
泛型的下限:
- 格式:
类型名称 <? super 类 > 对象名称
- 意义:
只能接收该类型及其父类型
比如:现已知Object类,String 类,Number类,Integer类,其中Number是Integer的父类
public class Test2 {
public static void main(String[] args) {
ArrayList<Object> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>();
ArrayList<Number> list3 = new ArrayList<>();
ArrayList<Integer> list4 = new ArrayList<>();
// m1(list1);
// m1(list2);
m1(list3);
m1(list4);
}
// 只可以接收Number以下 list3,list4
public static void m1(ArrayList<? extends Number> list){}
// 只可以接收Integer以上 list1, list3,list4
public static void m2(ArrayList<? super Integer> list){}
// 四个都能接收
public static void m3(ArrayList<?> list){}
// 四个都能接收
public static void m4(ArrayList list){}
}
案例2
package com.company.day13.fanxing;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @ Author :Eric Lee
* @ Date :Created in 19:27 2021/8/23
* @ Description:
* @ Modified By:
* @ Version : 1.0
*/
public class Hero<T extends List<Integer>> {
private String name;
private String id;
// 技能伤害列表
T t;
public Hero(String name, String id, T t) {
this.name = name;
this.id = id;
this.t = t;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
@Override
public String toString() {
return "Hero{" + "name='" + name + '\'' + ", id='" + id + '\'' + ", t=" + t + '}';
}
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
Collection<Integer> list2 = new ArrayList<>();
Collection<Number> list3 = new ArrayList<>();
ArrayList<String> list4 = new ArrayList<>();
Hero hero = new Hero<>("小鲁班", "12", list); // 可以
// Hero hero2 = new Hero<>("小鲁班", "12", list2); // 不可以
// Hero hero2 = new Hero<>("小鲁班", "12", list3); // 不可以
// Hero hero2 = new Hero<>("小鲁班", "12", list4); // 不可以
}
}
作业
一 编程题【Collection集合、迭代器】
1.1 题目
请定义一个Collection类型的集合,存储以下字符串:
“JavaEE企业级开发指南”,”Oracle高级编程”,”MySQL从入门到精通”,
”Java架构师之路”
请编程实现以下功能:
Ø 使用迭代器遍历所有元素,并打印
Ø 使用迭代器遍历所有元素,筛选书名小于10个字符的,并打印;
Ø 使用迭代器遍历所有元素,筛选书名中包含“Java”的,并打印
Ø 如果书名中包含“Oracle”,则删掉此书。删掉后,遍历集合,打印所有书名。
(注意:以上功能写在一个main()方法中,但请单独实现)
public class Test2_1 {
public static void main(String[] args) {
//1.使用多态创建Collection集合
Collection<String> col = new ArrayList<>();
//2.添加元素
col.add("JavaEE企业级开发指南");
col.add("Oracle高级编程");
col.add("MySQL从入门到精通");
col.add("Java架构师之路");
//3.使用迭代器遍历所有元素,并打印
System.out.println("————————————————————使用迭代器遍历所有元素,并打印——————————————————————");
Iterator<String> iterator = col.iterator();
while(iterator.hasNext()) {
String book = iterator.next();
System.out.println(book);
}
//4.使用迭代器遍历所有元素,筛选书名小于10个字符的,并打印;
//注意要重新获取新的迭代器,旧的无法再次使用
System.out.println("—————————————————————用迭代器遍历所有元素,筛选书名小于10个字符的,并打印—————————————————————");
iterator = col.iterator();
while(iterator.hasNext()) {
String book = iterator.next();
if(book.length()<10) {//判断书名小于10个字符
System.out.println(book);
}
}
//5.使用迭代器遍历所有元素,筛选书名中包含“Java”的,并打印
System.out.println("—————————————————————使用迭代器遍历所有元素,筛选书名中包含“Java”的,并打印—————————————————————");
iterator = col.iterator();
while(iterator.hasNext()) {
String book = iterator.next();
if(book.contains("Java")) {//判断书名是否包含Java字符
System.out.println(book);
}
}
//6.如果书名中包含“Oracle”,则删掉此书。删掉后,遍历集合,打印所有书名。
//题目要求要遍历两次,但是一次遍历其实也可以完成
System.out.println("—————————————————————如果书名中包含“Oracle”,则删掉此书。删掉后,遍历集合,打印所有书名。—————————————————————");
iterator = col.iterator();
while(iterator.hasNext()) {
String book = iterator.next();
if(book.contains("Oracle")) {//判断书名是否包含Oracle字符
//注意此处不要使用col.remove(book); 会有异常的风险,而应该使用迭代器的remove()方法
iterator.remove();
} else {
System.out.println(book);
}
}
}
}
二 编程题【增强for】
2.1 题目
请定义一个Collection类型的集合,存储以下分数信息:
88.5,39.2,77.1,56.8,89,99,59.5
请编程实现以下功能:
Ø 使用增强for遍历所有元素,并打印
Ø 使用增强for遍历所有元素,打印不及格的分数;
Ø 使用增强for遍历所有元素,计算不及格的分数的数量,和平均分,并打印计算结果。
Ø 使用增强for遍历所有元素,求出最高分,并打印;
(注意:以上所有功能写在一个main()方法中,但请单独实现)
public class Test3_1 {
public static void main(String[] args) {
//1.使用多态创建Collection集合
Collection<Double> col = new ArrayList<>();
//2.添加元素
col.add(88.5);
col.add(39.2);
col.add(77.1);
col.add(56.8);
col.add(89.0);
col.add(99.0);
col.add(59.5);
// 使用增强for遍历所有元素,并打印
System.out.println("————————————————————使用增强for遍历所有元素,并打印——————————————————————");
for (Double score : col) {
System.out.println(score);
}
// 使用增强for遍历所有元素,打印不及格的分数;
System.out.println("————————————————————使用增强for遍历所有元素,打印不及格的分数——————————————————————");
for (Double score : col) {
if(score<60) {
System.out.println(score);
}
}
// 使用增强for遍历所有元素,计算不及格的分数的数量,和平均分,并打印计算结果。
//定义变量用于统计不及格分数的数量
System.out.println("————————————————————用增强for遍历所有元素,计算不及格的分数的数量,和平均分,并打印计算结果——————————————————————");
int failNum = 0;
//定义变量用于统计不及格分数的总分,
double failSum = 0;
for (Double score : col) {
if(score<60) {
//统计人数与总分
failNum++;
failSum+=score;
}
}
//不及格的平均分=不及格总分/不及格数量
double failAvg = failSum/failNum;
System.out.println("不及格的平均分:"+failAvg);
// 使用增强for遍历所有元素,求出最高分,并打印;
System.out.println("————————————————————使用增强for遍历所有元素,求出最高分,并打印——————————————————————");
//定义变量记录最高分
double max = 0;
for (Double score : col) {
if(score>max) { //每次取出的分数如果比max大,就赋值给它
max = score;
}
}
System.out.println("最高分:"+max);
}
}
三 编程题【泛型】
3.1 题目
有以下类结构:
人员类(Person):
|–学生类(Student)
|–Java学生类(JavaStudent)
|–UI学生类(UIStudent)
|–教师类(Teacher)
|–Java教师类(JavaTeacher)
|–UI教师类(UITeacher)
要求:
Ø 请按上述要求定义类,并实现继承关系即可(不需要定义类成员)
Ø 请按以下格式和要求定义测试类和方法:
public class Test4_1{
public static void main(String[] args){
ArrayList list1 = new ArrayList<>();
ArrayList list2 = new ArrayList<>();
ArrayList list3 = new ArrayList<>();
ArrayList list4 = new ArrayList<>();
ArrayList list5 = new ArrayList<>();
ArrayList list6 = new ArrayList<>();
ArrayList list7 = new ArrayList<>();
ArrayList list8 = new ArrayList<>();
//请测试哪些集合可以调用print1()方法
//请测试哪些集合可以调用print2()方法
//请测试哪些集合可以调用print3()方法
//请测试哪些集合可以调用print4()方法
}
//要求:参数可以接收任何泛型的ArrayList参数
public static void print1(ArrayList<______________> list){
}
//要求:参数可以接收任何Person及其子类泛型的ArrayList参数
public static void print2(ArrayList<______________> list){
}
//要求:参数可以接收任何Student及其子类泛型的ArrayList参数
public static void print3(ArrayList<______________> list){
}
//要求:参数可以接收任何Java学员,及其父类泛型的ArrayList参数
public static void print4(ArrayList<______________> list){
}
}
各个基本类
public class Person {
}
public class Student extends Person {
}
public class JavaStudent extends Student{
}
public class UIStudent extends Student{
}
public class Teacher extends Person {
}
public class JavaTeacher extends Teacher{
}
public class UITeacher extends Teacher{
}
public class Test4_1 {
public static void main(String[] args){
ArrayList<String> list1 = new ArrayList<>();
ArrayList<Person> list2 = new ArrayList<>();
ArrayList<Student> list3 = new ArrayList<>();
ArrayList<JavaStudent> list4 = new ArrayList<>();
ArrayList<UIStudent> list5 = new ArrayList<>();
ArrayList<Teacher> list6 = new ArrayList<>();
ArrayList<JavaTeacher> list7 = new ArrayList<>();
ArrayList<UITeacher> list8 = new ArrayList<>();
//请测试哪些集合可以调用print1()方法
print1(list1);
print1(list2);
print1(list3);
print1(list4);
print1(list5);
print1(list6);
print1(list7);
print1(list8);
//请测试哪些集合可以调用print2()方法
//print2(list1);
print2(list2);
print2(list3);
print2(list4);
print2(list5);
print2(list6);
print2(list7);
print2(list8);
//请测试哪些集合可以调用print3()方法
//print3(list1);
//print3(list2);
print3(list3);
print3(list4);
print3(list5);
//print3(list6);
//print3(list7);
//print3(list8);
//请测试哪些集合可以调用print4()方法
//print4(list1);
print4(list2);
print4(list3);
print4(list4);
//print4(list5);
//print4(list6);
//print4(list7);
//print4(list8);
}
//要求:参数可以接收任何泛型的ArrayList参数
public static void print1(ArrayList<?> list){
}
//要求:参数可以接收任何Person及其子类泛型的ArrayList参数
public static void print2(ArrayList<? extends Person> list){
}
//要求:参数可以接收任何Student及其子类泛型的ArrayList参数
public static void print3(ArrayList<? extends Student> list){
}
//要求:参数可以接收任何Java学员,及其父类泛型的ArrayList参数
public static void print4(ArrayList<? super JavaStudent> list){
}
}