• 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());
        }
    }

    输出:

    (new1@15db9742,2)
    (new1@6d06d69c,2.5)
    (new1@7852e922,new2@4e25154f,2,2.3,2.3,)
    (new1@70dea4e,new2@5c647e05,2,2,2,)

    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()被无限次重载了一样。

    可变参数列表和泛型方法能够很好的共存:

    import java.util.*;
    
    public class Ex11 {
        static <T> List<T> makeList(T... args){
            List<T> result = new ArrayList<T>();
            for(T item : args) {
                result.add(item);
            }
            return result;
        }
        public static void main(String[] args) {
            List<String> list = makeList("233","2333","2333");
            System.out.println(list);
            List<Double> listd = makeList(2.3,2.33,2.333);
            System.out.println(listd);
        }
    }

    输出:

    [233, 2333, 2333]
    [2.3, 2.33, 2.333]

    5、匿名内部类

    使用匿名内部类实现Generator接口:

    import java.util.Random;
    
    interface Generator<T>{
        T next();
    }
    class Customer{
        private static long counter = 1;
        private final long id = counter++;
        private Customer() {}
        public String toString() {return "Customer" + id;}
        
        public static Generator<Customer> generator(){
            return new Generator<Customer>() {
                public Customer next() {
                    return new Customer();
                }    
            };
        }
    }
    class Teller{
        private static long counter = 1;
        private final long id = counter++;
        private Teller() {}
        public String toString() {return "Teller" + id;}
        
        public static Generator<Teller> generator =
         new Generator<Teller>() {
                public Teller next() {
                    return new Teller();
                }    
            };
    }
    public class Exp10 {
        public static void serve(Teller t, Customer c){
            System.out.println(t + " serve " + c);
        }
        public static void main(String[] args) {
            for(int i = 0; i < 5; i++) {
                serve(Teller.generator.next(),Customer.generator().next());
            }
        }
    }

    输出:

    Teller1 serve Customer1
    Teller2 serve Customer2
    Teller3 serve Customer3
    Teller4 serve Customer4
    Teller5 serve Customer5

    Customer和Teller都只有一个private的构造器,Customer的generator()能返回一个泛型为Customer的Generator类,并重写了其中的next方法产生一个Customer类对象,Teller中有一个static的Generator<Teller>的类对象,同样重写了next方法。

    <Customer>

  • 相关阅读:
    C++中头文件包含的问题
    linux环境变量
    win32进程和线程
    断言
    win32中的常用类型转换
    可变形参
    #define
    CString与char*互相转化
    extern
    手机CPU和GPU厂商
  • 原文地址:https://www.cnblogs.com/xxbbtt/p/7708459.html
Copyright © 2020-2023  润新知