1、简单泛型
使用Object:因为Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类。所以所有的类都能转型为Object类。
import java.util.*;public classEx7 {static voidf(Object a) {
System.out.println(a);
}public static voidmain(String[] args) {
f("233");
f(233);
f(2.33);
List list = new ArrayList();
list.add("233");
list.add(233);
list.add(2.33);for(Object a : list) {
System.out.println(a);
}
}
}
这里的f()函数可以处理三种类型的对象,list也可以存放三种类型的对象,但是其实他们都是处理或者储存的先转型为Object类型的对象。
输出:
233
233
2.33
233
233
2.33
通常而言,我们只会使用容器来存储一直类型的对象,泛型的主要目的之一就在于此,指定容器要持有什么类型的对象,然后由编译器来保证类型的正确性。
要达到这个目的,需要使用类型参数,用尖括号括住,放在类名后面,然后在使用这个类的时候用实际的类型替换此类型参数。
public class Ex7{voidf(T a) {
System.out.println(a);
}public static voidmain(String[] args) {
Ex7 exStr = new Ex7();
exStr.f("233");
Ex7 exInt = new Ex7();
exInt.f(2);
Ex7 exDou = new Ex7();
exDou.f(2.5);
}
}
当你创建Ex7对象时,必须指明想要持有的是什么类型的对象,将其置于尖括号中。然后你就只能在这个Ex7对象中存入该类型或是其子类。
输出:
233
2
2.5
2、一个元组类库
有时候我们希望一次返回就能返回多个对象,但是return语句只允许返回单个对象,所以解决方法就是创建一个对象,用它来持有想要返回的多个对象。
这样的概念称为元组,它是将一组对象直接打包存储于其中的一个单一对象,这个容器对象允许对象读取其中的元素,但是不允许向其中存放新的对象。因为是元嘛,所以只能用不能修改,要修改就得弄一个新的,不过这个不重要==
class TwoTuple{public finalA first;public finalB second;publicTwoTuple(A a, B b) {
first=a;
second=b;
}publicString toString() {return "(" + first + ","
+ second + ")";
}
}class FiveTuple extendsTwoTuple {public finalC third;public finalD fourth;public finalE fifth;publicFiveTuple(A a, B b,C c,D d,E e) {super(a, b);
third=c;
fourth=d;
fifth=e;
}publicString toString() {return "(" + first + ","
+ second + ","
+ third + ","
+ fourth + ","
+ fifth + ","
+ ")";
}
}
元组是可以具有任意长度的,这里创建了两个长度分别为2和5的元组,
元组中的对像可以是任意不同的类型的,不过最好是为每一个对象指明其类型。
还有之前说的可以读取,但是不允许存放新的元素和修改,final就解决这个问题了
toString只是用来显示列表中的值的
classnew1{}classnew2{}public classEx8 {static TwoTuplef(){return new TwoTuple(new new1(),2);
}static TwoTuplef1(){return new TwoTuple(new new1(),2.5);
}static FiveTupleg(){return new FiveTuple(new new1(),new new2(), 2, 2.3, 2.3);
}static FiveTupleg1(){return new FiveTuple(new new1(),new new2(), 2, 2, "2");
}public static voidmain(String[] args) {
TwoTuple test =f();
System.out.println(test);
System.out.println(f1());
System.out.println(g());
System.out.println(g1());
}
}
输出:
(new1@15db9742,2)
(new1@6d06d69c,2.5)
(new1@7852e922,new2@4e25154f,2,2.3,2.3,)
(new1@70dea4e,new2@5c647e05,2,2,2,)
3、泛型接口
interface Generator{
T next();
}classCoffee{private static long counter = 0;private final long id = counter++;publicString toString() {return getClass().getSimpleName() + " " +id;
}
}class Mocha extendsCoffee{}class Latte extendsCoffee{}class Cappuccino extendsCoffee{}public class Ex9 implements Generator{private Class[] type = {Mocha.class, Latte.class, Cappuccino.class};private Random rand = new Random(47);publicCoffee next() {try{return(Coffee) type[rand.nextInt(type.length)].newInstance();
}catch(Exception e) {throw newRuntimeException(e);
}
}public static voidmain(String[] args) {
Ex9 ex= newEx9();for(int i = 0; i < 5; i++)
System.out.println(ex.next());
}
}
Generator接口是一个用来专门负责生成对象的类,其中的next用于产生新的对象,然后实现这个接口的时候就需要指定这个T
输出:
Cappuccino 0Cappuccino1Latte2Cappuccino3Latte4
然后是一个生成斐波那契数列的类的例子:
interface Generator{
T next();
}public class Ex9 implements Generator{private int counter = 0;publicInteger next() {return fib(counter++);
}private int fib(intn){if(n < 2) return 1;return fib(n - 2) + fib(n - 1);
}public static voidmain(String[] args) {
Ex9 ex= newEx9();for(int i = 0; i < 18; i++)
System.out.print(ex.next()+ " ");
}
}
输出:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
4、泛型方法
要定义泛型方法,只需将泛型参数列表置于返回值之前
public classExp10 {public voidf(T x){
System.out.println(x.getClass().getName());
}public static voidmain(String[] args) {
Exp10 ex= newExp10();
ex.f("x");
ex.f(2);
ex.f(2.3);
ex.f(2l);
ex.f(4.55f);
}
}
输出:
java.lang.String
java.lang.Integer
java.lang.Double
java.lang.Long
java.lang.Float
在创建泛型类的时,必须在创建对象的时候指定类型参数的类型,而使用泛型方法的时候,通常不需要指明参数类型,编译器会为我们找出具体的类型,这被称为类型参数推断,我们像调用普通方法那样调用f(),就像f()被无限次重载了一样。
可变参数列表和泛型方法能够很好的共存:
import java.util.*;public classEx11 {static ListmakeList(T... args){
List result = new ArrayList();for(T item : args) {
result.add(item);
}returnresult;
}public static voidmain(String[] args) {
List list = makeList("233","2333","2333");
System.out.println(list);
List listd = makeList(2.3,2.33,2.333);
System.out.println(listd);
}
}
输出:
[233, 2333, 2333]
[2.3, 2.33, 2.333]
5、匿名内部类
使用匿名内部类实现Generator接口:
importjava.util.Random;interface Generator{
T next();
}classCustomer{private static long counter = 1;private final long id = counter++;privateCustomer() {}public String toString() {return "Customer" +id;}public static Generatorgenerator(){return new Generator() {publicCustomer next() {return newCustomer();
}
};
}
}classTeller{private static long counter = 1;private final long id = counter++;privateTeller() {}public String toString() {return "Teller" +id;}public static Generator generator =
new Generator() {publicTeller next() {return newTeller();
}
};
}public classExp10 {public static voidserve(Teller t, Customer c){
System.out.println(t+ " serve " +c);
}public static voidmain(String[] args) {for(int i = 0; i < 5; i++) {
serve(Teller.generator.next(),Customer.generator().next());
}
}
}
输出:
Teller1 serve Customer1
Teller2 serve Customer2
Teller3 serve Customer3
Teller4 serve Customer4
Teller5 serve Customer5
Customer和Teller都只有一个private的构造器,Customer的generator()能返回一个泛型为Customer的Generator类,并重写了其中的next方法产生一个Customer类对象,Teller中有一个static的Generator的类对象,同样重写了next方法。