List泛型相互的转换的一些现象

 Java Code 
 
List是原生类型,那它可不可以转成List<String>   List<?>    List<? Extends T>  等等的类型,那么这些类型之间可以怎样转来转去呢,运行过程中却有可能出现什么样的异常,我今天就大胆提出一些自己的观点,欢迎指正
我这里首先要提出一个观点就是: 引用跟对象是两回事,引用(如List<String>)负责类型检测,而new 出来的对象跟这个泛型没关系,对象不检查类型。 
  我下面的讲述也会围绕这点展开



List


1
List list= new ArrayList();
我们都知道在不给List容器加泛型的情况下话,会有以下警告

java是支持、且希望你为那些泛型类的对象添加一个有泛型的引用来对这个对象进行更严格的操作的。
因而,原List引用所指的对象可以由List<Type> 、List<? ectends Type>  、List<? super Type> 指向,

List转List<String>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public   class  TestList
{
    
public   static   void  main( String [] args)
    {
        List list=
new  ArrayList();
        List<
String > list1= new  ArrayList< String >();

        
        list.add(
"回到家还是" ); 
        list.add(
123 );
        list.add(
12 . 34 );
        
        
        list1=list; 
//warnings  类型安全:类型 List 的表达式需要进行未经检查的转换以符合 List<String>
        System.out.println(list1.get( 1 ));  //正常输出"回到家还是"
        System.out.println(list1.get( 0 )); //出现异常ClassCastException
        
        System.out.println(list1);
//此操作不会出现异常,因为toString不涉及泛型
    }

}


我应该说的准确一点, list1=list;这一步操作不叫转成,应该叫做:用  List<String> list1的这个引用操作  List list所指的对象new ArrayList();

解析一下:对象跟应用是两回事,在泛型中 类型检测是由引用来进行的的(不懂的朋友请参考这篇文章


用  List<String> list1 的这个引用去操作  List list所指的对象new ArrayList()是可以的,

首先、在   List list=new ArrayList(); 这一步中  list所指对象里面存的是Object


其次、 List<String> list1=new ArrayList<String>()   list1=list 用list1这个引用指向 list所指的那个对

象 new ArrayList()后,这样 new ArrayList()就只能执行更严格的操作,只能往里面存放String类型的数据,所以编译

器允许你这样做。但是很有可能在进行  list1=list  前 new ArrayList()这个对象已经放进了其他类型的数据(8 到10

 行),因而在在取出非String类型数据的时候,会出现转换异常


List转List<? extends Number> 

Java Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public  class TestList
{
     public  static  void main( String[] args)
    {
        List list= new ArrayList();
        list.add( 123);
        list.add( 33. 7);
        list.add( "cc");
        
        List<?  extends Number> list1=list;
        
        Number b=list1.get( 2); //运行时出错 ClassCastException

    }

}
道理跟上面的一样因为   List<? extends  Number> list1=list;List<? extends Number> list1引用能对 list所指

的 new ArrayList() 的对象执行更严格的操作,所以编译允许这样的操作通过。但是有可能  list1=list;之前的就已经放

了其他非Number的数据,所以在取出数据的时候可能发生ClassCastException异常。


List转List<? super Integer

 Java Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public  class TestList
{
     public  static  void main( String[] args)
    {
        
        List list= new ArrayList();
        list.add( 12. 34);
        list.add( "每一天");
        List<?  super Integer> listSup=list;  //
        listSup.add( 123);
                
         for ( int i =  0; i < list.size(); i++)
        {
            Object obj = listSup.get(i);
            System.out.println(obj);
        }
    }

}
这种情况跟上面有点特别   listSup = list 之前无论 list所指对象里面放了什么类型的数据,在listSup 指向后,仍能正常的取出数据而不出现ClassCastExcption异常,因为 List<? super Integer> 引用取出的都是Object对象。





List<? extends Type>  & List<? super  Type>

对于泛型对象(List容器),java希望没有通配符的尽量要有通配符,所以你可以看到上面的List可以转成List<Type> 、List<? ectends Type>  、List<? super Type>
等,但是对于已经有泛型的,他就要求准确,只能小的往大的转
1
2
3
4
List<?  extends Number> =  List<Integer> 
List<?  extends Number> =  List<?  extends Integer>
List<?  super Integer> =  List<?  super Number>
//语法肯定不对,只是做个比喻


List<? extends Object> 转 List<String>

 Java Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public  class TestList
{
     public  static  void main( String[] args)
    {
        List<?  extends Object> list_Exends_Object;
        List<?  extends  String> list_Exends_String;

        List< String> list_String =  new ArrayList< String>();
        
        
        list_String=list_Exends_String;  //error 
                                  //类型不匹配:不能从 List<capture#1-of ? extends String> 转换为 List<String>
        list_String=list_Exends_ Object;   //error 

    }

}
List<? extends Object> 所指的对象可能是专门放String 的List(List<String>)、专门放放Object的List(List<Object>)、、、都有可能。如果  list_String=list_Exends_Object;  这个操作成功,不就说你可以用 

List<String> list_String 这个引用去操纵一个可能是 Object、String、Number等的对象,List<String> list_String 这个

引用的泛型就表明只能往所指的对象Set 、Get  String对象,总不可能往Number对象中放String对象吧。




如果 List<String>List_String = list_Exends_Object;成功,不就意味着可以往 List<? extends Object> list_Exends_Object这个原来所指的对象放入String,

即:

 Java Code 
1
2
3
4
List< String> list= new ArrayList< String>();
List<?  extends Object> list_Exend_Object=list;
        
List< String> list_String = ist_Exend_Object; // error


因为新的引用是List<String>啊,但是原来的引用 List<? extends Object> list_Exends_Object所指向的具体对象是Number、还是String、或其他的,编译器根本不知

道,因而它不会让你一错再错。





List<? extends Number> 转 List<? extends Integer>

1
2
3
4
5
6
7
8
9
10
11
12
public  class TestList
{
     public  static  void main( String[] args)
    {
        List<?  extends Number> listN=null;
        List<?  extends Integer> listI=null;
            
        listN=listI;
         //listI=listN; 编译不通过,类型不匹配
    }

}
在这里 引用 List<? extends Number> listN 可以指向 List<? extends Integer> listI 的 对象,但是反过来却不可以。

理由也很简单如果引用 List<? extends Integer> listI 可以指向  List<? extends Number> listN所指的对象,就有可能出错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public  class TestList
{
     public  static  void main( String[] args)
    {
        List<?  extends Number> listN= new ArrayList<Number>();
              //listN 指向的是一个 只允许放 Number的 ArrayList
        List<?  extends Integer> listI=null;
        
        

        listI=listN;  //实际是错误的,在这里假设可行
        listI.get( 0); 
                    //返回的将是一个Integr
                    //原来的ArrayList放的是Number
                   //Number不一定可以转换成Integer
    }

}


List<? extends Type> 转 List<? super Type>

List<? extends AnyType> 引用是不能指向 List<? super AnyType> 所指的对象的,反过来也一样,因为 ? super Type   与  ? extends  Type 之间总是会有交集的,不存

在谁包含谁的关系。

 Java Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
public  class TestList
{
     public  static  void main( String[] args)
    {
        List<?  extends Number> listExt=null;            
        List<?  super Integer> listSup=null;
        
         //listExt=listSup;  
         //listSup=listExt;

    }

}






List<? >等价于 List<? extends Object>

List<? >的情况跟List<? extends Object>一样,以后我会另写文章论述





这是我的一己之见,上面内容纯粹是个人的猜测,难免会有错,请各位指正。

参考文章: http://blog.csdn.net/lonelyroamer/article/details/7868820


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值