泛型
泛型:在JDK1.4之前,容器什么类型的对象都可以存储,但是在取出时
需要用到对象的特有内容时,需要向下转型,
但是对象的类型不一致,导致了向下转型发生了ClassCastException
为了避免这个问题,只能主观上控制,往集合中存储的对象类型保持一致
JDK1.5以后,在定义集合时,就直接明确了集合中存储元素的具体类型,
这样,编译器在编译时,就可以对集合中存储的对象类型进行检查,
一旦发现类型不匹配,就编译失败,这个技术就是泛型。
|
|好处:1.将运行时期的问题转移到了编译时期。
| 2.避免了向下转型的麻烦。
|*总结:泛型就是应用在编译时期的一项安全机制。
泛型的擦除:编译器通过泛型对元素类型进行检查,只要检查通过,
就会生成class文件,但在class文件中,泛型的标识被去掉了
泛型类
背景前提:
当创建一个工具类的时候,想要对对象进行操作,但是对象类型不明确,
为了能使该类可以操作所有对象,可以使用Object类型来完成。
But弊端:
当出现转型的时候,如果类型输入的不一样,该错误无法在编译时期
被发现,所以就会出现类型转换异常,为了解决这种问题,所以可以
对外提供参数,由使用者通过传递参数的形式完成类型的确定。
例:1
2
3
4
5
6
7
8
9
10
11
12class Tool<lei>
{
private lei obj;
public lei getObj()
{
return obj;
}
public void setObj(lei obj)
{
this.obj = obj;
}
}
使用方式如下:1
2
3
4
5
6main{
Tool<student> T = new Tool<student>();
T.setObj(new Student());
Student stu = T.getObj();
Syso(stu);
}
优点:在使用时就明确了要输入什么类型,这样子如果之后输入错误就会被编译器报错,
并且这样使用不需要向下转型!
注意:静态方法无法访问类上定义的泛型的。
如果静态方法需要定义泛型,泛型只能定义在方法上。
泛型方法
背景前提:
class Demo
{
public void show(W w)
{
System.out.println(“show:”+w);
}
public void print(W w)
{
System.out.println(“print:”+w);
}
}
当我在使用该类时
Demo<String> d = new Demo<String>();
d.show("a");
d.print(6);
以上就会被报错,因为我已经声明了W类是String,
如果我想要打印出6,我就必须新建一个W是整型类的Demo类,
为了解决这个问题,我们可以使用泛型方法。
public <Q> void print(Q w)
{
System.out.println("print:"+w);
}
在方法类型之前写一个泛型,这样子就可以解决以上问题。
泛型接口
1 | interface Inter<T>// |
泛型的限定
<? extends E> -上限:接收E类型或者E的子类型
<? super E> -下限:接收E类型或者E的父类型
上限:一般往容器中存储元素时,如果集合定义了E类型,并且需要可以接收E类型的子类型
这时就需要将泛型从
下限:一般从容器中取出元素时,可以用E类型接收,也可以用E的父类型接收。
所以可以用<E>,也可以用<? super E>
通配符 ?
//在不明确具体类型的情况下,可以使用通配符表示
例如:我想要实现一个输出函数,专门打印出集合
List
Set
printcoll(list);
printcoll(set);
private static void printcoll(Collection<?> coll)
{
for(Iterator<?> it = coll.iterator(); it,hasNext();)
{
Object obj = it.next();
System.out.println(obj);
//迭代器输出功能
}
}