Javaのシンタックスシュガー - 自動梱包および開梱トラバーサルサイクル

参照元:「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
}
公開された19元の記事 ウォンの賞賛3 ビュー3819

おすすめ

転載: blog.csdn.net/weixin_42792088/article/details/100170401