一、泛型的引入原因

  在操作集合的时候,之前方法的定义都是Object类型,向集合中添加对象,都自动向上转型,加入的元素可以是任何类型

但是,在取出元素的时候,通常想要使用对象的特有功能,就必须向下转型,此时就可能出现类型转换异常,存在安全隐患。

在JDK1.5时候提出一个解决方案:泛型。

二、泛型的定义及好处

  泛型:是一种应用在编译时期的安全机制,具体的做法:有点类似于数组的思想,定义操作的时候,指定好要操作的类型信息

eg:ArrayList<String>:表示该ArrayList只能操作字符串类型的元素,假如要向其中添加Integer类型,就会编译失败。

<>尖括号中指定被操纵的对象的类型。

  好处:将运行期间可能出现的异常,转化为编译时期的强制检验,避免了强制类型转换;也提供了设计上的便捷

三、泛型的擦除和补偿

  泛型擦除:具体指的是编译器在堆源代码进行完类型检查后,在生成字节码文件的时候,会滤过泛型指定的类型信息,所以

生成的字节码文件中不含有具体的类型信息--变为Object或某个范围,使用泛型擦除主要的目的:其实为了兼容性,为了继续使用

Classloader加载类,同时还要满足以前没有泛型类的加载,所以就在检查完类型匹配后,将泛型类型的信息擦除。

  泛型补偿:当要本来具有泛型的方法在被调用的时候,根据实际类型的Class对象获取类型信息,自动的添加到原来的地方。

 import java.util.Iterator;
import java.util.TreeSet; /*泛型的简单使用
* */
public class GenericsDemo { public static void main(String[] args) {
//TreeSet在添加元素的时候排序,元素必须能够被比较/或传给TreeSet一个比较器
TreeSet<Unicorn> t = new TreeSet<Unicorn>();
t.add(new Unicorn(2,"huahua"));
t.add(new Unicorn(1,"tete"));
t.add(new Unicorn(1,"meme"));
//遍历集合
Iterator<Unicorn> it = t.iterator();
while(it.hasNext()){
Unicorn u = it.next();
System.out.println(u.getAge() + " " + u.getName());
}
}
} class Unicorn implements Comparable<Unicorn>{
private int age;
private String name; public Unicorn(int age, String name) {
this.age = age;
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public int compareTo(Unicorn u) {
int temp = this.age - u.age;
return temp == 0 ? this.name.compareTo(u.name):temp;
}
}

四、泛型的不同的使用场景

  1.泛型类或接口:表示该类或接口以后要操作的引用类型不确定,所以在定义的时候需要定义为泛型类或接口。

在创建对象的时候,指定具体要操作的类型。类/接口<参数类型>

  2.泛型方法:表示该方法以后要操作的引用类型不确定,所以在定义的时候定义为泛型方法,注意:泛型方法的

定义与其所在的类或接口是否为泛型类或接口没有关系。静态方法由于不能访问泛型类的类型参数,所以假如该静态

方法需要使用泛型,则将该方法定义为泛型方法。泛型方法的调用与普通方法没有区别。<参数类型> 返回值

五、泛型的高级应用

  1.泛型通配符:?表示,通常用于操作任意参数类型的泛型。强调的是通用性。

  2.泛型的界限:其目的是在一定范围内扩大可以操作的参数类型。分为上界限,和下界限。

  泛型上界:表现形式:<? extends A> 表示的含义是:可以操作的参数类型可以是,A类型以及A的子类。通常这种

在集合中取出元素的时候常常使用,通常用A类型来接收取出的元素。<=A

  泛型下界:表现形式:<? super A> 表示的含义是:可以操作的参数类型是:A类型及其父类型。通常这种在接收元素

做比较的时候使用,可以使用自己的比较器,也可以使用父类的比较器。泛型下限的使用不多 。>=A

注意:ArrayList<Animal> list = new ArrayList<Cat>(); 这是错误的两边的泛型类型不匹配。

   ArrayList<? extends Animal> list = new ArrayList<Cat>(); 这样才是正确的写法,泛型匹配。

 /*定义泛型类,泛型接口,泛型方法
*注意:既然使用泛型,就表示操作的类型不确定,通常可以调用的
*方法都是公共的方法,从Object里继承得到的方法。
* */
public class Tool<T> {
private T t; public T getT() {
return t;
} public void setT(T t) {
this.t = t;
} public void print(T t){
System.out.println("print " + t.toString());
}
public static <Y> void method(Y y){
System.out.println("method " + y.toString());
}
}
 /*泛型接口:要么在具体类实现的时候定义参数类型或在创建子类对象的时候明确参数类型
*这是根据什么时候可以明确操作的类型确定的。
* */
public interface GenericsInter<T> {
void method(T t);
} class A implements GenericsInter<String>{
@Override
public void method(String t) {
// TODO Auto-generated method stub }
} class B<T> implements GenericsInter<T>{
@Override
public void method(T t) {
// TODO Auto-generated method stub }
}
 import java.util.*;

 /*使用泛型的通配符,泛型上界限*/
public class GenericsBound {
public static void main(String[] args) {
ArrayList<Personn> list1 = new ArrayList<Personn>();
list1.add(new Personn(23, "hehe"));
list1.add(new Personn(34, "nini"));
ArrayList<Student> list2 = new ArrayList<Student>();
list2.add(new Student(13,"keke"));
list2.add(new Student(19,"oo"));
ArrayList<Integer> list3 = new ArrayList<Integer>();
list3.add(9);
list3.add(4);
printCollection(list1);
printCollection(list2);
printCollection(list3);
printCollection1(list1);
printCollection1(list2);
//printCollection1(list3);---限定了所以不可以传入该参数
} //使用的泛型通配符可以操作泛型参数类型是任意的
public static void printCollection(Collection<?> c){
Iterator<?> it = c.iterator();
while(it.hasNext()){
System.out.println(it.next().toString());
}
}
//只接收泛型参数类型是Personn及其子类的集合
public static void printCollection1(Collection<? extends Personn> c){
Iterator<? extends Personn> it = c.iterator();
while(it.hasNext()){
System.out.println(it.next().toString());
}
} } class Personn{
private int age;
private String name; public Personn(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} public String toString(){
return "person " + getName() + " " + getAge();
} } class Student extends Personn{ public Student(int age, String name) {
super(age, name);
}
public String toString(){
return "student " + getName() + " " + getAge();
}
} class Worker extends Personn { public Worker(int age, String name) {
super(age, name);
} public String toString(){
return "worker " + getName() + " " + getAge();
}
}
 public static void printCollection3(Collection<? super Student> c){
Iterator<? super Student> it = c.iterator();
while(it.hasNext()){
System.out.println(it.next().toString());
}
}
泛型下界限:此时只能打印参数类型为Student类型及其父类类型的集合
 import java.util.Comparator;
import java.util.TreeSet;
/*泛型下界限的使用
*TreeSet(Comparator<? super E>) 对于元素E类型可以使用自己的比较器或者父类的比较器*/
public class Generic_LowBound {
public static void main(String[] args) {
TreeSet<Student> t1 = new TreeSet<Student>(new ComparateByPersonn());
t1.add(new Student(12,"hyhy"));
t1.add(new Student(14,"uiui"));
System.out.println(t1);
TreeSet<Student> t2 = new TreeSet<Student>(new ComparateByStudent());
t2.add(new Student(12,"hyhy"));
t2.add(new Student(14,"uiui"));
System.out.println(t2);
}
} class ComparateByPersonn implements Comparator<Personn>{
@Override
public int compare(Personn o1, Personn o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp == 0 ? (o1.getAge() -o2.getAge()) :temp;
}
} class ComparateByStudent implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp == 0 ? (o1.getAge() -o2.getAge()) :temp;
}
} class ComparateByWorker implements Comparator<Worker>{
public int compare(Worker o1, Worker o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp == 0 ? (o1.getAge() -o2.getAge()) :temp;
}
}

  

Java泛型应用总结的更多相关文章

  1. Java泛型的历史

    为什么Java泛型会有当前的缺陷? 之前的章节里已经说明了Java泛型擦除会导致的问题,C++和C#的泛型都是在运行时存在的,难道Java天然不支持“真正的泛型”吗? 事实上,在Java1.5在200 ...

  2. 浅析Java 泛型

    泛型是JavaSE5引入的一个新概念,但是这个概念在编程语言中却是很普遍的一个概念.下面,根据以下内容,我们总结下在Java中使用泛型. 泛型使用的意义 什么是泛型 泛型类 泛型方法 泛型接口 泛型擦 ...

  3. Java:泛型基础

    泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...

  4. java泛型基础

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

  5. 使用java泛型设计通用方法

    泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张stu ...

  6. 关于Java泛型的使用

    在目前我遇到的java项目中,泛型应用的最多的就属集合了.当要从数据库取出多个对象或者说是多条记录时,往往都要使用集合,那么为什么这么使用,或者使用时有什么要注意的地方,请关注以下内容. 感谢Wind ...

  7. 初识java泛型

    1 协变数组类型(covariant array type) 数组的协变性: if A IS-A B then A[] IS-A B[] 也就是说,java中的数组兼容,一个类型的数组兼容他的子类类型 ...

  8. 【Java心得总结四】Java泛型下——万恶的擦除

    一.万恶的擦除 我在自己总结的[Java心得总结三]Java泛型上——初识泛型这篇博文中提到了Java中对泛型擦除的问题,考虑下面代码: import java.util.*; public clas ...

  9. 【Java心得总结三】Java泛型上——初识泛型

    一.函数参数与泛型比较 泛型(generics),从字面的意思理解就是泛化的类型,即参数化类型.泛型的作用是什么,这里与函数参数做一个比较: 无参数的函数: public int[] newIntAr ...

  10. 初识Java泛型以及桥接方法

    泛型的由来 在编写程序时,可能会有这样的需求:容器类,比如java中常见的list等.为了使容器可以保存多种类型的数据,需要编写多种容器类,每一个容器类中规定好了可以操作的数据类型.此时可能会有Int ...

随机推荐

  1. linux initcall 介绍 (转自http://blog.csdn.net/fenzhikeji/article/details/6860143)

    现在以module_init为例分析initcall在内核中的调用顺序 在头文件init.h中,有如下定义: #define module_init(x)     __initcall(x); 很明显 ...

  2. openjudge-NOI 2.6-1944 吃糖果

    题目链接:http://noi.openjudge.cn/ch0206/1944/ 题解: 递推,题目中给出了很详细的过程,不讲解 #include<cstdio> int n; int ...

  3. tyvj P1050 最长公共子序列

    题目链接:http://tyvj.cn/p/1050 题解: 裸题,只是为了测试LCS模板写对没有…… #include<cstdio> #include<cstring> # ...

  4. 在html页面中引入公共的头部和底部

    参考链接: http://www.cnblogs.com/jason-star/p/3345225.html http://blog.csdn.net/jsxzzliang/article/detai ...

  5. htaccess附录:正则表达式、重定向代码

    .htaccess正则表达式 # 位于行首时表示注释. [F] Forbidden(禁止): 命令服务器返回 403 Forbidden错误给用户浏览器 [L] Last rule(最后一条规则): ...

  6. Hadoop(一):概述

    一.Hadoop是什么? Hadoop是一个由Apache基金会所开发的分布式系统基础架构.Hadoop框架最核心的设计包含两个方面,一是分布式文件系统(Hadoop Distributed File ...

  7. asp基础

    0.1在浏览器中通过查看源代码的方式是无法看到 ASP 源代码的,你只能看到由 ASP 文件输出的结果,而那些只是纯粹的 HTML 而已.这是因为,在结果被送回浏览器前,脚本已经在服务器上执行了. 0 ...

  8. SG函数(转自百度百科)

    给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移 动者判负.事实上,这个游戏可以认为是所有Impartial Combinatorial Games的抽象 ...

  9. Mysql修改语句的运行流程

    执行修改语句前要先连接数据库,这是连接器的工作. 接下来,分析器会通过词法和语法解析知道这是一条更新语句.优化器决定要使用 ID 这个索引.然后,执行器负责具体执行,找到这一行,然后更新. Mysql ...

  10. 不修改系统日期和时间格式,解决Delphi报错提示 '****-**-**'is not a valid date and time

    假如操作系统的日期格式不是yyyy-MM-dd格式,而是用strtodate('2014-10-01')) 来转换的话,程序会提示爆粗 '****-**-**'is not a valid date ...