java泛型自己的理解

java泛型算是基础,整体都看过好多遍了,但是还是用的不熟悉,每次都不知道怎么写,后来思前想去,干脆死记硬背,这里记一下比较通用的写法。泛型分为::泛型类、泛型接口、泛型方法
泛型类:

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;

    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }

    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}

泛型类一般就这么定义就可以了,你想写其他逻辑也行,也不一定要把成员变量定义T由外部传入,但是如果你成员变量的类型写成T,那你就必须写成泛型类,如:

public class Generic<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private String key;

    public Generic(T key) {
        //这里强转,或者你写其他处理逻辑都行
        this.key = (String) key;
    }

    public String getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}

如果上面的属性或者方法有传入泛型,但是不定义泛型类,编译的时候就会报错如下是不允许的:

//编译报错
public class Generic{
    //key这个成员变量的类型为T,T的类型由外部指定  
    private String key;

  public T test(String key){
      return null;
  }

    public String getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}

泛型接口
型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中,可以看一个例子:

//定义一个泛型接口
public interface Generator<T> {
    public T next();
}

当实现泛型接口的类,未传入泛型实参时:

/**
 * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
 * 即:class FruitGenerator<T> implements Generator<T>{
 * 如果不声明泛型,如:class FruitGenerator implements Generator<T>,编译器会报错:"Unknown class"
 */
class FruitGenerator<T> implements Generator<T>{
    @Override
    public T next() {
        return null;
    }
}

当实现泛型接口的类,传入泛型实参时:

/**
 * 传入泛型实参时:
 * 定义一个生产器实现这个接口,虽然我们只创建了一个泛型接口Generator<T>
 * 但是我们可以为T传入无数个实参,形成无数种类型的Generator接口。
 * 在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型
 * 即:Generator<T>,public T next();中的的T都要替换成传入的String类型。
 */
public class FruitGenerator implements Generator<String> {

    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}

泛型通配符
我们知道Ingeter是Number的一个子类,同时在特性章节中我们也验证过Generic与Generic实际上是相同的一种基本类型。那么问题来了,在使用Generic作为形参的方法中,能否使用Generic的实例传入呢?在逻辑上类似于Generic和Generic是否可以看成具有父子关系的泛型类型呢?

为了弄清楚这个问题,我们使用Generic这个泛型类继续看下面的例子:

public void showKeyValue1(Generic obj){
Log.d(“泛型测试”,"key value is " + obj.getKey());
}

复制代码
Generic gInteger = new Generic(123);
Generic gNumber = new Generic(456);

showKeyValue(gNumber);

// showKeyValue这个方法编译器会为我们报错:Generic<java.lang.Integer>
// cannot be applied to Generic<java.lang.Number>
// showKeyValue(gInteger);
复制代码

通过提示信息我们可以看到Generic不能被看作为`Generic的子类。由此可以看出:同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。

回到上面的例子,如何解决上面的问题?总不能为了定义一个新的方法来处理Generic类型的类,这显然与java中的多台理念相违背。因此我们需要一个在逻辑上可以表示同时是Generic和Generic父类的引用类型。由此类型通配符应运而生。

我们可以将上面的方法改一下:

public void showKeyValue1(Generic<?> obj){
Log.d(“泛型测试”,"key value is " + obj.getKey());
}
类型通配符一般是使用?代替具体的类型实参,注意了,此处’?’是类型实参,而不是类型形参 。重要说三遍!此处’?’是类型实参,而不是类型形参 ! 此处’?’是类型实参,而不是类型形参 !再直白点的意思就是,此处的?和Number、String、Integer一样都是一种实际的类型,可以把?看成所有类型的父类。是一种真实的类型。

可以解决当具体类型不确定的时候,这个通配符就是 ? ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。

泛型方法:

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{
    //key这个成员变量的类型为T,T的类型由外部指定  
    private String key;

    public Generic(T key) {
        //这里强转,或者你写其他处理逻辑都行
        this.key = (String) key;
    }

    public String getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }

}
class TestFanxing{
//泛型通配符
    public  void showKeyValue1(Generic<?> obj){
        System.out.println("aaa");;
    }

    public  void mainaa() {
        Generic<Integer> gInteger = new Generic<Integer>(123);
        Generic<Number> gNumber = new Generic<Number>(456);

        showKeyValue1(gNumber);
        //泛型方法
        say("ss");
        TEXT("sss");
        TEXT(111);

    }

    public static void main(String[] args) {

    }
    public  <E> void say(E e){

    }
    public <E> E TEXT(E t){
        return (E) new String("a");
    }


}

可以看出格式就是

    public  <E> void say(E e){

    }
    public <E> E TEXT(E t){
        return (E) new String("a");
    }

泛型方法总结
泛型方法能使方法独立于类而产生变化,以下是一个基本的指导原则:

无论何时,如果你能做到,你就该尽量使用泛型方法。也就是说,如果使用泛型方法将整个类泛型化,

那么就应该使用泛型方法。另外对于一个static的方法而已,无法访问泛型类型的参数。

所以如果static方法要使用泛型能力,就必须使其成为泛型方法。

啥时候使用泛型通配符:
我自己就记住:当方法中传入泛型类的时候,这个泛型类中的类型又不确定是哪个参数,可以用?
如咱们的Generic;在方法中作为形参传入的时候:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值