欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

Java 语法糖 1:可变长 昆山软件开发 度参数以及 foreach 轮回道理

点击: 次  来源:宝鼎软件 时间:2017-05-31

原文出处: 五月的仓颉

语法糖

接下来几篇文章要开启一个Java语法糖系列,所以首先讲讲什么是语法糖。语法糖是一种险些每种语言或多或少都提供过的一些利便措施员开拓代码的语法,它只是编译器实现的一些小花招而已,编译期间以特定的字节码可能特定的方法对这些语法做一些处理惩罚,开拓者就可以直接利便地利用了。这些语法糖固然不会提供实质性的成果改造,可是它们或能提高机能、或能晋升语法的严谨性、或能淘汰编码堕落的时机。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:\代码\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这两行就可以了,看到了一个iterator,所以得出结论:在编译的时候编译器会自动将对for这个要害字的利用转化为对方针的迭代器的利用,这就是foreach轮回的道理。进而,我们再得出两个结论:

1、ArrayList之所以能利用foreach轮回遍历,是因为ArrayList所有的List都是Collection的子接口,而Collection是Iterable的子接口,ArrayList的父类AbstractList正确地实现了Iterable接口的iterator要领。之前我本身写的ArrayList用foreach轮回直接报空指针异常是因为我本身写的ArrayList并没有实现Iterable接口

2、任何一个荟萃,无论是JDK提供的照旧本身写的,只要想利用foreach轮回遍历,就必需正确地实现Iterable接口

实际上,这种做法就是23中设计模式中的迭代器模式。

数组呢?