Java中泛型的使用(genericity)

本文详细介绍了Java中的泛型概念,包括NoGenericity(非泛型)、GenericParam(泛型参数)、BoundedGenericity(有界限的泛型)以及泛型方法的使用,涵盖了单参数、多参数、通配符和类型限制等知识点。
摘要由CSDN通过智能技术生成

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的类型之后,我们可以定义到他的子类型来定义泛型。如我们可以定义BusCar对于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 -> 问号
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>