Java 泛型

为什么需要泛型

在没有泛型时,假如我们现在需要一个类来打印Integer类型的变量

package org.albert;

public class InetgerPrinter {
    Integer content;
    InetgerPrinter(Integer content) {
        this.content = content;
    }

    public void print() {
        System.out.println(content);
    }
}
public class Main {
    public static void main(String[] args) {
        InetgerPrinter printer = new InetgerPrinter(123);
        printer.print();
    }
}
//输出:123

内容是这样的。

现在有一个问题,如果这个时候我想换一种类型打印呢?

显然我们需要重建一个StringPrinter类,

package org.albert;

public class StringPrinter {
    String content;
    StringPrinter(String content) {
        this.content = content;
    }

    public void print() {
        System.out.println(content);
    }
}
public class Main {
    public static void main(String[] args) {
        StringPrinter printer = new StringPrinter("hello world");
        printer.print();
    }
}
//输出:hello world

这里说明,如果我们要新打印一个类型的话,就必须重建一个class。

这样会给代码带来很多的重复性,因此我们引进了Generics的概念,以至于我们建立一个类,就可以处理所有的类型。

这里我们新建一个Printer类,来处理所有类型变量的打印问题。

如何来声明一个Generics类呢?

在类的主题大括号和类名之间去声明,通过用尖括号包裹起来的一个类型参数来声明泛型类。

例如这里的

public class Printer<T> {
}

这里就是用T来声明泛型类,代表着这个类可以传入任何类型的参数(字母T可以更改)

那么仿照上面的模型,完整的Printer类:

public class Printer<T> {
    T content;
    Printer(T content) {
        this.content = content;
    }
    
    public void print() {
        System.out.println(content);
    }
}

那么在Main函数中我们要如何使用Printer类呢?

public class Main {
    public static void main(String[] args) {
        //假如我们要打印Integer类的变量
        Printer<Integer> printer = new Printer<>(123);
        printer.print();
    }
}
//输出:123

在这里我们可以得到泛型的声明格式为

public class 类名 <T>{
	...
}

使用格式:

类名<ElemType> 实例名 = new 类名<>(初始化数据);

这里的T是自定义的任何字符。

  • 实际上T为何种类型,是由调用时我们传进去的类型决定的。

  • 泛型的作用在于,如果我们需要打印出String类型或Double类型的变量时,不需要再重新书写出它们各自的打印类,只需要改变< >中的类型即可。

  • 并且注意,< >中不能是基本数据类型,即int、char、double等,必须是包装后的类型,如Integer、String等。

    也可以是我们自己声明的一些类,必须Car、Vehicle、bus等等。

多泛型参数

例如,

package org.albert;

public class Printer<T, K> {
    T content;
    K content2;
    Printer(T content, K content2) {
        this.content = content;
        this.content2 = content2;
    }

    public void print() {
        System.out.println(content);
        System.out.println(content2);
    }
}

那这时我们在Main函数中的应用则为:

package org.albert;

public class Main {
    public static void main(String[] args) {
        //假如我们要打印Integer类和String类的变量
        Printer<Integer, String> printer = new Printer<>(123, "Hello World");
        printer.print();
    }
}
//输出:
123
Hello World

bounded generics

指有界限的泛型:对泛型参数进行约束

我们实际在做项目的时候,可能这个类型参数T不需要满足所有的类型,这时,我们可以对这个类型参数T进行约束,通过继承的方法来对类型参数T进行约束,就是说,T类型参数比如是什么类型的子类型。

package org.albert;

public class Printer<T extends Vehicle> {
    T content;
    Printer(T content) {
        this.content = content;
    }

    public void print() {
        System.out.println(content);
    }
}

重点看< >部分,T必须是继承Vehicle的子类,即Car或Bus等。

package org.albert;

public class Main {
    public static void main(String[] args) {
        Printer<Car> printer = new Printer<>(new Car());
        printer.print();
    }
}

传递进去的类型必须是Vehicle的子类型。

当然我们也可以用接口的方式来约束。

package org.albert;

public class Printer<T extends Thing> {
    ...
}

但需要注意的是,虽然是类实现接口,但在这里需要用extends关键字来说明,类型参数T是实现接口的子类型,而不是用implements关键字。

或者,我们可以同时用类和接口去约束泛型

package org.albert;

public class Printer<T extends Vehicle & Thing> {
    ...
}

用一个&来连接,注意这里必须是父类在接口前面,否则会报错。

这里参数T必须是Vehicle的子类,同时也是实现接口Thing的子类。

泛型方法

假如我们在类中想声明一个能打印任何类型参数的方法,则是

package org.albert;

public class Main {
    public static void main(String[] args) {
        //假如我们要打印Integer类和String类的变量
        print(123);
        print("Hello World");
    }
    public static <T> void print(T content) {
        System.out.println(content);
    }
}

在函数的返回值类型前面加上即可

可以对泛型方法的T进行约束,如

 public static <T extends Vehicle & Thing> void print(T content) {
        System.out.println(content);
 }

也可以传入多个参数。

 public static <T, K> void print(T content, K conten 2) {
        System.out.println(content);
        System.out.println(content2);
 }

学习视频:Java中的泛型 Generics in Java-哔哩哔哩

  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值