zoukankan      html  css  js  c++  java
  • 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>

  • 相关阅读:
    HDU 2089 不要62
    HDU 5038 Grade(分级)
    FZU 2105 Digits Count(位数计算)
    FZU 2218 Simple String Problem(简单字符串问题)
    FZU 2221 RunningMan(跑男)
    FZU 2216 The Longest Straight(最长直道)
    FZU 2212 Super Mobile Charger(超级充电宝)
    FZU 2219 StarCraft(星际争霸)
    FZU 2213 Common Tangents(公切线)
    FZU 2215 Simple Polynomial Problem(简单多项式问题)
  • 原文地址:https://www.cnblogs.com/xxbbtt/p/7708459.html
Copyright © 2011-2022 走看看