没有java泛型会存在的问题
- 假设我们有一个方法,希望通过传递不同类型的参数,输出不同类型的对象值。正常情况下我们可能会写不同的方法来实现,但是这样会导致类不断增加,并且类方法很相似,不能够复用。进而导致类爆炸
- 假设有一个方法,我们希望传参具有一定约束,而不是像Object对象一样随便传参
java泛型的常见使用
包装类型参数
- 定义一个方法,打印各种包装类型
public class Generics1<T> {
private T name;
public Generics1(T name) {
this.name = name;
}
public void allPrint(){
System.out.println(name);
}
}
- main
public class Main {
public static void main(String[] args) {
Generics1<Integer> integerGenerics1 = new Generics1<>(1);
integerGenerics1.allPrint();
Generics1<String> stringGenerics2 = new Generics1<>("222222");
stringGenerics2.allPrint();
Generics1<Long> longGenerics3 = new Generics1<>(222L);
longGenerics3.allPrint();
}
}
注意:泛型里面必须是对象,或者包装类型。基础类型是不被允许的
多个包装类型参数
- 两个泛型参数
public class Generics2<T,K> {
private T name;
private K context;
public Generics2(T name,K context) {
this.name = name;
this.context=context;
}
public void allPrint(){
System.out.println(name);
System.out.println(context);
}
}
- Main
public class Main2 {
public static void main(String[] args) {
Generics2<String, Integer> stringIntegerGenerics2 = new Generics2<>("1111", 222);
stringIntegerGenerics2.allPrint();
}
}
上界继承
- 限定使用者传递的参数必须继承某个父类之下
public class Generics3<T extends Vehicle> {
private T name;
public Generics3(T name) {
this.name = name;
}
public void allPrint(){
System.out.println(name.getName());
}
}
- 父类
public class Vehicle {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void run(String name){
System.out.println(name+"can run");
}
}
- 子类
public class Car extends Vehicle{
private Integer wheel;
public Integer getWheel() {
return wheel;
}
public void setWheel(Integer wheel) {
this.wheel = wheel;
}
public void getWheel(String name,Integer wheel) {
System.out.println(name+"有"+wheel+"个轮子");
}
}
- 可以不是父 类,可以是接口。接口有更好的扩展性
public class Generics4<T extends Vehi> {
private T vehics;
public Generics4(T vehics) {
this.vehics = vehics;
}
public void allPrint(){
vehics.run();
}
}
- 接口
public interface Vehi {
void run();
}
使用上界继承的好处
- 使用上界继承的最大好处是:必然我们会用到接口或者父类,那么我们可以抽取一些公共方法,放到父类或接口里面。不同的实现拥有不同的处理方式。具备更强的扩展性
- java里面虽然有Object来实现传递各种类型参数(如下),但是不推荐这么做。会产生一种。例如:当我们从List取值的时候,java是无法推断里面值的类型,编译器就会报错
上面这个代码在运行时,获取第二个值时,就会报错。
使用Object,在编译阶段是没有问题的,但是在运行时就会出现问题。
而使用泛型,在编译阶段,就能检查出来问题
泛型函数:Generic method
泛型函数方法的定义
- 在返回类型前添加泛型类型: 。参数设置为泛型
private static <T> void printAll(T myOb){
}
- 举例子
public class Main5 {
public static void main(String[] args) {
printAll(new BigCar(3,"myba"));
}
private static <T> void printAll(T myOb){
System.out.println(myOb);
}
}
- 同理也可以使用上界继承限定
private static <T> void printAll(T myOb){
System.out.println(myOb);
}
private static <T extends Vehicle & Vehi> void printAll(T myOb){
System.out.println(myOb);
}
- 配置多个参数
private static <T,K> void printAll2(T myOb,K myob2){
System.out.println(myOb);
System.out.println(myob2);
}
泛型通配符
- String,Integer,Long我们在传递参数时,可以用Object来定义参数。但是:List,却不是List的子类。这种情况怎么处理?
- 通配符的使用
private static void printAll(List<?> myOb){
System.out.println(myOb);
}
上界通配符
- 意思是,传入的参数必须是Vehi的子类或者实现,或者本身
private static void printAll(List<? extends Vehi> myOb){
System.out.println(myOb);
}
下界通配符
- 意思是传入的参数必须是Car的父类或者Car本身
private static void printAll(List<? super Car> myOb){
System.out.println(myOb);
}