## 1.为什么需要泛型?

JDK提供了ArrayList,可以看作“可变长度”的数组:

  • 比数组使用方便

    示例1:如果使用ArrayList存储String类型:
  • 需要强制转型
  • 不方便,易出错
//演示代码
public class ArrayList1{
private Object[] array;
public void add(Object e){...}
public void remove(int index){...}
public Object get(int index){...}
} public class Main {
public static void main(String[] args){
ArrayList1 list = new ArrayList1();
list.add("hello");
String one = (String) list.get(0);//需要强制转型
list.add(new Integer(123));//加入Integer类型,提示Error : ClassCastException
String second = (String) list.get(1);
}
}

示例2: 为了解决示例1中的问题,为String单独编写一种ArrayList:

  • 不需要强制转型
  • 编译器强制检查放入的类型
public class ArrayList1{
private String[] array;
public void add(String e){}
public void remove(int index){}
public String get(int index){return array[index];}
} public class Main {
public static void main(String[] args){
ArrayList1 list = new ArrayList1();
list.add("hello");
String one = list.get(0);//不再需要强制转型
list.add(new Integer(123));//IDE就会提示编译错误,不需要等到编译时
String second = (String) list.get(1);
}
}

新的问题:还需要为其他所有从class单独编写一种ArrayList:Long, Double, Person, Integer。

必须把ArrayList变成一种模版.

1.1范型就是定义一种模版,例如ArrayList

  • 在代码中为用到的类创建对应的ArrayList<类型>

    * ArrayList strList = new ArrayList();
  • 编译器针对类型做检查

    * strList.add("hello");

    * strList.add(new Integer(123));//compile error
public class ArrayList1<T> {
private T[] array;
public void add(T e){}
public void remove(int index){}
public T get(int index){return array[index];}
} public class Main {
public static void main(String[] args){
ArrayList1<String> strList = new ArrayList1<String>();
ArrayList1<Integer> inList = new ArrayList1<Integer>();
ArrayList1<Float> flList = new ArrayList1<Float>();
}
}

2.泛型的继承关系

ArrayList1<T>实现了List<T>接口,ArrayList1<T>可以向上转型为List<T>.
//示例代码,忽略错误
public class ArrayList1<T> implements List<T> {
private T[] array;
public void add(T e){}
public void remove(int index){}
public T get(int index){return array[index];}
//List<T>的方法...
} public class Main {
public static void main(String[] args){
ArrayList1<String> strList = new ArrayList1<String>();
List<String> list = new ArrayList<String>();
}
}
不能把ArrayList1<Integer>向上转型为ArrayList1<Numberr>或List<Number>
ArrayList1<Integer>和ArrayList1<Number>两者没有继承关系。
而Number包含float的子类,ArrayList1<Integer>不接受float。
import java.util.ArrayList;
//使用JDK的ArrayList<t>
public class Main {
public static void main(String[] args){
ArrayList<String> strList = new ArrayList<String>();
strList.add("abc");
strList.add("xyz");
//strList.add(new Integer(123));
String first = strList.get(0);
System.out.println(first);
}
}

3.总结:

  • 泛型就是编写模版代码来适应任意类型
  • 不必对类型进行强制转换
  • 编译器将对类型进行检查
  • 注意泛型的继承关系:
    *    可以把ArrayList<Integer>向上转型为List<Integer> (T不能变)
* 不能ArrayList<Integer>向上转型为ArrayList<Number>

廖雪峰Java4反射与范型-3范型-1什么是泛型的更多相关文章

  1. 廖雪峰Java4反射与泛型-3范型-4擦拭法

    1.擦拭法是Java泛型的实现方式. 编译器把类型视为Object. * 泛型代码编译的时候,编译器实际上把所有的泛型类型T统一视为Object类型.换句话说,虚拟机对泛型一无所知,所有的工作都是编译 ...

  2. 廖雪峰Java4反射与泛型-3范型-3编写泛型

    编写泛型类比普通的类要麻烦,而且很少编写泛型类. 1.编写一个泛型类: 按照某种类型(例如String)编写类 标记所有的特定类型例如String 把特定类型替换为T,并申明 Pair.java pa ...

  3. 廖雪峰Java4反射与泛型-3范型-6super通配符

    1.super通配符 1.1super通配符第一种用法 泛型的继承关系 Pair<Integer>不是Pair<Number>的子类,如 static void set(Pai ...

  4. 廖雪峰Java4反射与泛型-3范型-5extends通配符

    1.泛型的继承关系: Pair<Integer>不是Pair<Number>的子类 add()不接受Pair<Integer> Pair.java package ...

  5. 廖雪峰Java4反射与泛型-3泛型-7泛型和反射

    1.部分反射API是泛型 1.1获取反射API的泛型 部分反射API是泛型,如Class<T>是泛型 //如果使用Class,不带泛型,出现compile warning编译警告 Clas ...

  6. 廖雪峰Java4反射与泛型-2注解-3处理注解

    1.处理注解 注解本身对对代码逻辑没有任何影响 SOURCE类型的注解在编译期就被丢掉了 CLASS类型的注解仅保存在class文件中 RUNTIME类型的注解在运行期可以被读取 如何使用注解由工具决 ...

  7. 廖雪峰Java4反射与泛型-1反射-2访问字段Field和3调用方法Method

    2.字段Field 2.1.通过Class实例获取字段field信息: getField(name): 获取某个public的field,包括父类 getDeclaredField(name): 获取 ...

  8. 廖雪峰Java4反射与泛型-1反射-1Class类

    1.Class类与反射定义 Class类本身是一种数据类型(Type),class/interface的数据类型是Class,JVM为每个加载的class创建了唯一的Class实例. Class实例包 ...

  9. 廖雪峰Java4反射与泛型-2注解-2定义注解

    1.定义注解 使用@interface定义注解Annotation 注解的参数类似无参数方法 可以设定一个默认值(推荐) 把最常用的参数命名为value(推荐) 2.元注解 2.1Target使用方式 ...

随机推荐

  1. 20165313 《Java程序设计》第六周学习总结

    教材学习总结 一点浅见,不足之处还请谅解. 正则表达式:正则表达式是一个String对象的字符序列,该字符序列中含有具有特殊意义的字符,这些特殊字符称作正则表达式的元字符. 链表:由若干个称作结点的对 ...

  2. Go Example--闭包

    package main import "fmt" func main() { //这里需要将闭包函数当作一个类理解,这里是实例化 nextInt := intSeq() fmt. ...

  3. maven(二)

    1.1     Maven的好处 节省空间 对jar包做了统一管理 依赖管理 一键构建 可跨平台 应用在大型项目可提高开发效率 1.2     Maven安装部署配置 1.3     Maven的仓库 ...

  4. MySQL5.6在线DDL不锁表(在线添加字段)

    解答你也看一下MySQL5.6在线DDL不锁表,现在我有一张1亿的表,需要增加一个字段,假如我让你去增加这个字段,你应该注意什么,具体怎么操作? 操作如下:1.注意磁盘空间(临时表目录 参数 tmpd ...

  5. python基础(四)——正则表达式

    #!/usr/bin/python # -*- coding: utf-8 -*- import re print(re.match('www', 'www.runoob.com').span()) ...

  6. <--------------------------StringBuffer的常用方法------------------------------>

    StringBuffer定义: 是可变字符数组,是线程安全的可变字符序列. StringBuffer和String的区别: String是一个不可变的字符序列. 实例: public class St ...

  7. Unity3D用户手册 学习

  8. Oracle数据类型与.NET中的对应关系

    Oracle连接添加的引用不同,会存在数据类型不同以及其他一些差别,就工作中遇到的问题暂时总结下. 两种不同的添加引用语句: (1)System.Data.OracleClient; (2)Oracl ...

  9. 使用http-server创建本地服务

    在很多情况下, 都需要开启本地http服务器来测试, 所以就需要一个简单省事的http服务器, , 以前的时候可以使用express或者webpack-dev-server来启动一个服务, 这未免有点 ...

  10. js 递归

    我理解的递归就是自己调用自己,也就是函数在调用的时候会形成 call stack 调用堆栈.这些数据是用来函数调用完成后,回复之前的函数环境或者局部变量之类的,一般这个都有大小限制,不可能无限生成函数 ...