1. 泛型

泛型 - 图1

1.1 泛型实现机制?

从Java5开始引入,泛型作用域: 泛型方法,泛型类,泛型参数;
编译期有效,运行期无效,仅仅是编码时期的约束, JVM无法识别.

1.1 Java泛型使用类型擦除实现,优点:

  • 运行时内存开销小,节约方法区内存开销;
  • 例如: List,List, 都会编译成List;
  • 考虑兼容性,从Java5开始加入泛型,兼容4之前代码(通过强转实现).

    1.2 类型擦除的缺点:

  • Java泛型基本类型无法作为泛型实参;由于泛型会擦除类型,只能使用包装类型,需要拆箱装箱,但安卓中避免了拆箱装箱的开耗,设计了SparseArray(内存优化);

  • 泛型类型作为方法时候无法方法重载,因为编译完成都是一样的类型,参数被擦除了,方法签名相同

    1. private void test(List<String> ls){}
    2. private void test(List<Integer> li){}
  • 泛型类型无法当做真实类型使用,由于不知道真实类型,所以无法通过new关键字实例化,不能创建类型参数的实例,但是反射可以.无法使用在数组,无法获取类型,无法使用instanceof

    1. // new 无法编译
    2. private <T> void test(List<T> lt) {
    3. T t = new T(); // 无法new
    4. T[] ts = new T[0];// 无法创建数组
    5. Class c = T.class;// 无法获取类型
    6. if (lt instanceof List<String>){} // 无法类型判断
    7. if (lt instanceof List){} // √
    8. List<T> tt = new ArrayList<T>();// 泛型传递,作用在其他泛型处
    9. }
    10. // 反射 通过编译
    11. private <T> void test(List<T> lt, Class<T> ct) throws NoSuchMethodException, InvocationTargetException
    12. , InstantiationException, IllegalAccessException {
    13. // T t = ct.newInstance();// @Deprecated(since="9")
    14. T t = ct.getDeclaredConstructor().newInstance();
    15. lt.add(t);
    16. }
  • 静态方法无法引用类泛型参数;因为类泛型参数只有实例化时候知道,静态方法不需要类的实例,通过静态方法声明泛型参数即可解决;

    public class Test<T> {
      private T t;// √
      private static T tt;// × 无法使用在静态字段
      private static T test(T t) {return t;}// × 静态方法无法引用类泛型参数
      private static <T> T test(T t, T b) {return t;}// √ 静态方法可以声明泛型参数
    }
    

    1.3 泛型类型签名信息可以通过反射获取.

1.4 泛型通配符

无边界通配符
泛型操作符用于解决当泛型实参的类型不确定的情况,用?来替代类型实参,可以将其看成所有类型的父类。

    // 泛型参数 无边界通配符 ?
    private void test(List<?> list) {
        list.add(1);
        list.add(null);

        list.get(0).hashCode();
    }

上下边界通配符
上边界 extends
List 中的元素必定是 Integer 或它的子类

    // 固定上边界 ? extends
    private void test(List<? extends String> list) {
        list.add("");
        list.add(null);

        list.get(0).toString();
    }

下边界 super
List 中的元素必定是 Integer 或它的父类

    // 固定下边界 ? super
    private void test(List<? super Integer> list) {
        list.add(1);
        list.add(null);
    }

2. 注解

泛型 - 图2

2.1 元注解

元注解是描述注解的注解, JDK中提供的原始注解, 方便自定义注解, 注解标志: @interface
列举使用最频繁的两个注解:

@Target(ElementType.METHOD)
参数表示注解作用域: ElementType枚举类型常用的包括:
TYPE: 类,接口,注解,枚举
METHOD: 方法
FIELD: 属性

@Retention(RetentionPolicy.RUNTIME)
注解保留的阶段, RetentionPolicy枚举类型, 3个固定枚举:
SOURCE: 编译阶段, 这个注解会被移除, 不会包含在编译后的class文件中
CLASS: 注解会被保留在class文件中, 运行时会被移除
RUNTIME: 注解会被保留到运行时, 可以在运行时通过反射解析这个注解


3. 反射