泛型综合练习
1、需求
-
定义一个继承结构:
-
属性:名字、年龄
-
行为:吃东西
波斯猫方法体打印:一只叫做XXX的,X岁的波斯猫,正在吃小饼干~ 狸花猫方法体打印:一只叫做XXX的,X岁的狸花猫,正在吃鱼儿~ 泰迪方法体打印:一只叫做XXX的,X岁的泰迪,正在吃骨头,边吃边蹭~ 哈士奇方法体打印:一只叫做XXX的,X岁的哈士奇,正在吃骨头,边吃边拆家~
-
测试类中定义一个方法用于饲养动物
public static void keepPet(ArrayList<???> list) { // 遍历集合,调用动物的eat方法 }
-
要求:
- 1、该方法能养所有品种的猫,但是不能养狗
- 2、该方法能养所有品种的狗,但是不能养猫
- 3、该方法能养所有的动物,但是不能传递其他类型
2、实现
动物类
package com.app.demo28_genericity_test;
/*
动物类(抽象)
*/
public abstract class Animal{
// 属性:名字、年龄
private String name;
private int age;
// 行为:吃东西,但是吃的食物不一样,因此需要定义抽象方法,让动物们自己实现
public abstract void eat();
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Animal{name = " + name + ", age = " + age + "}";
}
}
猫类
package com.app.demo28_genericity_test;
/*
猫类:继承动物类(抽象)
*/
public abstract class Cat extends Animal{
/*
继承抽象类之后的解决方法:
1、重写抽象类里面所有的抽象方法
2、将本类也定义为抽象类,让继承本类的子类再重写抽象方法
*/
}
狗类
package com.app.demo28_genericity_test;
/*
狗类:继承动物类(抽象)
*/
public abstract class Dog extends Animal{
}
波斯猫类
package com.app.demo28_genericity_test;
/*
波斯猫类:继承猫类(抽象)
*/
public class PersianCat extends Cat{
public PersianCat() {
}
// 重写父类的抽象方法
@Override
public void eat() {
System.out.println("一只叫做" + getName() + "的," + getAge() + "岁的波斯猫,正在吃小饼干~");
}
}
狸花猫类
package com.app.demo28_genericity_test;
/*
狸花猫类:继承猫类(抽象)
*/
public class DragonLi extends Cat{
public DragonLi() {
}
// 重写父类的抽象方法
@Override
public void eat() {
System.out.println("一只叫做" + getName() + "的," + getAge() + "岁的狸花猫,正在吃鱼儿~");
}
}
泰迪狗类
package com.app.demo28_genericity_test;
/*
泰迪类:继承狗类(抽象)
*/
public class Teddy extends Dog{
public Teddy() {
}
// 重写父类的抽象方法
@Override
public void eat() {
System.out.println("一只叫做" + getName() + "的," + getAge() + "岁的泰迪,正在吃骨头,边吃边蹭~");
}
}
哈士奇狗类
package com.app.demo28_genericity_test;
/*
哈士奇类:继承狗类(抽象)
*/
public class Huskie extends Dog{
public Huskie() {
}
// 重写父类的抽象方法
@Override
public void eat() {
System.out.println("一只叫做" + getName() + "的," + getAge() + "岁的哈士奇,正在吃骨头,边吃边拆家~");
}
}
测试类
package com.app.demo28_genericity_test.test;
import com.app.demo28_genericity_test.been.*;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
// 1.创建集合
// 方式1
ArrayList<PersianCat> persList = new ArrayList<>();
ArrayList<DragonLi> dragList = new ArrayList<>();
ArrayList<Teddy> tedList = new ArrayList<>();
ArrayList<Huskie> husList = new ArrayList<>();
// 方式2
ArrayList<Cat> cats = new ArrayList<>();
ArrayList<Dog> dogs = new ArrayList<>();
// 2.创建对象,并初始化属性
PersianCat persianCat = new PersianCat();
persianCat.setName("小波儿");
persianCat.setAge(3);
DragonLi dragonLi = new DragonLi();
dragonLi.setName("小狸儿");
dragonLi.setAge(5);
Teddy teddy = new Teddy();
teddy.setName("小泰儿");
teddy.setAge(2);
Huskie huskie = new Huskie();
huskie.setName("小哈儿");
huskie.setAge(7);
// 3.将对象添加进集合中
// 方式1
persList.add(persianCat);
dragList.add(dragonLi);
tedList.add(teddy);
husList.add(huskie);
// 方式2
cats.add(persianCat);
cats.add(dragonLi);
dogs.add(teddy);
dogs.add(huskie);
// 调用饲养方法,将集合传入
keepPet1(persList);
keepPet1(dragList);
keepPet2(tedList);
keepPet2(husList);
System.out.println("---------");
keepPet1(cats);
keepPet2(dogs);
System.out.println("======================================");
keepPet3(persList);
keepPet3(dragList);
keepPet3(tedList);
keepPet3(husList);
System.out.println("---------");
keepPet3(cats);
keepPet3(dogs);
}
// 要求1:该方法能养所有品种的猫,但是不能养狗
public static void keepPet1(ArrayList<? extends Cat> list) {
// 遍历集合,调用动物的eat方法
for (Cat cat : list) {
cat.eat();
}
}
// 要求2:该方法能养所有品种的狗,但是不能养猫
public static void keepPet2(ArrayList<? extends Dog> list) {
// 遍历集合,调用动物的eat方法
for (Dog dog : list) {
dog.eat();
}
}
// 要求3:该方法能养所有的动物,但是不能传递其他类型
public static void keepPet3(ArrayList<? extends Animal> list) {
// 遍历集合,调用动物的eat方法
for (Animal animal : list) {
animal.eat();
}
}
}
测试结果
一只叫做小波儿的,3岁的波斯猫,正在吃小饼干~
一只叫做小狸儿的,5岁的狸花猫,正在吃鱼儿~
一只叫做小泰儿的,2岁的泰迪,正在吃骨头,边吃边蹭~
一只叫做小哈儿的,7岁的哈士奇,正在吃骨头,边吃边拆家~
---------
一只叫做小波儿的,3岁的波斯猫,正在吃小饼干~
一只叫做小狸儿的,5岁的狸花猫,正在吃鱼儿~
一只叫做小泰儿的,2岁的泰迪,正在吃骨头,边吃边蹭~
一只叫做小哈儿的,7岁的哈士奇,正在吃骨头,边吃边拆家~
======================================
一只叫做小波儿的,3岁的波斯猫,正在吃小饼干~
一只叫做小狸儿的,5岁的狸花猫,正在吃鱼儿~
一只叫做小泰儿的,2岁的泰迪,正在吃骨头,边吃边蹭~
一只叫做小哈儿的,7岁的哈士奇,正在吃骨头,边吃边拆家~
---------
一只叫做小波儿的,3岁的波斯猫,正在吃小饼干~
一只叫做小狸儿的,5岁的狸花猫,正在吃鱼儿~
一只叫做小泰儿的,2岁的泰迪,正在吃骨头,边吃边蹭~
一只叫做小哈儿的,7岁的哈士奇,正在吃骨头,边吃边拆家~
Process finished with exit code 0
3、总结
1、什么是泛型?
- JDK5引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。
2、泛型的好处?
- 统一数据类型;
- 把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段,类型就能确定下来了。
3、泛型的细节?
- 泛型中不能写基本数据类型;
- 指定泛型的具体类型后,传递数据时,可以传入该类型和它的子类类型;
- 如果不写泛型,类型默认是Object。
4、哪里定义泛型?
- 泛型类:在类名后面定义泛型,创建该类对象的时候,确定类型。
- 泛型方法:在修饰符后面定义方法,调用该方法的时候,确定类型。
- 泛型接口:在接口名后面定义泛型,实现类确定类型,实现类延续泛型。
5、泛型的继承
-
泛型是不具备继承性的
-
但是数据是具备继承性的
6、泛型的通配符?
- 通配符:
- ?:表示不确定的类型,一切类型
- ? extends E:表示E或者是E的子类
- ? super E:表示E或者是E的父类
7、泛型的使用场景?
- 定义类、方法、接口的时候,如果类型不确定,就可以定义泛型。
- 如果类型不确定,但是能知道是哪个继承体系中的,可以使用泛型的通配符。