java编程之泛型

java泛型实现了“参数化类型”的概念,所谓“参数化类型”是指将操作的数据类型指定为一个参数,这点在容器中用的最多,例如:List<String> strlist=new ArrayList<String>(),List<Integer> intlist=new ArrayList<Integer>();strlist可以操作的数据类型是String类型,intlist可以操作的数据类型是int类型,泛型在容器中得到了充分的应用。

泛型是使得代码重用得到很大的提升,我们在程序中也会想一些办法设计代码重用的方法,例如输出一个内容,我们要用System.out.println(...),敲这么多东西还是麻烦,我们可以定义一个println()方法,如下:

static void println(Object o){

  System.out.println(o);

}

再在程序中输出东西时,只需调用println(...)即可,这个println()方法就有了“泛化”的机制,它可以输出任何System.out.println()可以输出的东西,该方法的参数类型被设置为基类Object类型,我们知道,Java中的基本数据类型都有相对应的类类型的数据,比如int类型的数据对应的有Integer类类型的数据,java有“自动装箱”功能,也就是将对应的基本类型的数据转化为对应类类型的对象,例如上面的println(3),在编译后会变成println(Integer.valueOf(3));而所有的java类都是继承自Object类,所以当然可以用println()方法了。

那么将数据类型都定义为Object类型不就可以设计一个泛化类型的方法,类和接口了吗?答案是可以的,但是“太泛化”了,以至于没了边界。这里先给出代码:

 1 public class gen{
 2
 3     public static void main(String[] args){
 4         myList list=new myList();
 5         list.push("helloworld");
 6         list.push(12);
 7         Object val;
 8         while((val=list.pop())!=null){
 9             System.out.println(val.getClass());
10         }
11     }
12 }
13
14 class myList{
15     class Node{
16         Object val=null;
17         Node next=null;
18         Node(Object val,Node next){
19             this.val=val;
20             this.next=next;
21         }
22         Node(){
23             val=null;
24             next=null;
25         }
26         boolean end(){
27             return val==null && next==null;
28         }
29     }
30     private Node top=null;
31     myList(){
32         top=new Node();
33     }
34     //插入新值
35     public void push(Object val){
36         top=new Node(val,top);
37     }
38     //返回头结点的值
39     public Object pop(){
40         Object val=top.val;
41         if(!top.end()){
42             top=top.next;
43         }
44         return val;
45     }
46 }

我们自定义了一个list链表,为了使这个链表有更好的普遍使用性,我们将链表类内部的数据定义为Object类型,这样我们可以插入String类型数据、int类型数据....。但是这个设计“太泛化”了,你甚至可以“混插”,比如上面的执行结果,int类型的数据和String类型的数据插到了一起,显然在后续的操作中可能出现错误,例如你创建了一个自以为全是int类型的链表并对它们求和,但是不小心插入了字符串类型的数字"123",程序编译也能通过,你以为你的程序是对的,结果运行的时候出错了!你深受打击,自挂东南枝,全球计算机行业从此一蹶不振.....

为了防止上面悲剧的发生,我们还是希望错误在编译时期就能暴露出来,以便将错误及时地扼杀与萌芽状态,泛型设计的一项重大功能体现出来了:提前指定我们的链表可以插入什么样的数据类型,并由编译器验证其类型的正确性!这时,我们可以这样设计:

 1 public class gen{
 2     public static void main(String[] args){
 3         //这里指定list2中的数据类型为String类型,也就是将T设置为String类型
 4         myList2<String> list2=new myList2<String>();
 5         list2.push("hello world");
 6         list2.push("hello code");
 7         //list2.push(23);//编译时便会提醒错误
 8         String s;
 9         while((s=list2.pop())!=null){
10             System.out.println(s);
11         }
12     }
13 }
14 class myList2<T>{
15     class Node<U>{
16         U val=null;
17         Node<U> next=null;
18         Node(U val,Node<U> next){
19             this.val=val;
20             this.next=next;
21         }
22         Node(){
23             val=null;
24             next=null;
25         }
26         boolean end(){
27             return val==null && next==null;
28         }
29     }//这里将Node中的值类型设定为U类型,也就是将U传递给T
30     private Node<T> top=null;
31     myList2(){
32         top=new Node<T>();
33     }
34     public void push(T val){
35         top=new Node<T>(val,top);
36     }
37     public T pop(){
38         T val=top.val;
39         if(!top.end()){
40             top=top.next;
41         }
42         return val;
43     }
44 }

当我们不小心执行list2.push(23)时,编译器在编译阶段就会提醒:你错啦!于是我们很愉快地就可以将错误的代码修正过来。

Java容器类可以说是Java代码重用设计的一个重要体现,而Java容器类设计的基础就是泛型,这就是Java泛型的重要之处。

注:以上代码设计部分参考自《Thinking In Java》,感谢Bruce Eckel。

时间: 2024-09-30 13:59:34

java编程之泛型的相关文章

Java编程手册-泛型

1. 泛型的引入(JDK 1.5) 在方法中传入一个参数,这个大家一定非常熟悉,一般的做法就是把参数放在一个圆括号()中并且将他们传递给方法,在泛型中,我们可以跟方法中传递参数一样来传递类型信息,做法就是将类型放在一个尖括号<>中. JDK 1.5中引入了泛型,它允许我们对类型进行参数化,也就是类的设计者在类的定义过程中使用泛型,这样使用者在类的实例化或者方法调用的时候可以动态指定类型,这样在类的内部就可以动态使用这个类型了. 例如,类ArrayList就是被设计者设计成泛型,它带有一个泛型类

Java编程思想-泛型-简单泛型例子

基本类型无法做为类型参数 代码如下: /** * */ package test.thinkinjava.Generics; import java.util.ArrayList; import java.util.List; /** * @author Luo * */ public class Abc<T> { private List<T> list = new ArrayList<T>(); private T element; @Override public

Java编程思想-泛型-泛型方法

代码示例如下: package generics; //: generics/GenericMethods.java public class GenericMethods<A> { // private static A element; public <T> void f(T x) { System.out.println(x.getClass().getName()); } // public static void staticMethod(A x) { // // } p

java编程思想-泛型思维导图

后续加深理解

Java 中的泛型详解-Java编程思想

Java中的泛型参考了C++的模板,Java的界限是Java泛型的局限. 2.简单泛型 促成泛型出现最引人注目的一个原因就是为了创造容器类. 首先看一个只能持有单个对象的类,这个类可以明确指定其持有的对象的类型 class Holder1 { private Circle a; public Holder1(Circle a) { this.a = a; } Circle get() { return a; } } 上面的类的可重用性不怎么样,无法持有其他类型的任何对象,下面通过持有Object

Java中的泛型 --- Java 编程思想

前言 ? 我一直都认为泛型是程序语言设计中一个非常基础,重要的概念,Java 中的泛型到底是怎么样的,为什么会有泛型,泛型怎么发展出来的.通透理解泛型是学好基础里面中非常重要的.于是,我对<Java编程思想>这本书中泛型章节进行了研读.可惜遗憾的是,自己没有太多的经验,有些东西看了几次也是有点懵.只能以后有机会,再进行学习了.但是自己也理解了挺多的.下面就是自己对于泛型的理解与感悟.如有不对,望指出. 概念 由来: Java 一开始设计之初是没有泛型这个特性的,直到jdk 1.5中引入了这个特

Java编程的逻辑 (35) - 泛型 (上) - 基本概念和原理

之前章节中我们多次提到过泛型这个概念,从本节开始,我们就来详细讨论Java中的泛型,虽然泛型的基本思维和概念是比较简单的,但它有一些非常令人费解的语法.细节.以及局限性,内容比较多. 所以我们分为三节,逐步来讨论,本节我们主要来介绍泛型的基本概念和原理,下节我们重点讨论令人费解的通配符,最后一节,我们讨论一些细节和泛型的局限性. 后续章节我们会介绍各种容器类,容器类可以说是日常程序开发中天天用到的,没有容器类,难以想象能开发什么真正有用的程序.而容器类是基于泛型的,不理解泛型,我们就难以深刻理解

Java编程思想学习(十一) 泛型

1.概要 generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. 泛型能在定义类,接口和方法时将类型(类和接口)作为参数.和方法声明时的形式参数很类似,都是为了在不同的输入时重用相同的代码.不同的是形式参数输入的是值而泛型是类型. 2.为什么使用泛型 1.编译时更加强的(Stronger)类型检测java编译器对泛型代码进行强类型检

Java编程思想读书笔记

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4290955.html 第一章对象导论... 1 第二章一切都是对象... 4 第三章操作符... 10 第四章流程控制... 12 第五章初始化与清理... 14 第六章访问权限控制... 15 第七章复用... 23 第八章多态... 2