在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的方式去修改数组中的元素,例如:
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的同学来说,也是百思不得其解的地方。
举个例子:
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中一些常见的语法糖的介绍了,希望对你有所帮助。