黑马程序员学习笔记之五(java中的泛型)
2012-03-07 14:38
681 查看
---------------------- android培训、java培训、期待与您交流! ----------------------
泛型的概念
泛型(Generic type 或者 generics)是对java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。
可以在集合框架(Collection framework)中看到泛型的动机。例如,Map 类允许您向一个 Map 添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如 String)的对象。
因为 Map.get() 被定义为返回 Object,所以一般必须将 Map.get() 的结果强制类型转换为期望的类型,如下面的代码所示:
Map m = new HashMap();
m.put("key", "blarg");
String s = (String) m.get("key");
要让程序通过编译,必须将 get() 的结果强制类型转换为 String,并且希望结果真的是一个 String。但是有可能某人已经在该映射中保存了不是 String 的东西,这样的话,上面的代码将会抛出 ClassCastException。
理想情况下,您可能会得出这样一个观点,即 m 是一个 Map,它将 String 键映射到 String 值。这可以让您消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。这就是泛型所做的工作。
泛型的好处
Java语言中引入泛型是一个较大的功能增强。不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了。这带来了很多好处:
类型安全。泛型的主要目标是提高Java程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。
示例:
泛型类
泛型类最常见的用例是容器类(比如集合框架)。编写一个类,用来接收或者返回一个Worker或者Student类型的对象,我们采用两种方式来实现,一种不使用泛型,一种使用泛型,进行对比。
泛型方法
通过在类的定义中添加一个形式类型参数列表,可以将类泛型化。方法也可以被泛型化,不管它们定义在其中的类是不是泛型化的。
泛型类在多个方法签名间实施类型约束。在 List<V> 中,类型参数 V 出现在 get()、add()、contains() 等方法的签名中。当创建一个 Map<K, V> 类型的变量时,您就在方法之间宣称一个类型约束。您传递给 add() 的值将与 get() 返回的值的类型相同。
类似地,之所以声明泛型方法,一般是因为您想要在该方法的多个参数之间宣称一个类型约束。如下:
特殊之处:
静态方法不可以访问类上定义的泛型。
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
泛型接口
泛型定义在接口上面,通常在数据库的CRUD操作中比较常见,代码如下:
泛型通配符与泛型限定
在前面的泛型的例子中,类型参数 T是无约束的或无限制的 类型。有时在还没有完全指定类型参数时,需要对类型参数指定附加的约束。
上例中的Comp比较器既可以接受Person对象,也可以接受Student对象。
---------------------- android培训、java培训、期待与您交流! ----------------------
泛型的概念
泛型(Generic type 或者 generics)是对java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。
可以在集合框架(Collection framework)中看到泛型的动机。例如,Map 类允许您向一个 Map 添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如 String)的对象。
因为 Map.get() 被定义为返回 Object,所以一般必须将 Map.get() 的结果强制类型转换为期望的类型,如下面的代码所示:
Map m = new HashMap();
m.put("key", "blarg");
String s = (String) m.get("key");
要让程序通过编译,必须将 get() 的结果强制类型转换为 String,并且希望结果真的是一个 String。但是有可能某人已经在该映射中保存了不是 String 的东西,这样的话,上面的代码将会抛出 ClassCastException。
理想情况下,您可能会得出这样一个观点,即 m 是一个 Map,它将 String 键映射到 String 值。这可以让您消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。这就是泛型所做的工作。
泛型的好处
Java语言中引入泛型是一个较大的功能增强。不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了。这带来了很多好处:
类型安全。泛型的主要目标是提高Java程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。
示例:
import java.util.*; class GenericDemo2 { public static void main(String[] args) { TreeSet<String> ts = new TreeSet<String>(new LenComparator()); ts.add("abcd"); ts.add("cc"); ts.add("cba"); ts.add("aaa"); ts.add("z"); ts.add("hahaha"); Iterator<String> it = ts.iterator(); while(it.hasNext()) { String s = it.next(); System.out.println(s); } } } class LenComparator implements Comparator<String> { public int compare(String o1,String o2) { int num = new Integer(o2.length()).compareTo(new Integer(o1.length())); if(num==0) return o2.compareTo(o1); return num; } }
泛型类
泛型类最常见的用例是容器类(比如集合框架)。编写一个类,用来接收或者返回一个Worker或者Student类型的对象,我们采用两种方式来实现,一种不使用泛型,一种使用泛型,进行对比。
/* class Tool { private Worker w; public void setWorker(Worker w) { this.w = w; } public Worker getWorker() { return w; } } */ class Worker { } class Student { } //泛型前做法。 class Tool { private Object obj; public void setObject(Object obj) { this.obj = obj; } public Object getObject() { return obj; } } //泛型类。 /* 什么时候定义泛型类? 当类中要操作的引用数据类型不确定的时候, 早期定义Object来完成扩展。 现在定义泛型来完成扩展。 */ class Utils<T> { private T t; public void setObject(T t)
{ this.t = t; } public T getObject() { return t; } } class GenericDemo3 { public static void main(String[] args) { Utils<Worker> u = new Utils<Worker>(); u.setObject(new Student()); Worker w = u.getObject();; /* Tool t = new Tool(); t.setObject(new Student()); Worker w = (Worker)t.getObject(); */ } }
泛型方法
通过在类的定义中添加一个形式类型参数列表,可以将类泛型化。方法也可以被泛型化,不管它们定义在其中的类是不是泛型化的。
泛型类在多个方法签名间实施类型约束。在 List<V> 中,类型参数 V 出现在 get()、add()、contains() 等方法的签名中。当创建一个 Map<K, V> 类型的变量时,您就在方法之间宣称一个类型约束。您传递给 add() 的值将与 get() 返回的值的类型相同。
类似地,之所以声明泛型方法,一般是因为您想要在该方法的多个参数之间宣称一个类型约束。如下:
//泛型类定义的泛型,在整个类中有效。如果被方法使用, //那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。 // //为了让不同方法可以操作不同类型,而且类型还不确定。 //那么可以将泛型定义在方法上。 /* 特殊之处: 静态方法不可以访问类上定义的泛型。 如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。 */ class Demo<T> { public void show(T t) { System.out.println("show:"+t); } public <Q> void print(Q q) { System.out.println("print:"+q); } public static <W> void method(W t) { System.out.println("method:"+t); } } class GenericDemo4 { public static void main(String[] args) { Demo <String> d = new Demo<String>(); d.show("haha"); //d.show(4); // show方法接受的参数类型已经声明为String类型了,不能接受Integer d.print(5); d.print("hehe"); Demo.method("hahahahha"); /* Demo d = new Demo(); d.show("haha"); d.show(new Integer(4)); d.print("heihei"); */ /* Demo<Integer> d = new Demo<Integer>(); d.show(new Integer(4)); d.print("hah"); Demo<String> d1 = new Demo<String>(); d1.print("haha"); d1.show(5); */ } }
特殊之处:
静态方法不可以访问类上定义的泛型。
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
泛型接口
泛型定义在接口上面,通常在数据库的CRUD操作中比较常见,代码如下:
// 泛型定义在接口上 interface Dao<T> { void save(T t); T find(id); void delet(T t); void update(T t); } class JDBCDao<T> implements Dao<T> // 使用JDBC实现CRUD操作 { public void save(T t) { // ... } public T find(T t) { // ... } public void find(T t) { // ... } public void update(T t) { // ... } } class HibernateDao implements Dao<T> // 使用Hibernate实现CRUD操作 { public void save(T t) { // ... } public T find(T t) { // ... } public void find(T t) { // ... } public void update(T t) { // ... } } class GenericDemo5 { public static void main(String[] args) { Student s = new Student(); // 使用JDBC进行CRUD操作 Dao dao<Student> = new JDBCDao<Student>(); dao.add(s) // 使用JDBC进行CRUD操作 Dao dao<Student> = new HibernateDao<Student>(); dao.delete(s); } }
泛型通配符与泛型限定
在前面的泛型的例子中,类型参数 T是无约束的或无限制的 类型。有时在还没有完全指定类型参数时,需要对类型参数指定附加的约束。
import java.util.*; /* ? 通配符。也可以理解为占位符。 泛型的限定; ? extends E: 可以接收E类型或者E的子类型。上限。 ? super E: 可以接收E类型或者E的父类型。下限 */ class GenericDemo6 { public static void main(String[] args) { /* ArrayList<String> al = new ArrayList<String>(); al.add("abc1"); al.add("abc2"); al.add("abc3"); ArrayList<Integer> al1 = new ArrayList<Integer>(); al1.add(4); al1.add(7); al1.add(1); printColl(al); // 此处调用的是 printColl(ArrayList<?> al)方法,ArrayList中可以存放任何类型的对象 printColl(al1); */ ArrayList<Person> al = new ArrayList<Person>(); al.add(new Person("abc1")); al.add(new Person("abc2")); al.add(new Person("abc3")); //printColl(al); ArrayList<Student> al1 = new ArrayList<Student>(); al1.add(new Student("abc--1")); al1.add(new Student("abc--2")); al1.add(new Student("abc--3")); printColl(al1); //ArrayList<? extends Person> al = new ArrayList<Student>();error } public static void printColl(Collection<? extends Person> al) // Collection 中可以是Person类及其子类对象 { Iterator<? extends Person> it = al.iterator(); while(it.hasNext()) { System.out.println(it.next().getName()); } } /* // ? 通配符,表示泛型中的参数可以是任何类型 public static void printColl(ArrayList<?> al)//ArrayList al = new ArrayList<Integer>();error { Iterator<?> it = al.iterator(); while(it.hasNext()) { System.out.println(it.next().toString()); } } */ } // class Person { private String name; Person(String name) { this.name = name; } public String getName() { return name; } } class Student extends Person { Student(String name) { super(name); } } class Comp implements Comparator<Person> //<? super E> { public int compare(Person s1,Person s2) { //Person s1 = new Student("abc1"); return s1.getName().compareTo(s2.getName()); } } class GenericDemo7 { public static void main(String[] args) { TreeSet<Student> ts = new TreeSet<Student>(new Comp()); ts.add(new Student("abc1")); ts.add(new Student("abc2")); ts.add(new Student("abc3")); } }
上例中的Comp比较器既可以接受Person对象,也可以接受Student对象。
---------------------- android培训、java培训、期待与您交流! ----------------------
相关文章推荐
- 黑马程序员—15—java基础:有关泛型的学习笔记和学习心得体会
- 黑马程序员—Java基础加强学习笔记之泛型
- 黑马程序员----Java集合框架学习笔记2 Map-工具类-泛型
- 黑马程序员---java学习笔记之泛型
- 黑马程序员--Java基础学习笔记【集合-List、泛型】
- 黑马程序员________Java集合Map及其JDK1.5新特性泛型机制的学习笔记
- 黑马程序员-java学习笔记-泛型
- 黑马程序员——java 泛型学习笔记
- 黑马程序员_java基础学习笔记11_反射
- 【黑马程序员】Java学习笔记--IO流
- java 动态代理 黑马程序员学习笔记(8)
- 黑马程序员 java学习笔记——IO流3
- 黑马程序员_毕向东_Java基础视频教程学习笔记(十)
- 黑马程序员---Java基础学习笔记IO
- 黑马程序员---Java 学习笔记
- 黑马程序员-java学习笔记-高新技术
- 黑马程序员----Java集合框架学习笔记1-List 与Set
- Java学习笔记003——继承、抽象类、类相等测试、泛型数组列表、可变参数方法
- 【黑马程序员】 学习笔记 - Java数组及排序算法
- 黑马程序员——java基础学习笔记——第四天