码迷,mamicode.com
首页 > 编程语言 > 详细

十(3)、泛型与数组以及泛型的边界

时间:2015-09-18 13:40:06      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:

一、首先要强调,数组不支持泛型

1.数组是编译期间检查并且要求有确定类型存在, 而泛型由于擦除的存在, 类型信息被删除, 所以数组不支持泛型。

见下例:

 1 import java.lang.reflect.Array;
 2 import java.util.Arrays;
 3 
 4 /**
 5 * 创建一个类,它支持泛型, 本意是希望提供一个方法,该方法
 6 * 能够根据泛型来返回一个该类型的数组
 7 */
 8 public class ArrayMarker<T> {
 9     private Class<T> kind;
10     public ArrayMarker(Class<T> kind) {
11         this.kind = kind;
12     }
13     
14     T[] create(int size) {//创建方法
15         return (T[])Array.newInstance(kind, size);
16     }
17     
18     public static void main(String[]args) {
19         ArrayMarker<String> stringMarker = 
20             new ArrayMarker<String>(String.class);
21         
22         String[] stringArray = stringMarker.create(9);
23         System.out.println(Arrays.toString(stringArray));
24     }
25 }

结果如下:

技术分享

可以看到, 虽然尝试传递类型, 但是由于泛型的存在将类型信息删除, 最终生成的只是null。

2.泛型删除的只是类型信息,而不是值本身

这点需要注意, 泛型并不会删除传过去的值本身, 只是传过去的值对它来说不再有原来的类型信息, 见下例:

 1 public class ArrayMarker<T> {
 2     private Class<T> kind;
 3     public ArrayMarker(Class<T> kind) {
 4         this.kind = kind;
 5     }
 6     
 7     T[] create(int size) {
 8         return (T[])Array.newInstance(kind, size);
 9     }
10     
11     T[] create2(T t,int size) {
12         T[] tarr = (T[])Array.newInstance(kind, size);
13         for(int i=0;i<tarr.length;i++) {
14             tarr[i] = t;//值设置
15         }
16         return tarr;
17     }
18     
19     public static void main(String[]args) {
20         ArrayMarker<String> stringMarker = 
21             new ArrayMarker<String>(String.class);
22         
23         String[] stringArray = stringMarker.create2("hello",4);
24         System.out.println(Arrays.toString(stringArray));
25     }
26 }

 

结果如下:

技术分享

并不是说由于擦除的存在,导致T本身,就变成Object了, 只是说它的具体类型信息Class里面的东西,被擦除掉, 但是方法指针什么还在,还能够调用a方法, 还能够显示T的值,只是T.t.getClass()的时候,返回的已经不是Weight 的类型信息了,它的类型信息已经被擦除 。

如果要关联上泛型来使用容器, 不要使用数组, 使用Collection,Map。

3.关于泛型和数组,再看两个例子:

 二、泛型的边界

 1.extends关键字

前面的博客中,有提到使用<T  extends HasF> 这种形式来确定边界 ,下面是一个更复杂的例子:

  1 import java.awt.Color;
  2 //定义一个颜色接口
  3 interface HasColor {
  4     Color getColor();
  5 }
  6 
  7 //定义一个着色类,注意 T这里继承的是接口,说明T也是接口类型
  8 class Colored<T extends HasColor> {
  9     T item;
 10     Colored(T item) {
 11         this.item = item;
 12     }
 13     T getItem() {
 14         return this.item;
 15     }
 16     
 17     Color color() {
 18         return item.getColor();
 19     }
 20 }
 21 
 22 //定义一个三维类
 23 class Dimension {
 24     public int x,y,z;
 25 }
 26 
 27 
 28 //这里报错,首先了解到可以用&来这么写, 另一个问题就是如果这么写,必须要先写类,后写接口
 29 //class ColoredDimension<T extends HasColor & Dimension> {
 30 //    
 31 //}
 32 
 33 class ColoredDimension<T extends Dimension & HasColor > {
 34     T item;
 35     public ColoredDimension(T item) {
 36         this.item = item;
 37     }
 38     
 39     T getItem() {
 40         return this.item;
 41     }
 42     
 43     Color color() {
 44         return item.getColor();
 45     }
 46     
 47     int getX() {
 48         return item.x;
 49     }
 50     
 51     int getY() {
 52         return item.y;
 53     }
 54     
 55     int getZ() {
 56         return item.z;
 57     }
 58     
 59 }
 60 
 61 interface Weight {
 62     int weight();
 63 }
 64 
 65 /**
 66  * 这里,还能够在泛型中extends关键字后面写多个接口
 67  */
 68 class Solid<T extends Dimension & HasColor & Weight> {
 69     T item;
 70     public Solid(T item) {
 71         this.item = item;
 72     }
 73     
 74     T getItem() {
 75         return this.item;
 76     }
 77     
 78     Color color() {
 79         return item.getColor();
 80     }
 81     
 82     int getX() {
 83         return item.x;
 84     }
 85     
 86     int getY() {
 87         return item.y;
 88     }
 89     
 90     int getZ() {
 91         return item.z;
 92     }
 93 
 94     public int weight() {
 95         return item.weight();
 96     }
 97 }
 98 
 99 /**
100  * 这里,继承Dimension ,并且实现HasColor,Weight接口,但是没采用泛型
101  */
102 class Bounded extends Dimension implements HasColor,Weight {
103     public Color getColor() {
104         return null;
105     }
106     
107     public int weight() {
108         return 0;
109     }
110 }
111 
112 public class BasicBounds {
113     public static void main(String[] agrs) {
114         Solid<Bounded> solid = new Solid<Bounded>(new Bounded());
115         
116         System.out.println(solid.color());
117         System.out.println(solid.getY());
118         System.out.println(solid.weight());
119     }
120 }

简单的理解,就是泛型可以用<T extends HasColor & Dimension> 这种形式来确定边界 ,extends哪个,就可以仍然拥有哪个类的方法(可以参考之前博客的例子) ,并且extends后面也可以接接口, 用&来连接。

但是不支持<T  implements  Dimension>这种形式。

2.extends关键字的反面 super关键字 (逆变)

首先看一个例子:

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 public class ConvariantArrays {
 5     public static void main(String[] args) {
 6         List<? extends Father> list = new ArrayList<Son>();
 7         list.add(null);
 8 //        list.add(new Father()); //报错
 9 //        list.add(new Son());    //报错
10 //        list.add(new Object()); //报错
11         
12     }
13 }
14 
15 class Father {}
16 
17 class Son extends Father {}

这里看似是只要extends Father的类都能放入,但是事实上除了放入null, 其他包括放Object都会报错。

但是类似的如果用super关键字

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 public class SuperTypeWildcards {
 5     
 6     public static void main(String[] args) {
 7         List<? super Apple> list = new ArrayList<Apple>();
 8         list.add(new Apple());
 9     }
10 }

这里可以成功。如果大神路过,求给个解释一下。

 

十(3)、泛型与数组以及泛型的边界

标签:

原文地址:http://www.cnblogs.com/kaiguoguo/p/4818809.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!