day714.switch表达式-java8后最重要新特性(代码片段)

阿昌喜欢吃黄桃 阿昌喜欢吃黄桃     2022-10-22     620

关键词:

switch表达式

Hi,我是阿昌,今天学习记录的是关于 switch表达式

switch 表达式这个特性,首先在 JDK 12 中以预览版的形式发布。在 JDK 13 中,改进的 switch 表达式再次以预览版的形式发布。最后,switch 表达式在 JDK 14 正式发布

不论你学习什么样的编程语言,合理地分析、判断、处理不同的情况都是必备的基本功。

比如我们使用的 if-else 语句,还有 switch 语句,都是用来处理种种不同的情况的。

我们都知道 switch 语句,那么 switch 表达式又是什么呢?switch 语句和 switch 表达式又有什么不同呢?

如果你了解了 Java 的语句和表达式这两个基本概念,你的困扰也许会少一点。

Java 规范里,表达式完成对数据的操作。一个表达式的结果可以是一个数值(i * 4);或者是一个变量(i = 4);或者什么都不是(void 类型)。

Java 语句是 Java 最基本的可执行单位,它本身不是一个数值,也不是一个变量。

Java 语句的标志性符号是分号(代码)和双引号(代码块),比如 if-else 语句,赋值语句等。这样再来看,就很简单了:switch 表达式就是一个表达式,而 switch 语句就是一个语句。

switch 表达式是什么样子的?为什么需要 switch 表达式?

一、阅读案例

该怎么用代码计算一个月有多少天?

生活中,我们熟悉这样的顺口溜,“一三五七八十腊,三十一天永不差,四六九冬三十整,平年二月二十八,闰年二月把一加”。

下面的这段代码,就是按照这个顺口溜的逻辑来计算了一下,今天所在的这个月,一共有多少天。

class DaysInMonth 
    public static void main(String[] args) 
        Calendar today = Calendar.getInstance();
        int month = today.get(Calendar.MONTH);
        int year = today.get(Calendar.YEAR);

        int daysInMonth;
        switch (month) 
            case Calendar.JANUARY:
            case Calendar.MARCH:
            case Calendar.MAY:
            case Calendar.JULY:
            case Calendar.AUGUST:
            case Calendar.OCTOBER:
            case Calendar.DECEMBER:
                daysInMonth = 31;
                break;
            case Calendar.APRIL:
            case Calendar.JUNE:
            case Calendar.SEPTEMBER:
            case Calendar.NOVEMBER:
                daysInMonth = 30;
                break;
            case Calendar.FEBRUARY:
                if (((year % 4 == 0) && !(year % 100 == 0))
                        || (year % 400 == 0)) 
                    daysInMonth = 29;
                 else 
                    daysInMonth = 28;
                
                break;
            default:
                throw new RuntimeException(
                    "Calendar in JDK does not work");
        

        System.out.println(
            "There are " + daysInMonth + " days in this month.");
    

这段代码里,我们使用了 switch 语句。代码本身并没有什么错误,但是,至少有两个容易犯错误的地方。

第一个容易犯错的地方,就是在 break 关键字的使用上。

上面的代码里,如果多使用一个 break 关键字,代码的逻辑就会发生变化;

同样的,少使用一个 break 关键字也会出现问题。


int daysInMonth;
switch (month) 
    case Calendar.JANUARY:
    case Calendar.MARCH:
    case Calendar.MAY:
        break;    // WRONG BREAK!!!
    case Calendar.JULY:
    case Calendar.AUGUST:
    case Calendar.OCTOBER:
    case Calendar.DECEMBER:
        daysInMonth = 31;
        break;
    // snipped

int daysInMonth;
switch (month) 
    // snipped
    case Calendar.APRIL:
    case Calendar.JUNE:
    case Calendar.SEPTEMBER:
    case Calendar.NOVEMBER:
        daysInMonth = 30;
                         // WRONG, NO BREAK!!!
    case Calendar.FEBRUARY:
        if (((year % 4 == 0) && !(year % 100 == 0))
                || (year % 400 == 0)) 
            daysInMonth = 29;
         else 
            daysInMonth = 28;
        
        break;
    // snipped

break 语句的遗漏或者冗余,这样的错误如此得常见,甚至于被单列成了一个常见软件安全漏洞

凡是使用 switch 语句的代码,都有可能成为黑客们重点关注的对象。由于逻辑的错误和黑客的特殊关照,我们在编写代码的时候,需要十二分的小心;

阅读代码的时候,也需要反复地查验 break 语句的前后语境。

毫无疑问,这增加了代码维护的成本,降低了生产效率。为什么 switch 语句里需要使用 break 呢?

最主要的原因,就是希望能够在不同的情况下,共享部分或者全部的代码片段。比如上面的例子中,四月、六月、九月、十一月这四种情景,可以共享每个月都是 30 天这样的代码片段。

这个代码片段只需要写在十一月情景的后面,前面的四月、六月和九月这三个情景都会顺次执行下面的操作(fall-through),直到遇到下一个 break 语句或者 switch 语句终结。

现在我们都知道了,这样是一个弊大于利的设计。

但很遗憾,Java 初始的设计就是采用了这样的设计思想。

如果要新设计一门现代的语言,我们需要更多地使用 switch 语句,但是就不要再使用 break 语句了。

不过,不同的情景共享代码片段,仍然是一个真实的需求。在废弃掉 break 语句之前,我们要找到在不同的情景间共享代码片段的新规则。第二个容易犯错的地方,是反复出现的赋值语句。

在上面的代码中,daysInMonth 这个本地变量的变量声明和实际赋值是分开的。赋值语句需要反复出现,以适应不同的情景。

如果在 switch 语句里,daysInMonth 变量没有被赋值,编译器也不会报错,缺省的或者初始的变量值就会被使用。

int daysInMonth = 0;
switch (month) 
    // snipped
    case Calendar.APRIL:
    case Calendar.JUNE:
    case Calendar.SEPTEMBER:
    case Calendar.NOVEMBER:
        break;   // WRONG, INITIAL daysInMonth value IS USED!!!
    case Calendar.FEBRUARY:
    // snipped

在上面的例子里,初始的变量值不是一个合适的数据;

当然,在另外一个例子里,缺省的或者初始的变量值也可能就是一个合适的数据了。

为了判断这个本地变量有没有合适的值,我们需要通览整个 switch 语句块,确保赋值没有遗漏,也没有多余。

这增加了编码出错的几率,也增加了阅读代码的成本。那么,能不能让多情景处理的代码块拥有一个数值呢?

或者换个说法,多情景处理的代码块能不能变成一个表达式?这个想法,就催生了 Java 语言的新特性:“switch 表达式”。

二、switch 表达式

switch 表达式是什么样子的呢?

下面的这段代码,使用的就是 switch 表达式,它改进了上面阅读案例里的代码。

你可以带着上面遇到的问题,来阅读这段代码。这些问题包括:

  • switch 表达式是怎么表示一个数值,从而可以给变量赋值的?
  • 在不同的情景间,switch 表达式是怎么共享代码片段的?
  • 使用 switch 表达式的代码,有没有变得更简单、更皮实、更容易理解?
class DaysInMonth 
    public static void main(String[] args) 
        Calendar today = Calendar.getInstance();
        int month = today.get(Calendar.MONTH);
        int year = today.get(Calendar.YEAR);

        int daysInMonth = switch (month) 
            case Calendar.JANUARY,
                 Calendar.MARCH,
                 Calendar.MAY,
                 Calendar.JULY,
                 Calendar.AUGUST,
                 Calendar.OCTOBER,
                 Calendar.DECEMBER -> 31;
            case Calendar.APRIL,
                 Calendar.JUNE,
                 Calendar.SEPTEMBER,
                 Calendar.NOVEMBER -> 30;
            case Calendar.FEBRUARY -> 
                if (((year % 4 == 0) && !(year % 100 == 0))
                        || (year % 400 == 0)) 
                    yield 29;
                 else 
                    yield 28;
                
            
            default -> throw new RuntimeException(
                    "Calendar in JDK does not work");
        ;

        System.out.println(
                "There are " + daysInMonth + " days in this month.");
    

我们最先看到的变化,就是 switch 代码块出现在了赋值运算符的右侧。这也就意味着,这个 switch 代码块表示的是一个数值,或者是一个变量。换句话说,这个 switch 代码块是一个表达式。

int daysInMonth = switch (month) 
    // snipped

我们看到的第二个变化,是多情景的合并。也就是说,一个 case 语句,可以处理多个情景。这些情景,使用逗号分隔开来,共享一个代码块。而传统的 switch 代码,一个 case 语句只能处理一种情景。

case Calendar.JANUARY,
     Calendar.MARCH,
     // snipped

多情景的合并的设计,满足了共享代码片段的需求。而且,由于只使用一个 case 语句,也就不再需要使用 break 语句来满足这个需求了。所以,break 语句从 switch 表达式里消失了。

不同之处在于,传统的 switch 代码,不同的 case 语句之间可以共享部分的代码片段;

而 switch 表达式里,需要共享全部的代码片段。

这看似是一个损失,但其实,共享部分代码片段的能力给代码的编写者带来的困惑远远多于它带来的好处。如果需要共享部分的代码片段,我们总是可以找到替换的办法,比如把需要共享的代码封装成更小的方法。

所以,我们没有必要担心 switch 表达式不支持共享部分代码片段。

下一个变化,是一个新的情景操作符“->”,它是一个箭头标识符。这个符号使用在 case 语句里,一般化的形式是“case L ->”。

这里的 L,就是要匹配的一个或者多个情景。如果目标变量和情景匹配,那么就执行操作符右边的表达式或者代码块。如果要匹配的情景有两个或者两个以上,就要使用逗号“,”用分隔符把它们分割开来。

case Calendar.JANUARY,
     // snipped
     Calendar.DECEMBER -> 31;

传统的 switch 代码,这个一般化的形式是“case L :”,也就是使用冒号标识符。

为什么不延续使用传统的情景操作符呢?这主要是出于简化代码的考虑。

我们依然可以在 switch 表达式里使用冒号标识符,使用冒号标识符的一个 case 语句只能匹配一个情景,这种情况我们稍后再讨论。

下一个我们看到的变化,是箭头标识符右侧的数值。这个数值,代表的就是该匹配情景下,switch 表达式的数值。需要注意的是,箭头标识符右侧可以是表达式、代码块或者异常抛出语句,而不能是其他的形式。

如果只需要一个语句,这个语句也要以代码块的形式呈现出来。

case Calendar.JANUARY,
     // snipped
     Calendar.DECEMBER ->   // CORRECT, enclosed with braces.
    yield 31;

没有以代码块形式呈现的代码,编译的时候,就会报错。这是一个很棒的约束。

代码块的形式,增强了视觉效果,减少了编码的失误。

case Calendar.JANUARY,
     // snipped
     Calendar.DECEMBER ->   // WRONG, not a block.
    yield 31;

另外,箭头标识符右侧需要一个表达 switch 表达式的数值,这是一个很强的约束。

如果一个语句破坏了这个需要,它就不能出现在 switch 表达式里。

比如,下面的代码里的 return 语句,意图退出该方法,而没有表达这个 switch 表达式的数值。

这段代码就不能通过编译器的审查。

int daysInMonth = switch (month) 
    // snipped
    case Calendar.APRIL,
         // snipped
         Calendar.NOVEMBER -> 
        // yield 30;
        return; // WRONG, return outside of enclosing switch expression.
    
    // snipped

最后一个我们能够看到的变化,是出现了一个新的关键字“yield”

用JDK8中的lambda表达式中的return去理解他。

大多数情况下,switch 表达式箭头标识符的右侧是一个数值或者是一个表达式。

如果需要一个或者多个语句,我们就要使用代码块的形式。这时候,我们就需要引入一个新的 yield 语句来产生一个值,这个值就成为这个封闭代码块代表的数值。为了便于理解,我们可以把 yield 语句产生的值看成是 switch 表达式的返回值。

所以,yield 只能用在 switch 表达式里,而不能用在 switch 语句里。

case Calendar.FEBRUARY -> 
    if (((year % 4 == 0) && !(year % 100 == 0))
            || (year % 400 == 0)) 
        yield 29;
     else 
        yield 28;
    

其实,这里还有一个我们从上述的代码里看不到的变化。在 switch 表达式里,所有的情景都要列举出来,不能多、也不能少(这也就是我们常说的穷举)

比如说,在上面的例子里,如果没有最后的 default 情景分支,编译器就会报错。

这是一个影响深远的改进,它会使得 switch 表达式的代码更加健壮,大幅度降低维护成本,如果未来需要增加一个情景分支的话,就更是如此了。

int daysInMonth = switch (month) 
    case Calendar.JANUARY,
         // snipped
         Calendar.DECEMBER -> 31;
    case Calendar.APRIL,
         // snipped
         Calendar.NOVEMBER -> 30;
    case Calendar.FEBRUARY -> 
             // snipped
    
    // WRONG to comment out the default branch, 'switch' expression
    // MUST cover all possible input values.
    //
    // default -> throw new RuntimeException(
    //        "Calendar in JDK does not work");
;

三、改进的 switch 语句

那这些变化有没有影响 switch 语句呢?

比如说,我们能够在 switch 语句里使用箭头标识符吗?

我们前面说过,yield 语句是来产生一个 switch 表达式代表的数值的,因此 yield 语句只能用在 switch 表达式里,不能用在 switch 语句。

其他的变化呢?我们还是先来看下面一段代码。

private static int daysInMonth(int year, int month) 
    int daysInMonth = 0;
    switch (month) 
        case Calendar.JANUARY,
             Calendar.MARCH,
             Calendar.MAY,
             Calendar.JULY,
             Calendar.AUGUST,
             Calendar.OCTOBER,
             Calendar.DECEMBER ->
            daysInMonth = 31;
        case Calendar.APRIL,
             Calendar.JUNE,
             Calendar.SEPTEMBER,
             Calendar.NOVEMBER ->
            daysInMonth = 30;
        case Calendar.FEBRUARY -> 
            if (((year % 4 == 0) && !(year % 100 == 0))
                    || (year % 400 == 0)) 
                daysInMonth = 29;
                break;
            

            daysInMonth = 28;
        
        // default -> throw new RuntimeException(
        //        "Calendar in JDK does not work");
    

    return daysInMonth;

在这段代码里,我们看到了箭头标识符,看到了 break 语句,看到了注释掉的 default 语句。

这是一段合法的、能够工作的代码。

换个说法,switch 语句可以使用箭头标识符,也可以使用 break 语句,也不需要列出所有的情景。

表面上看起来,switch 语句的改进不是那么显而易见。

其实,switch 语句的改进主要体现在 break 语句的使用上。

我们应该也看到了,break 语句没有出现在下一个 case 语句之前。

这也就意味着,使用箭头标识符的 switch 语句不再需要 break 语句来实现情景间的代码共享了。

虽然我们还可以这样使用 break 语句,但是已经不再必要了。

switch (month) 
    // snipped
    case Calendar.APRIL,
             // snipped
         Calendar.NOVEMBER -> 
            daysInMonth = 30;
            break;  // UNNECESSARY, could be removed safely.
        
    // snipped

有没有 break 语句,使用箭头标识符的 switch 语句都不会顺次执行下面的操作(fall-through)。

这样,我们前面谈到的 break 语句带来的烦恼也就消失不见了。

不过,使用箭头标识符的 switch 语句并没有禁止 break 语句,而是恢复了它本来的意义:

从代码片段里抽身,就像它在循环语句里扮演的角色一样。

switch (month) 
   // snipped
   case Calendar.FEBRUARY -> 
        if (((year % 4 == 0) && !(year % 100 == 0))
                || (year % 400 == 0)) 
            daysInMonth = 29;
            break;     // BREAK the switch statement
        
    
        daysInMonth = 28;
    
   // snipped

四、怪味的 switch 表达式

我们前面说过,switch 表达式也可以使用冒号标识符。

使用冒号标识符的一个 case 语句只能匹配一个情景,而且支持 fall-through。

和箭头标识符的 switch 表达式一样,使用冒号标识符 switch 表达式也不支持 break 语句,取而代之的是 yield 语句。这是一个充满了怪味道的编码形式,我并不推荐使用这种形式,但我可以带你略作了解。

下面的这段代码,就是我们试着把箭头标识符替换成冒号标识符的一个例子。

你可以比较一下使用冒号标识符和箭头标识符的两段代码,想一想两种不同形式的优劣。

毫无疑问,使用箭头标识符的代码更加简洁。

class DaysInMonth 
    public static void main(String[] args) 
        Calendar today = Calendar.getInstance();
        int month = today.get(Calendar.MONTH);
        int year = today.get(Calendar.YEAR);

    int daysInMonth = switch (month) 
        case Calendar.JANUARY:
        case Calendar.MARCH:
        case Calendar.MAY:
        case Calendar.JULY:
        case Calendar.AUGUST:
        case Calendar.OCTOBER:
        case Calendar.DECEMBER:
            yield 31;
        case Calendar.APRIL:
        case Calendar.JUNE:
        case Calendar.SEPTEMBER:
        case Calendar.NOVEMBER:
            yield 30;
        case Calendar.FEBRUARY:
            if (((year % 4 == 0) && !(year % 100 == 0))
                    || (year % 400 == 0)) 
                yield 29;
             else 
                yield 28;
            
        default:
            throw new RuntimeException(
                    "Calendar in JDK does not work");
        ;

        System.out.println(
            "There are " + daysInMonth + " days in this month.");
    

有了使用箭头标识符的 switch 语句和 switch 表达式之后,不再推荐使用冒号标识符的 switch 语句和 switch 表达式

学习并使用箭头标识符的 switch 语句和 switch 表达式,会使代码更简洁、更健壮。

五、总结

了解了 switch 表达式和改进的 switch 语句。

讨论了 switch 表达式带来的新概念和新的关键字,了解了这些基本概念以及它们的适用范围。

新的 switch 形式、语句和表达式,不同的使用范围,这些概念交织在一起,让 switch 的学习和使用都变成了一件有点挑战性的事情。

箭头标识符的引入,简化了代码,提高了编码效率。

可是,学习这么多种 switch 的表现形式,也增加了我们的学习负担。

不同的 switch 表达形式,以及它们支持的特征,放在了下面这张表格里。

或者,你也可以记住下面的总结:

  • break 语句只能出现在 switch 语句里,不能出现在 switch 表达式里;
  • yield 语句只能出现在 switch 表达式里,不能出现在 switch 语句里;
  • switch 表达式需要穷举出所有的情景,而 switch 语句不需要情景穷举;
  • 使用冒号标识符的 swtich 形式,支持情景间的 fall-through;
  • 而使用箭头标识符的 swtich 形式不支持 fall-through;
  • 使用箭头标识符的 swtich 形式,一个 case 语句支持多个情景;
  • 而使用冒号标识符的 swtich 形式不支持多情景的 case 语句。

使用箭头标识符的 swtich 形式,废止了容易出问题的 fall-through 这个特征。

因此,我们推荐使用箭头标识符的 swtich 形式,逐步废止使用冒号标识符的 swtich 形式。在 switch 表达式和 switch 语句之间,我们应该优先使用 switch 表达式。

这些选择,都可以帮助我们简化代码逻辑,减少代码错误,提高生产效率。

如果你要丰富你的代码评审清单,你可以加入下面这一条:

使用冒号标识符的 swtich 形式,是不是可以更改为使用箭头标识符?
使用 switch 语句赋值的操作,是不是可以更改为使用 switch 表达式?

另外,我还拎出了几个今天讨论过的技术要点,这些都可能在你们面试中出现哦。

通过这一次学习,你应该能够:

  • 知道 switch 表达式,并且能够使用 switch 表达式;
    • 面试问题:你知道 switch 表达式吗?该怎么处理 switch 表达式里的语句?
  • 了解 switch 表达式要解决的问题,并且知道解决掉这些问题的办法;
    • 面试问题:使用 switch 表达式有哪些好处?
  • 了解不同的 switch 的表现形式,能够看得懂不同的表现形式,并且给出改进意见。
    • 面试问题:你更喜欢使用箭头标识符还是冒号标识符?

如果你能够有意识地使用箭头标识符的 switch 表达式,应该可以大幅度提高编码的效率和质量;

如果你能够了解不同的 switch 表现形式,并且对每种形式都有自己的见解,你就能帮助你的同事提高编码的效率和质量。

毫无疑问,在面试的时候,有意识地在代码里使用 switch 表达式,是一个能够展现你的学习能力、理解能力和对新知识的接受能力的一个好机会。


java8新特性你知道java8为什么要引入lambda表达式吗?(代码片段)

...官竟然问他这样一个问题:你说说Java8中为什么引入Lambda表达式?引入Lambda表达式后有哪些好处呢?还好这个朋友对Java8早有准备。不过,如果是看文章的你出去面试,面试官问你这样的问题,你是否也能轻松回答呢?什么是Lambd... 查看详情

java8lambda表达式

1.什么是λ表达式λ表达式本质上是一个匿名方法。让我们来看下面这个例子:   publicintadd(intx,inty){       returnx+y;   }转成λ表达式后是这个样子:      &n 查看详情

day640.java8的日期时间类问题-java业务开发常见错误

Java8的日期时间类问题Hi,阿昌来也!今天记录分享的是Java8的日期时间类问题在Java8之前,我们处理日期时间需求时,使用Date、Calender和SimpleDateFormat,来声明时间戳、使用日历处理日期和格式化解析日期时间。但是... 查看详情

day22:yield的表达形式,面向过程变成

一、yield的表达形式deffoo():print(‘starting‘)whileTrue:x=yieldNone#return2print(‘value:‘,x)g=foo()print(next(g))print(g.send(2))运行结果:starting#运行函数,打印starting后碰到yield停住None   #next()触发后yield将None赋值给x,打印None后循 查看详情

初探java8lambda表达式

...在java8中我们终于迎来了类似函数式编程-Java风格的lambda表达式,在用lambda重构你的代码后,啥感觉?倍爽!这篇博客我们就来 查看详情

day9:yield的表达式形式面向过程编程(grep-rl'root'/etc)

一.yield的表达式deffoo():print(‘starting‘)whileTrue:x=yieldNone#return2print(‘value:‘,x)g=foo()print(next(g))print(g.send(2))运行结果:starting#运行函数,打印starting后碰到yield停住None   #next()触发后yield将None赋值给x,打印None后循环 查看详情

重学java8新特性|第3讲——我们为什么要使用lambda表达式?(代码片段)

...c;我就已经讲过了,Java8新特性中最为核心的便是Lambda表达式与StreamAPI,只不过这一讲我首先会为大家讲解Lambda表达式。其实,Lambda表达式就是Java8提出的一种新的语法格式。在讲这个语法格式之前,我们首先得了... 查看详情

java8的改进和新的特性

...法,当实现接口后,就可以使用默认方法。lambda表达式。不用使用匿名的对象,使用更简洁的方式进行编程。lambda表达式可以访问外层作用域,如果访问局部变量那么可以不声明为final(匿名对象需要生命为fin... 查看详情

day2

...名称,如填写title,则可用${title}引用它。  (2)正则表达式:    ():括起来的部分就是要提取的。    .:匹配任何字符串。    +:一次或多次。    ?:不要太贪婪,在找到第一个匹配项后停止。  (3... 查看详情

day710.文字块-java8后最重要新特性(代码片段)

文字块Hi,我是阿昌,今天学习的是关于所见即所得的文字块(textblocks)。文字块(textblocks)这个特性,首先在JDK13中以预览版的形式发布。在JDK14中,改进的文字块再次以预览版的形式发布。最后,文字块在JDK15正... 查看详情

day723.现代密码-java8后最重要新特性(代码片段)

现代密码Hi,我是阿昌,今天学习记录的是关于现代密码。Java语言安全的基础,主要有两块内容。一块是Java语言的安全设计,比如字节码的校验,内存保护机制等等;另外一块是Java平台的保护机制,... 查看详情

day719.矢量运算-java8后最重要新特性(代码片段)

矢量运算Hi,阿昌来也,今天学习记录的是关于此时此刻还在预览阶段的矢量运算。Java的矢量运算,我写这篇文章的时候还在孵化期,还没有发布预览版。这个技术代表了Java语言发展的一个重要方向,在未来... 查看详情

day711.档案类-java8后最重要新特性(代码片段)

档案类:不可变数据的透明载体Hi,我是阿昌,今天学习的是关于一个不可变数据的透明载体,档案类。档案类这个特性,首先在JDK14中以预览版的形式发布。在JDK15中,改进的档案类再次以预览版的形式发布。... 查看详情

java8lambda表达式(代码片段)

...ava8时间日期使用 java8中一个非常重要的特性就是lambda表达式,我们可以把它看成是一种闭包,它允许把函数当做参数来使用,是面向函数式编程的思想,一定程度上可以使代码看起来更加简洁。例如以前我们使用匿名内部类... 查看详情

java8-03-笔记(代码片段)

...自己看的@@个人感觉这块知识点不太好用,Lambda表达式可以说的匿名函数格式的简化 查看详情

java8lambda表达式示例

例1、用lambda表达式实现Runnable我开始使用Java8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例。看一下Java8之前的runnable实现方法,需要4行代码,而使用lambda表达式只需要一行代码。我们在这... 查看详情

day725.java为何需要模块化-java8后最重要新特性(代码片段)

Java为何需要模块化Hi,我是阿昌,今天学习的是关于Java为何需要模块化。Java平台模块系统(JavaPlatformModuleSystem,JPMS)。Java平台模块系统是在JDK9正式发布的。为了沟通起来方便,有时候就直接简称为Java模... 查看详情

day726.java平台模块系统-java8后最重要新特性(代码片段)

Java平台模块系统Hi,我是阿昌,今天学习记录的是关于Java平台模块系统。Java平台模块系统是在JDK9正式发布的。这项重要的技术从萌芽到诞生,花费了十多年的时间,堪称Java出现以来最重要的新软件工程技术。模... 查看详情