java中什么是可变长度参数?foreach循环原理是什么?

如果下载的源码需要作者授权,请更换源码。本站免费分享资源不会增加授权

本篇文章给大家带来的内容是介绍java中什么是可变长度参数?foreach循环原理是什么?有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所助。

一、语法糖

语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的字节码或者特定的方式对这些语法做一些处理,开发者就可以直接方便地使用了。这些语法糖虽然不会提供实质性的功能改进,但是它们或能提高性能、或能提升语法的严谨性、或能减少编码出错的机会。Java提供给了用户大量的语法糖,比如泛型、自动装箱、自动拆箱、foreach循环、变长参数、内部类、枚举类、断言(assert)等。

二、可变长参数

先讲可变长度参数,看一段代码:

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]);     } }

print方法的参数的意思是表示传入的String个数是不定的,看一下代码的运行结果:

000 111 222 333

我用数组遍历的方式成功地将输入的参数遍历出来了,这说明两个问题:

1、可以使用遍历数组的方式去遍历可变长参数

2、可变参数是利用数组实现的

既然这样,那我其实main函数也可以这么写,完全可以:

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

那直接传入一个数组不就好了?问题是,数组是要指定长度的,万一这次我想传2个String,下次我想传3个String怎么办呢?

最后,注意一点,可变长度参数必须作为方法参数列表中的的最后一个参数且方法参数列表中只能有一个可变长度参数

三、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循环去遍历这个list,结果就不说了,都知道。看一下Java是如何处理这个foreach循环的,javap反编译一下:

F:代码MyEclipseTestArticlebincomxrqtest21>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这两行就可以了,看到了一个iterator,所以得出结论:在编译的时候编译器会自动将对foreach这个关键字的使用转化为对目标的迭代器的使用这就是foreach循环的原理。进而,我们再得出两个结论:

1、ArrayList之所以能使用foreach循环遍历,是因为ArrayList所有的List都是Collection的子接口,而Collection是Iterable的子接口,ArrayList的父类AbstractList正确地实现了Iterable接口的iterator方法。之前我自己写的ArrayList用foreach循环直接报空指针异常是因为我自己写的ArrayList并没有实现Iterable接口

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视频教程!

本文由(壳先生)整理自网络,如转载请注明出处:https://www.mrshell.com;
本站发布的内容若侵犯到您的权益,请邮件联系 i@mrshell.com 删除,我们将及时处理!
===========================================================================

1. 本站大部分下载资源收集于网络,不保证其完整性以及安全性,请下载后自行测试。
2. 本站资源仅供学习和交流使用,版权归资源原作者所有,请在下载后24小时之内自觉删除。
3. 不得使用于非法商业用途,商用请支持正版!不得违反国家法律,否则后果自负!
4. 若作商业用途,请购买正版,由于未及时购买和付费发生的侵权行为,与本站无关。
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!

=================================================================

壳先生 » java中什么是可变长度参数?foreach循环原理是什么?

发表评论

提供最优质的资源集合

立即查看 了解详情