Java学习点滴——泛型
基于《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学习点滴——泛型的更多相关文章
- Java学习之——泛型
1.概要 generics enable types (classes and interfaces) to be parameters when defining classes, interfac ...
- 5 Java学习之 泛型
1. 基本概念 泛型是Java SE 1.5的新特性,泛型的本质是 参数化类型 ,也就是说所操作的 数据类型 被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为 ...
- Java学习笔记--泛型
一个泛型类就是具有一个或者多个类型变量的类. 我们可以只关注泛型,而不会为数据存储的细节而烦恼 . java泛型(一).泛型的基本介绍和使用 http://blog.csdn.net/lonelyro ...
- Java学习笔记——泛型
假定T不仅要指定接口的类继承.使用下面的方式: public class some<T extends Iterable<T> & Comparable<T>&g ...
- Java学习点滴——初识Java
基于<Java编程思想>第四版 前言 "程序就是算法加数据结构",而算法就是控制语句加操作符,编写一个程序就是使用控制语句加操作符去操作数据结构,因此我从Java的控制 ...
- JAVA学习之泛型
ArrayList<E>类定义和ArrayList<Integer>类引用中涉及的术语:1.整个ArrayList<E>称为泛型类型 2.ArrayList< ...
- Java学习之泛型和异常
泛型 1,设计原则或目的:只要代码在编译的时候没有错误,就不会抛异常. 2,泛型通配符 :类型通配符一般是使用 ? 代替具体的类型实参.注意了,此处是类型实参,而不是类型形参!相当于(父类作用)L ...
- Java学习之==>泛型
一.什么是泛型 泛型,即“参数化类型”,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型.也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类.接口 ...
- Java学习_泛型
什么是泛型. Java标准库提供的ArrayList内部就是一个Object[]数组,配合存储一个当前分配的长度,就可以充当"可变数组". public class ArrayLi ...
随机推荐
- H5 新特性之 fileReader 实现本地图片视频资源的预览
大家好 !! 又见面了, 今天我们来搞一搞 H5的新增API FileReader 真是一个超级超级方便的API呢!!!很多场景都可以使用.......... 我们先不赘述MDN文 ...
- Haskell学习-functor
原文地址:Haskell学习-functor 什么是Functor functor 就是可以执行map操作的对象,functor就像是附加了语义的表达式,可以用盒子进行比喻.functor 的定义可以 ...
- SpringBoot之旅第二篇-配置
一.引言 虽然springboot帮我们进行了自动配置,但配置还是不可避免的,比如最简单的端口号,数据库连接.但springboot的配置一般不用xml进行配置,而是yml和properties,选择 ...
- 『Möbius函数与Möbius反演』
Möbius函数 定义 设正整数\(n\)算数基本定理分解后为\(n=\prod_{i=1}^{k}p_i^{a_i}\),定义函数 \[ \mu(n)= \begin{cases} 0\ \ (\e ...
- Windows下Goland的Terminal设置为Git Bash
Windows下Terminal默认的使用的是系统自带的cmd,功能实在太少,用起来远不如Git Bash来得方利和高效.其实要在Goland的Terminal中使用Bash设置起来也很简单,设置位置 ...
- TensorFlow从1到2(二)续讲从锅炉工到AI专家
图片样本可视化 原文第四篇中,我们介绍了官方的入门案例MNIST,功能是识别手写的数字0-9.这是一个非常基础的TensorFlow应用,地位相当于通常语言学习的"Hello World!& ...
- 『取巧』VS2015试用期过后 继续试用
背景: 个人电脑 安装的 VS2015 Community 社区版. 一直用得挺好,都忘了要登录. 直到近来,30天试用期过 —— VS弹窗:要登录用户名.密码 才能继续使用. 但是,输入了无数次 邮 ...
- UiPath实践经验总结(一)
用UiPath做RPA也有一段时间了,初上阵不久,遇到过不少大大小小的坑.以下列出一些心得体会,望能抛砖引玉,与同行进行更多交流. 1. 日志策略:将UiPath Robot的Logging Leve ...
- vivo4.0系统怎么不ROOT激活Xposed框架的教程
在越来越多应用室的引流,或业务操作中,大多数需要使用安卓的强大Xposed框架,前几天,我们应用室采购了一批新的vivo4.0系统,大多数都是基于7.0以上系统,大多数不能够刷入Root的su权限,即 ...
- Python之路【第六篇】:Python迭代器、生成器、面向过程编程
阅读目录 一.迭代器 1.迭代的概念 #迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 代码如下: while True: ...