(泛型接口&泛型方法)详解

  泛型出现的目的是创造容器类。可以同时持有多种类型的对象,泛型的目的是指定容器持有什么类型的对象。

简单泛型

元组类库

堆栈类

RandomList

泛型接口

泛型方法

可变参数与泛型方法

伪代码:

類 例泛類<T> {
  值 : T

  設置值(新值 : T) {
    值 := 新值
  }

  獲取值() : T {
    返回 值
  }
}

例方法1() {
  例物件 : 例泛類<整數型>
  例物件 := 新 例泛類<整數型>()
  例物件.設置值(5)
  输出整数(例对象.获取值())
}

例方法2() {
  例物件 : 例泛類<浮點數型>
  例物件 := 新 例泛類<浮點數型>()
  例物件.設置值(5.5)
  输出浮点数(例对象.获取值())
}

简单泛型

  下面给出一个简单实例:

package Generic;



public class Box <T> {
   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) {
        Box<Integer>b1=new Box<>(3);
        Box<Character>b2=new Box<>('A');
        Box<Boolean>b3=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<A,B,C> {
    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<A,B,C,D> 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<T> {
    private static class Node<U>{
        U item;
        Node<U>next;
        Node(){
            item=null;
            next = null;
        }
        Node(U item,Node<U> next){
            this.item = item;
            this.next = next;
        }
        boolean end(){
            return item==null&&next==null;
        }
    }
    private Node<T>top=new Node<T>();
    public void push(T item){
        top=new Node<T>(item,top);
    }
    public T pop(){
        T result=top.item;
        if(!top.end())
            top=top.next;
        return result;
    }

    public static void main(String[] args) {
        LinkedStack<Character>ls=new LinkedStack<Character>();
        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<T>对象,将其链接到前一个Node<T>对象,调用pop()方法,总是返回top.item,然后丢弃当前top指向Node<T>对象转移到下一个Node<T>对象。

RandomList

  创建一个特有容器,每次调用此容器select()方法,随机选取一个元素,如果我们希望这个容器可以应用于各种类型的对象的工具,需要使用泛型。

package Generic;


import java.util.ArrayList;
import java.util.Random;

public class RandomList<T> {
    private ArrayList<T> storage=new ArrayList<T>();
    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) {
        RandomList<Character>rs=new RandomList<Character>();
        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>{
    T next();
}

生成Fibonacci数列:

package Generic;



public class Fib implements Generator<Integer>{
    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 <T>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 <T> List<T>makeList(T...args){
        List<T>res=new ArrayList<>();
        for (T item :args){
            res.add(item);
        }
        return res;
    }

    public static void main(String[] args) {
        List<String>ls=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]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值