泛型
- 用于解决安全问题,可以看做一个安全机制
三种使用方式,分别为:泛型类、泛型接口、泛型方法
先举一个例子:
ArrayList<String> al = new ArrayList<String>();
//这句话的意思就是,定义了一个ArrayList容器,容器中的元素是String类型
那么它解决了什么问题呢?
再举一个例子:
import java.util.*;
class GenericsDemo{
public static void main(String[] args){
ArrayList<String> a1 = new ArrayList<String>();
//ArrayList a1 = new ArrayList();
a1.add("123");
a1.add("312");
a1.add(123);
for(Iterator<String> it = a1.iterator();it.hasNext();){
String s = it.next();
System.out.println(s);
}
}
}
我们可以看到在编译的时候控制台就会报异常,但是用第二句不用泛型呢,你会看到可以编译通过,控制台之后给你一个不安全操作的提示,但是当你运行的时候一样会报ClassCastException
如果你说你就是要存入不同数据类型的元素,这当然也是可以,但是没啥用,因为元素间不能比较,就只能存进去,然后打印出来。建议用StringBuffer或StringBuilder。
- 所以泛型首先能够让我们更快的发现解决问题,让运行问题减少,安全。
- 其次,它避免了强制转换的麻烦。
import java.util.*;
class GenericsDemo2{
public static void main(String[] args){
TreeSet<String> a1 = new TreeSet<String>(new LenComparator());
a1.add("312");
a1.add("sd");
a1.add("sad");
a1.add("12ewr");
for(Iterator<String> it = a1.iterator();it.hasNext();){
String s = it.next();
System.out.println(s);
}
}
}
class LenComparator implements Comparator<String>{
public int compare(String s1,String s2){
int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num == 0)
return s1.compareTo(s2);
return num;
}
}
Interface Comparator<T>
从它的使用就可以看出<>可以接受一个引用数据类型(注意基础数据类型是不行的)
泛型使用
- 泛型类:在整个类中都有效,如果被方法调用那么泛型类的对象明确要操作的具体类型后,所有的操作类型就固定了。
- 泛型方法:为了让不同的方法可以操作不同类型,而且类型还不明确,那么可以将泛型定义在方法上。
- 静态方法不可以访问类上定义的泛型,如果静态方法操作的数据类型不确定可以使用泛型方法。
<T>
放的位置是返回值前修饰符后- 泛型接口:和泛型类作用一样
class GenericsDemo3{
public static void main(String[] args){
new Demo1<String>().print("123");
new Demo1<String>().show(123);
new Demo2().print(123);
new Demo2().print("123");
new Demo2().show(123);
new Demo2().show("123");
new Demo3<String>().print("123");
new Demo3<String>().show(123);
new Demo3<String>().method(123);
}
}
//泛型定义在类上
class Demo1<T>{
public void print(T t){
System.out.println(t);
}
public void show(int t){
System.out.println(t);
}
}
//泛型定义在方法上
class Demo2{
public <T> void print(T t){
System.out.println(t);
}
public <Q> void show(Q t){
System.out.println(t);
}
}
class Demo3<T>{
public void print(T t){
System.out.println(t);
}
public <Q> void show(Q t){
System.out.println(t);
}
//静态得先加载 所以不能访问类上的泛型T
public static <W> void method(W w){
System.out.println(w);
}
}
//泛型定义在接口上
interface inte<T>{
void show(T t);
}
class inteimpl<T> implements inte<T>{
public void show(T t){
System.out.println("show:"+t);
}
}
泛型中的符号
- 泛型中
<E> <T>
代表Element和Type - 泛型中还有一个通配符/占位符
?
表示在不能明确数据类型的情况下表示
import java.util.*;
class GenericsDemo5{
public static void main(String[] args){
ArrayList<String> a1 = new ArrayList<String>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
a1.add("aa11");
a1.add("aa12");
a1.add("aa13");
a2.add(11);
a2.add(12);
a2.add(3);
print(a1);
// print(a2);
}
public static void print(ArrayList<String> a1){
for (Iterator<String> it = a1.iterator();it.hasNext() ; ) {
System.out.println(it.next().length());
}
}
public static void print(ArrayList<?> a1){
for (Iterator<?> it = a1.iterator();it.hasNext() ; ) {
System.out.println(it.next());
}
}
public static <T> void print2(ArrayList<T> a1){
for (Iterator<T> it = a1.iterator();it.hasNext() ; ) {
T t = it.next();
try{
System.out.println(t instanceof String);
}catch(Exception e){}
}
}
}
- 泛型属于多态的一种表现形式,所以它也不能预先使用子类其特有的方法。(函数重载、继承/方法重写、运算符重载等一样)
泛型的限定
- 泛型的限定是为了限定泛型,扩展。
<? extends E>
可以接受E类型或E的子类型,上限。<? super E>
可以接受E类型或E的父类型,下限。