Java编程思想读书笔记——泛型(一)

第十五章 泛型

15.1 与C++的比较

15.2 简单泛型

泛型类

package com.mzm.chapter15;

/**
 * 
 * 泛型类,持有泛化类型的对象,取出对象无需转型
 */
public class Holder3 {
    private T a;

    public Holder3(T a){
        this.a = a;
    }

    public void set(T a) {
        this.a = a;
    }

    public T get(){
        return a;
    }

    public static void main(String[] args){
        Holder3 h3 = new Holder3<>(new Automobile());
        Automobile a = h3.get();
    }
}
15.2.1 一个元组类库

元组(tuple)是将一组对象直接打包存储的容器对象,这一容器对象容许读取其中的元素,但是不允许存放新的对象。元组也被称为数据传送对象或信使。
元组具有任意长度,其持有的对象可以是不同类型的。

package com.mzm.chapter15;

/**
 * 二维元组
 * 
 */
public class TwoTuple {
    public final A first;
    public final B second;

    public TwoTuple(A a, B b){
        this.first = a;
        this.second = b;
    }

    public String toString(){
        return "(" + first + ", " + second + ")";
    }
}
package com.mzm.chapter15;

/**
 * 三维元组,使用继承机制实现长度更长的元组
 * 
 */
public class ThreeTuple<A, B, C> extends TwoTuple<A, B> {

    public final C third;

    public ThreeTuple(A a, B b, C c) {
        super(a, b);
        this.third = c;
    }

    public String toString() {
        return "(" + first + ", " + second + ", " + third + ")";
    }
}

更长的元组依次类推。

15.2.2 一个堆栈类

传统的下推堆栈

package com.mzm.chapter15;

/**
 * 
 */
public class LinkedStack {

    private static class Node {
        U item;
        Node next;

        Node() {
            this.item = null;
            this.next = null;
        }

        Node(U item, Node next) {
            this.item = item;
            this.next = next;
        }

        /**
         * 末端哨兵,判断堆栈是否为空
         * @return
         */
        boolean end() {
            return item == null && next == null;
        }

    }

    private Node top = 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) {
        LinkedStack lss = new LinkedStack<>();
        for (String s : "Phasers on stun!".split(" ")) {
            lss.push(s);
        }
        String s;
        while((s = lss.pop()) != null) {
            System.out.println(s);
        }
    }
}
15.2.3 RandomList
package com.mzm.chapter15;

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

/**
 * 
 */
public class RandomList {

    private ArrayList storage = new ArrayList<>();
    private Random rand = new Random(47);

    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 rs = new RandomList<>();
        for(String s : "The quick brown fox jumped over the lazy brown dog".split(" ")) {
            rs.add(s);
        }

        for(int i = 0; i < 11; i++) {
            System.out.print(rs.select() + " ");
        }
    }
}

15.3 泛型接口

泛型接口的例子:
生成器(generator),是一种专门负责创建对象的类,是工厂方法设计模式的一种应用。不同的是,使用生成器创建对象时,不需要任何参数,而工厂方法一般需要参数。

package com.mzm.chapter15;

/**
 * 生成器的通用接口
 */
public interface Generator {

    T next();

}
package com.mzm.chapter15;

import java.util.Iterator;
import java.util.Random;

/**
 * 使用生成器接口生成对象
 */
public class CoffeeGenerator implements Generator<Coffee>, Iterable<Coffee> {

    private Class[] types = {
            Latte.class,
            Mocha.class,
            Cappuccino.class,
            Americano.class,
            Breve.class,
    };
    private static Random rand = new Random(47);

    public CoffeeGenerator() {

    }
    private int size = 0;

    public CoffeeGenerator(int sz) {
        this.size = sz;
    }

    @Override
    public Coffee next() {
        try {
            return (Coffee) types[rand.nextInt(types.length)].newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    class CoffeeIterator implements Iterator<Coffee> {

        int count = size;

        @Override
        public boolean hasNext() {
            return count > 0;
        }

        @Override
        public Coffee next() {
            count--;
            return CoffeeGenerator.this.next();
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    @Override
    public Iterator iterator() {
        return new CoffeeIterator();
    }

    public static void main(String[] args) {
        CoffeeGenerator gen = new CoffeeGenerator();
        for(int i = 0; i < 5; i++) {
            System.out.println(gen.next());
        }
        for(Coffee c : new CoffeeGenerator(5)) {
            System.out.println(c);
        }
    }
}

15.4 泛型方法

是否拥有泛型方法与该类是不是泛型类无关。

定义泛型方法只需要将泛型参数列表置于返回值之前。

使用泛型类创建对象时必须指定类型参数,而在使用泛型方法时则不必指定类型参数,编译器会进行类型参数推断(type argument inference),找出具体的类型。

15.4.1 杠杆利用类型参数推断

类型推断只对赋值操作有效,不能将一个泛型方法的返回结果作为参数,传递给另一个方法,因为编译器认为,泛型方法的返回值是被赋值给一个Object类型的变量(泛型方法的返回值类型实际上是Object类型?)。

显式类型说明
要想实现上述目的,可以使用显式类型说明。即在点操作符与方法名之间插入尖号,并指明类型。如果是在定义该方法的类内部,则在点操作符之前使用this关键字,如果是static方法,则在点操作符之前加类名。

package com.mzm.chapter15;

import com.mzm.chapter14.Person;
import com.mzm.chapter14.Pet;

import java.util.List;
import java.util.Map;

/**
 * 
 */
public class LimitsOfInference {

    static void f(Map> petPeople) {

    }

    public static void main(String[] args) {
        //f(New.map();
        f(New.>map());
    }
}
15.4.2 可变参数与泛型方法

可变参数可与泛型方法并存

15.4.3 用于Generator的泛型方法
15.4.4 一个通用的Generator
package com.mzm.chapter15;

/**
 * 
 */
public class BasicGenerator<T> implements Generator<T> {

    private Class type;

    public BasicGenerator(Class type) {
        this.type = type;
    }

    @Override
    public T next() {
        try {
            return type.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static  Generator create(Class type) {
        return new BasicGenerator<>(type);
    }
}
15.4.5 简化元组的使用
15.4.6 一个Set实用工具
package com.mzm.chapter15;

import java.util.HashSet;
import java.util.Set;

/**
 * 集合的各种运算
 * 
 */
public class Sets {

    public static  Set union(Set a, Set b) {
        Set result = new HashSet<>(a);
        result.addAll(b);
        return result;
    }

    public static  Set intersection(Set a, Set b) {
        Set result = new HashSet<>(a);
        result.retainAll(b);
        return result;
    }

    public static  Set difference(Set superset, Set subset) {
        Set result = new HashSet<>(superset);
        result.removeAll(subset);
        return result;
    }

    public static  Set complement(Set a, Set b) {
        return difference(union(a, b), difference(a, b));
    }
}

15.5 匿名内部类

将泛型应用于匿名内部类

package com.mzm.chapter15;

import java.util.*;

/**
 * Teller和Customer的默认构造器均为private,必须使用Generator创建对象
 * 
 */
public class BankTeller {

    public static void serve(Teller t, Customer c) {
        System.out.println(t + " servers " + c);
    }

    public static void main(String[] args) {
        Random rand = new Random(47);
        Queue line = new LinkedList<>();
        Generators.fill(line, Customer.generator(), 15);
        List tellers = new ArrayList<>();
        Generators.fill(tellers, Teller.generator(), 4);
        for(Customer c : line) {
            serve(tellers.get(rand.nextInt(tellers.size())), c);
        }
    }
}

class Customer {
    private static long counter = 1;
    private final long id = counter++;

    private Customer() {
    }

    public String toString() {
        return getClass().getSimpleName() + " " + id;
    }

    public static Generator generator() {
        return new Generator() {
            @Override
            public Customer next() {
                return new Customer();
            }
        };
    }
}

class Teller {

    private static long counter = 1;
    private final long id = counter++;

    private Teller() {

    }

    public String toString() {
        return getClass().getSimpleName() + " " + id;
    }

    public static Generator generator() {
        return new Generator() {
            @Override
            public Teller next() {
                return new Teller();
            }
        };
    }
}

15.6 构建复杂模型

泛型可以简单而安全地创建复杂的模型。

你可能感兴趣的:(java)