重学Android基础系列篇(二):泛型

本文详细介绍了Java中的泛型,从基本概念、泛型类、泛型方法、泛型接口,到通配符的使用,包括无限定通配符、上界通配符和下界通配符,以及类型擦除的概念和影响。文章还探讨了泛型边界与输入输出类型的差异,并通过实例分析了策略模式的核心思想。通过本文,读者可以深入了解Java泛型的各个方面及其在实际编程中的应用。
摘要由CSDN通过智能技术生成

前言

本系列文章主要是汇总了一下大佬们的技术文章,属于Android基础部分,作为一名合格的安卓开发工程师,咱们肯定要熟练掌握java和android,本期就来说说这些~

[非商业用途,如有侵权,请告知我,我会删除]

DD一下: Android进阶开发各类文档,也可关注公众号<Android苦做舟>获取。

1.Android高级开发工程师必备基础技能
2.Android性能优化核心知识笔记
3.Android+音视频进阶开发面试题冲刺合集
4.Android 音视频开发入门到实战学习手册
5.Android Framework精编内核解析
6.Flutter实战进阶技术手册
7.近百个Android录播视频+音视频视频dome
.......

泛型

1.泛型的基本介绍
1.1泛型的定义和使用

泛型按照使用情况可以分为 3 种。

  • 泛型类。
  • 泛型方法。
  • 泛型接口。
1.2泛型类

我们可以这样定义一个泛型类。

public class Test<T> {
  T field1;
}

尖括号 <>中的 T 被称作是类型参数,用于指代任何类型。事实上,T 只是一种习惯性写法,如果你愿意。你可以这样写。

public class Test<Hello> {
  Hello field1;
}

但出于规范的目的,Java 还是建议我们用单个大写字母来代表类型参数。常见的如:

  • T 代表一般的任何类。
  • E 代表 Element 的意思,或者 Exception 异常的意思。
  • K 代表 Key 的意思。
  • V 代表 Value 的意思,通常与 K 一起配合使用。
  • S 代表 Subtype 的意思

如果一个类被 的形式定义,那么它就被称为是泛型类。

Test<String> test1 = new Test<>();
Test<Integer> test2 = new Test<>();

只要在对泛型类创建实例的时候,在尖括号中赋值相应的类型便是。T 就会被替换成对应的类型,如 String 或者是 Integer。你可以相像一下,当一个泛型类被创建时,内部自动扩展成下面的代码。

public class Test<String> {
  String field1;
}

当然,泛型类不至接受一个类型参数,它还可以这样接受多个类型参数。

public class MultiType <E,T>{
  E value1;
  T value2;
  
  public E getValue1(){
    return value1;
  }
  
  public T getValue2(){
    return value2;
  }
}
1.3泛型方法
public class Test1 {
  public <T> void testMethod(T t){
    
  }
}

泛型方法与泛型类稍有不同的地方是,类型参数也就是尖括号那一部分是写在返回值前面的。中的 T 被称为类型参数,而方法中的 T 被称为参数化类型,它不是运行时真正的参数。

当然,声明的类型参数,其实也是可以当作返回值的类型的。

public  <T> T testMethod1(T t){
    return null;
}
1.4泛型类与泛型方法的共存
public class Test1<T>{
​
  public  void testMethod(T t){
    System.out.println(t.getClass().getName());
  }
  public  <T> T testMethod1(T t){
    return t;
  }
}

上面代码中,Test1是泛型类,testMethod 是泛型类中的普通方法,而 testMethod1 是一个泛型方法。

而泛型类中的类型参数与泛型方法中的类型参数是没有相应的联系的,泛型方法始终以自己定义的类型参数为准。

所以,针对上面的代码,我们可以这样编写测试代码。

Test1<String> t = new Test1();
t.testMethod("generic");
Integer i = t.testMethod1(new Integer(1));

泛型类的实际类型参数是 String,而传递给泛型方法的类型参数是 Integer,两者不相干。

但是,为了避免混淆,如果在一个泛型类中存在泛型方法,那么两者的类型参数最好不要同名。比如,Test1代码可以更改为这样

public class Test1<T>{

  public  void testMethod(T t){
    System.out.println(t.getClass().getName());
  }
  public  <E> E testMethod1(E e){
    return e;
  }
}
1.5泛型接口

泛型接口和泛型类差不多

public interface Iterable<T> {
}
1.6通配符 ?

除了用 表示泛型外,还有 <?>这种形式。? 被称为通配符。

class Base{}

class Sub extends Base{}

Sub sub = new Sub();
Base base = sub;      

上面代码显示,Base 是 Sub 的父类,它们之间是继承关系,所以 Sub 的实例可以给一个 Base 引用赋值,那么

List<Sub> lsub = new ArrayList<>();
List<Base> lbase = lsub;

最后一行代码成立吗?编译会通过吗?答案是否定的。

 编译器不会让它通过的。Sub 是 Base 的子类,不代表 List<Sub>和 List<Base>有继承关系。

但是,在现实编码中,确实有这样的需求,希望泛型能够处理某一范围内的数据类型,比如某个类和它的子类,对此 Java 引入了通配符这个概念。

所以,通配符的出现是为了指定泛型中的类型范围,通配符有 3 种形式。

<?>被称作无限定的通配符。

<? extends T>被称作有上限的通配符。

<? super T>被称作有下限的通配符。
1.7无限定通配符 <?>

无限定通配符经常与容器类配合使用,它其中的 ? 其实代表的是未知类型,所以涉及到 ? 时的操作,一定与具体类型无关。

public void testWildCards(Collection<?> collection){
}

上面的代码中,方法内的参数是被无限定通配符修饰的 Collection 对象,它隐略地表达了一个意图或者可以说是限定,那就是 testWidlCards() 这个方法内部无需关注 Collection 中的真实类型,因为它是未知的。所以,你只能调用 Collection 中与类型无关的方法。

当 <?>存在时,Collection 对象丧失了 add() 方法的功能,编译器不通过。

List<?> wildlist = new Arr
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值