您的位置:首页 > 编程语言 > Java开发

jdk 1.5新特性——泛型

2013-10-25 21:33 295 查看
----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
15,泛型
15.1泛型

泛型的符号:<泛型标识符,泛型标识符……>

泛型的作用:泛型就是用于接收具体引用数据类型的参数范围。

泛型什么时候用?

当操作的引用数据类型不确定的时候,就可以使用泛型。

使用泛型的好处:

1,将运行时期的问题转到的编译时期。

2,避免了强转的麻烦。

泛型是JDK1.5的新特性,目的是增加安全性。

15.2泛型的擦除和补偿

java源文件中定义的泛型在运行时会被擦除,生成的字节码文件是不带泛型的,称为泛型的擦除。

当在运行.class字节码文件时,会进行泛型的补偿,目的是避免使用者强转的动作。

泛型在集合、类、方法和接口中都有广泛的应用。

15.3泛型类

当类中操作的引用数据类型不确定时,就可以使用泛型类

类上定义泛型的格式:

权限饰符 class类名<泛型标识符1,泛型标识符2…….>{

                    …….CODE;

}

如:集合框架中的ArrayList<E>类,定义了泛型,用来明确集合中要存放什么类型的元素,集合对象创建时需要传入具体的引用数据类型,一旦集合的泛型接收了具体的引用数据类型,那么这个集合中只能存储这一类型的元素,当传入其它类型的元素,编译器就会报错。

ArrayList<String>al=new ArrayList<String>();

//添加元素

al.add("abc1");

al.add("abc2");

al.add("abc2");

al.add("abc1");

al.add("abc4");

al.add("abc5");

for(Iterator<String> it=al.iterator();it.hasNext();){

String s=it.next();//如果不加泛型就需要强转:String s=(String)it.next();

System.out.println(s);

}


 

如上,集合泛型为String类型,那么集合中的元素,就必须是这一类型,否则编译会报错,提高了安全性。

在元素的取出过程中,因为next()取出的元素类型默认是Object类型,如果加了泛型就不需要再进行强转的动作,否则必须要强转,避免了强转的麻烦。

如:以下自定义类中使用的泛型。


public class GenericDemo{

public static void main(String[]args){

Person<String,Integer> person=new Person<String,Integer>("lisi",23);//创建对象时指定具体泛型类型。

Student<String,Integer> student=new student<String,Integer>("zhangsan",23,100);

person.show();

student.show();

}

}

class Person<N,A>{//Person类上定义了泛型

private Aa;

private Nn;

Person(){

}

Person(N n,A a){//构造参数使用了类上的泛型

this.n=n;

this.a=a;

}

public void show(){

System.out.println("姓名:"+this.n+" 年龄:"+this.a);

}

}

class Student<N,A>extends Person<N,A>{//当子类继承父类时,没有传入具体泛型类型时,子类也要定义泛型 

private A a;

private N n;

private int s;

Student(N n, A a, int s) {

this.n=n;

this.a=a;

this.s = s;

}

public void show(){

System.out.println("姓名:"+this.n+"年龄:"+this.a+"分数:"+this.s);

}

}

/*

姓名:lisi 年龄:23

姓名:zhangsan年龄:23分数:100

*/

15.4泛型方法

如果一个类定义了泛型,那么类中的方法可以使用类上的泛型作为参数。当然,如果方法中的参数类型不确定,则可以在方法上重新定义泛型。

注意:泛型在方法上的位置,只能定义在返回值的前面,修饰符的后面

格式:

权限修饰符 成员修饰符 <泛型标识符1,泛型标识符2……>返回值类型 方法名称(泛型标识符1 变量,泛型标识符2
4000
 变量,.....,其它参数){ 


            方法体;  

   
}


如:

class Generic<T>{//定义了泛型的类

private T  t;

Generic(T t){

this.t=t;

}

public void show_1(T t){//此方法的参数直接使用了类上的泛型,类上传入什么类型,这个方法的参数就是什么类型。

}

public <A> void show_2(A a){//此方法的参数,没有使用类上的泛型,而是使用了其他的泛型,则需要在方法上定义泛型。

}

public static <B> void show_3(B b){//注意,对于静态方法的参数是不能直接访问类上的泛型的,如果要使用泛型则需要在方法上重新定义泛型。

}

}

注意:对于静态方法是不能直接访问类上的泛型的,因为类上的泛型是依赖对象的,而静态方法不需要对象去调用,所以,静态方法不能直接使用类上定义的泛型。如果静态方法要使用泛型,则需要在静态方法上定义泛型。
 

15.5泛型接口 

格式:

interface接口名<泛型标识符1,泛型标识符2……>{

}

如:

interface Inter<T>{

void show(T t);

}


 

注意:如果一个类实现了带有泛型的接口时,如果没有明确具体泛型类型,则这个类也必须要定义泛型。

如:

interface Inter<T>{

void show(T t);

}class Generic <T> implements Inter<T>{//没有明确接口上泛型的具体类型,类也要定义泛型

@Override

public void show(T t) {

}

}

如果在实现一个泛型接口时,明确具体的泛型类型,就把具体的类型传给接口上的泛型。这样类上就需要再定义泛型。

如:


interface Inter<T>{

void show(T t);

}class Genericimplements Inter<String>{//明确接口上泛型的具体类型,直接传入具体类型到接口上的泛型。

@Override

publicvoid show(String t) {

}

}

 

15.6泛型通配符

泛型通配符:?,表示未知的泛型类型。

用字母作为泛型标识符和泛型通配符?有什么区别呢?

用字母作为泛型的标识符,可以对其进行操作。

如:泛型方中,作为方法的返回值 ,作为一个类型,声明一个变量,传给类中的构造函数等等。

public <T> T show(T t){

//方法体;
}


 

而泛型通配符,代表未知的任意类型,是不能够直接操作的,通配符多用于对泛型的限定。

泛型的限定分为:上限和下限

上限:<? extends具体引用类型A> ,表示可以接收A类型及其A的子类类型。

下限:<? super具体引用类型B>,表示可以收的B类型及B的父类类型。

上限和下限同样可以用于对字母泛型标识符的限定。

 
如:上限

public class GenericDemo{

public static void main(String[]args){

new Generic().show("abc"); //传入字符串类型,可以打印

new Generic().show(123);//传入其它类型,就报错。

}

}

class Generic{

public <T extends String> void show(T t){//show(T t)方法的参数类型T必须是,String及其子类,不能传入其它类型参数。

System.out.println(t);

}

}


 

如:下限

public class GenericDemo<T>{

public static void main(String[]args){

Person<String> p=new Person<String>("LISI",23);

new Generic().show(p);

}

}

class Generic{

public void show(Person<?super String> g){//此方法,用来接收Person类型 参数,对Person的泛型进行了下限。

System.out.println(g.getT()+":"+g.getAge());

}

}

class Person<T>{

private T t;

private int age;

public Person(T t,int age) {

super();

this.t = t;

this.age = age;

}

public T getT() {

return t;

}

public int getAge() {

return age;

}
}

15.7泛型在集合中的应用
泛型在集合中都有所应用,集合中使用泛型可以避免强转。集合定义泛型,在创建集合对象时,可以明确具体的泛型类型,元素在取出时,就不需再进行强转。

如:ArrayList集合

public class GenericDemo<T>{

public static void main(String[]args){

ArrayList al=newArrayList();//创建集合对象

al.add("abc1");//add(Objectobj);方法中接收的参数都会被提升为Object类型。

al.add("abc2");

al.add("abc3");

al.add("abc4");

Iterator it=al.iterator();

while(it.hasNext()){

String s=(String)it.next();//添加的元素被提升为Object类型,取出时也是Object类型,要强转。

System.out.println(s);

}

}

}

因为没有加泛型,所以在元素取出时必须要强转。

把泛型加入集合:

:

import java.util.ArrayList;

import java.util.Iterator;

public class GenericDemo<T>{

public static void main(String[]args){

ArrayList<String> al=new ArrayList<String>();//创建集合对象,并明确泛型类型

al.add("abc1");//add(Objectobj);方法中接收的参数都会被提升为Object类型。

al.add("abc2");

al.add("abc3");

al.add("abc4");

Iterator <String>it=al.iterator();//元素的取出明确泛型

while(it.hasNext()){

String s=it.next();//添加的元素被是String,取出时也是String类型,不需要强转。

System.out.println(s);

}

}

}


 

可见,泛型的应用,不仅可以对集合中元素的添加进行类型的限定,增强安全性,避免出错,而且避免了元素在取出中强转的麻烦。

----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: