文章目录

  • 泛型作用: 限制加入集合中元素的类型,将类型限制为同一种类型
  • 一.泛型的基本应用
  • 二.泛型的扩展
  • 1.泛型类
  • 1.1 创建泛型类时,类型不确定,只有在创建对象时才确定
  • 2.泛型方法
  • 2.泛型接口
  • 三.泛型受限
  • 1.泛型上限:? extends A :只要泛型为A或A的子类都可传入
  • 2.泛型下限:? super A : 只要泛型为A或A的父类都可传入


泛型作用: 限制加入集合中元素的类型,将类型限制为同一种类型

泛型在编译期间生效,不允许加入其他类型

一.泛型的基本应用

public class Animal{
	public String name;
	public String color;
	public Animal(String name,String color)
	{
		super();
		this.name = name;
		this.color = color;
	}
	
	public String toString()
	{
		return "Animal [name=" + name + ", color=" + color + "]";
	}
	
	}
	
public class AnimalTest
{

	public static void main(String[] args)
	{
		List<Animal> list = new ArrayList<>();
		
		Animal cat = new Animal("cat","White");
		Animal dog = new Animal("dog","black");
		Animal rabbit = new Animal("rabbit","white");
		
		list.add(cat);
		list.add(dog);
		list.add(rabbit);
		
		for(Object o : list) {      //增强for循环,遍历list,遍历出的每一个对象都用Object类型的o接收
		System.out.println(o);   //相当于‘Object o=每个对象’,父类引用指向子类对象(Object为如何子类的父类),实则为多态
		}
		
	}

}

Output:

Animal [name=cat, color=White]
Animal [name=dog, color=black]
Animal [name=rabbit, color=white]

但是加了泛型之后的遍历

for(Animal a : list) {    //遍历list,遍历出的每一个对象都用Animal类型的a接收
			System.out.println(a);
		}

二.泛型的扩展

1.泛型类

定义泛型类的语法格式

类访问修饰符  class  泛型类名 <类型参数> {
			类体
	}

类型参数可以用任何单个大写字母表示,通常使用E来表示集合元素类型,用K与V分别表示键-值对中的键类型与值类型,用T、U、S表示任意类型

1.1 创建泛型类时,类型不确定,只有在创建对象时才确定

具体实例:

public class Animal <A> {                     //在此创建了<A>的泛型类
.....
}

class Test{
	public static void main(String[] args){
             Animal<Integer> a1 = new Animal<>();   //此时A的类型为Integer
             Animal<String>  a2 = new Animal<>();   //此时A的类型为String
             .....
	}
}

2.泛型方法

Java 泛型工厂模式应用 泛型 java 应用_泛型类


图中代码,第二个方法的参数类型为A,A即为public class GenericTest< A > 中的泛型A,由于GenericTest< Integer > gt = new GenericTest<>();中已经确定< A >的类型为Integer,所以

Java 泛型工厂模式应用 泛型 java 应用_泛型_02


gt调用方法时,b方法确定为Integer。

c方法,由于方法的参数类型为B,B不是public class GenericTest< A > 中的泛型A,所以在方法体内加入< B >,否则会报错。由于B的加入,B为不确定类型,即任意类型都可。

Java 泛型工厂模式应用 泛型 java 应用_Java 泛型工厂模式应用_03


因此,c方法帮我们解决了不同数据类型做参数的重载问题。通俗而言,如果想要传入不同类型的数据,不用写不同参数类型的方法,只需写public< B > void c(B b)即可实现。注意:

Java 泛型工厂模式应用 泛型 java 应用_泛型_04


如果在方法中加入static,则b方法报错,c方法可以。

原因是,static修饰的方法存在于对象之前,由于泛型A的类型在创建对象时确定,所以a方法报错。然而,c方法不受类型限制,因此static对此方法没有限制。

2.泛型接口

泛型接口的定义格式如下:

interface 	接口名<类型参数列表>
{
...
}

在实现接口时,也应当声明与接口相同的类型参数。格式如下:

class		类名<类型参数列表>		implements 接口名<类型参数列表>
{
...
}

具体实例如下:

Java 泛型工厂模式应用 泛型 java 应用_父类_05


在实现类classA中确定了泛型A为String类型。

注意: 实现类class B中的泛型是BB不是泛型A,BB类型为不确定型,因此会报错。应当改成:class B < BB>implements GenericInterface< BB>{}

三.泛型受限

1.泛型上限:? extends A :只要泛型为A或A的子类都可传入

2.泛型下限:? super A : 只要泛型为A或A的父类都可传入

public class Person{
	public String name;
	public int age;
	
	public Person(String name, int age)
	{
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString()
	{
		return "Person [name=" + name + ", age=" + age + "]";
	}
}
public class Student extends Person{
	public int id;

	public Student(String name, int age, int id)
	{
		super(name, age);
		this.id = id;
	}

	@Override
	public String toString()
	{
		return "Student [id=" + id + "]";
	}
}
import java.util.ArrayList;

class Test{
	public static void main(String[] args) {
		ArrayList<Person> a1= new ArrayList<Person>();
		a1.add(new Person("nana",18));
		a1.add(new Person("haha",19));
		show(a1);
		
		ArrayList<Student> a2= new ArrayList<Student>();
		a2.add(new Student("yiyi",20,1));
		a2.add(new Student("bobo",21,2));
		show(a2);
		
	}
	
	public static void show(ArrayList<? extends Person> ab) {  //泛型上限
		for(Person a : ab) {
			System.out.println(a);
		}
	}
}

Output:

Person [name=nana, age=18]
Person [name=haha, age=19]
Student [id=1]
Student [id=2]