>  기사  >  Java  >  Java의 가변 길이 매개변수란 무엇입니까? foreach 루프의 원리는 무엇입니까?

Java의 가변 길이 매개변수란 무엇입니까? foreach 루프의 원리는 무엇입니까?

青灯夜游
青灯夜游앞으로
2018-10-19 17:19:252177검색

이 글의 내용은 Java의 가변 길이 매개 변수가 무엇인지 소개하는 것입니다. foreach 루프의 원리는 무엇입니까? 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

1. 구문 설탕

구문 설탕은 프로그래머가 코드를 쉽게 개발할 수 있도록 거의 모든 언어에서 제공되는 구문입니다. 단지 컴파일러 일 뿐입니다. 이 구문은 컴파일 중에 특정 바이트 코드 또는 특정 방식으로 처리되며 개발자는 이를 직접적이고 편리하게 사용할 수 있습니다. 이러한 구문 설탕은 실질적인 기능 향상을 제공하지는 않지만 성능을 향상시키고 문법의 엄격함을 향상시키거나 코딩 오류 가능성을 줄일 수 있습니다. Java는 사용자에게 제네릭, 오토박싱, 오토언박싱, foreach 루프, 가변 길이 매개변수, 내부 클래스, 열거형 클래스, 어설션 등과 같은 다양한 구문 설탕을 제공합니다.

2. 가변 길이 매개변수

먼저 가변 길이 매개변수에 대해 이야기해 보겠습니다.

public static void main(String[] args)
{
    print("000", "111", "222", "333");
}
    
public static void print(String... strs)
{
    for (int i = 0; i < strs.length; i++)
    {
        System.out.println(strs[i]);
    }
}

인쇄 메소드의 매개변수는 전달된 문자열의 수가 다음과 같다는 것을 의미합니다. 변수, 코드 실행 결과를 살펴보세요.

000
111
222
333

배열 순회를 사용하여 입력 매개변수를 성공적으로 순회했습니다. 이는 두 가지 문제를 보여줍니다.

1 배열 순회를 사용하여 가변 길이 매개변수를 순회할 수 있습니다.

2. 가변 매개변수는 배열을 사용하여 구현됩니다.

이 경우 실제로는 다음과 같이 기본 함수를 작성할 수 있습니다.

String[] strs = {"000", "111", "222", "333"};
print(strs);

그렇다면 직접 전달하는 것이 좋지 않을까요? 배열? 문제는 배열의 길이를 지정해야 한다는 것입니다. 이번에는 2개의 문자열을 전달하고 다음에는 3개의 문자열을 전달하려면 어떻게 해야 합니까?

마지막으로,

가변 길이 매개변수는 메소드 매개변수 목록의 마지막 매개변수로 사용해야 하며 메소드 매개변수 목록에는 가변 길이 매개변수가 하나만 있을 수 있습니다.

3. foreach 루프 원리

이전에 foreach 루프를 사용한 방법은 다음과 같습니다. foreach 루프의 원리를 연구하게 된 이유는 약 두 달 전에 제가 직접 ArrayList를 작성했기 때문입니다. foreach 루프를 사용하여 쓰기 효과를 확인한 후 널 포인터 예외가 보고되었습니다. 이 기사에서는 foreach 루프의 원리에 대해 설명합니다. 먼저 다음 코드를 살펴보세요.

public static void main(String[] args)
{
    List<String> list = new ArrayList<String>();
    list.add("111");
    list.add("222");
    
    for (String str : list)
    {
        System.out.println(str);
    }
}
foreach 루프를 사용하여 이 목록을 탐색합니다. 결과에 대해서는 언급하지 않겠습니다. Java가 이 foreach 루프를 처리하는 방법을 살펴보겠습니다. javap:

F:\代码\MyEclipse\TestArticle\bin\com\xrq\test21>javap -verbose TestMain.class
디컴파일된 콘텐츠는 클래스 정보, 기호 참조 및 바이트 코드 정보를 포함하여 많습니다.

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: new           #16                 // class java/util/ArrayList
         3: dup
         4: invokespecial #18                 // Method java/util/ArrayList."<in
it>":()V
         7: astore_1
         8: aload_1
         9: ldc           #19                 // String 111
        11: invokeinterface #21,  2           // InterfaceMethod java/util/List.
add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #27                 // String 222
        20: invokeinterface #21,  2           // InterfaceMethod java/util/List.
add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: invokeinterface #29,  1           // InterfaceMethod java/util/List.
iterator:()Ljava/util/Iterator;

그렇지 않습니다. 이해하지 못해도 상관없습니다. new, dup 및 Invokespecial은 원래 바이트코드 명령어 테이블에 정의된 명령어입니다. 가상 머신은 이러한 명령어를 기반으로 지정된 C++ 코드를 실행하여 각 명령어의 기능을 완성합니다. 핵심은 21과 22 두 줄을 보는 것입니다. 반복자를 보고 결론에 도달했습니다. 컴파일할 때 컴파일러는 자동으로 foreach 을 컴파일합니다. 이 키워드를 사용하면 대상 반복자 , 이것이 foreach 루프의 원리입니다. 또한 두 가지 결론을 더 내립니다.

1 foreach 루프를 사용하여 ArrayList를 탐색할 수 있는 이유는 ArrayList의 모든 목록이 Collection의 하위 인터페이스이고 Collection이 Iterable이기 때문입니다. 상위 클래스 AbstractList인 ArrayList의 하위 인터페이스는 Iterable 인터페이스의 반복자 메서드를 올바르게 구현합니다. 이전에 작성한 ArrayList는 Iterable 인터페이스를 구현하지 않았기 때문에 foreach 루프를 사용하여 널 포인터 예외를 직접 보고했습니다

2、任何一个集合,无论是JDK提供的还是自己写的只要想使用foreach循环遍历,就必须正确地实现Iterable接口实际上,这种做法就是23中设计模式中的迭代器模式

数组呢?

上面的讲完了,好理解,但是不知道大家有没有疑问,至少我是有一个疑问的:数组并没有实现Iterable接口啊,为什么数组也可以用foreach循环遍历呢?先给一段代码,再反编译:

public static void main(String[] args)
{
    int[] ints = {1,2,3,4,5};
        
    for (int i : ints)
        System.out.println(i);
}

同样反编译一下,看一下关键的信息:

0: iconst_2
         1: newarray       int
         3: dup
         4: iconst_0
         5: iconst_1
         6: iastore
         7: dup
         8: iconst_1
         9: iconst_2
        10: iastore
        11: astore_1
        12: aload_1
        13: dup
        14: astore        5
        16: arraylength
        17: istore        4
        19: iconst_0
        20: istore_3
        21: goto          39
        24: aload         5
        26: iload_3
        27: iaload
        28: istore_2
        29: getstatic     #16                 // Field java/lang/System.out:Ljav
a/io/PrintStream;
        32: iload_2
        33: invokevirtual #22                 // Method java/io/PrintStream.prin
tln:(I)V
        36: iinc          3, 1
        39: iload_3
        40: iload         4
        42: if_icmplt     24
        45: return

这是完整的这段main函数对应的45个字节码指令,因为这涉及一些压栈、出栈、推送等一些计算机原理性的内容且对于这些字节码指令的知识的理解需要一些C++的知识,所以就不解释了。简单对照字节码指令表之后,我个人对于这45个字节码的理解是Java将对于数组的foreach循环转换为对于这个数组每一个的循环引用

总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。更多相关教程请访问Java视频教程java开发图文教程bootstrap视频教程

위 내용은 Java의 가변 길이 매개변수란 무엇입니까? foreach 루프의 원리는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제