Java:泛型学习

一:泛型简介

1 泛型简介

1.1 泛型的基本概念

  • 泛型的本质就是“数据类型的参数化”----------把类型当作是参数一样传递,数据类型只能是引用类型
  • 可以把泛型理解为数据类型的占位符(类似形式参数),即告诉编译器,在调用泛型时必须传入的实际类型。
  • 这种参数类型可以用在类,接口和方法中,分别被成为泛型类,泛型接口,泛型方法

1.2 泛型的好处

  • 代码可读性更好(没有泛型就得使用Object类型来实现任意参数类型,使用的时候需要进行类型转换,instanceof方法)
  • 程序更加安全(只要编译时期没有警告,运行时期就不会出现ClassCastException异常)

1.3 类型擦除

  • 类型擦除:编码时使用泛型写的类型参数,编译器会在编译时去掉,这称之为类型擦除
  • 泛型参数在编译后被替换成Object,运行时虚拟机并不知道泛型

泛型主要用于编译阶段,编译后生成的字节码文件不包含泛型中的类型信息,设计类型转换仍然是普通的强制类型转换

2 泛型的使用

2.1 定义泛型

泛型字符可以是任何字符,一般采用:E,T,K,V,N,?

泛型标记对应单词说明
EElement在容器中使用,表示容器中的元素
TType表示普通的Java类
KKey表示键
VValue表示值
NNumber表示数值类型
表示不确定的java类型

2.2 泛型类

泛型类就是把泛型定义在类上,用户使用到该类的时候才把类型明确下来。
泛型类的具体使用方法:在类的名称后添加一个或多个类型参数声明,如,<T,K,V>

2.2.1 语法结构

public class 类名<泛型表示符号>

2.2.2 示例
public class Test {
    public static void main(String[] args) {
        Demo3<String> demo3 = new Demo3<>();
        demo3.setFlag("admin");
        String flag = demo3.getFlag();
        System.out.println(flag);
    }
}

2.3 泛型接口

2.3.1 语法结构

public interface 接口名<泛型表示符号>

2.3.2 示例
public interface Demo4<T> {
    public T getName(T name);
}

public class Demo5 implements Demo4<String>{
    @Override
    public String getName(String name) {
        return name;
    }
}

Demo5 demo5 = new Demo5();
String name = demo5.getName("张三");
System.out.println(name);

Demo4<String> demo4 = new Demo5();
String name1 = demo4.getName("李四");
System.out.println(name1);

Demo4 demo4 = new Demo5();  // 接口指向实现类
String name1 = (String)demo4.getName("李四"); //如果没有指定类型,将是Object类型
System.out.println(name1);

2.4 泛型方法

泛型类中所定义的泛型,在方法中也可以使用,但是我们经常需要使用仅仅在某一个方法上使用泛型,这个时候可以使用泛型方法。
泛型方法:是指将方法的类型参数定义成泛型,以便在调用时接受不同类型的参数。类型参数可以有多个,如<k,v>,定义时,类型参数一般放到返回值前面。
调用泛型方法时不需要像泛型类一样告诉编译器是什么类型,编译器可以自动推断出类型。

2.4.1 非静态方法
2.4.1.1 语法结构

public <泛型表示符号> void getName(泛型表示符号 name){}
public <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name){}

2.4.1.2 示例
public <T> void setName(T name){
        System.out.println(name);
    }

public <T> T getName(T name){
        return name;
    }
2.4.2 静态方法

静态方法需要注意的点:不能使用类上定义的泛型(因为静态方法在对象之前加载)

2.4.2.1 语法结构

public abstract <泛型表示符号> void getName(泛型表示符号 name){}
public abstract <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name){}

2.4.2.2 示例
public abstract <T> void setName(T name){
        System.out.println(name);
    }

public abstract <T> T getName(T name){
        return name;
    }
2.4.3 泛型方法和可变参数

在泛型方法中,泛型也可以定义成可变参数

2.4.3.1 语法结构

public <泛型表示符号> void showMsg(泛型表示符号 ... args){}

2.4.3.2 示例
public <T> void method(T...args){
        for (T t:args){
            System.out.println(t);
        }
    }

MethodGeneric methodGeneric1 = new MethodGeneric();
String[] arr = new String[]{"a","b","c"};
methodGeneric1.method(arr);

2.5 通配符和上下限定

  • 通配符只能用在定义变量的时候,不能用在泛型类上,同下限限定
  • 可以限定类型
  • 没有做限定的时候,泛型定义的变量只能使用Object的方法,因为编译器不知道它的具体类型,使用限定过的泛型就可以使用其父类或者父接口的方法了。
2.5.1 无界通配符(可以表示任意类型)

“?” 表示类型通配符,用于替代具体的类型,它只能在<>中使用,可以解决当具体类型不确定的问题。这样就可以不先确定泛型类的类型。

2.5.1.1 语法结构

public void showFlag(Generic<?> generic){}

2.5.1.2 示例
public class showMsg {
    public void showFlag(Demo3<?> demo3){
        System.out.println(demo3.getFlag());
    }
}

showMsg showMsg = new showMsg();
Demo3<String> demo31 = new Demo3<>();
demo3.setFlag("张三");
showMsg.showFlag(demo3);
2.5.2 通配符的上限限定

上限限定表示通配符的类型是T类以及T类的子类或者T接口以及T接口的子接口。
该方式同样使用于泛型的上限限定。

2.5.2.1 语法结构

public void showFlag(Generic<? extends Number> generic){}

2.5.2.2 示例
public void showFlag(Demo3<? extends Number> demo3){
        System.out.println(demo3.getFlag());
    }

showMsg showMsg = new showMsg();
Demo3<Number> demo31 = new Demo3<>();
demo31.setFlag(123);
showMsg.showFlag(demo31);
2.5.3 通配符的下限限定

下限限定表示通配符的类型是T类以及T类的父类或者T接口以及T接口的父接口。
注意:该方法不适用泛型类

2.5.3.1 语法结构

public void showFlag(Generic<? super Integer> generic)

2.5.3.2 示例
public void showFlag(Demo3<? super Integer> demo3){
        System.out.println(demo3.getFlag());
    }

showMsg showMsg = new showMsg();
Demo3<Number> demo31 = new Demo3<>();
demo31.setFlag(123);
showMsg.showFlag(demo31);

3 泛型总结

泛型用于编译阶段
类型参数在编译后被替换成Object,运行时虚拟机并不知道泛型

  1. 基本类型不能用于泛型,可以使用其包装类
  2. 不能通过类型参数创建对象 T elm = new T (); // 不支持
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值