Java之泛型

1. 概述
          在引入泛型之前,Java类型分为原始类型、复杂类型,其中复杂类型分为数组和类。引入泛型后,一个复杂类型就可以在细分成更多的类型。
          例如原先的类型List,现在在细分成List<Object>, List<String>等更多的类型。
          注意,现在List<Object>, List<String>是两种不同的类型,他们之间没有继承关系,即使String继承了Object。下面的代码是非法的:

1 List<String> ls = new ArrayList<String>();
2 List<Object> lo = ls;

这样设计的原因在于,根据lo的声明,编译器允许你向lo中添加任意对象(例如Integer),但是此对象是List<String>,破坏了数据类型的完整性。
         在引入范型之前,要在类中的方法支持多个数据类型,就需要对方法进行重载,在引入范型后,可以解决此问题(多态),更进一步可以定义多个参数以及返回值之间的关系。例如:

1 public void write(Integer i, Integer[] ia);
2 public void write(Double  d, Double[] da);

的范型版本为:

1 public <T> void write(T t, T[] ta);

在看下面代码:

 1 public class GenericTest {
 2
 3     public static void main(String[] args) {
 4         List list = new ArrayList();
 5         list.add("qqyumidi");
 6         list.add("corn");
 7         list.add(100);
 8
 9         for (int i = 0; i < list.size(); i++) {
10             String name = (String) list.get(i); // 1
11             System.out.println("name:" + name);
12         }
13     }
14 }

定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

通过使用泛型,解决上面异常,修改代码如下:

 1 public class GenericTest {
 2
 3     public static void main(String[] args) {
 4         /*
 5         List list = new ArrayList();
 6         list.add("qqyumidi");
 7         list.add("corn");
 8         list.add(100);
 9         */
10
11         List<String> list = new ArrayList<String>();
12         list.add("qqyumidi");
13         list.add("corn");
14         //list.add(100);   // 1  提示编译错误
15
16         for (int i = 0; i < list.size(); i++) {
17             String name = list.get(i); // 2
18             System.out.println("name:" + name);
19         }
20     }
21 }

总结: 使用泛型可以指代任意对象类型,定义的容器所放的内容是一个统一的类型;   

java中泛型的引入主要是为了解决两个方面的问题:
1. 集合类型元素在运行期出现类型装换异常,引入泛型增加编译时类型的检查;(即:消除强制类型转换,提高 Java 程序的类型安全)
2. 解决开发时重复代码的编写,能够复用算法。(比如:在类中的方法支持多个数据类型,就需要对方法进行重载)

2. 定义泛型类

我们直接上代码:

 1 package com.learn.chap06.sec01;
 2
 3 public class Fdemo<T> {  // 泛型类
 4     private T a;
 5
 6     public Fdemo(T a) {
 7         super();
 8         this.a = a;
 9     }
10
11     public T getA() {
12         return a;
13     }
14
15     public void setA(T a) {
16         this.a = a;
17     }
18
19     public void print(){
20         System.out.println("Obeject类型为:"+a.getClass().getName());
21     }
22
23
24 }
 1 package com.learn.chap06.sec01;
 2 /**
 3  * 定义泛型类    (使用泛型可以指代任意对象类型)
 4  * @author Administrator
 5  *
 6  */
 7 public class Fdemotest {
 8
 9     public static void main(String[] args) {
10         Fdemo<Integer> test = new Fdemo<Integer>(12);
11         test.print();
12         System.out.println("test="+test.getA());
13
14         Fdemo<String> strFdemo = new Fdemo<String>("我是中国人");
15         strFdemo.print();
16         System.out.println("strFdemo="+strFdemo.getA());
17     }
18 }

运行结果:

Obeject类型为:java.lang.Integer
test=12
Obeject类型为:java.lang.String
strFdemo=我是中国人

3. 限制泛型:

我们直接上代码:

1 package com.learn.chap06.sec02;
2
3 public class Animal {
4     public void say() {
5         System.out.println("它是动物");
6     }
7 }
 1 package com.learn.chap06.sec02;
 2
 3 public class Dog extends Animal{
 4
 5     @Override
 6     public void say() {
 7         // TODO Auto-generated method stub
 8         System.out.println("它是一只狗");
 9     }
10
11
12 }
 1 package com.learn.chap06.sec02;
 2
 3 public class Cat extends Animal{
 4
 5     @Override
 6     public void say() {
 7         // TODO Auto-generated method stub
 8         System.out.println("它是一只猫");
 9     }
10
11
12 }
 1 package com.learn.chap06.sec02;
 2
 3 public class Demo<T extends Animal>{
 4     private T ob;
 5
 6     public Demo(T ob) {
 7         super();
 8         this.ob = ob;
 9     }
10
11     public T getOb() {
12         return ob;
13     }
14
15     public void setOb(T ob) {
16         this.ob = ob;
17     }
18
19     public void print(){
20         System.out.println("T的类型是:"+ob.getClass().getName());
21     }
22 }
 1 package com.learn.chap06.sec02;
 2 /**
 3  * 限制泛型
 4  * @author Administrator
 5  *
 6  */
 7 public class Test {
 8     public static void main(String[] args) {
 9         Demo<Dog> demo = new Demo<Dog>(new Dog());
10         //demo.say();
11         demo.print();
12
13         //Demo<Integer> demo = new Demo<Integer>(new Dog()); // 由于泛型定义Demo类的类型必须为Animal或其子类Dog和Cat,而Integer不是Animal的子类,所以类型被限制,即:限制泛型,导致编译报错
14         Demo<Animal> demo2 = new Demo<Animal>(new Cat());
15         demo2.print();
16
17         Demo<Cat> demo3 = new Demo<Cat>(new Cat());
18         demo3.print();
19
20     }
21 }

运行结果:

T的类型是:com.learn.chap06.sec02.Dog
T的类型是:com.learn.chap06.sec02.Cat
T的类型是:com.learn.chap06.sec02.Cat

4. 通配符泛型:

我们直接上代码:

 1 package com.learn.chap06.sec03;
 2
 3 import com.learn.chap06.sec02.Animal;
 4 import com.learn.chap06.sec02.Cat;
 5 import com.learn.chap06.sec02.Demo;
 6 import com.learn.chap06.sec02.Dog;
 7
 8 public class Test1 {
 9     /**
10      * 通配符泛型
11      * @param demo
12      */
13     public static void take(Demo<?> demo){ // <?> 即为:通配符泛型
14         demo.print();
15     }
16
17     public static void main(String[] args) {
18         Demo<Dog> demo1 = new Demo<Dog>(new Dog());
19         take(demo1);
20
21         Demo<Cat> demo2 = new Demo<Cat>(new Cat());
22         take(demo2);
23
24         Demo<Animal> demo3 = new Demo<Animal>(new Animal());
25         take(demo3);
26     }
27 }

运行结果:

T的类型是:com.learn.chap06.sec02.Dog
T的类型是:com.learn.chap06.sec02.Cat
T的类型是:com.learn.chap06.sec02.Animal

5. 泛型方法:

 1 package com.learn.chap06.sec04;
 2
 3 public class Test {
 4
 5     /**
 6      * 泛型方法
 7      * @param t
 8      */
 9     public  static <T> void f(T t) {
10         System.out.println("T的类型是:"+t.getClass().getName());
11     }
12
13     public static void main(String[] args) {
14         f(1);
15         f("hello");
16         f(1.0f);
17         f(new Object());
18     }
19 }

运行结果:

T的类型是:java.lang.Integer
T的类型是:java.lang.String
T的类型是:java.lang.Float
T的类型是:java.lang.Object

现在使用泛型没问题了吧!呵呵

时间: 2024-11-05 20:45:19

Java之泛型的相关文章

Java中泛型的协变

在工作中遇到一个问题,用代码描述如下: package test; import java.util.LinkedList; import java.util.List; public class ListTest {     public void func(List<Base> list) {     }     public static void main(String args[]) {         ListTest lt = new ListTest();         Li

Java 容器 & 泛型:一、认识容器

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 容器是Java语言学习中重要的一部分.泥瓦匠我的感觉是刚开始挺难学的,但等你熟悉它,接触多了,也就"顺理成章"地知道了.Java的容器类主要由两个接口派生而出:Collection和Map. 一.Collection vs Collections 首先,Collection 和 Collections 是两个不同的概念.之所以放在一起,是为了更好的比较.Collection是容器层次结构中

Java 泛型 Java使用泛型的意义

Java 泛型 Java使用泛型的意义 @author ixenos 直接意义 在编译时保证类型安全 根本意义 a) 类型安全问题源自可复用性代码的设计,泛型保证了类型安全的复用模板 b) 使用复用性模板时不用手动强制类型转换 三种泛型实现方式的优缺点 C++:模板方式实现,在编译时完全展开并且支持偏特化,类型精度高,代码共享差: Java 5:擦除方式实现,仅用于编译时类型检查,在运行时擦除,向后兼容性好,代码共享好,类型精度非常差: C# 2.0:混合方式实现,在运行时展开特化,类型精度高,

Java 中泛型的全面解析

Java泛型(generics) 是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在JDK 5中的新集合类框架中.对于泛型概念的引入,开发社区的观点是褒贬不一.从好的方面来说,泛型的引入可以解决之前的集合类框架在使用过程中通常会出现的运行时刻类型错误,因为编译器可以在编译时刻就发现很多明显的错误.而从不好的地方来说,为了保证与旧有版本的兼容性,Java泛型的实现上存在着一些不够优雅的

Java 中 泛型的限定

泛型 一般 出现在集合中,迭代器中 也会出现! 泛型 是为了 提高代码的 安全性. 泛型 确保数据类型的唯一性. 在我们常用的容器中,  越是 单一 约好处理啊! 泛型的限定: ? 是通配符 指代 任意类型 泛型的限定上限: <? extends E> 接受 E 或者 E 的子类型. 泛型的限定下限: <?  super   E>  接收  E 或者 E 的父类. 泛型的限定上限 (定义父类 填装子类 类型!) 代码: package stu.love.v; import java

Java中泛型 使用

泛型: 1.5  之后出现  提高安全 1      泛型 确定 集合容器的类型. 2      <> 接收一种数据类型,(引用数据类型) ArrayList<String> lis = new ArrayList<String>() 目的: 将运行时期的 错误 转化到 编译时期,提高了安全性! 3      不需要 强制类型转换.  更加安全! 泛型的 擦除: 泛型在编译时期使用!使用完毕直接擦除. 编译完的时候 不存在 泛型. 好处: 使用了 泛型,不自需要强制类型

java遍历泛型的方法

一.List遍历 Java中List遍历有三种方法来遍历泛型,主要为: 1.for循环遍历 2.iterator遍历 3.foreach遍历 package com.gmail.lsgjzhuwei; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.junit.Test; public class test { //第一种方法:for循环遍历 @Test public

Java核心 --- 泛型

CoreJava 泛型 java泛型的出现避免了强制类型转换,便于代码更好的被阅读 本文的写作参照了张孝祥的泛型介绍:http://www.itcast.cn/news/dbfd20f1/f4b1/412d/9b40/c1a81b8bf1da.shtml 更多疑问请参考:http://www.vaikan.com/java-generics-quick-tutorial/ 1.可以接收类型参数的类型在接受类型参数后变为泛型,但是,虽然是不同的泛型但是还是相同的类型 package com.yuk

Java 之泛型

两种快速理解泛型的描述 1. 数据类型是抽象的,这个类可以处理很多数据类型.里面的T在被实例化的时候可以用任意类型代替. 2.  泛型,想成一个桶,你装水或者装沙子都行,这个桶只负责提供装满水或者装满沙子的功能 . 官方解释: 泛型是程序设计语言的一种特性.允许程序员在强类型程序设计语言中编写代码时定义一些可变部份,那些部份在使用前必须作出指明. 泛型的定义主要有以下两种: 在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个别对象.(这是当今较常见的定义) 在程序编码

JAVA基础—泛型小结

概念: 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Java语言引入泛型的好处是安全简单. 泛型的常用字符代表意思: ? 表示不确定的java类型. T  表示java类型. K V 分别代表java键值中的Key Value. E 代表Element. 下面转载于cnblog上一个写的很好的例子 真的很好,我写了半天,当看到他这个后,立即删除~ 普通泛型