泛型学习笔记

        泛型,对于我来说,就是类型的参数化,类型不再固定,根据使用时,传入的类的类型而定。

一、为什么需要泛型

        为什么需要泛型,可以看下下面这个简单例子。

public static void main(String[] args){
        List list = new ArrayList();

        list.add("aaa");
        list.add(100);

        for (int i=0;i< list.size();i++){
            System.out.println((String) list.get(i));
        }
    }

        以上输出结果会报错,java.lang.Integer cannot be cast to java.lang.String。一直到程序运行阶段才会暴出错误,为什么在程序编译阶段没有发现错误?这是因为JVM在编译阶段会类型擦除。

        为了使上述的错误,在编译阶段就被发现,泛型营运而生。"<>"中指定泛型的具体类型,在编译阶段就可以发现类型不对这个故障。

        以上代码做如下修改,指定泛型具体类型为String,编译阶段就会报错。

 二、泛型的使用

        泛型的使用分为三种类型:泛型类、泛型接口、泛型方法

        泛型的的标识可以是任意字母,但是为了规范,行业内有默认的规则:

  1. T——代表任何类
  2. E——Element或者Exception
  3. K——代表key
  4. V——代表value,和key一起使用

2.1 泛型类

        泛型类型用于类的定义中,称之为泛型类。通过泛型可以对一组类的操作对外开放相同的接口。最典型的就是集合类,比如list、map、set。

        泛型类使用模板如下

class 类名称 <泛型标识,一般T>{
    
    private 泛型标识 /*成员变量*/ var;
}

泛型类使用简单示例

public class Generic<T> {

    private T type;

    public Generic(T type){
        this.type = type;
    }

    public T getType(){
        return type;
    }


    public static void main(String[] args){
        Generic<Integer> g1 = new Generic<Integer>(12345);
        Generic<String> g2 = new Generic<>("cc");

        System.out.println(g1.getType());
        System.out.println(g2.getType());
    }
}

 2.2 泛型接口

        对于泛型接口的使用,一般是各种类的生产器,生成继承接口方法的类。两种使用方法:定义类指定具体的类型和定义类不指定具体类型(和泛型类一样)

        首先定义一个泛型接口

public interface Generator<T> {

    public T text();
}

2.2.1 不指定具体类型

public class FruitGenerator<T> implements Generator<T> {


    @Override
    public T text(T fruit) {
        return fruit;
    }

    public static void main(String[] args){
        FruitGenerator<String> f = new FruitGenerator<>();

        System.out.println(f.text("apple"));

        FruitGenerator<Integer> f1 = new FruitGenerator<>();

        System.out.println(f1.text(123));
    }
}

2.2.2 指定具体类型

        新建对象时,只能时String类型。

public class FruitGenerator2 implements Generator<String>{


    @Override
    public String text(String fruit) {
        return fruit;
    }
    
    public static void main(String[] args){
        FruitGenerator2 f2 = new FruitGenerator2();
        
        f2.text("1243");
    }
}

2.3泛型方法

        泛型类和泛型方法经常和泛型类一起使用,很容易搞蒙,记住一点,泛型类,是在实例化类的时候,指明泛型的具体类型;泛型方法,是在使用方法时指明泛型的基本类型。

/**
     * 泛型方法介绍
     *
     * @param tClass
     * @param <T>
     * @return 返回值为T类型
     * 说明:
     *      1) public和返回值中间的'<T>'是定义泛型的关键
     *      2) 只用申明了<T>的方法,才是泛型方法
     *      3) <T>表明该方法使用泛型类型T,此时才可以在方法中使用泛型类型T
     *     
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public <T> T genericMethod(Class<T> tClass) throws InstantiationException, IllegalAccessException {
        T instance = tClass.newInstance();
        return instance;
    }

        使用示例,其中Generic为泛型类,参考2.1小节的样例。

public class GenericMethod {

    public <T> T showType(Generic<T> generic){

        System.out.println("type: "+generic.getType());

        return generic.getType();
    }

    public static void main(String[] args){
        Generic<String> generic = new Generic<>("123");
        GenericMethod method = new GenericMethod();
        method.showType(generic);
    }
}

2.3.1 泛型类中的泛型方法

        泛型方法中"T"和泛型类中的"T"可以不是一样的类型,如下代码,按规则,我们一般会使用"E"来作为泛型中的参数。

public class GenericMethod2<T> {

    private T key;

    public T getKey() {
        return key;
    }

    public void setKey(T key) {
        this.key = key;
    }


    public <T> T show2(T t){
       return t;
    }

    public static void main(String[] args){
        GenericMethod2<String> genericMethod = new GenericMethod2<>();
        genericMethod.setKey("ccc");
        System.out.println(genericMethod.getKey());

        System.out.println(genericMethod.show2(123));
    }
}

三、泛型方法中的通配符和可变参数

        有点简单了,就举个例子

        可变参数

public class GenericFlag {

    /**
     * 限制泛型方法的泛型类型为Number
     * @param n
     * @param <T>
     */
    public <T extends Number> void show(T... n){
        for (T t : n){
            System.out.println(t.toString());
        }
    }




    public static void main(String[] args){
        GenericFlag g = new GenericFlag();
        g.show(123,12.11);
    }
}

        通配符,使用2.1中Generic这个泛型类来演示。注意一点,"?"已经是类型的实参,不是形参,即"?"和Integer、String意义是一样的。

public static void main(String[] args){
        Generic<? extends Number> generic = new Generic<>(12);
        System.out.println(generic.getType());
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值