`
xiangshouxiyang
  • 浏览: 48188 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

java增强for循环的原理验证

阅读更多

     在java里,我们是怎么写for循环的代码呢。一般都是用这两种写法:

第一种:最传统的for循环写法,for(代码段a;代码段b;代码段c),其中代码段a是初次进入for循环时执行的代码,代码段b是一个boolean的表达式,true则继续执行for循环内容,false则停止for循环,代码段c则是在for循环内部执行完后执行。

第二种:针对集合的遍历,for(类型 单个对象:集合对象)。第二种即是增强for循环。

     本文的目的就是讲解增强for循环的原理。先看我的测试用例:

jdk版本:1.7.0_51

 java 用例代码:

package com.onlyou.olyfinance.supply.web;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * 增强for循环编译测试
 * Created by cd_huang on 2017/4/14.
 */
public class ForeachTest {

	public static void superForeachTestArray(){
		String[] args =new String[]{"1","2"};
		for(String s:args) {
			System.out.println(s);
		}
	}

	public static void foreachTestArray(){
		String[] args =new String[]{"1","2"};
		String[] args2 = args;
		int len = args.length;
		for(int i = 0; i < len; ++i) {
			String s= args2[i];
			System.out.println(s);
		}
	}

	public static void superForeachTestIterator(){
		List<String> list = Arrays.asList(new String[]{"1","2"});
		for(String s:list) {
			System.out.println(s);
		}
	}

	public static void foreachTestIterator(){
		List<String> list = Arrays.asList(new String[]{"1","2"});
		Iterator it = list.iterator();
		while(it.hasNext()) {
			String s = (String)it.next();
			System.out.println(s);
		}
	}
}

 命令行输入:C:\Users\hcd>javac c:\ForeachTest.java

生成StringTest.class文件。

命令行输入:C:\Users\hcd>javap -v c:\ForeachTest.class

生成java编译后的字节码指令。

Classfile /c:/ForeachTest.class
  Last modified 2017-4-14; size 1307 bytes
  MD5 checksum 5296942b41a468b4fa1f88e3123db02f
  Compiled from "ForeachTest.java"
public class com.onlyou.olyfinance.supply.web.ForeachTest
  SourceFile: "ForeachTest.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER

Constant pool:
   #1 = Methodref          #13.#28        //  java/lang/Object."<init>":()V
   #2 = Class              #29            //  java/lang/String
   #3 = String             #30            //  1
   #4 = String             #31            //  2
   #5 = Fieldref           #32.#33        //  java/lang/System.out:Ljava/io/PrintStream;
   #6 = Methodref          #34.#35        //  java/io/PrintStream.println:(Ljava/lang/String;)V
   #7 = Methodref          #36.#37        //  java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
   #8 = InterfaceMethodref #38.#39        //  java/util/List.iterator:()Ljava/util/Iterator;
   #9 = InterfaceMethodref #40.#41        //  java/util/Iterator.hasNext:()Z
  #10 = InterfaceMethodref #40.#42        //  java/util/Iterator.next:()Ljava/lang/Object;
  #11 = InterfaceMethodref #38.#39        //  java/util/List.iterator:()Ljava/util/Iterator;
  #12 = Class              #43            //  com/onlyou/olyfinance/supply/web/ForeachTest
  #13 = Class              #44            //  java/lang/Object
  #14 = Utf8               <init>
  #15 = Utf8               ()V
  #16 = Utf8               Code
  #17 = Utf8               LineNumberTable
  #18 = Utf8               superForeachTestArray
  #19 = Utf8               StackMapTable
  #20 = Class              #45            //  "[Ljava/lang/String;"
  #21 = Utf8               foreachTestArray
  #22 = Utf8               superForeachTestIterator
  #23 = Class              #46            //  java/util/List
  #24 = Class              #47            //  java/util/Iterator
  #25 = Utf8               foreachTestIterator
  #26 = Utf8               SourceFile
  #27 = Utf8               ForeachTest.java
  #28 = NameAndType        #14:#15        //  "<init>":()V
  #29 = Utf8               java/lang/String
  #30 = Utf8               1
  #31 = Utf8               2
  #32 = Class              #48            //  java/lang/System
  #33 = NameAndType        #49:#50        //  out:Ljava/io/PrintStream;
  #34 = Class              #51            //  java/io/PrintStream
  #35 = NameAndType        #52:#53        //  println:(Ljava/lang/String;)V
  #36 = Class              #54            //  java/util/Arrays
  #37 = NameAndType        #55:#56        //  asList:([Ljava/lang/Object;)Ljava/util/List;
  #38 = Class              #46            //  java/util/List
  #39 = NameAndType        #57:#58        //  iterator:()Ljava/util/Iterator;
  #40 = Class              #47            //  java/util/Iterator
  #41 = NameAndType        #59:#60        //  hasNext:()Z
  #42 = NameAndType        #61:#62        //  next:()Ljava/lang/Object;
  #43 = Utf8               com/onlyou/olyfinance/supply/web/ForeachTest
  #44 = Utf8               java/lang/Object
  #45 = Utf8               [Ljava/lang/String;
  #46 = Utf8               java/util/List
  #47 = Utf8               java/util/Iterator
  #48 = Utf8               java/lang/System
  #49 = Utf8               out
  #50 = Utf8               Ljava/io/PrintStream;
  #51 = Utf8               java/io/PrintStream
  #52 = Utf8               println
  #53 = Utf8               (Ljava/lang/String;)V
  #54 = Utf8               java/util/Arrays
  #55 = Utf8               asList
  #56 = Utf8               ([Ljava/lang/Object;)Ljava/util/List;
  #57 = Utf8               iterator
  #58 = Utf8               ()Ljava/util/Iterator;
  #59 = Utf8               hasNext
  #60 = Utf8               ()Z
  #61 = Utf8               next
  #62 = Utf8               ()Ljava/lang/Object;
{
  public com.onlyou.olyfinance.supply.web.ForeachTest();
    flags: ACC_PUBLIC

    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return        
      LineNumberTable:
        line 11: 0

  public static void superForeachTestArray();
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=4, locals=5, args_size=0
         0: iconst_2      
         1: anewarray     #2                  // class java/lang/String
         4: dup           
         5: iconst_0      
         6: ldc           #3                  // String 1
         8: aastore       
         9: dup           
        10: iconst_1      
        11: ldc           #4                  // String 2
        13: aastore       
        14: astore_0      
        15: aload_0       
        16: astore_1      
        17: aload_1       
        18: arraylength   
        19: istore_2      
        20: iconst_0      
        21: istore_3      
        22: iload_3       
        23: iload_2       
        24: if_icmpge     46
        27: aload_1       
        28: iload_3       
        29: aaload        
        30: astore        4
        32: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        35: aload         4
        37: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        40: iinc          3, 1
        43: goto          22
        46: return        
      LineNumberTable:
        line 14: 0
        line 15: 15
        line 16: 32
        line 15: 40
        line 18: 46
      StackMapTable: number_of_entries = 2
           frame_type = 255 /* full_frame */
          offset_delta = 22
          locals = [ class "[Ljava/lang/String;", class "[Ljava/lang/String;", int, int ]
          stack = []
           frame_type = 248 /* chop */
          offset_delta = 23


  public static void foreachTestArray();
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=4, locals=5, args_size=0
         0: iconst_2      
         1: anewarray     #2                  // class java/lang/String
         4: dup           
         5: iconst_0      
         6: ldc           #3                  // String 1
         8: aastore       
         9: dup           
        10: iconst_1      
        11: ldc           #4                  // String 2
        13: aastore       
        14: astore_0      
        15: aload_0       
        16: astore_1      
        17: aload_0       
        18: arraylength   
        19: istore_2      
        20: iconst_0      
        21: istore_3      
        22: iload_3       
        23: iload_2       
        24: if_icmpge     46
        27: aload_1       
        28: iload_3       
        29: aaload        
        30: astore        4
        32: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        35: aload         4
        37: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        40: iinc          3, 1
        43: goto          22
        46: return        
      LineNumberTable:
        line 21: 0
        line 22: 15
        line 23: 17
        line 24: 20
        line 25: 27
        line 26: 32
        line 24: 40
        line 28: 46
      StackMapTable: number_of_entries = 2
           frame_type = 255 /* full_frame */
          offset_delta = 22
          locals = [ class "[Ljava/lang/String;", class "[Ljava/lang/String;", int, int ]
          stack = []
           frame_type = 250 /* chop */
          offset_delta = 23


  public static void superForeachTestIterator();
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=4, locals=3, args_size=0
         0: iconst_2      
         1: anewarray     #2                  // class java/lang/String
         4: dup           
         5: iconst_0      
         6: ldc           #3                  // String 1
         8: aastore       
         9: dup           
        10: iconst_1      
        11: ldc           #4                  // String 2
        13: aastore       
        14: invokestatic  #7                  // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
        17: astore_0      
        18: aload_0       
        19: invokeinterface #8,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
        24: astore_1      
        25: aload_1       
        26: invokeinterface #9,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
        31: ifeq          54
        34: aload_1       
        35: invokeinterface #10,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
        40: checkcast     #2                  // class java/lang/String
        43: astore_2      
        44: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        47: aload_2       
        48: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        51: goto          25
        54: return        
      LineNumberTable:
        line 31: 0
        line 32: 18
        line 33: 44
        line 34: 51
        line 35: 54
      StackMapTable: number_of_entries = 2
           frame_type = 253 /* append */
             offset_delta = 25
        locals = [ class java/util/List, class java/util/Iterator ]
           frame_type = 250 /* chop */
          offset_delta = 28


  public static void foreachTestIterator();
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=4, locals=3, args_size=0
         0: iconst_2      
         1: anewarray     #2                  // class java/lang/String
         4: dup           
         5: iconst_0      
         6: ldc           #3                  // String 1
         8: aastore       
         9: dup           
        10: iconst_1      
        11: ldc           #4                  // String 2
        13: aastore       
        14: invokestatic  #7                  // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
        17: astore_0      
        18: aload_0       
        19: invokeinterface #11,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
        24: astore_1      
        25: aload_1       
        26: invokeinterface #9,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
        31: ifeq          54
        34: aload_1       
        35: invokeinterface #10,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
        40: checkcast     #2                  // class java/lang/String
        43: astore_2      
        44: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        47: aload_2       
        48: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        51: goto          25
        54: return        
      LineNumberTable:
        line 38: 0
        line 39: 18
        line 40: 25
        line 41: 34
        line 42: 44
        line 43: 51
        line 44: 54
      StackMapTable: number_of_entries = 2
           frame_type = 253 /* append */
             offset_delta = 25
        locals = [ class java/util/List, class java/util/Iterator ]
           frame_type = 28 /* same */

}

   上面的是java代码编译过后的二进制指令。如果对这些指令是什么意思有兴趣的可以看这篇博客:http://www.blogjava.net/DLevin/archive/2011/09/13/358497.html。不过单单看这个肯定是不够的。需要对java的运行时内存模型有一定的了解,明白栈帧,操作数栈,局部变量表,常量池这些东西的概念,才能理解在执行这些指令时,对应的东西里会产生什么变化。当然,要理解我说的增强for循环原理,并不需要看懂这些指令。认真观察上面的二进制指令,superForeachTestArray()方法编译后的指令,即第86行到121行,和foreachTestArray() 方法编译后的指令,即第137行到172行,两个方法编译后的指令是一样的。

superForeachTestIterator()方法编译后的指令,即第191行到222行,和foreachTestIterator() 方法编译后的指令,即第237行到268行,两个方法编译后的指令是一样的。

    这说明什么问题?说明了增强for循环是一个编译前的概念,在编译后编译器会对代码进行优化。有两种对象支持增强for循环:一种是数组,编译器对数组的优化只是写法上的优化,即superForeachTestArray()方法内的增强for循环在编译后会变成foreachTestArray() 方法里for循环的代码。一种是实现了Iterable接口的对象,对于这种,其实质是拿到对象的迭代器进行遍历,即superForeachTestIterator()方法内的增强for循环在编译后会变成foreachTestIterator() 方法内的迭代器遍历。迭代器遍历的好处是安全,且它是对遍历的一种抽象,有种解耦的意味在里面。

分享到:
评论
1 楼 xiaozhang51 2017-04-14  
学习了  

相关推荐

    使用Java语言理解程序逻辑(Logic Java)3

    2. 循环结构:Java提供了for、while和do-while循环,它们用于重复执行一段代码直到满足特定条件。理解这些循环的工作原理对于编写迭代逻辑至关重要,例如遍历数组、计算数学序列或执行重复任务。 3. 函数(方法):...

    Java课件 Java课件 Java课件 Java课件

    1. **基础语法**:包括变量、数据类型、运算符、流程控制(如if-else、switch、for、while等循环结构)、方法定义与调用、数组等。这是学习任何编程语言的基础,掌握好这些能帮助我们编写简单的程序。 2. **类与...

    java例子sample

    1. **基础语法**:包括变量声明、数据类型(如int、String等)、运算符、控制结构(如if语句、for循环、while循环)和函数定义等。这些是编写任何Java程序的基础。 2. **类与对象**:Java是一种面向对象的语言,...

    java-learning & java-safety

    1. **基础语法**:开始学习Java,首先要掌握基础语法,包括变量、数据类型、运算符、控制结构(如if语句、for循环、while循环)、方法定义等。理解这些基础知识是构建更复杂程序的基础。 2. **类与对象**:Java是一...

    JAVA 2应用编程150例

    1. **基础语法**:Java的基础语法是所有编程实例的基石,包括数据类型(如整型、浮点型、字符型和布尔型)、变量声明、常量定义、运算符、流程控制(如if语句、switch语句、for循环、while循环)以及方法的定义和...

    java基础所有例子

    3. **流程控制**:Java提供了if语句、switch语句进行条件判断,while、do-while和for循环用于重复执行代码块。这些控制结构是程序逻辑的基础。 4. **方法**:方法是代码的封装单位,可以实现特定功能。通过方法,...

    java技术资料

    1. **Java基础**:学习Java首先要掌握其基本语法,包括数据类型(如整型、浮点型、字符型和布尔型)、变量、运算符、流程控制(如if语句、for循环、while循环和switch case结构)以及方法定义等。 2. **类和对象**...

    300个java 练习 入门 精通

    - 遍历集合:foreach循环、迭代器和增强for循环的使用。 - 泛型:理解泛型的限制和好处,以及如何在类、接口和方法中使用泛型。 5. **输入/输出流** - 文件操作:学习File类,进行文件的创建、读写和删除。 - ...

    Java程序案例

    1. **基础语法**:包括变量、数据类型、运算符、流程控制(如if语句、for循环、while循环)、函数等。 2. **面向对象编程**:类、对象、封装、继承、多态是Java的核心特性,案例可能包含这些概念的实际应用。 3. *...

    Java技术大合集

    1. **Java基础**: 任何学习Java的旅程都从基础开始,包括了解变量、数据类型、运算符、流程控制(如if-else、switch、for、while循环)、函数和类的定义与使用。此外,面向对象编程的基本概念——封装、继承和多态也...

    SCJP5.0(Sun Certified Programmer for the Java 2 )

    Java SCJP(Sun Certified Programmer for the Java 2 Platform, Standard Edition 5.0)是Java开发者认证的一个重要里程碑,由Sun Microsystems(后被Oracle收购)推出,旨在验证程序员对Java SE 5.0(也称为Java ...

    java基础教程_java_

    在控制流程方面,Java提供了if-else语句、switch-case结构、for、while和do-while循环等。这些工具使得程序能够根据条件执行不同的分支,或者重复执行某些任务。 数组是存储同类型数据的集合,可以是一维、二维或...

    达内CORE JAVA部分笔记,代码,练习

    - 控制结构:包括条件语句(if-else, switch)和循环(for, while, do-while),这些构成了程序的基本逻辑框架。 - 方法:函数是实现代码重用的关键,Java中的方法定义了特定任务的执行流程。 2. **面向对象编程*...

    43010-Java程序设计教程慕课版-习题答案.rar.rar

    它包括变量声明、数据类型(如int、double、String等)、控制结构(如if语句、for循环、while循环)、方法定义和调用等。 3. **类与对象**:在Java中,一切皆为对象。类是创建对象的模板,包含了数据(属性)和行为...

    java核心技术卷一(英文版mobi格式)

    这包括数据类型(如整型、浮点型、字符型和布尔型)、变量声明、运算符、流程控制语句(如if-else、switch、for、while循环)以及方法的定义和调用。 2. **类与对象**:Java是一种面向对象的语言,"万物皆对象"是其...

    java基础案例与开发详解案例源码全

    4.5 增强for循环116 4.6 本章练习117 第5章 5.1 面向过程的设计思想120 5.2 面向对象的设计思想120 5.3 抽象121 5.3.1 对象的理解121 5.3.2 Java抽象思想的实现122 5.4 封装124 5.4.1 对象封装的概念理解124 5.4.2 ...

    《JAVA程序设计教程》电子教案.rar

    Java的基础语法包括变量声明、数据类型(如整型、浮点型、字符型、布尔型)、运算符(算术、比较、逻辑、位操作等)、流程控制(如if语句、switch语句、循环结构for、while、do-while等)。同时,理解类和对象的概念...

    Java小游戏箭头对对碰源码

    这包括类的定义、方法的编写、变量的声明以及控制流程(如if-else、for循环、while循环)的运用。 2. **图形用户界面(GUI)设计**:游戏可能使用了Java的Swing或JavaFX库来构建用户界面,这两个库提供了丰富的组件...

    java实用教程电子版

    2. **基础语法**:学习Java的基本数据类型(整型、浮点型、字符型、布尔型),变量声明,运算符,流程控制语句(如if-else、switch、for、while循环)以及方法的定义和调用。 3. **类与对象**:理解面向对象编程的...

    java练习,将系统学习如何使用Java,更快捷方便的使用java.zip

    1. **Java基础知识**:这是学习任何编程语言的起点,包括了解Java的历史、语法结构、数据类型、变量、运算符、控制流(如if语句、for循环和while循环)、方法以及类与对象的概念。 2. **面向对象编程**:Java是纯...

Global site tag (gtag.js) - Google Analytics