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

Java ---学习笔记(泛型)

2017-09-15 22:25 239 查看
一、为什么需要泛型
  在 Java SE 5.0 以前操作集合有许多缺点,一是从集合取出对象时,需要执行类型转换操作,我们在前面讲过,集合中存储都是以 Object 对象进行存储的,这无疑让我们的操作变得麻烦。二是由于没有类型检查,可以向集合添加任意对象,不便于我们对集合的管理,有时候甚至会导致严重的错误。

  而泛型就帮我们提供了类型参数,让我们提取规定好集合对象的类型。在前面的实验中我们已经接触过泛型了。

例如:

//注意:引入了泛型以后,List<Object>, List<String>是两种不同的类型

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

/*
*下面的代码是非法的
*List<Object> lo = files;
*/


我们在集合的类型后面添加上一对
<>
,尖括号中填上我们需要规范的集合里对象的类型,我们可以指定一个或多个类型参数的名字,同时也可以对类型参数的取值范围进行限定,多个类型参数之间用
,
分隔。这样编辑器便会在编译时帮我们检查出不符合规范的元素添加。

  下面我们来看一看定义泛型的规则吧,同学们先有个印象,我们在后面定义泛型类和方法,以及使用泛型的时候,大家在结合我们这里讲解的规则,去深入地理解泛型吧!

泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。

同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。

泛型的类型参数可以有多个。

泛型的参数类型可以使用 extends 语句,例如 <T extends superclass>。习惯上称为“有界类型”。

泛型的参数类型还可以是通配符类型。例如 Class<?> classType = Class.forName("java.lang.String");

二、定义带类型参数的类

接下来我们来定义一个泛型类,它有一个成员,成员的类型待定。

/*
使用T代表类型,无论何时都没有比这更具体的类型来区分它。如果有多个类型参数,我们可能使用字母表中T的临近的字母,比如S。
*/
class Test<T> {
private T ob;

/*
定义泛型成员变量,定义完类型参数后,可以在定义位置之后的方法的任意地方使用类型参数,就像使用普通的类型一样。
注意,父类定义的类型参数不能被子类继承。
*/

//构造函数
public Test(T ob) {
this.ob = ob;
}

//getter 方法
public T getOb() {
return ob;
}

//setter 方法
public void setOb(T ob) {
this.ob = ob;
}

public void showType() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}

public class TestDemo {
public static void main(String[] args) {
// 定义泛型类 Test 的一个Integer版本
Test<Integer> intOb = new Test<Integer>(88);
intOb.showType();
int i = intOb.getOb();
System.out.println("value= " + i);
System.out.println("----------------------------------");
// 定义泛型类Test的一个String版本
Test<String> strOb = new Test<String>("Hello Gen!");
strOb.showType();
String s = strOb.getOb();
System.out.println("value= " + s);
}
}


三、使用泛型方法

我们先来看一看代码:

1、定义一个 Animal 类

public class Animal {
public Animal(){
System.out.println("我是动物");
}
}


2、定义一个 Dog 类

public class Dog extends Animal {
public Dog(){
System.out.println("我是狗");
}
}


3、定义一个 Test 类

public class Test {

/*
注意:定义带类型参数的方法,骑主要目的是为了表达多个参数以及返回值之间的关系。例如本例子中T和S的继承关系, 返回值的类型和第一个类型参数的值相同。
*/

public<T, S extends T> T testDemo(T t, S s){
System.out.println("我是 T 类型,我的类型是" + s.getClass().getName());
System.out.println("我是 S 类型,我的类型是" + t.getClass().getName());
return t;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Test test = new Test();
Dog d = new Dog();
Animal a0 = new Animal();
Animal a1  = test.testDemo(a0, d);
System.out.println("我是整数 a,我的类型是" + a1.getClass().getName());
}

}


4、上面的例子中我们对类型参数赋予了具体的类型,当然我们有时候也无法确定类型参数的类型,这个时候我们便可以使用通配符。如果仅仅是想实现多态,请优先使用通配符解决。

例如:

import java.util.List;

public class Test {

public void testDemo(List<?> s){
for(Object obj:s){
System.out.println("我的类型是" + obj.getClass().getName());
}
}

public static void main(String[] args) {
// TODO Auto-generated method stub
Test test = new Test();
Dog a0 = new Dog();
Animal a1 = new Animal();
List<Animal> s = null;
s.add(a0);
s.add(a1);
test.testDemo(s);
}

}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: