2,当方法静态时,不能访问类上定义的泛型,如果静态方法是用泛型,只能将泛型定义在方法上。
如果在Tool
//如果此方法上不加泛型,参数Y obj会编译报错,泛型需要对象来明确, //如Tooltool = new Tool ();静态是不需要对象的,所以必须在void前加泛型。 public static void method(Y obj) { System.out.println("method" + obj); }
调用这个方法的时候:
Tool.method("bcd");//bcd
Tool.method(new Integer(9));//9
18-6,泛型接口
1,泛型接口就是将泛型定义在接口上。
//定义泛型时一般不明确具体类型,可以接受任意指定类型的对象,在创建对象的时候明确。 interface Inter{ public void show(T t); } //实现接口可以明确要操作的类型,那么在这个类上直接加上指定类型的泛型即可。 class ImterImpl implements Inter { public void show(String str) { System.out.println("show:" + str); } }
调用show方法时:
InterImpl in = new InterImpl();//这样new对象时就不用加泛型了。
in.show("abc");//这样调用就行
2,在实现接口的类中还是不能明确使用的类型:
class InterImplimplements Inter{ public void show(Q q) { System.out.println("show:" + q); } }
在new这个InterImpl类的时候才能明确使用的类型,那么就定义成上述的样子,在new对象的时候再明确其泛型。
InterImplin = new InterImpl (); in.show(5);
这样一来,in对象就只能接收Integer类型的对象了。
18-7,泛型的界定-上限
1,有多个集合,要想用Iterator取出多个集合中的数据,这时不要定义多个Iterator,要提高代码的复用性,就要单独定义一个方法来进行迭代。例如有这么两个集合:
ArrayList
ArrayList
假如这两个集合中已经有了数据,这时要取出里面的数据,定义一个迭代方法:
//这里接收的是Collection,所以可以迭代List,Set等所有集合,但这里也定义了泛型,所以只能接受String了。 public static void printCollection(Collectional) { Iterator it = al.iterator(); while(it.hasNext()) { System.out.println(it.next()); } }
这是要考虑到接收的集合中的元素类型是不确定的,怎样接收不同类型的元素呢?可以用泛型通配符表示。
2,泛型的通配符--- ,表示未知类型。
public static void printCollection(Collection
al) {
Iterator
it = al.iterator();
while(it.hasNext()) {
//由于参数类型不确定,所以直接用it.next()就OK了。
System.out.println(it.next());
}
}
也可以在方法上加上泛型:
public staticvoid printCollection(Collection al) Iterator it = al.iterator(); while(it.hasNext()) { T str = it.next(); System.out.println(str); }
但是这么做有些麻烦。但也有另外的好处,如果这么写:
public staticT printCollection(Collection al) { Iterator it = al.iterator(); T t = it.next(); return t; }
这样就可以对传入的T返回其对象,并进行操作,不过主要还是用通配符-- 。
3,需求:迭代方法中,只能接收Person及其子类。
分析:首先?就不行了,因为不能接受所有对象。
例如Person的子类有Worker,Student,若要迭代这两个而不能迭代Person以外的类(例如String),可以这么写:
//
表示泛型定义是所有继承Person的类型或Person类型
public static void printCollection(Collection
al){
Iterator
it = al.iterator();
while(it.hasNext()) {
Person p = it.next();//已经可以明确接收的是Person或其子类
System.out.println(p.getName() + ":" + p.getAge());
}
}
若想用此方法迭代String类型的对象,则在编译时会直接报错,因为String不是Person的子类,这就是泛型的上限,其实,泛型写 是 的缩略。
18-8,下限
1,定义方式: 表示指定的类型必须是E或E的父类。
例如Student和Worker都是Person的子类,
定义了三个集合:
ArrayListal1 = new ArrayList (); ArrayList al2 = new ArrayList (); ArrayList al3 = new ArrayList ();
然后定义一个方法:
public static void printCollection(Collection
al) {
Iterator
it = al.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
这时一个迭代集合元素的方法,泛型类型指的是Student或Student的父类,由于Student继承自Person,Worker也继承自Person,所以这里如果传入Worker是不行的,会报错。这就是泛型的下限。
18-9,选择使用集合的技巧
1,几何元素需要唯一么?
|--需要:用Set
|--需要指定顺序么?
|--需要:TreeSet
|--不需要:HashSet
|--但是想要一个和存储一致的顺序(有序):LinkedHashSet
|--不需要:用List
|--需要频繁增删么?
|--需要:LinkedList
|--不需要:ArrayList
2,如何记住每个容器的结构和所属的体系呢?看名字!
List
|--ArrayList
|--LinkedList
Set
|--HashSet
|--TreeSet
后缀名就是该集合所属的体系。
前缀名就是该集合