Genericity
1.No Genericity(没有使用泛型)
在java中,我们使用数据类型或者自定义类型,以打印方法为例,当我们不使用泛型时
public class IntegerPrinter {
Integer content;
public IntegerPrinter(Integer content){
this.content = content;
}
public void print(){
System.out.println(content);
}
}
- 由以上代码我们可以打印出数据类型为Integer的变量
public class StringPrinter {
String content;
public StringPrinter(String content){
this.content = content;
}
public void print(){
System.out.println(content);
}
}
- 由以上代码,我们可以打印出数据类型为String的变量
在主函数中,我们需要定义两个对象来专门打印方法
//Integer
IntegerPrinter printer = new IntegerPrinter(123);
printer.print();
//String
StringPrinter stringPrinter = new StringPrinter("123");
stringPrinter.print();
总结:当不使用泛型时,您需要为每个泛型创建一个自己的类来接受不同的类型
2.GenecricParam(泛型参数)
2.1 单参数情况
当我们需要一个参数的时候,使用以下代码
public class PrintOneParam<T> {
T content;
public PrintOneParam(T content) {
this.content = content;
}
public void print(){
System.out.println(content);
}
}
- 其中,我们可以使用T来代替任何类型
- 可以不为T,我们可以是用任意字符来代替T,例如K,V,AnyThing
PrintOneParam<Integer> integerPrint = new PrintOneParam<>(123);
integerPrint.print();
PrintOneParam<String> stringPrint = new PrintOneParam<>("1234");
stringPrint.print();
- 在定义完成之后,可以对响应的T进行变化,来赋予各种数据类型
注意:在尖括号中必须使用包装类对象来定义
2.2 多参数情况
public class PrintManyParam<T,K>{
T content;
K content2;
public PrintManyParam(T content, K content2) {
this.content = content;
this.content2 = content2;
}
public void print(){
System.out.println(content+","+content2);
}
}
- 在定义到多个参数时,需要两个不同的字符来代替,例如<T,K>,与单个的定义方式相同
PrintManyParam<String,Integer> printManyParam = new PrintManyParam<>("123",123);
printManyParam.print();
注意:在尖括号中必须使用包装类对象来定义
3.Bounded Genericity (有界限的泛型)
3.1 给出以下类
public class Bus extends Vehicle implements Thing{
Integer passenger;
public Bus(Integer passenger) {
this.passenger = passenger;
}
public Bus() {
}
}
public class Car extends Vehicle implements Thing{
Integer price;
String name;
public Car(Integer price, String name) {
this.price = price;
this.name = name;
}
public Car() {
}
@Override
public String toString() {
return "Car{" +
"price=" + price +
", name='" + name + '\'' +
'}';
}
}
public class Vehicle{
String brand;
String color;
public String getBrand(){
return brand;
}
public String getColor(){
return color;
}
}
public interface Thing {
}
3.1 结合Extends关键字继承类
当我们对于类型进行限制的使用,可以使用extends来定义T的父类型
这样的好处就是我们在定义T的同时就可以拿到Vehicle中定义的成员方法
public class PrintExtend<T extends Vehicle> {
T content;
public PrintExtend(T content) {
this.content = content;
}
public void print(){
content.getBrand();
content.getColor();
System.out.println(content);
}
}
3.2 同时可以结合Extends来规范接口
同时我们也可以定义界限泛型是接口,但是和其他的区别是不能使用implements继续使用extends
public class PrintInterface<T extends Thing>{
T content;
public PrintInterface(T content) {
this.content = content;
}
public void print(){
System.out.println(content);
}
}
3.3 如果存在多种约束,可以使用&运算符进行连接
- 同时定义多个限制,使用*&*来约束,可以约束继承和接口类型
public class PrintExtendAndInterface<T extends Vehicle & Thing> {
T content;
public PrintExtendAndInterface(T content) {
this.content = content;
}
public void print(){
System.out.println(content);
}
}
- 值得注意的是:class必须放在interface之前,否则会产生error
3.4 使用
当使用到Extends的类型之后,我们可以定义到他的子类型来定义泛型。如我们可以定义Bus,Car对于Vehicle的泛型
PrintExtend<Bus> printExtendBus = new PrintExtend<>(new Bus());
PrintExtend<Car> printExtendCar = new PrintExtend<>(new Car());
4.Generic Methods(泛型方法)
4.1 单个参数的泛型方法
public static <T> void print(T content){
System.out.println(content);
}
- 使用时直接调用即可
4.2 单个参数带有限制的泛型方法
public static <T extends Vehicle & Thing> void print1(T content){
System.out.println(content);
}
- 这个限制方法和有界限的泛型界限是相互类似的
- 在使用的时候,只能传入Vehicle的子类并且实现Thing的类
4.3 通配符 Wildcard
- 假设存在一个方法,他能够打印Integer类型的list集合方法
- 引用通配符Wildcard概念 ?
4.3.1 无限制
public static void print3(List<?> list){
System.out.println(list);
}
- 在以上例子中,使用了?代替了T。在以上中,它的元素类型可以匹配任何类型
/**
* 打印集合的方法
*/
List<String> strings = new ArrayList<>();
strings.add("123");
strings.add("234");
print3(strings);
4.3.2 有上限
public static void print4(List<? extends Vehicle> list){
System.out.println(list);
}
- 在以上例子中,使用extends来限制通配符,即,?可以代替Vehicle的子类,其余类型不可以使用
- 限制通配符 上界限通配符 ? extends Vehicle
/**
* 打印上界性泛型 可以接受本类和子类
*/
List<Car> cars = new ArrayList<>();
cars.add(new Car(1,"2"));
print4(cars);
4.3.3 有下限
public static void print5(List<? super Car> list){
System.out.println(list);
}
- 在以上代码中,使用super来限制通配符,即,?可以代替Car的父类和本身,其余类型不可以使用
- 限制通配符 下界限通配符 ? super Car ,必须是Car的父类或者他自己的本身
/**
* 打印下界性泛型 可以接受父类和自己类
*/
List<Vehicle> vehicles = new ArrayList<>();
vehicles.add(new Vehicle());
print5(vehicles);
List<Car> car2 = new ArrayList<>();
car2.add(new Car(1,"2"));
print5(car2);
- 以上中,如果使用Bus,则会发生限制错误。
5.以上中用到的专业词汇
- Generics -> 泛型
- Wildcard -> 通配符
- {} Curly Braces -> 大括号 /花括号
- <> Angle Brackets -> 尖括号
- ? Question Mark -> 问号