泛型是JDK5时的技术,主要作用于编译时期,是编译时期的安全技术。
一、元组
1、引入:仅一次方法调用就能返回多个对象,编码中应该会使用到该功能。但是对于一个方法的return来说,一次只能返回一个对象。因此,解决办法就是创建一个对象,让其持有想要返回的多个对象。每次需要该种场景的情况时,我们就创建一个类来完成工作。
2、元组:将一组对象直接打包存储于一个单一的对象中。可以理解为元组为一个容器对象,该容器对象只允许读取其中的元素,不允许向其中存放新的元素。因此,该对象的成员声明时用final修饰。
3、示例如下:
package net.oschina.tkj.chapter15.tuple; /** * 元组类 * * @author Freedom * * @param <A> * @param <B> */ public class TwoTuple<A, B> { private final A a; public final B b; public TwoTuple(A a, B b) { this.a = a; this.b = b; } public A getA() { return a; } public B getB() { return b; } @Override public String toString() { return "TwoTuple [a=" + a + ", b=" + b + "]"; } public static void main(String[] args) { Red red = new Red(); red.setAge(11); red.setName("红色方"); VmInfo vm = new VmInfo(); vm.setVmId(1); vm.setVmName("POPDAS"); vm.setVmNum(2); // 二元元组 TwoTuple<Red, VmInfo> two = new TwoTuple<Red, VmInfo>(red, vm); System.out.println("元组对象:"+two); // 获取元组中的成员 VmInfo tupleRed = two.getB(); Red redTuple = two.getA(); System.out.println("tupleRed:" + tupleRed); System.out.println("redTuple:" + redTuple); } }
二、泛型类模拟一个简单堆栈
1、代码示例
package net.oschina.tkj.chapter15.stack; /** * 泛型类,简单的堆栈 * * @author Freedom * */ public class SimpleStack<T> { /* * 内部类用于提供数据 */ private static class Node<K> { K item; Node<K> next; // 创建外部类对象时,同时创建一个内部类型对象,该对象为末端哨兵 Node() { this.item = null; this.next = null; } Node(K item, Node<K> next) { this.item = item; this.next = next; } boolean end() { return item == null && next == null; } } // 创建外部类对象时,初始化一个内部类对象,充当末端哨兵 private Node<T> bottom = new Node<T>(); // 添加元素 public void push(T item) { bottom = new Node<T>(item, bottom); } // 取出元素 public T pop() { T res = bottom.item; if (!bottom.end()) { bottom = bottom.next; } return res; } public static void main(String[] args) { SimpleStack<String> simple = new SimpleStack<String>(); String str = "this is a luck dog"; for (String s : str.split(" ")) { simple.push(s); } String s; while ((s = simple.pop()) != null) { System.out.print(s+" "); } } }
示例中使用了末端哨兵的功能,来判断堆栈何时为空。
三、泛型方法
1、类中可以包含参数化的方法,而该方法所在的类可以是泛型类,也可以不是泛型类。简言之,泛型方法与泛型类没有必然关系。
2、泛型方法使用原则:
①使用泛型方法可以取代整个类的泛型化,则优先使用泛型方法;
②对static方法而言,无法访问泛型类的类型参数(报错信息:Cannot make a static reference to the non-static type T);如果static方法需要使用泛型能力,必须要在自己的方法上声明泛型(原因:因为类上声明的参数化类型,需要创建的对象的时具体制定,对于static方法而言,可以不用创建对象直接调用,此时不能知道参数化的具体类型,因此编译不通过;通过方法声明时,在调用方法时可以确定具体的泛型的类型)
错误示例:
package net.oschina.tkj.chapter15.method; public class GenerateMethods<T> { /* * 该方法会报错:Cannot make a static reference to the non-static type T * static方法无法访问泛型类的类型参数 */ public static void f(T t) { } /* * 该方法正确,是static方法具备泛型能力,必须在自己的方法上声明泛型 */ public static <K> void f1(K k) { } }
泛型方法示例:
package net.oschina.tkj.chapter15.method; import java.util.ArrayList; import java.util.List; import net.oschina.tkj.chapter15.tuple.TwoTuple; import net.oschina.tkj.chapter15.tupleclass.Red; import net.oschina.tkj.chapter15.tupleclass.VnfInfo; public class GenerateMethods<T> { /* * 非static方法可以直接使用,泛型类声明的泛型类型 */ public void g(T t) { } /* * 如下static方法需在自己方法上声明泛型类型 */ public static <T> void f(T t) { System.out.println(t.getClass().getSimpleName()); } public static <K, V> TwoTuple<K, V> f1(K k, V v) { return new TwoTuple<K, V>(k, v); } public static <T> List<T> f2(T... args) { List<T> list = new ArrayList<T>(); for (T t : args) { list.add(t); } return list; } public static void main(String[] args) { // 泛型方法 f(new Red()); TwoTuple<Red, VnfInfo> method = f1(new Red(), new VnfInfo()); System.out.println("method:" + method); f2("a", "b", "c"); f2(new String[] { "c", "d", "e" }); f2(new ArrayList<String>()); List<Object> list = f2(new Red(), new VnfInfo()); for (Object o : list) { System.out.println(o); } } }
如上:未完待续......