java for each 原理_Java语言基础----------foreach原理

Java中的foreach是在JDK1.5中增加的内容,使用起来非常方便,是for的增强版。foreach的目标对象有两种,分别是数组和实现了Iterable接口的对象(Set和Map等集合)。

1. foreach使用和原理

1.1 数组中的使用

public class Test {

public static void main(String[] args)

{

int[] num = {1,2,3};

for (int temp : num)

{

System.out.println(temp);

}

}

}

在数组中,使用foreach实现遍历。对代码进行反编译,其运行逻辑与直接使用for循环是一样的,详细运行结果如下:

[C:\Users\zhangsz\Downloads\Downloads\just_java\src]$ javap -c Test.class

Compiled from "Test.java"

public class Test {

public Test();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

public static void main(java.lang.String[]);

Code:

0: iconst_3

1: newarray int

3: dup

4: iconst_0

5: iconst_1

6: iastore

7: dup

8: iconst_1

9: iconst_2

10: iastore

11: dup

12: iconst_2

13: iconst_3

14: iastore

15: astore_1

16: aload_1

17: astore_2

18: aload_2

19: arraylength

20: istore_3

21: iconst_0

22: istore 4

24: iload 4

26: iload_3

27: if_icmpge 50

30: aload_2

31: iload 4

33: iaload

34: istore 5

36: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

39: iload 5

41: invokevirtual #3 // Method java/io/PrintStream.println:(I)V

44: iinc 4, 1

47: goto 24

50: return

}

1.2 对象中的使用

当foreach的使用目标是对象的时候,对象必须实现Iterable接口。

import java.util.ArrayList;

import java.util.List;

public class Test {

public static void main(String[] args)

{

List hello = new ArrayList<>();

for (int i = 0;i < 3;i ++)

{

hello.add("hello world");

}

for (String temp : hello)

{

System.out.println(temp);

}

}

}

对代码进行反编译,可以看到在实际遍历的时候,是调用的Iterable接口中的hasNext方法和next方法。所以对于非数组的对象,要想使用foreach,就必须实现Iterable接口。

[C:\Users\zhangsz\Downloads\Downloads\just_java\src]$ javap -c Test.class

Compiled from "Test.java"

public class Test {

public Test();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

public static void main(java.lang.String[]);

Code:

0: new #2 // class java/util/ArrayList

3: dup

4: invokespecial #3 // Method java/util/ArrayList."":()V

7: astore_1

8: iconst_0

9: istore_2

10: iload_2

11: iconst_3

12: if_icmpge 30

15: aload_1

16: ldc #4 // String hello world

18: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z

23: pop

24: iinc 2, 1

27: goto 10

30: aload_1

31: invokeinterface #6, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;

36: astore_2

37: aload_2

38: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z

43: ifeq 66

46: aload_2

47: invokeinterface #8, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;

52: checkcast #9 // class java/lang/String

55: astore_3

56: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream;

59: aload_3

60: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

63: goto 37

66: return

}

2. Java源码中foreach实现

上文使用foreach的例子,使用的是ArrayList。下来看一下其JDK的代码,是如何实现Iterable接口的。

ArrayList、List和Iterator的关系如下图所示。

AAffA0nNPuCLAAAAAElFTkSuQmCC

在Iterator接口中,定义了Iterator iterator();方法,所以在最终的ArrayList中需要进行实现。实现逻辑如下:

public Iterator iterator() {

return new Itr();

}

private class Itr implements Iterator {

int cursor; // index of next element to return

int lastRet = -1; // index of last element returned; -1 if no such

int expectedModCount = modCount;

// prevent creating a synthetic constructor

Itr() {}

public boolean hasNext() {

return cursor != size;

}

@SuppressWarnings("unchecked")

public E next() {

checkForComodification();

int i = cursor;

if (i >= size)

throw new NoSuchElementException();

Object[] elementData = ArrayList.this.elementData;

if (i >= elementData.length)

throw new ConcurrentModificationException();

cursor = i + 1;

return (E) elementData[lastRet = i];

}

public void remove() {

if (lastRet < 0)

throw new IllegalStateException();

checkForComodification();

try {

ArrayList.this.remove(lastRet);

cursor = lastRet;

lastRet = -1;

expectedModCount = modCount;

} catch (IndexOutOfBoundsException ex) {

throw new ConcurrentModificationException();

}

}

@Override

public void forEachRemaining(Consumer super E> action) {

Objects.requireNonNull(action);

final int size = ArrayList.this.size;

int i = cursor;

if (i < size) {

final Object[] es = elementData;

if (i >= es.length)

throw new ConcurrentModificationException();

for (; i < size && modCount == expectedModCount; i++)

action.accept(elementAt(es, i));

// update once at end to reduce heap write traffic

cursor = i;

lastRet = i - 1;

checkForComodification();

}

}

final void checkForComodification() {

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

}

}

代码中,hasNext方法查看是否后一位还存在元素,next方法用于获取下一个具体的元素。

3. 自己实现的foreach目标类

import java.util.Iterator;

public class Test1 {

public static void main(String[] args)

{

ForeachTest foreachTest = new ForeachTest();

for (String i : foreachTest)

{

System.out.println(i);

}

}

}

class ForeachTest implements Iterable{

String[] test = {"hello","world","!"};

@Override

public Iterator iterator() {

return new Ite();

}

private class Ite implements Iterator{

int pt = 0;

public Ite(){

}

@Override

public boolean hasNext() {

return pt < test.length;

}

@Override

public String next() {

return test[pt++];

}

}

}

运行结果如下:

AAffA0nNPuCLAAAAAElFTkSuQmCC

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值