参照元:「Java仮想マシンの深い理解、」周志明前進を
最後の章:Javaのシンタックスシュガー-ジェネリック医薬品と型消去
自動梱包・開梱トラバーサルサイクルは、我々はJavaの内部のほとんどで使用するものです。
右の例オフましょうスタート
public class Test {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5);
int sum = 0;
for (int i:list){
sum+=i;
}
System.out.println(sum);
}
}
見javap -c
ての解析の結果、あなたが私に似ている場合は、Javaバイトコードのバイトコード命令を、すべての権利に精通していない、私は逆コンパイラデコンパイル、それを所有する、などのコメントが結果からプラグと、ここでブックの共同アイデアをコンパイル見ます結果は(真の標準逆コンパイラAであることを主張私が見て気にしないでください)ケーススタディとして来る
結果デコンパイルブック
public static void main(String[] args){
List list=Arrrays.asList(new Integer[]{
Integer.valueOf(1),
Integer.valueOf(2),
Integer.valueOf(3),
Integer.valueOf(4),
Integer.valueOf(5)
});
int sum = 0;
for(Iterator localItrerator=list.iterator();localIterator.haoNext();){
int i = ((Integer)localIterator.next()).intValue();
sum+=i;
}
System.out.println(sum);
}
这段代码的反编译结果中涉及到了泛型、自动装箱、自动拆箱、遍历循环、以及变长参数。泛型的类型擦除我在这里就不去详细描述了,那么我在这里简单的说一下自动装箱和自动拆箱:
自动装箱:
从上面的代码里面我们可以看到,装箱无非就是把一个基本的数据类型包装成一个对象(基本数据类型 如 byte,short,char,int,long,float,double等对应的包装类Byte,Short,Character,Integer,Long,Float,Double),这样就能在使用对象的地方使用它们,这个过程不是我们认为的操作,而是底层操作,如本例中调用Integer.valueOf方法,故称为 自动装箱。
自动拆箱:
既然有装箱,那就会有拆箱,拆箱的操作与装箱是相反的,也就是需要用到基本数据类型的操作时,相对于的包装类对象就会拆箱,也就是褪去自己对象的属性,变成一个基本数据类型,这也是底层操作,如本例中自己调用Integer.intValue方法,故称为自动拆箱
那么也许我们都会思考,它们会在什么时候发生呢?
一般会发生在:需要参数为对象的方法,你传了一个基本的数据类型,那么底层将会帮你自动装箱,或需要参数为基本数据类型,你传了一个是某个基本的数据类型的包装类对象,那么它也会发生自动拆箱操作。
关于变长参数和遍历循环:
变长参数的实现是通过传递数组对象来实现的,如例子中的Integer[]
遍历循环就是转换成迭代器的实现,所以一般要使用就必须实现Iterable接口。
上面的几个知识都是相对简单的,很容易就能够理解它的意思,感觉是没有任何我们值得注意的地方
不过,这里有个坑
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
System.out.println(c == d);
System.out.println(e == f);
System.out.println(c == (a + b));
System.out.println(c.equals(a + b));
System.out.println(g == (a + b));
System.out.println(g.equals(a + b));
}
结果是这样的
true
false
true
true
true
false
最初のペアで最初に見
真偽
明確に示されているが、オブジェクトへのポインタが同じである、理由は異なるオブジェクト、?
のvalueOfソースオートボクシングを見てみましょう。
だからここに、それぞれ、低および高だが、どれだけそれがあります?
IntegerCacheが既に存在するオブジェクト参照へのポインタですが、以上のことは、新たな整数になります、我々は上記の結果を持つことになります。この範囲で、-128127あります
私は一緒にいくつかのバックを持っていると言う
の注意を:ラッパークラス「==」演算子を自動的にアンパック算術演算を経験せずに(のみ算術演算の場合にはアンボクシング遭遇することを意味している)しません、同様に彼らのequalsメソッドは、データ変換の問題に対処しないと
言うことです比較は同じオブジェクトかどうかの比較を開梱することは価値があるの後に、「==」開梱せず、その後、理解しやすいがあるだろう。
私たちは、ソースコードの等号を見ることができます。
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
複数のオブジェクトが存在することになるので、そのため、第1内側euals開梱開始する最初の演算、及び自動運転パラメータ渡し梱包後、そして、それは(cは整数、+ bのパッキンである第一等しい戻る真であります後も整数)は
第2の戻りに等しい(gはロングです)偽である
ので、あなたが理解できますか?
バイトコード実行指示逆コンパイルあなたに投げる戻って
Compiled from "Test.java"
public class kexie.test.Test {
public kexie.test.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: iconst_2
6: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
9: astore_2
10: iconst_3
11: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
14: astore_3
15: iconst_3
16: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
19: astore 4
21: sipush 321
24: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
27: astore 5
29: sipush 321
32: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
35: astore 6
37: ldc2_w #3 // long 3l
40: invokestatic #5 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
43: astore 7
45: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
48: aload_3
49: aload 4
51: if_acmpne 58
54: iconst_1
55: goto 59
58: iconst_0
59: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
62: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
65: aload 5
67: aload 6
69: if_acmpne 76
72: iconst_1
73: goto 77
76: iconst_0
77: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
80: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
83: aload_3
84: invokevirtual #8 // Method java/lang/Integer.intValue:()I
87: aload_1
88: invokevirtual #8 // Method java/lang/Integer.intValue:()I
91: aload_2
92: invokevirtual #8 // Method java/lang/Integer.intValue:()I
95: iadd
96: if_icmpne 103
99: iconst_1
100: goto 104
103: iconst_0
104: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
107: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
110: aload_3
111: aload_1
112: invokevirtual #8 // Method java/lang/Integer.intValue:()I
115: aload_2
116: invokevirtual #8 // Method java/lang/Integer.intValue:()I
119: iadd
120: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
123: invokevirtual #9 // Method java/lang/Integer.equals:(Ljava/lang/Object;)Z
126: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
129: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
132: aload 7
134: invokevirtual #10 // Method java/lang/Long.longValue:()J
137: aload_1
138: invokevirtual #8 // Method java/lang/Integer.intValue:()I
141: aload_2
142: invokevirtual #8 // Method java/lang/Integer.intValue:()I
145: iadd
146: i2l
147: lcmp
148: ifne 155
151: iconst_1
152: goto 156
155: iconst_0
156: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
159: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
162: aload 7
164: aload_1
165: invokevirtual #8 // Method java/lang/Integer.intValue:()I
168: aload_2
169: invokevirtual #8 // Method java/lang/Integer.intValue:()I
172: iadd
173: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
176: invokevirtual #11 // Method java/lang/Long.equals:(Ljava/lang/Object;)Z
179: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
182: return
}