JAVA中的参数问题

本文详细介绍了Java中的可变参数(varargs)和泛型中的问号(? extends)的用法。可变参数允许方法接受任意数量的相同类型的参数,而泛型中的问号用于指定类型参数的上限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.可变参数

以前遇到java中参数有...的情况,这个是java的可变参数,也就是说java的方法的参数其实是可变的。

A.main方法可以写成如下的方式并且这个方法和(String []args)可以看做是同一个方法,不能同时存在:

public static void main(String... args){}
而且这种方法在调用的时候可以用一下调用方法:
main();
main(null);
main(null,null);
main(null,null,null);
......
main("a");
main("a","b");
main("a","b","c");
......
main(new String[]{});
(String...匹配String*,而null也可以是一个特殊的String)


B 参数位置
使用...的参数只能是最后一个参数.不然谁知道你调用的时候,点点点匹配到哪个实参?

public static void main(String[] args,int index)//可以
public static void main(String... args,int index)//不行!

C 重载

假设有以下两个方法:

public static void main(String... args)//方法1
public static void main(String a,String... args)//方法3
  从语法上来看,这个重载完全没有错误,eclipse也没有报错.但是当调用时使用的参数个数大于这些方法中点点点参数前面的参数个数时,eclipse就会发现这个错误了.很拗口是不是?嘿嘿~还是举例来说吧.以上这两个方法,如果调用时
  main();
  编译器会认出这个调用的是方法1.但是如果调用时
  main("");
  编译器就疯了...因为一个String参数,既符合方法1的点点点,也符合方法3的String+点点点,编译器就不知道调用的是哪个方法了.
  String[]参数不会有这种问题.
  所以重载时要注意,如果点点点参数前面有跟它类型相同的参数...最好的方法,似乎就是换回数组形式了,要么就给方法改个名字吧.


D遇上泛型加外包

用个实例来说
java.util.Arrays是个工具类,所有方法都是静态的,对数组的操作.里面有个方法asList(T... args),用来把类型T的数组转化成List<T>.
这是个很有用的方法,在绝大多数情况下都能如你所愿.
但是,你可以试试下面的写法
int[] is=...//自定义的数组,或者从什么地方获取来的数组
List<Integer> list=Arrays.asList(is);
很不幸,不要说执行,编译都通不过.错误的意思大概是:
不能将List<int[]>转化成List<Integer>
明白了吧?
你的设想是,把int[]中的每一个元素对应T...中的每一个点,
可编译器不这么想.因为int是原始类型,不是Object的子类.而泛型T隐含的条件是T extends Object.所以编译器不会把每一个int看做T,不会把int[]看做T点点点.虽然java已经支持自动将原始类型封包成外包类,但那是单个的情况.
而数组(不管什么类型)则是一种特殊的类型,是Object的子类,所以编译器觉得整个int[]对应一个T,你调用的方法是asList<int[]>(int[]... args)而不是你想象中的asList<Integer>(Integer...)

参考文档:http://hi.baidu.com/rcpsbwudesblmod/item/04b154d0b6054c94270ae766

二 泛型中的?的用途

以下是一个父类和子类

//类Parent
 public   class  Parent  {
  //  your code 
 } 
 
//类Child
 public   class  Child  extends  Parent {
 //  your code 
 }
再调用的时候
public   class  Test  {
     public   static   void  doTest(List < Parent >  list) {
        
    } 
      public static void  main(String[] args) {
        List < Parent >  parentList  =   new  ArrayList < Parent > ();
        List < Child >  childList  =   new  ArrayList < Child > ();
        doTest(parentList);
        // 注意这里编译错误 
        doTest(childList);
        
    } 
}
你会发现编译错误,但是在我们的需求中Child的集合类是可以代替Parent的集合类来使用的,但是因为编译器不认同,因为两个集合类之间没有直接的继承关系。如果实现呢?在Jdk1.5的Source中我们找到了答案,随便找一个带有泛型的类,点进去可以看到泛型的定义,例如ArrayList<E>  HashMap<K,V>  等等。


也就是我们把代码改成如下即可:

public   class  Test  {
      // 这里更改一下,利用问号解决问题  
      public   static   void  doTest(List <?   extends  Parent >  list) {
        
    } 
      public   static   void  main(String[] args) {
        List < Parent >  parentList  =   new  ArrayList < Parent > ();
        List < Child >  childList  =   new  ArrayList < Child > ();
        doTest(parentList);
        // 注意这里编译正确        
        doTest(childList)    } 
}


参考文档:http://www.blogjava.net/dreamstone/archive/2007/02/10/99195.html

总结一下,这里主要是jdk1.5之后一些不常用的参数方法,比如可变参数点点点和泛型问号的用法。


转载于:https://my.oschina.net/zimingforever/blog/138236

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值