JavaSE第五十八讲:可变参数详解

1. 参考前几讲的一个例子:MapTest4.java [用户输入单词,统计单词个数的例子],用自动装箱/拆箱的形式将其实现:

package com.ahuier.jdk5;

import java.util.HashMap;
import java.util.Map;

public class Frequency {
	public static void main(String[] args) {
		//使用Map存储数据,key为单词String类型,value为单词个数Integer类型
		Map<String, Integer> map = new HashMap<String, Integer>();
		
		//遍历传递的参数args(就是输入的单词)
		for(String word : args){
			
//			map.put(word, (null == map.get(word)) ? 1 : map.get(word) + 1); 一行代码实现下面的功能
			
			//判断输入的单词是否存在,如果不存在,则置1,如果已经存在,则再原有基础上+1.
			Integer freq = map.get(word);
			map.put(word, (null == freq) ? 1 : freq + 1); //传入的1,实际上用到了自动装箱		
		}
		System.out.println(map);
	}
}

2.  Integer类有一个缓存,它会缓存介于-128~127之间的整数。  比较以下两个程序,剖析Integer类的源代码

程序一:

package com.ahuier.jdk5;

public class BoxTest2 {
	public static void main(String[] args) {
		Integer i1 = 100;
		Integer i2 = 100;
		
		if(i1 == i2){
			System.out.println("i1 == i2");
		}
		else{
			System.out.println("i1 != I2");
		}
	}
}

编译执行结果:i1 == i2

程序二:

package com.ahuier.jdk5;

public class BoxTest2 {
	public static void main(String[] args) {
		Integer i1 = 200;
		Integer i2 = 200;
		
		if(i1 == i2){
			System.out.println("i1 == i2");
		}
		else{
			System.out.println("i1 != I2");
		}
	}
}
编译执行结果:

i1 != I2

【说明】:同样的程序结构,仅是修改数值,程序结果就矛盾了。剖析Integer源代码,掌握其原因

    public static Integer valueOf(int i) {
	final int offset = 128;
	if (i >= -128 && i <= 127) { // must cache 
	    return IntegerCache.cache[i + offset];
	}
        return new Integer(i);
    }

继续跟踪IntegerCache

    private static class IntegerCache {
	private IntegerCache(){}

	static final Integer cache[] = new Integer[-(-128) + 127 + 1];

	static {
	    for(int i = 0; i < cache.length; i++)
		cache[i] = new Integer(i - 128);
	}
    }
[-128,127]这一部分之间的256个数是被Integer被缓存起来了。正好是byte 类型的范围。

当你使用自动装箱的机制生成一个Integer对象是100的话,它便不会给你生成一个新的对象,而是使用缓存里面的对象。

Integer i1 = 100;
Integer i2 = 100; //第二次自动装箱生成的100是使用缓存里面的对象


当你使用自动装箱的机制生成一个Integer对象是200的话,它便不会给你生成一个新的对象,而是使用缓存里面的对象。

Integer i1 = 200;
Integer i2 = 200; //超过Integer缓存范围,重新生成一个对象。

所以便有程序一是相等,而程序是不相等的。

查看JDK Doc中的valueOf()方法:

valueOf
  public static Integer valueOf(int i)
    Returns a Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. 

【注意,这边如果是用Integer的构造方法的时候是不存在缓存这个概念的,new一次的就生成一个对象,new出来的两个对象它们判断肯定是不相同的】

3. 这边的自动装箱/拆箱都是针对来Integer来讲的,其他的八个原生数据类型都是一样的方式。下面继续讲解JDK 5.0的其他新特性:

可变参数详解(Varargs)

可变参数使程序员可以声明一个接受可变数目参数的方法。注意,可变参数必须是方法声明中的最后一个参数

package com.ahuier.jdk5;

public class TestVarargs {
	
	//以前传递多个参数要这样写
/*	private static int sum(int a, int b, int c){
		
	}*/ 
	/*
	 * 现在利用Java中的可变参数可以这样写
	 * int... 相当于int[],注意这边如果定义成数组了,则它就必须传递数组,而非类似下面的离散值了
	 * 如果方法接受两个或者两个以上参数的时候,例如:private static int sum(int... nums, String str)这样写是不合法的,可变参数必须放在最末尾
	 * 所以方法需要接受可变参数必须只能接受一个,不能接受两个或者两个以上,因为这样必然有一个可变参数不再末尾,导致语法错误。
	 */
	private static int sum(String str, int... nums){
		System.out.println(str);
		int sum = 0;
		for(int num : nums){
			sum = sum + num;
		}
		return sum;
	}
	public static void main(String[] args) {
		int result = sum("a", 1, 2);
		System.out.println(result);
		
		result = sum("a", new int[]{1, 2}); //由于可变参数本质上是一个数组,所以在传递参数的时候可以这样传递
		System.out.println(result);
		
		result = sum("a", 1, 2, 3, 4);
		System.out.println(result);
	}
}
编译执行结果:

a
3
a
3
a
10

【总结】:

1. 可变参数:可变参数本质上就是一个数组,对于某个声明了可变参数的方法来说我们既可以传递离散的值,也可以传递数组对象。但如果将方法中的参数定义为数组,那么只能传递数组对象而不能传递离散的值。 

2. 可变参数必须要作为方法参数的最后一个参数,即一个方法不可能具有两个或两个以上的可变参数。 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值