基于《Java编程思想》第四版

前言

虽然Java的泛型在语法上和C++相比是类似的,但在实现上两者是全然不同的。

语法

Java只需要一个<>就可定义泛型。在<>中可以使用任意符合Java语法要求的字符作为类型的标识,可以定义泛型类、泛型接口、泛型方法等。

class A<T>{
    T a;

    public <Q> void foo(Q a){

    }
}
interface B<T>{
    void foo(T a);
}

实现

Java的泛型并不像C++那样是在编译时根据需要按照模板实例化对应的类。比如下面这段C++代码,会以A为模板实例化两个类。

template<typename T>
class A
{
public:
    A(){}
    T a;
};
int main()
{
    A<int> a;
    A<float> b;

    return 0;
}

查看汇编可以证实,调用的是两个不同类的构造函数

   0x0000000000400545 <+15>:    callq  0x40056c <A<int>::A()>
   0x0000000000400551 <+27>:    callq  0x400578 <A<float>::A()>

Java中所有类都继承自Object,任意类对象都可以向上转型后,使用Object变量存储其引用。基于这一点,Java的泛型实现时其实只有一种类型。以下两个类实际是等同的

class A<T>{
    T a;
}
class A{
    Object a;
}

当使用反射机制获取泛型类的信息时,可以发现class A<T>实际就是class A

public static void main(String[] args) {
    A<Integer> a = new A();
    Field[] f = a.getClass().getDeclaredFields();
    System.out.println(Arrays.toString(f));
}
// 输出为 [java.lang.Object A.a]

由此我们也可以知道为什么下面这段代码总是输出same class

public static void main(String[] args) {
    A<Integer> a = new A();
    A<Double> b = new A();
    if( a.getClass() == b.getClass() ){
        System.out.println("same class");
    }
}

因为基础类型并不继承自Object,所以Java的泛型是不支持基础类型的。如果这么做了,就会得到一个错误提示Type argument cannot be of primitive type

自限定类型

因为使用泛型时,其类型参数会被当做Object来处理,所以编译器就无法感知真实类型的方法了。
比如下面这段代码,就无法通过编译

class A{
    public void foo(){
        System.out.println("A.foo()");
    }
}

class B<T>{
    T a;
    B(T a){
        this.a = a;
    }
    public bar(){
        a.foo();    // 此处会提示编译错误,Object类型不存在foo()方法
    }
}

此时必须将泛型类B的类型参数做限定,让编译器能从限定中获取到足够的信息去判断类型参数是存在foo()方法的。

class B<T extends A>{
    T a;
    B(T a){
        this.a = a;
    }
    public bar(){
        a.foo();
    }
}

Java学习点滴——泛型的更多相关文章

  1. Java学习之——泛型

    1.概要 generics enable types (classes and interfaces) to be parameters when defining classes, interfac ...

  2. 5 Java学习之 泛型

    1. 基本概念          泛型是Java SE 1.5的新特性,泛型的本质是 参数化类型 ,也就是说所操作的 数据类型 被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为 ...

  3. Java学习笔记--泛型

    一个泛型类就是具有一个或者多个类型变量的类. 我们可以只关注泛型,而不会为数据存储的细节而烦恼 . java泛型(一).泛型的基本介绍和使用 http://blog.csdn.net/lonelyro ...

  4. Java学习笔记——泛型

    假定T不仅要指定接口的类继承.使用下面的方式: public class some<T extends Iterable<T> & Comparable<T>&g ...

  5. Java学习点滴——初识Java

    基于<Java编程思想>第四版 前言 "程序就是算法加数据结构",而算法就是控制语句加操作符,编写一个程序就是使用控制语句加操作符去操作数据结构,因此我从Java的控制 ...

  6. JAVA学习之泛型

    ArrayList<E>类定义和ArrayList<Integer>类引用中涉及的术语:1.整个ArrayList<E>称为泛型类型 2.ArrayList< ...

  7. Java学习之泛型和异常

    泛型 1,设计原则或目的:只要代码在编译的时候没有错误,就不会抛异常.  2,泛型通配符  :类型通配符一般是使用 ? 代替具体的类型实参.注意了,此处是类型实参,而不是类型形参!相当于(父类作用)L ...

  8. Java学习之==>泛型

    一.什么是泛型 泛型,即“参数化类型”,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型.也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类.接口 ...

  9. Java学习_泛型

    什么是泛型. Java标准库提供的ArrayList内部就是一个Object[]数组,配合存储一个当前分配的长度,就可以充当"可变数组". public class ArrayLi ...

随机推荐

  1. Helm学习笔记

    Helm学习笔记 Helm 是 Kubernetes 生态系统中的一个软件包管理工具.本文将介绍 Helm 中的相关概念和基本工作原理,并通过一个具体的示例学习如何使用 Helm 打包.分发.安装.升 ...

  2. [dotnet core]落地微服务特色的DevOps管道,持续集成/部署到kubernetes。

    目录 前言 目标 工具 - 最小的学习成本 方案 - 愿景 1. 持续集成 - CI 2. 持续部署 - CD 部署环境 1. 部署gitlab-runner 2. 注册gitlab-runner 搭 ...

  3. Redis 缓存失效和回收机制续

    二.Redis Key失效机制 Redis的Key失效机制,主要借助借助EXPIRE命令: EXPIRE key 30 上面的命令即为key设置30秒的过期时间,超过这个时间,我们应该就访问不到这个值 ...

  4. mqtt服务器apollo的搭建和测试工具paho的使用

    (1)前言 MQTT协议是IBM开发的一个即时通讯协议; 基于发布/订阅的消息协议,近些年来被广泛应用于能源.电力.....等硬件性能低下的远程设备,此外国内很多企业使用MQTT作为android手机 ...

  5. 运用《深入理解Java虚拟机》书中知识解决实际问题

    前言 以前看别人博客说看完<深入理解Java虚拟机>这本书并没有让自己的编程水平提高多少,不过却大大提高了自己的装逼水平.其实,我倒不这么认为,至少在我看完一遍这本书后,有一种醍醐灌顶的感 ...

  6. maven 依赖中scope标签的配置范围详解

    在创建Maven项目时,需要在pom.xml 文件中添加相应的依赖,其中有一个scope标签,该标签是设置该依赖范围 (maven项目包含三种classpath{编译classpath,测试class ...

  7. 驰骋工作流引擎-流程数据md5加密

    关键字:工作流程数据加密  md5  数据保密流程数据防篡改软加密设置方式: 对工作流引擎的数据加密研究, 流程数据的加密方案与实现过程.输入图片说明需求背景1, 流程数据加密是为了防止流程数据被篡改 ...

  8. 当心Azure跨区域数据传输产生额外费用

    最近同事发现Azure上一台虚拟机的费用环比增加了一部分.后面仔细检查发现费用来自数据传输, 因为这是早期部署的一台Azure虚拟机(Iaas),我们在本地生成备份,然后通过AzCopy到存储账号的B ...

  9. kali linux中的yum、rpm常见的问题

    事件起因:今天我在kali里面使用yum命令来部署Linux环境时,出现了错误: bash:yum command not found,然后就百度,找到一片好的文章,链接:http://www.pia ...

  10. Java中String做为synchronized同步锁使用详解

    Java中使用String作同步锁 在Java中String是一种特殊的类型存在,在jdk中String在创建后是共享常量池的,即使在jdk1.8之后实现有所不同,但是功能还是差不多的. 借助这个特点 ...