java——泛型

Posted xxbbtt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java——泛型相关的知识,希望对你有一定的参考价值。

1、简单泛型

使用Object:因为Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类。所以所有的类都能转型为Object类。

import java.util.*;

public class Ex7 {
    static void f(Object a) {
        System.out.println(a);
    }
    public static void main(String[] args) {
        f("233");
        f(233);
        f(2.33);
        List<Object> list = new ArrayList<Object>();
        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<T> {
    void f(T a) {
        System.out.println(a);
    }
    public static void main(String[] args) {
        Ex7<String> exStr = new Ex7<String>();
        exStr.f("233");
        Ex7<Integer> exInt = new Ex7<Integer>();
        exInt.f(2);
        Ex7<Double> exDou = new Ex7<Double>();
        exDou.f(2.5);
        }
}

当你创建Ex7对象时,必须指明想要持有的是什么类型的对象,将其置于尖括号中。然后你就只能在这个Ex7对象中存入该类型或是其子类。

输出:

233
2
2.5

 

 

2、一个元组类库

有时候我们希望一次返回就能返回多个对象,但是return语句只允许返回单个对象,所以解决方法就是创建一个对象,用它来持有想要返回的多个对象。

这样的概念称为元组,它是将一组对象直接打包存储于其中的一个单一对象,这个容器对象允许对象读取其中的元素,但是不允许向其中存放新的对象。因为是元嘛,所以只能用不能修改,要修改就得弄一个新的,不过这个不重要==

class TwoTuple<A,B>{
    public final A first;
    public final B second;
    public TwoTuple(A a, B b) {
        first = a;
        second = b;
    }
    public String toString() {
        return "(" + first + ","
                   + second + ")";
    }
}
class FiveTuple<A,B,C,D,E> extends TwoTuple {
    public final C third;
    public final D fourth;
    public final E fifth;
    public FiveTuple(A a, B b,C c,D d,E e) {
        super(a, b);
        third = c;
        fourth = d;
        fifth = e;
    }
    public String toString() {
        return "(" + first + ","
                   + second + ","
                   + third + ","
                   + fourth + ","
                   + fifth + ","
                   + ")";
    }
}
  • 元组是可以具有任意长度的,这里创建了两个长度分别为2和5的元组,
  • 元组中的对像可以是任意不同的类型的,不过最好是为每一个对象指明其类型。
  • 还有之前说的可以读取,但是不允许存放新的元素和修改,final就解决这个问题了
  • toString只是用来显示列表中的值的
class new1{}
class new2{}
public class Ex8 {
    static TwoTuple<new1,Integer> f(){
        return new TwoTuple<new1,Integer>(new new1(),2);
    }
    static TwoTuple<new1,Double> f1(){
        return new TwoTuple<new1,Double>(new new1(),2.5);
    }
    static FiveTuple<new1,new2,Integer,Double,Double> g(){
        return new FiveTuple<new1,new2,Integer,Double,Double>
                    (new new1(),new new2(), 2, 2.3, 2.3);
    }
    static FiveTuple<new1,new2,Integer,Integer,String> g1(){
        return new FiveTuple<new1,new2,Integer,Integer,String>
                    (new new1(),new new2(), 2, 2, "2");
    }
    public static void main(String[] args) {
        TwoTuple<new1,Integer> test = f();
        System.out.println(test);
        System.out.println(f1());
        System.out.println(g());
        System.out.println(g1());
    }
}

输出:

 

3、泛型接口

interface Generator<T>{
    T next();
}
class Coffee{
    private static long counter = 0;
    private final long id = counter++;
    public String toString() {
        return getClass().getSimpleName() + " " + id;
    }
}
class Mocha extends Coffee{}
class Latte extends Coffee{}
class Cappuccino extends Coffee{}
public class Ex9 implements Generator<Coffee>{

    private  Class[] type = {Mocha.class, Latte.class, Cappuccino.class};
    private  Random rand = new Random(47);
    public Coffee next() {
        try {
            return (Coffee) type[rand.nextInt(type.length)].newInstance();
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        Ex9 ex = new Ex9();
        for(int i = 0; i < 5; i++) 
            System.out.println(ex.next());
    }
}

Generator<T>接口是一个用来专门负责生成对象的类,其中的next用于产生新的对象,然后实现这个接口的时候就需要指定这个T

输出:

Cappuccino 0
Cappuccino 1
Latte 2
Cappuccino 3
Latte 4

然后是一个生成斐波那契数列的类的例子:

interface Generator<T>{
    T next();
}

public class Ex9 implements Generator<Integer>{
    private int counter = 0;
    public Integer next() {
            return fib(counter++);
    
    }
    private int fib(int n){
        if(n < 2) return 1;
        return fib(n - 2) + fib(n - 1);
    }
    public static void main(String[] args) {
        Ex9 ex = new Ex9();
        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 class Exp10 {
    public <T>void f(T x){
        System.out.println(x.getClass().getName());
    }
    public static void main(String[] args) {
        Exp10 ex = new Exp10();
        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()被无限次重载了一样。

以上是关于java——泛型的主要内容,如果未能解决你的问题,请参考以下文章

201621123062《java程序设计》第九周作业总结

什么意思 在HashMap之前 ? Java中的泛型[重复]

这个嵌套类构造函数片段可以应用于泛型类吗?

201621123037 《Java程序设计》第9周学习总结

Java——泛型

作业09-集合与泛型