Java基础18--泛型--工具类--JDK1.5新特性(一)

2014-11-24 03:26:40 · 作者: · 浏览: 5

18-1,泛型-概述

1,泛型是JDK1.5出现的新技术,新技术的出现是为了解决问题。

2,泛型可以用于明确一个集合中存储什么类型的元素

ArrayList
  
    al = new ArrayList
   
    (); al.add("abc");//正确 //al.add(3);//编译直接报错 //在迭代器上加上泛型,下面取出来的时候就不用强转了 Iterator
    
      it = al.iterator(); while(it.hasNext()) { //在这里不用强转了,因为从it中取出的肯定是String String str = it.next(); System.out.println(str); } 
    
   
  

3,好处

(1)将运行时间的问题ClassCastException转到了编译时期。

(2)避免了强制转换的麻烦。

4,泛型什么时候用呢?

当操作的引用数据类型不确定的时候,就用泛型,将要操作的引用数据类型写在<>中即可。其实<>就是一个用于接收具体引用数据类型的参数范围。

在程序中,只要用到了带有<>的类型或者接口,就要明确传入的具体引用数据类型。

也可以同时接受多个数据类型:

class Tool
  
   
Tool
   
     t = new Tool
    
     (); 
    
   
  

18-2,泛型-擦除&补偿

1,泛型解决了编译时期的安全问题,是给编译器使用的技术。

2,运行时,会将泛型去掉,生成的class文件中是不带有泛型的,这个称为泛型的擦除。

为什么要擦除呢?

因为为了兼容运行时的类加载器,因为泛型是JDK1.5的新特性,如果class文件中加上泛型的话,类加载器会不认识,若想要类加载器认识泛型,类加载器也要升级,为了避免升级类加载器的麻烦,泛型将交由编译器处理,编译通过后就会把他删去,使之前的类加载器也能运行它。

3,泛型的补偿:

擦除后,如果对元素进行取出的赋值动作,如:String str =it.next();是否需要加上强转呢?答案是不用了,首先,加上泛型且编译通过就能保证集合中的数据是指定的类型了,所以认为不会出现规定类型以外的元素。其实,在运行时,是自动添加了一步动作,通过用getClass()方法获取元素的类型再对其进行一次转换动作,就不用使用者在强制转换了。

18-3,泛型-在集合中的应用

1,以TreeSet为例,TreeSet具备比较功能,但存入的类型必须实现Comparable接口并实现了里面的compareTo方法才可以;或者定义一个比较器,实现Comparator接口并实现里面的compare方法也可以。定义TreeSet时,如果不加泛型Eclipse等IDE会有黄色波浪线提示,加上泛型,黄色波浪线即可消失。

2,上一章提到的Person类实现Comparable接口时Comparable接口也需要指定泛型,如:Comparable ,指定后,覆写的compareTo方法中的参数就可以不写Object了,直接写Person就可以,方法体中的代码也不用强制向下转型了。Comparator接口也要加上泛型,它里面的compare方法的两个参数也直接接受Person类型就可以了。例如:

class Person implements Comparable
  
    {
	...code...
	public int compareTo(Person p) {
		//Person p = (Person)p;//强转可以省去,因为定义了泛型
		int temp = this.age = p.age;
		return temp == 0   this.name.compareTo(p.name) : temp;
	}
	...code...
}

  

18-4,泛型类

1,以前定义工具类的时候这么定义:

public class Tool {
	private Object object;
	public Object getObject() {
		return object;
	}
	public void setObject(Object object) {
		this.object = object;
	}
}

别的类用这个工具类的时候,可以这样做:

Tool tool = new Tool();
/*
这里因为没有Worker这个类,所以是错误的。
Worker为传入的错误值,但编译不会报错,因为Tool中接收的是Object类型,
下面的语句必须做强转才能匹配类型,因为把Worker向上提升为了Object。
*/
tool.setObject(new Worker());
Student stu = (Student)tool.getObject();

工具类是针对所有类型的,而任何一个类都是Object的子类,所以根据多态的特性,通过将参数定义成Object我们就可以使这个方法接收所有类型的参数,在没有泛型的时候我们就只能这么做。

在JDK1.5之后,使用泛型来接收类中要操作的引用数据类型,这就是泛型类。

泛型类什么时候用呢?

当类中的操作的引用数据类型不确定的时候,就是用泛型来表示。

例如:

public class Tool {
	private  Q q;
	public Q getObect() {
		return q;
	}
	public void setObject(Q object) {
		this.q = object;
	}
}

有泛型后,在别的类用到工具类的时候,可以这么做:

Tool
  
    tool = new Tool
   
    (); //tool.setObject(new Worker());//编译报错,因为有了泛型指定的Student,所以别的不能进入集合。 tool.setObject(new Student()); Student stu = tool.getObject(); 
   
  

18-5,泛型方法

1,在18-4中有泛型的Tool类中加入泛型方法,Tool

public class Tool {
	private  Q q;
	public Q getObect() {
		return q;
	}
	public void setObject(Q object) {
		this.q = object;
	}
	/*
	如果方法不加泛型会报错,因为Tool明确只能接收QQ类型,
	所以不能操作W类型,要想让其中一个方法操作W类型,
	必须在返回值类型前加上泛型
   
    。 */ public 
    
      void show(W str) { System.out.println("show" + str.toString()); } /* 另外,print接收的是字符串,那么能不能打印字符串的长度呢? 答案是不能的,因为QQ str = "abc"(这里假设传入abc),将"abc"提升为QQ类型, QQ类型不知道String类型中的特有方法length(),所以不能打印。但由于QQ也 继承自Object,所以可以使用Object中的方法。 */ public void print(QQ str) { System.out.println("print" + str); } } 
    
   

调用的时候:

Tool
  
    tool = new Tool
   
    (); tool.show(new Integer(4));//因为show加了泛型,所以可以接受Tool定义的String以外的类型。 tool.show("abc");//符合To