黑马程序员-Generic

来源:互联网 发布:白酒网络推广方案 编辑:程序博客网 时间:2024/04/29 06:17

---------------------android培训、java培训、期待与您交流! -------------------------

Generic Types:
A generic type is a generic class or interface that is parameterized over types.

通过示例代码,对Java中的Generic有个直观的认识:

//普通的Generic Typeclass Box<T> {private T t;public void set(T t) {this.t = t;}public T get() {return this.t;}}//Bounded Type Parametersclass NaturalNumber<T extends Number> {private T n;public NaturalNumber(T n) {this.n = n;}public boolean isEven() {return n.intValue() % 2 == 0;}}//Multiple Type Parametersinterface Pair<K, V> {void setKey(K k);void setValue(V v);K getKey();V getValue();}class OrderedPair<K, V> implements Pair<K, V> {private K key;private V value;public OrderedPair() {}public OrderedPair(K key, V value) {this.key = key;this.value = value;}@Overridepublic void setKey(K k) {this.key = k;}@Overridepublic void setValue(V v) {this.value = v;}@Overridepublic K getKey() {return this.key;}@Overridepublic V getValue() {return this.value;}}class Util {//Generic Methodpublic static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {return p1.getKey().equals(p2.getKey()) &&p2.getValue().equals(p2.getValue());}//generic Methods and Bounded Type Parameterspublic static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) {int count = 0;for (T e : anArray) {if (e.compareTo(elem) > 0) {count++;}}return count;}}public class UCTest {@Testpublic void test1() {//A type variable can be any non-primitive type you specify://any class type, any interface type, any array type, or even//another type variable.Box<Integer> box = new Box<>();box.set(Integer.valueOf(3));//由于存在auto boxing 机制, 也可以采用如下的调用方式box.set(5);Integer i = box.get();//从此句代码看出,Generic后类型的好处,提供类型信息,减少代码出错System.out.println(i);}@Testpublic void test2() {//The diamond , complier infer since 1.7Pair<Integer, String> p1 = new OrderedPair<>(1, "apple");Pair<Integer, String> p2 = new OrderedPair<Integer, String>(2, "pear");System.out.println("IsSame: " + Util.compare(p1, p2));Box<String> box = new Box<>();Pair<Integer, Box<String>> p3 = new OrderedPair<>(3, box);box.set("p3");System.out.format("%s:%s%n", p3.getKey(), p3.getValue().get());}@Testpublic void test3() {/* * A raw type is the name of generic class or interface without any type arguments. * However, a non-generic class or interface type is not raw type */Box<String> stringBox = new Box<>();Box rawBox = stringBox;//rawBox.set(3);//System.out.println(rawBox.get());Box<Integer> intBox = rawBox;//warning: unchecked conversion}}

Generics, Inheritance, and Subtypes

public void boxTest(Box<number> n) { /*...*/ }//上面的函数只接受 Box<number></number>

interface PayLoadList<E, P> extends List<E> {     /*...*/}

Type Inference

class BoxDemo {public static <U> void addBox(U u, List<Box<U> list) {Box<u> box = new Box<>();box.set(u);list.add(box);}public static <U> void outputBoxes(List<Box<U>> list) {int counter = 0;for (Box<U> box : list) {U boxContents = box.get();System.out.println("Box #" + counter + "contains [" +boxContents + "]");counter++;}}}@Testpublic void test4() {//The type Inference of Generic class, since 1.7List<Box<Integer>> list = new ArrayList<>();BoxDemo.<Integer>addBox(Integer.valueOf(3), list);//The Type Inference of Generic MethodBoxDemo.addBox(4, list);BoxDemo.addBox(5, list);BoxDemo.outputBoxes(list);}//Target Typesvoid processStringList(List<String> stringList) {}processStringList(Collections.<string>emptyList());</string>

Wildcards

//Upper Bounded Wildcardspublic static double sumOfList(List<? extends Number> list) {    double s = 0.0;    for (Number n : list)        s += n.doubleValue();    return s;}//Unbounded Wildcardspublic static void printList(List<?> list) {    for (Object elem: list)        System.out.print(elem + " ");    System.out.println();}//Lower Bounded Wildcardspublic static void addNumbers(List<? super Integer> list) {    for (int i = 1; i <= 10; i++) {        list.add(i);    }}

Type Erasure

public class Node<T> {    private T data;    private Node<T> next;    public Node(T data, Node<t> next) }        this.data = data;        this.next = next;    }    public T getData() { return data; }    // ...}//Erasure of Generic Typespublic class Node {    private Object data;    private Node next;    public Node(Object data, Node next) {        this.data = data;        this.next = next;    }    public Object getData() { return data; }    // ...}//bounded type parameterpublic class Node<T> extends Comparable<T> {    private T data;    private Node<T> next;    public Node(T data, Node<t> next) {        this.data = data;        this.next = next;    }    public T getData() { return data; }    // ...}//The Java compiler replaces the bounded type parameter T with the first bound class, Comparable:public class Node {    private Comparable data;    private Node next;    public Node(Comparable data, Node next) {        this.data = data;        this.next = next;    }    public Comparable getData() { return data; }    // ...}//erasure of generic methodspublic static <T> int count(T[] anArray, T elem)public static int count(Object[] anArray, Object elem)//Suppose the following classes are defined:class Shape { /* ... */ }class Circle extends Shape { /* ... */ }class Rectangle extends Shape { /* ... */ }//You can write a generic method to draw different shapes:public static <T extends Shape> void draw(T shape) { /* ... */ }//The Java compiler replaces T with Shape:public static void draw(Shape shape) { /* ... */ }//bridge methodsclass MyNode extends Node<Integer> {    //bridge method generated by the compiler    public void setData(Object data) {      setData((Integer)data);    }}</t>

总结

//由于存在ErasureBox<String> box = new Box<>();Box<Integer> box1 = new Box<>();System.out.Println(box.getClass() == box1.getClass())//output: true
//Generic type的类型决断只在编译时起作用//可以通过reflect修改Generic type的值, 不受参数类型约束//类型限制只存在编译前,如果通过反射绕过编译器,则可以设置其他类型的值//Type parameter 要用Object.class替代,实际字节流中就是ObjectBox<Integer> box = new Box<>();Class<?> c = box.getClass();Method m = c.getMethod("set", new Class<?>[] {Object.class});m.invoke(box, "haha");System.out.println(box.get());//output: haha//获取类型参数TypeVariable[] tv = c.getTypeParameters();
//获取Generic Methods 相关信息public class GenericTest {           public static void main(String[] args) throws Exception {          Method method = GenericTest. class.getMethod("applyVector" , Vector.class);        Type[] types = method.getGenericParameterTypes();        ParameterizedType pType = (ParameterizedType)types[0];        System.out.println(pType.getRawType());        //结果:class java.util.Vector        System. out.println(pType.getActualTypeArguments()[0]);        //结果:class java.util.Date      }           public static void applyVector(Vector≶Date> v1){             }}
//不可以用原始数据类型实例化Generic TypeBox<int> box = new Box<>(); //非法
//不可以创建类型参数的实例 public static <E> void append(List<E> list) {    E e = new E(); //compile-time error}
//static修饰的成员的类型与类的类型参数相同class<T> Myclass {    public static <T> test() {} //complie-time error    public static T os;}
//不可以 Cast or instanceof with parameterized typespublic static void rtti(List<?> list) {   if (list instanceof ArrayList<Integer>) {      //compile-time error   }}List<integer> li = new ArrayList<>();List<number> ln = (List<number>)li; //compile-time error</number></number></integer>
//Cnnot create arrays of parameterized typesT[] arr = new T[0]; //compile-time error
//Cannot create, catch, or throw objects of parameterized type//you canclass Parser<T extends Exception> {     public void parse() throws T {     }}
//Cannot Overload a Method Where the Formal Parameter Types of Each Overload Erase to the Same Raw Typepublic class Example {    public void print(Set<string> strSet) { }    public void print(Set<integer> intSet) { }}//The overloads would all share the same classfile representation and will generate a compile-time error.</integer></string>

---------------------android培训、java培训、期待与您交流! -------------------------

0 0
原创粉丝点击