泛型出现的目的是创造容器类。可以同时持有多种类型的对象,泛型的目的是指定容器持有什么类型的对象。
简单泛型
元组类库
堆栈类
RandomList
泛型接口
泛型方法
可变参数与泛型方法
伪代码:
類 例泛類 {
值 : T
設置值(新值 : T) {
值 := 新值
}
獲取值() : T {
返回 值
}
}
例方法1() {
例物件 : 例泛類<整數型>
例物件 := 新 例泛類<整數型>()
例物件.設置值(5)
输出整数(例对象.获取值())
}
例方法2() {
例物件 : 例泛類<浮點數型>
例物件 := 新 例泛類<浮點數型>()
例物件.設置值(5.5)
输出浮点数(例对象.获取值())
}
下面给出一个简单实例:
package Generic;
public class Box {
private T a;
public Box(T a) {
this.a = a;
}
public void set(T a){
this.a = a;
}
public T get(){
return a;
}
public static void main(String[] args) {
Boxb1=new Box<>(3);
Boxb2=new Box<>('A');
Boxb3=new Box<>(false);
System.out.println(b1.get());
System.out.println(b2.get());
System.out.println(b3.get());
}
}
控制台输出:
3
A
false
我们暂时不指定类型,稍后决定具体使用什么类型,达到这个目的,需要使用泛型参数用尖括号括住放在类名后。使用这个类时,用实际类型替换泛型参数,这里泛型参数为T。
仅一次方法调用返回多个对象,return只允许返回单个对象。解决方法是创建一个对象,用它来持有想要返回的多个对象。这个概念叫做元组(tuple)。
package Generic;
public class Tuple {
public final A a;
public final B b;
public final C c;
public Tuple(A a, B b, C c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public String toString() {
return "Tuple{" +
"a=" + a +
", b=" + b +
", c=" + c +
'}';
}
public static void main(String[] args) {
Tuple t=new Tuple("hello",'A',1000);
System.out.println(t.toString());
}
}
控制台信息
Tuple{a=hello, b=A, c=1000}
这是一个能够持有3个对象的三维元组。元组允许读取其中元素,但不允许存放新对象。
我们也可以利用继承机制实现更长元组:
package Generic;
public class Tuple1 extends Tuple{
public final D d;
public Tuple1(A o, B o2, C o3, D d) {
super(o, o2, o3);
this.d = d;
}
@Override
public String toString() {
return "Tuple1{" +
"d=" + d +
", a=" + a +
", b=" + b +
", c=" + c +
'}';
}
public static void main(String[] args) {
Tuple1 t1=new Tuple1("hello",true,100,'D');
System.out.println(t1.toString());
}
}
控制台:
Tuple1{d=D, a=hello, b=true, c=100}
元组可以是任意长度,元组的对象类型也可以不相同。
使用LinkedList实现传统下推堆栈,创造泛型类。
package Generic;
public class LinkedStack {
private static class Node{
U item;
Nodenext;
Node(){
item=null;
next = null;
}
Node(U item,Node next){
this.item = item;
this.next = next;
}
boolean end(){
return item==null&&next==null;
}
}
private Nodetop=new Node();
public void push(T item){
top=new Node(item,top);
}
public T pop(){
T result=top.item;
if(!top.end())
top=top.next;
return result;
}
public static void main(String[] args) {
LinkedStackls=new LinkedStack();
for (Character c:"helloworld".toCharArray()){
ls.push(c);
}
Character c;
while ((c=ls.pop())!=null){
System.out.println(c);
}
}
}
控制台:
d
l
r
o
w
o
l
l
e
h
内部类Node也是泛型,每次调用push()方法,创建一个Node
对象,将其链接到前一个Node 对象,调用pop()方法,总是返回top.item,然后丢弃当前top指向Node 对象转移到下一个Node 对象。
创建一个特有容器,每次调用此容器select()方法,随机选取一个元素,如果我们希望这个容器可以应用于各种类型的对象的工具,需要使用泛型。
package Generic;
import java.util.ArrayList;
import java.util.Random;
public class RandomList {
private ArrayList storage=new ArrayList();
private Random rand=new Random(66);
public void add(T item){
storage.add(item);
}
public T select(){
return storage.get(rand.nextInt(storage.size()));
}
public static void main(String[] args) {
RandomListrs=new RandomList();
for (char c :"helloworld".toCharArray()){
rs.add(c);
}
for (int i = 0; i < 10; i++) {
System.out.print(rs.select()+" ");
}
}
}
控制台:
o r l l o e o d l o
泛型也可以应用于接口。例如工厂模式的生成器(专门创造对象的类)。一般而言,一个生成器只定义一个方法,该方法用来产生新的对象。这里使用next()方法.。
package Generic;
public interface Generator {
T next();
}
生成Fibonacci数列:
package Generic;
public class Fib implements Generator{
private int cnt=0;
@Override
public Integer next() {
return fib(cnt++);
}
private int fib(int n){
if(n<2)return 1;
return fib(n-2)+fib(n-1);
}
public static void main(String[] args) {
Fib generator=new Fib();
for (int i = 0; i < 20; i++) {
System.out.print(generator.next()+" ");
}
}
}
控制台:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
泛型方法能使方法独立于类而产生变化。如果使用可以取代整个类泛型化那么应该只用泛型方法。
package Generic;
public class Methods {
public void f(T x){
System.out.println(x.getClass().getName() );
}
public static void main(String[] args) {
Methods m=new Methods();
m.f("hello");
m.f(12);
m.f(11.1);
m.f('A');
m.f(false);
}
}
控制台:
java.lang.String
java.lang.Integer
java.lang.Double
java.lang.Character
java.lang.Boolean
Methods并没有参数化,只有f()拥有类型参数。使用泛型类时,必须在创建对象时指定参数类型,而泛型方法通常不必指明参数类型。
package Generic;
import java.util.*;
public class Varargs {
public static ListmakeList(T...args){
Listres=new ArrayList<>();
for (T item :args){
res.add(item);
}
return res;
}
public static void main(String[] args) {
Listls=makeList("H");
System.out.println(ls);
ls=makeList("H","E","L");
System.out.println(ls);
ls=makeList("HELLOWORLD".split(""));
System.out.println(ls);
}
}
控制台:
[H]
[H, E, L]
[H, E, L, L, O, W, O, R, L, D]