为什么要用泛型?
1)为了避免类型转换异常
2)使用泛型类,泛型接口,可以复用代码,降低耦合。
类、接口和方法代码可以应用于非常广泛的类型,代码与它们能够操作的数据类型不再绑定在一起,同一套代码,可以用于多种数据类型,这样,不仅可以复用代码,降低耦合,同时,还可以提高代码的可读性和安全性。
—————————————————————————————————————————>
首先看一下这段代码:
public class GenericTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("qqyumidi");
list.add("corn");
list.add(100);
for (int i = 0; i < list.size(); i++) {
String name = (String) list.get(i); // 1
System.out.println("name:" + name);
}
}
}
定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。
在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”(类转化异常)异常。因此,导致此类错误编码过程中不易发现。
在如上的编码过程中,我们发现主要存在两个问题:1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,该对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。
2. //1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常—————————————————————————————————————————>
怎么理解泛型?
"泛型"字面意思就是广泛的类型
容器类是基于泛型的,不理解泛型,我们就难以深刻理解容器类(泛型类和泛型接口都是容器)。
泛型类其实是容器类,用来容纳并管理多项数据类型的。
public class Student<T> {
//定义一个泛型类,其中泛型类型为T,在类中定义一个泛型类型的成员变量。
private T activity;
}
T是泛型通配符,,T表示类型参数,泛型就是类型参数化(类型不固定,以参数的形式传递进来),处理的数据类型不是固定的,而是可以作为参数传入。—————————————————————————————————————————>
1)如何定义泛型类?
2)如何定义泛型接口?
3)有界泛型与通配符
4)泛型类型参数到底是什么呢?
泛型: 主要用于限定约束数据类型的.避免强制类型转化
泛型: 泛型接口、泛型类和泛型方法 ; 泛型在集合中的使用
泛型类:把泛型定义在类上;
格式public class Student<T>{ }
注意:泛型类型必须是引用类型。 泛型类用于限定谁的数据类型/T表示形式参数
泛型方法:把泛型定义在方法上
格式: public <泛型类型>返回类型 方法名(泛型类型)
/**
* Created on 2016/8/5.
* Author:crs
* Description:泛型方法的使用 把泛型定义在方法的参数上
*/
public class FanXing {
public <QQ> void show(QQ qq) {
System.out.print(qq);
}
}
泛型接口: 把泛型定义在接口上
格式: public interface 接口名<泛型类型>{ }
核心问题是: 泛型类型什么时候确定?泛型类中,创建对象的时候确性泛型的类型。
private List<Vehicle> list = null;
声明集合的时候,明确指定了集合中存储的数据类型,不能存储其他类型的数据,否则编译不通过。
—————————————————————————————————————————>
关键是泛型如何使用?一、定义一个泛型接口
/**
* Created on 2016/8/5.
* Author:crs
* Description:定义泛型接口,泛型接口如何使用?
*/
public interface FanInterface<TT> {
void show(TT tt);
}
二、定义一个类来实现带有泛型的接口:1、在实现接口的时候,明确了泛型的数据类型
/**
* Created on 2016/8/5.
* Author:crs
* Description:定义泛型接口,泛型接口如何使用?
*/
public class FanInterfaceImplements implements FanInterface<String> {
@Override
public void show(String s) {
System.out.print(s);
}
}
2、在实现接口的时候不明确泛型的实现类型 //在创建对象的时候,明确泛型的数据类型
/**
* Created on 2016/8/5.
* Author:crs
* Description:定义泛型接口,泛型接口如何使用?
*/
public class FanInterfaceImplements<TT> implements FanInterface<TT> {
@Override
public void show(TT tt) {
System.out.print(tt);
}
}
//在创建对象的时候,明确泛型的数据类型
FanInterfaceImplements<String> fanInterfaceImplements = new FanInterfaceImplements<>();
fanInterfaceImplements.show("一世红尘");
//泛型应用最广泛的地方是把泛型定义在接口上
—————————————————————————————————————————>
泛型通配符<?>
在创建集合的时候,不知道集合里面要放什么类型的元素?
<?> 任意类型,如果没有明确,那就是Object类型以及任意的Java类
? extends E 向下限定,通配符?代表的只能是E类及其子类
向下限定、泛型的类型
—————————————————————————————————————————>
1)凡是出现TT的地方均表示接受相同的来自外部的类型实参。
2)在泛型接口、泛型类和泛型方法的定义过程中,我们常见的如T、E、K、V等形式的参数常用于表示泛型形参,由于接收来自外部使用时候传入的类型实参。
3)通配符一般是使用 ? 代替具体的类型实参。注意了,此处是类型实参,而不是类型形参!
4)可以使用泛型去简化开发,且能很好的保证代码质量。
—————————————————————————————————————————>
项目中泛型的使用:
public interface ListItem extends Serializable{
<T extends ListItem> T newObject();
void praseFromJson(JsonUtil jsonUtil);
}
这是一个抽象方法,它的返回值类型是泛型类型,必须是ListItem类型或者其子类类型,
@Override
public Address newObject() {
return new Address();
}
这种做法的好处是:直接可以获取一个当前类的对象。由于项目中存在大量的数据模型...
—————————————————————————————————————————>
public class Teacher<K,V> {
//定义泛型类的时候,指定两个泛型类型。
//定义泛型类型的成员变量
//K,V:表示泛型通配符
private K k;
}
在定义一个泛型类的时候,在 “<>”之间定义形式类型参数,例如:“class TestGen<K,V>”,其中“K” , “V”不代表值,而是表示类型。
泛型类型必须是引用类型。
实例化泛型对象的时候,一定要在类名后面指定类型参数的值(类型)
//实例化泛型类的时候,一定要指明泛型类型。
//创建泛型对象
Student<String> s = new Student<>();
//定义一个接口对象
IView<String> iView = null;
iView = new IViewImpl("陈如水");
————————————————————————————————>
泛型方法:把泛型定义在方法上
格式: public <泛型类型>返回类型 方法名(泛型类型)
public class FanXing {
public <QQ> void show(QQ qq) {
System.out.print(qq);
}
}
二、定义一个类来实现带有泛型的接口:
1、在实现接口的时候,明确了泛型的数据类型
泛型应用最广泛的地方是把泛型定义在接口上
public interface IView<T> {
//☆定义一个泛型类型的接口,其中抽象方法的返回值为泛型类型
//定义抽象方法,抽象方法的返回值就是泛型类型
T getType();
}
public class IViewImpl<T> implements IView<T> {
//定义泛型接口的子类
//泛型接口的实现方式:在子类的定义上也要声明泛型类型。
private T var;
//通过构造函数为泛型类型设置值
public IViewImpl(T var) {
this.var = var;
}
@Override
public T getType() {
return this.var;
}
}
定义一个泛型类,其中包含两个泛型类型。
定义一个泛型类型的成员变量。
在泛型接口、泛型类和泛型方法的定义过程中,我们常见的如T、E、K、V等形式的参数常用于表示泛型形参,由于接收来自外部使用时候传入的类型实参。
泛型接口能够方便的应用于工厂模式,能够创建各种不同类型的对象。
有界泛型:
public class Info<T extends Number> {
//泛型只能是数字类型
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}