当前位置: 首页 > news >正文

java中的泛型

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

泛型,即“参数化类型”

(1)泛型只在编译阶段有效;

0、边界符:<T extends Comparable<T>>,说明T 必须继承Comparable才能使用   

(1)T可以为任意标识,如T、E、K、V等常用于表示泛型;

(2)泛型的上下边界添加,必须与泛型的声明在一起;

public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) {
    int count = 0;
    for (T e : anArray)
        if (e.compareTo(elem) > 0)
            ++count;
    return count;
}

1、泛型类

(2)泛型类型:逻辑上是多个不同的类型,实际上是相同基本类型;

(3)泛型类型参数只能是类类型,不能是简单类型;

144431_abHC_3847203.png

2、泛型方法

(1)泛型类,是在实例化类的时候指明泛型的具体类型;

(2)泛型方法,是在调用方法的时候指明泛型的具体类型;

(4)多个泛型类型例子:


class GenerateTest<T>{ //<T>在类中声明T泛型,与下文的方法声明的T不是同一个
    public <T,H,K> K showKeyName(Generic<T> container){
        //出现多个泛型类型时使用,T、K可以在任意地方使用
        //方法内的T不是  外面类的T
    }
}

(3)public 与 返回值中间<K,V>可以理解为声明此方法为泛型方法;

144707_343j_3847203.png

1、虽然Integer和Double是Number的子类,但是Box<Integer>或者Box<Double>Box<Number>之间无关;

2、通配符?: List<? extends T> list

(1)实现了<? extends T>的集合类,对外提供get方法,不可以set;

(2)实现了<? super T>的集合类,可以使用set,不能get;

(3)同时读取、写入,不能使用通配符,或者<? extends T><? super T>同时使用;

(4)?是类型实参,而不是类型形参;

public class Collections {
    public static <T> void copy(List<? super T> dest, List<? extends T> src) {
        for (int i=0; i<src.size(); i++)
            dest.set(i, src.get(i));
    }
}

3、类型擦除

(1)java泛型只能用于编译器静态类型检查,编译后代码会擦除类型信息;

(2)运行期jvm不知道泛型所指具体类型:Node<String>Node<Integer>,均视为Node<Object>

编译前:

145224_ZC90_3847203.png

编译后:

public class Node {
    private Object data;
    private Node next;
    public Node(Object data, Node next) {
        this.data = data;
        this.next = next;
    }
    public Object getData() { return data; }
    // ...
}

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

编译前:

145301_rLZ4_3847203.png

编译后:

public class Node {
    private Comparable data;
    private Node next;
    public Node(Comparable data, Node next) {
        this.data = data;
        this.next = next;
    }
    public Comparable getData() { return data; }
    // ...
}

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

4、问题:不允许创建泛型数组,除非使用通配符

List<Integer>[] arrayOfLists = new List<Integer>[2];  // compile-time error

List<?>[] lsa = new List<?>[10]; // OK, array of unbounded wildcard type.  
Object o = lsa;    
Object[] oa = (Object[]) o;    
List<Integer> li = new ArrayList<Integer>();    
li.add(new Integer(3));    
oa[1] = li; // Correct.    
Integer i = (Integer) lsa[1].get(0); // OK 
public class ErasedTypeEquivalence {
    public static void main(String[] args) {
        Class c1 = new ArrayList<String>().getClass();
        Class c2 = new ArrayList<Integer>().getClass();
        System.out.println(c1 == c2); // true   泛型擦除的缘故
    }
}

5、问题:编译器会偷偷帮我们实现Bridge method:

编译前:

145403_60ig_3847203.png

编译后:

class MyNode extends Node {
    // Bridge method generated by the compiler
    public void setData(Object data) {/编译器自动生成
        setData((Integer) data);
    }
    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }
    // ...
}

6、问题:参数类型创建实例,编译不通过:

public static <E> void append(List<E> list) {
    E elem = new E();  // compile-time error
    list.add(elem);
}

反射可以创建实例:

public static <E> void append(List<E> list, Class<E> cls) throws Exception {
    E elem = cls.newInstance();   // OK
    list.add(elem);
}
public static void main(String[] args) {
    List<String> ls = new ArrayList<>();  //调用方法
    append(ls, String.class);
}

7、问题:无法对泛型直接使用instanceof:

public static <E> void rtti(List<E> list) {
    if (list instanceof ArrayList<Integer>) {  // compile-time error
        // ...
    }
}

通配符可以解决:

public static void rtti(List<?> list) {
    if (list instanceof ArrayList<?>) {  // OK; instanceof requires a reifiable type
        // ...
    }
}

8、可变参数:

161214_wnkp_3847203.png

9、静态方法:

(1)静态方法无法访问类上定义的泛型;

(2)如果要使用,必须将泛型定义在方法上;

 

转载于:https://my.oschina.net/u/3847203/blog/1812272

相关文章:

  • AI和量子计算的“联姻”开启新世界
  • zookeeper - 多线程分析(10)
  • Android 8.0 功能和 API
  • 1000个中国“富一代”今日来杭州,要搞什么大事?
  • Zabbix监控指定端口
  • 网卡绑定技术teaming!
  • Date8
  • Promise初体验
  • PHP 使用GD库生成二维码 实现圆角
  • session一致性架构设计
  • 《shell编程实战》第4章shell变量进阶(上)
  • 批量实现多台服务器之间ssh无密码登录的相互信任关系
  • 与Bob McWhirter的问答:WildFly Swarm更名为Thorntail项目
  • AsyncTask实现原理
  • 最简单的无缝轮播
  • [deviceone开发]-do_Webview的基本示例
  • [译]前端离线指南(上)
  • 「面试题」如何实现一个圣杯布局?
  • 5、React组件事件详解
  • angular2开源库收集
  • Date型的使用
  • django开发-定时任务的使用
  • IndexedDB
  • Java-详解HashMap
  • LeetCode18.四数之和 JavaScript
  • React的组件模式
  • SpringBoot几种定时任务的实现方式
  • Terraform入门 - 3. 变更基础设施
  • tweak 支持第三方库
  • XML已死 ?
  • 关于字符编码你应该知道的事情
  • 十年未变!安全,谁之责?(下)
  • 实现简单的正则表达式引擎
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 用 Swift 编写面向协议的视图
  • 交换综合实验一
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​水经微图Web1.5.0版即将上线
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (1)常见O(n^2)排序算法解析
  • (3)STL算法之搜索
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (windows2012共享文件夹和防火墙设置
  • (十) 初识 Docker file
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)德国人的记事本
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • .NET 5种线程安全集合
  • .NET BackgroundWorker
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .net 调用php,php 调用.net com组件 --
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .NET下的多线程编程—1-线程机制概述