泛型是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);
}
}
}
如上:未完待续......