java中语法糖特性

在java中很多语法使用方式让人感觉都特别的奇怪。
下面就来介绍以下在java中一些比较 “调皮” 的使用方式,我们称之为语法糖。

静态引入:

     学过java的同学都知道,使用一个外部类,之前需要导入包。
一般我们导入的方式是,例如: import java.lang.Math*。之后我们就可以使用Math对象去调用该类的方法了,当然这里因为Math对象是java.lang包的类,所以我们不导入也是可以使用的。
     但是这种引入方式你是否使用过呢?例如:import static java.lang.Math.*; 这种引入方式你就在需要使用Math.abs(-324)了,而是直接使用abs(-324);是不是就是特别方便呢。
注意:但是这种方式有一个特别不好的地方就是,如果你自己也定义了一个同名的方法,这时候就会混淆了。因此虽然有这种方式但是并不推荐使用。



可变参数:

一般我们声明一个方法,形参中有数组类型是这样声明的。

public void test (String[] arr){

}

你是否使用过以下这种方式呢?

public void test(String . .  . arr){

}

总结:其上以上String…arr这种方式和String[ ] arr的效果是一样的,因为String …arr的的底层就是使用String[ ] arr。通过反编译课验证。



for-each:

for-each操作数组修改数组数据为什么不会影响元数据?
意思就是通过for-each的方式去修改数组中的元素,例如:

	int arr[]= {2,3,4};
		
		for(int t:arr) {
			t=232222;
			System.out.println(t);
		}
		
		//通过t修改之后,再遍历arr
		for(int tmp:arr) {
			System.out.println(tmp);
		}

输出结果:
232222
232222
232222
2
3
4

为什么这里修改tmp的值,arr数组中的值不会被修改呢?
让我们来看看与之相对应反编译后的代码:

int[] arr = new int[]{2, 3, 4};
		int[] var5 = arr;
		int var4 = arr.length;

		int t;
		int var3;
		for (var3 = 0; var3 < var4; ++var3) {
			int var10000 = var5[var3];
			t= 232222;
			System.out.println(t);
		}
		
		//通过t修改之后,再遍历arr
		var5 = arr;
		var4 = arr.length;

		for (var3 = 0; var3 < var4; ++var3) {
			tmp = var5[var3];
			System.out.println(tmp);
		}

结论:原来for-each内部使用的还是普通的for循环遍历的,至于为什么我们修改了t的值,对arr数组的元素没有影响。我们从反编译的代码可以看出,t是另外再声明出来的变量,而且这里又是基本数据类型,因此这里并不是修改的数组中的元素,因此是不会修改到元数据的。



java中的基本数据类型的包装数据类型的缓存机制

这个语法糖就比较有意思了,相信对于刚开始学java的同学来说,也是百思不得其解的地方。
举个例子:

	Integer a=100;
	Integer b=100;
		
	Integer c=200;
	Integer d=200;
		
	System.out.println(a==b);
	System.out.println(c==d);

输出结果:
true
false

相信很多同学在看到这个结果的时候,忍不住爆一句粗口了。

别急为什么会造成这种情况呢?这就是因为 java中包装数据类型的缓存机制 造成的。

Integer的部分源码:

 private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

结论: 从上面的源码可以看出在对于-128到127范围的数字,java对其作了优化,在该范围中包装类型Integer创建出来的对象指向的是同一个对象。

注意:除了Integer类,Byte、Short、Long、Character。包装类也有缓存机制,需要注意的是只有Character的缓存范围是在0到128。





以上就是对java中一些常见的语法糖的介绍了,希望对你有所帮助。

你可能感兴趣的:(java)