可以把List<String>传递给一个接受List<Object>参数的方法吗?

讨论了在Java中List&lt;String&gt;是否可以作为参数传递给接受List&lt;Object&gt;的方法,并解释了泛型传递的原理。


打印  上一主题  下一主题

可以把List<String>传递给一个接受List<Object>参数的方法吗? 

[复制链接]

该用户从未签到

13

黑马币

25

技术分

11

主题

中级黑马

Rank: 3Rank: 3

跳转到指定楼层
楼主
  发表于 2014-8-11 12:52:21  |  只看该作者  回帖奖励
本帖最后由 jiangweibin2573 于 2014-8-11 13:30 编辑

如果一个方法定义接受的参数是List<Object>;我可以把List<String>传给该方法吗?为什么!
就想下面这样
  1. import java.util.*;

  2. public class Test {

  3.         public static void main(String[] args) {
  4.                 List<String> str = new ArrayList<>();
  5.                 printList(str);
  6.         }

  7.         public static void printList(List<Object> str) {
  8.                 Iterator it = str.iterator();
  9.                 while(it.hasNext()){
  10.                         System.out.println(it.next());
  11.                 }
  12.         }
  13. }
复制代码

 

该用户从未签到

20

黑马币

25

技术分

14

主题

中级黑马

Rank: 3Rank: 3

沙发
  发表于 2014-8-11 13:00:31  |  只看该作者
可以啊,所有类都继承Object。传递后相当于多态了。
 
 

该用户从未签到

171

黑马币

91

技术分

17

主题

金牌黑马

Rank: 5Rank: 5

黑马骑士勋章

藤椅
  发表于 2014-8-11 13:03:11  |  只看该作者
不行吧,你让一个能管大学生中学生小学生的老师(List<Object>)去管一个能管中学生的老师(List<String>),合适吗?
 
 

该用户从未签到

112

黑马币

49

技术分

14

主题

中级黑马

Rank: 3Rank: 3

板凳
  发表于 2014-8-11 13:04:22  |  只看该作者
不行不行..
 
 

该用户从未签到

13

黑马币

25

技术分

11

主题

中级黑马

Rank: 3Rank: 3

报纸
  楼主 |  发表于 2014-8-11 13:11:20  |  只看该作者
fantacyleo 发表于 2014-8-11 13:03
不行吧,你让一个能管大学生中学生小学生的老师(List)去管一个能管中学生的老师(List),合适吗? ...

但是,我这个问题,按你的比方来说,我这么描述:将一个中学老师交给一个可以管大、中、小学老师的机构,不可以吗
 
 

该用户从未签到

171

黑马币

91

技术分

17

主题

金牌黑马

Rank: 5Rank: 5

黑马骑士勋章

地板
  发表于 2014-8-11 13:16:45  |  只看该作者
jiangweibin2573 发表于 2014-8-11 13:11
但是,我这个问题,按你的比方来说,我这么描述:将一个中学老师交给一个可以管大、中、小学老师的机构, ...

当然不可以。如果你认为List<String>是中学老师,那么List就是老师,你又怎么能把List<Object>的List解读为机构呢?
财经专业出身的编程爱好者~绝不发水帖,偶尔回复水帖~
 

该用户从未签到

13

黑马币

25

技术分

11

主题

中级黑马

Rank: 3Rank: 3

7#
  楼主 |  发表于 2014-8-11 13:26:53  |  只看该作者
fantacyleo 发表于 2014-8-11 13:16
当然不可以。如果你认为List是中学老师,那么List就是老师,你又怎么能把List的List解读为机构呢? ...

String是一个对象,Object可以接受任意类型对象。
这个问题中,我是把List<String>当参数去传给一个方法,不知道具体为啥不行。
List<String>是实际参数,List<Object>是形式参数,形参可以接受的范围不是已经包括了实参范围吗?
 
 

该用户从未签到

38

黑马币

26

技术分

15

主题

中级黑马

Rank: 3Rank: 3

8#
  发表于 2014-8-11 13:39:07  来自手机  |  只看该作者
泛型中写什么就是什么吧,不考虑继承
 
 

该用户从未签到

101

黑马币

37

技术分

3

主题

中级黑马

Rank: 3Rank: 3

9#
  发表于 2014-8-11 13:44:35  |  只看该作者
完整的写法是 List<? extends Object> list
在这里 extends Object 是必然的,可以写作 List<?> list
不要用 str 命名不是字符串的东西…
 
 

该用户从未签到

171

黑马币

91

技术分

17

主题

金牌黑马

Rank: 5Rank: 5

黑马骑士勋章

10#
  发表于 2014-8-11 13:58:16  |  只看该作者
jiangweibin2573 发表于 2014-8-11 13:26
String是一个对象,Object可以接受任意类型对象。
这个问题中,我是把List当参数去传给一个方法,不知道 ...

。。。又回到我之前打的比方上了。这样吧,再说一个编译通不过的例子:
List<Fruit> fruits =  new ArrayList<Apple>();

左边是一个装水果的容器,右边是一个装苹果的容器。你可以用装水果的容器装苹果,但用装水果的容器去装一个装苹果的容器就不合适了吧?
财经专业出身的编程爱好者~绝不发水帖,偶尔回复水帖~
 

该用户从未签到

43

黑马币

25

技术分

22

主题

中级黑马

Rank: 3Rank: 3

11#
  发表于 2014-8-11 14:31:32  |  只看该作者
没试过,不过根据多态应该可以,楼主可以试试
 
 

该用户从未签到

79

黑马币

27

技术分

10

主题

中级黑马

Rank: 3Rank: 3

QQ
12#
  发表于 2014-8-11 20:58:37  |  只看该作者
是不可以的.list是泛型,也就是传入的这个类,是告诉人家有这么一个类型 。是不会考虑继承关系的
 
 

该用户从未签到

70

黑马币

33

技术分

54

主题

中级黑马

Rank: 3Rank: 3

13#
  发表于 2014-8-11 22:39:35  |  只看该作者
很简单,String是一个对象的基本类型,而Object是所有类的父类,这是两个不相关的概念.
 
 

该用户从未签到

226

黑马币

58

技术分

16

主题

高级黑马

Rank: 4

黑马骑士勋章

14#
  发表于 2014-8-12 08:43:37  |  只看该作者
无耻的借用一下张老师的PPT:使用泛型的注意事项:

          参数化类型可以引用一个原始类型的对象,编译报告警告,例如,
          Collection<String> c = new Vector();//可不可以,不就是编译器一句话的事吗?

          原始类型可以引用一个参数化类型的对象,编译报告警告,例如,
          Collection c = new Vector<String>();//原来的方法接受一个集合参数,新的类型也要能传进去

          参数化类型不考虑类型参数的继承关系:

          Vector<String> v = new Vector<Object>(); //错误!///不写<Object>没错,写了就是明知故犯

          Vector<Object> v = new Vector<String>(); //也错误!

          编译器不允许创建泛型变量的数组。即在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:

            Vector<Integer> vectorList[] = new Vector<Integer>[10];

          泛型中的类型参数严格说明集合中装载的数据类型是什么和可以加入什么类型的数据,注意:Collection<String>和Collection<Object>是两个没有转换关系的参数化的类型。

          假设Vector<String> v = new Vector<Object>();可以的话,那么以后从v中取出的对象当作String用,而v实际指向的对象中可以加入任意的类型对象;假设Vector<Object> v = new Vector<String>();可以的话,那么以后可以向v中加入任意的类型对象,而v实际指向的集合中只能装String类型的对象。肯定会报错了



 
 

该用户从未签到

26

黑马币

25

技术分

2

主题

中级黑马

Rank: 3Rank: 3

QQ
15#
  发表于 2014-8-12 09:00:30  |  只看该作者
是不行的,高新里面有说到泛型,这么做是明知故犯,编译不通过的
 
 

该用户从未签到

22

黑马币

30

技术分

7

主题

中级黑马

Rank: 3Rank: 3

16#
  发表于 2014-8-12 09:40:52  |  只看该作者
不可以,因为形参List<Object>声明的是什么类型都可以装,而List<String>只能装String类型的。泛型中不存在继承关系。当你把List<String>作为实参传入形参为List<Object>的时候,就相当于是:List<Object> str = new List<String>(),这两个集合类型想让是不一样的。
 
 

该用户从未签到

170

黑马币

28

技术分

11

主题

中级黑马

Rank: 3Rank: 3

QQ
17#
  发表于 2014-8-12 10:12:42  |  只看该作者
貌似有点那么一点感觉,我看到这个就想起了转型,你传入一个很大范围的类型对象到接收一个很小范围的类型变量的方法中去肯定也要进行强转的啊,个人觉得不行。。。
很懒没留
 

该用户从未签到

20

黑马币

25

技术分

22

主题

中级黑马

Rank: 3Rank: 3

18#
  发表于 2014-8-12 16:14:02  |  只看该作者
等式两边可以在任意一边使用泛型,在另一边不使用(考虑向后兼容);
ArrayList<String> al = new ArrayList<Object>();  //错
//要保证左右两边的泛型具体类型一致就可以了,这样不容易出错。
ArrayList<? extends Object> al = new ArrayList<String>();
上面这种是可以的,但是不能进行添加,因为仍然不清楚引用的类型到底是什么
al.add("aa");  //错
就相当于你只知道老虎在动物园里,但是却不知道把老虎添加到哪个笼子里一样。
 
 

该用户从未签到

62

黑马币

13

技术分

2

主题

中级黑马

Rank: 3Rank: 3

19#
  发表于 2014-8-12 16:28:58  |  只看该作者
学习来的.......
 
 

该用户从未签到

13

黑马币

25

技术分

11

主题

中级黑马

Rank: 3Rank: 3

20#
  楼主 |  发表于 2014-8-12 16:41:16  |  只看该作者
a6511631 发表于 2014-8-12 08:43
无耻的借用一下张老师的PPT:使用泛型的注意事项:
          参数化类型可以引用一个原始类型的对象,编译 ...

他只是这么说的,没怎么透彻
打印  上一主题  下一主题

可以把List<String>传递给一个接受List<Object>参数的方法吗? 

[复制链接]

该用户从未签到

13

黑马币

25

技术分

11

主题

中级黑马

Rank: 3Rank: 3

跳转到指定楼层
楼主
  发表于 2014-8-11 12:52:21  |  只看该作者  回帖奖励
本帖最后由 jiangweibin2573 于 2014-8-11 13:30 编辑

如果一个方法定义接受的参数是List<Object>;我可以把List<String>传给该方法吗?为什么!
就想下面这样
  1. import java.util.*;

  2. public class Test {

  3.         public static void main(String[] args) {
  4.                 List<String> str = new ArrayList<>();
  5.                 printList(str);
  6.         }

  7.         public static void printList(List<Object> str) {
  8.                 Iterator it = str.iterator();
  9.                 while(it.hasNext()){
  10.                         System.out.println(it.next());
  11.                 }
  12.         }
  13. }
复制代码

 

该用户从未签到

20

黑马币

25

技术分

14

主题

中级黑马

Rank: 3Rank: 3

沙发
  发表于 2014-8-11 13:00:31  |  只看该作者
可以啊,所有类都继承Object。传递后相当于多态了。
 
 

该用户从未签到

171

黑马币

91

技术分

17

主题

金牌黑马

Rank: 5Rank: 5

黑马骑士勋章

藤椅
  发表于 2014-8-11 13:03:11  |  只看该作者
不行吧,你让一个能管大学生中学生小学生的老师(List<Object>)去管一个能管中学生的老师(List<String>),合适吗?
 
 

该用户从未签到

112

黑马币

49

技术分

14

主题

中级黑马

Rank: 3Rank: 3

板凳
  发表于 2014-8-11 13:04:22  |  只看该作者
不行不行..
 
 

该用户从未签到

13

黑马币

25

技术分

11

主题

中级黑马

Rank: 3Rank: 3

报纸
  楼主 |  发表于 2014-8-11 13:11:20  |  只看该作者
fantacyleo 发表于 2014-8-11 13:03
不行吧,你让一个能管大学生中学生小学生的老师(List)去管一个能管中学生的老师(List),合适吗? ...

但是,我这个问题,按你的比方来说,我这么描述:将一个中学老师交给一个可以管大、中、小学老师的机构,不可以吗
 
 

该用户从未签到

171

黑马币

91

技术分

17

主题

金牌黑马

Rank: 5Rank: 5

黑马骑士勋章

地板
  发表于 2014-8-11 13:16:45  |  只看该作者
jiangweibin2573 发表于 2014-8-11 13:11
但是,我这个问题,按你的比方来说,我这么描述:将一个中学老师交给一个可以管大、中、小学老师的机构, ...

当然不可以。如果你认为List<String>是中学老师,那么List就是老师,你又怎么能把List<Object>的List解读为机构呢?
财经专业出身的编程爱好者~绝不发水帖,偶尔回复水帖~
 

该用户从未签到

13

黑马币

25

技术分

11

主题

中级黑马

Rank: 3Rank: 3

7#
  楼主 |  发表于 2014-8-11 13:26:53  |  只看该作者
fantacyleo 发表于 2014-8-11 13:16
当然不可以。如果你认为List是中学老师,那么List就是老师,你又怎么能把List的List解读为机构呢? ...

String是一个对象,Object可以接受任意类型对象。
这个问题中,我是把List<String>当参数去传给一个方法,不知道具体为啥不行。
List<String>是实际参数,List<Object>是形式参数,形参可以接受的范围不是已经包括了实参范围吗?
 
 

该用户从未签到

38

黑马币

26

技术分

15

主题

中级黑马

Rank: 3Rank: 3

8#
  发表于 2014-8-11 13:39:07  来自手机  |  只看该作者
泛型中写什么就是什么吧,不考虑继承
 
 

该用户从未签到

101

黑马币

37

技术分

3

主题

中级黑马

Rank: 3Rank: 3

9#
  发表于 2014-8-11 13:44:35  |  只看该作者
完整的写法是 List<? extends Object> list
在这里 extends Object 是必然的,可以写作 List<?> list
不要用 str 命名不是字符串的东西…
 
 

该用户从未签到

171

黑马币

91

技术分

17

主题

金牌黑马

Rank: 5Rank: 5

黑马骑士勋章

10#
  发表于 2014-8-11 13:58:16  |  只看该作者
jiangweibin2573 发表于 2014-8-11 13:26
String是一个对象,Object可以接受任意类型对象。
这个问题中,我是把List当参数去传给一个方法,不知道 ...

。。。又回到我之前打的比方上了。这样吧,再说一个编译通不过的例子:
List<Fruit> fruits =  new ArrayList<Apple>();

左边是一个装水果的容器,右边是一个装苹果的容器。你可以用装水果的容器装苹果,但用装水果的容器去装一个装苹果的容器就不合适了吧?
财经专业出身的编程爱好者~绝不发水帖,偶尔回复水帖~
 

该用户从未签到

43

黑马币

25

技术分

22

主题

中级黑马

Rank: 3Rank: 3

11#
  发表于 2014-8-11 14:31:32  |  只看该作者
没试过,不过根据多态应该可以,楼主可以试试
 
 

该用户从未签到

79

黑马币

27

技术分

10

主题

中级黑马

Rank: 3Rank: 3

QQ
12#
  发表于 2014-8-11 20:58:37  |  只看该作者
是不可以的.list是泛型,也就是传入的这个类,是告诉人家有这么一个类型 。是不会考虑继承关系的
 
 

该用户从未签到

70

黑马币

33

技术分

54

主题

中级黑马

Rank: 3Rank: 3

13#
  发表于 2014-8-11 22:39:35  |  只看该作者
很简单,String是一个对象的基本类型,而Object是所有类的父类,这是两个不相关的概念.
 
 

该用户从未签到

226

黑马币

58

技术分

16

主题

高级黑马

Rank: 4

黑马骑士勋章

14#
  发表于 2014-8-12 08:43:37  |  只看该作者
无耻的借用一下张老师的PPT:使用泛型的注意事项:

          参数化类型可以引用一个原始类型的对象,编译报告警告,例如,
          Collection<String> c = new Vector();//可不可以,不就是编译器一句话的事吗?

          原始类型可以引用一个参数化类型的对象,编译报告警告,例如,
          Collection c = new Vector<String>();//原来的方法接受一个集合参数,新的类型也要能传进去

          参数化类型不考虑类型参数的继承关系:

          Vector<String> v = new Vector<Object>(); //错误!///不写<Object>没错,写了就是明知故犯

          Vector<Object> v = new Vector<String>(); //也错误!

          编译器不允许创建泛型变量的数组。即在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:

            Vector<Integer> vectorList[] = new Vector<Integer>[10];

          泛型中的类型参数严格说明集合中装载的数据类型是什么和可以加入什么类型的数据,注意:Collection<String>和Collection<Object>是两个没有转换关系的参数化的类型。

          假设Vector<String> v = new Vector<Object>();可以的话,那么以后从v中取出的对象当作String用,而v实际指向的对象中可以加入任意的类型对象;假设Vector<Object> v = new Vector<String>();可以的话,那么以后可以向v中加入任意的类型对象,而v实际指向的集合中只能装String类型的对象。肯定会报错了



 
 

该用户从未签到

26

黑马币

25

技术分

2

主题

中级黑马

Rank: 3Rank: 3

QQ
15#
  发表于 2014-8-12 09:00:30  |  只看该作者
是不行的,高新里面有说到泛型,这么做是明知故犯,编译不通过的
 
 

该用户从未签到

22

黑马币

30

技术分

7

主题

中级黑马

Rank: 3Rank: 3

16#
  发表于 2014-8-12 09:40:52  |  只看该作者
不可以,因为形参List<Object>声明的是什么类型都可以装,而List<String>只能装String类型的。泛型中不存在继承关系。当你把List<String>作为实参传入形参为List<Object>的时候,就相当于是:List<Object> str = new List<String>(),这两个集合类型想让是不一样的。
 
 

该用户从未签到

170

黑马币

28

技术分

11

主题

中级黑马

Rank: 3Rank: 3

QQ
17#
  发表于 2014-8-12 10:12:42  |  只看该作者
貌似有点那么一点感觉,我看到这个就想起了转型,你传入一个很大范围的类型对象到接收一个很小范围的类型变量的方法中去肯定也要进行强转的啊,个人觉得不行。。。
很懒没留
 

该用户从未签到

20

黑马币

25

技术分

22

主题

中级黑马

Rank: 3Rank: 3

18#
  发表于 2014-8-12 16:14:02  |  只看该作者
等式两边可以在任意一边使用泛型,在另一边不使用(考虑向后兼容);
ArrayList<String> al = new ArrayList<Object>();  //错
//要保证左右两边的泛型具体类型一致就可以了,这样不容易出错。
ArrayList<? extends Object> al = new ArrayList<String>();
上面这种是可以的,但是不能进行添加,因为仍然不清楚引用的类型到底是什么
al.add("aa");  //错
就相当于你只知道老虎在动物园里,但是却不知道把老虎添加到哪个笼子里一样。
 
 

该用户从未签到

62

黑马币

13

技术分

2

主题

中级黑马

Rank: 3Rank: 3

19#
  发表于 2014-8-12 16:28:58  |  只看该作者
学习来的.......
 
 

该用户从未签到

13

黑马币

25

技术分

11

主题

中级黑马

Rank: 3Rank: 3

20#
  楼主 |  发表于 2014-8-12 16:41:16  |  只看该作者
a6511631 发表于 2014-8-12 08:43
无耻的借用一下张老师的PPT:使用泛型的注意事项:
          参数化类型可以引用一个原始类型的对象,编译 ...

他只是这么说的,没怎么透彻
<think>嗯,用户问的是Java中是否可以把List<String>传递接受List<Object>参数方法。这个问题涉及到Java泛型的继承规则,我得仔细想想。 首先,我记得Java的泛型是不变的,也就是说List<String>并不是List<Object>的子类型。虽然String是Object的子类,但List<String>和List<Object>在类型系统里是无关的。所以直接传递的话,编译器应该会报类型不匹配的错误。 然后,用户可能遇到这样的情况,比如有一个方法参数是List<Object>,他们可能想传入一个包含字符串的列表。这时候如果直接传,确实不行。那有没有解决办法呢?可能需要使用通配符或者类型转换。 比如,使用通配符<? extends Object>,这样方法参数可以接受任何泛型类型为Object子类的List。或者,在调用方法的时候进行类型转换,不过这样可能会有警告,需要加上@SuppressWarnings("unchecked")。 不过,这样做会有类型安全的风险。如果方法里往列表里添加非String的元素,可能会导致运行时错误。所以需要确保方法不会修改列表的内容,或者使用不可变的列表。 另外,Java的数组在这方面和泛型不同,数组是协变的,所以String[]可以赋值给Object[],但泛型不是这样的。这也是为什么Java泛型更安全,避免了一些运行时错误。 用户可能在实际开发中遇到了这样的问题,比如在处理集合类的时候,想要传递不同类型的列表,但被编译器阻止了。这时候他们需要了解泛型的设计原则和如何正确使用通配符来解决这个问题。 总结下来,直接传递是不允许的,但可以通过通配符或者强制转换来实现,同时需要注意类型安全和潜在的风险。需要向用户解释清楚原因,并提供解决方案和注意事项。</think>在Java中,$List<String>$ 不能直接传递接受 $List<Object>$ 参数方法。这是由Java泛型的不变性(Invariance)决定的[^1]。以下是逐步分析: 1. **类型不兼容性** Java的泛型设计遵循类型擦除原则,且泛型类型参数不具备协变性(Covariance)。虽然 $String$ 是 $Object$ 的子类,但 $List<String>$ 和 $List<Object>$ 在类型系统中被视为完全无关的类型。尝试直接传递会导致编译错误: ```java void process(List<Object> list) {} List<String> strings = new ArrayList<>(); process(strings); // 编译错误:类型不匹配 ``` 2. **通配符解决方案** 若需要实现类似功能,可通过泛型通配符 $? extends Object$ 定义方法参数: ```java void processWildcard(List<? extends Object> list) {} List<String> strings = new ArrayList<>(); processWildcard(strings); // 合法 ``` 这种写法允许接受任何泛型类型为 $Object$ 子类的列表,但代价是无法向列表添加新元素(只能读取)[^1]。 3. **强制类型转换的风险** 强制转换虽然能绕过编译器检查,但会破坏类型安全: ```java @SuppressWarnings("unchecked") void processUnsafe(List<Object> list) {} processUnsafe((List<Object>)(List<?>) strings); // 运行时可能引发问题 ``` 若方法内部尝试添加非 $String$ 对象,会导致运行时 $ClassCastException$。 4. **设计建议** - 优先使用通配符定义方法参数(如 $List<? extends T>$) - 若需要写入操作,应要求调用方传递精确匹配的类型 - 考虑使用泛型方法定义: ```java <T> void processGeneric(List<T> list) {} ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值