Win a copy of Emmy in the Key of Code this week in the General Computing forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Junilu Lacar
  • Jeanne Boyarsky
  • Bear Bibeault
Sheriffs:
  • Knute Snortum
  • Devaka Cooray
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Ron McLeod
  • Carey Brown
Bartenders:
  • Paweł Baczyński
  • Piet Souris
  • Vijitha Kumara

What are the new changes to switch statements in Java 13?

 
Bartender
Posts: 2401
106
Google Web Toolkit Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How does it look like? Will the case pass through still work the same ?
 
Marshal
Posts: 66135
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

salvin francis wrote:. . . Will the case pass through still work the same ?

No.


I have a copy of Mala Gupta's Java 11 and 12 – New Features (Packt, 2019); pages 126‑137 describe what she thinks the new type of switch will look like. Instead of fall‑through, you would write a comma‑separated list of cases all pointing to the same expression.
 
Ranch Hand
Posts: 75
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here https://jaxenter.com/java-13-jdk-deep-dive-new-features-162272.html the author of the post provide some detail of the new changes with code snippets:


* Enhancements for Switch Expressions
 
Campbell Ritchie
Marshal
Posts: 66135
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Where does that chap get that syntax from; the JLS (=Java® Language Specification) (Java13 edition) doesn't show yield as a keyword. This is what the JLS says about switch; I can't seem to find anything about the new switch. Maybe that is a “preview” feature, which has to be enabled with a command‑line option.
 
Jorge Ruiz-Aquino
Ranch Hand
Posts: 75
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, it's a preview feature.
According to the lecture, they have moved some other features from release 13 to the 14 as well.

It has not been easy for me to keep up to date with the new pace of releases. So this kind of discussions and post makes me research a little bit.
Thank you.
 
Campbell Ritchie
Marshal
Posts: 66135
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It isn't easy for anybody to keep up with the changes. Particularly if they predict change “A” and deliver change “B”.
 
Master Rancher
Posts: 3396
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Where does that chap get that syntax from


He gave a link to Java enhancement proposals that made it into JDK 13; that in turn has a link for switch expressions.  These are the most authoritative sources I know of for documentation of the preview features.  Since they're not enabled by default, they're not part of the language proper that's documented in the JLS.
 
Campbell Ritchie
Marshal
Posts: 66135
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Mike Simmons wrote:. . . a link for switch expressions. . . .

Thank you. Read that link, which explains it all. The whole lot might change before Java14, however.
 
salvin francis
Bartender
Posts: 2401
106
Google Web Toolkit Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yield   Somehow I find that term a bit confusing from a switch case point of view.
 
Mike Simmons
Master Rancher
Posts: 3396
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yeah, earlier they were using "return" instead of yield - but that was confusing too, since we're not returning from a method, or a a lambda, just a switch.  Someone thought it would be clearer to use a different term I guess.  "Yield" is used in some other languages like Python and Ruby, so now it's found its way to Java...
 
Saloon Keeper
Posts: 6398
60
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I read something last night about java-12's switch() expressions using '->' will still work with java-13. They seem to do the same thing to me as 'yield', so, which one?

Java-12
 
Campbell Ritchie
Marshal
Posts: 66135
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

salvin francis wrote:yield   Somehow I find that term a bit confusing from a switch case point of view.

And it would mean adding another keyword/reserved word You could do the whole thing with -> alone.
 
Carey Brown
Saloon Keeper
Posts: 6398
60
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I turned on 'preview' in Eclipse and my old Thread's broke where they called yield(). I had to replace them to a call to super.yield().
 
Mike Simmons
Master Rancher
Posts: 3396
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First, I misremembered earlier when I said earlier (Java 12) used return instead of yield.  Actually, Java 12 used break instead of yield.  So in Java 12 you would have had:

And the Java 13 version would be

Or using arrow notation... Java 12:

or Java 13:

Campbell Ritchie wrote:And it would mean adding another keyword/reserved word You could do the whole thing with -> alone.


I agree they're adding a new reserved word, which can be troubling.  But even when using ->, if the thing after -> is more than one line, we need braces {} around it... and then we also need some keyword for the thing we're returning, or breaking, or yielding. Or whatever.

They could have instituted a rule that makes the last statement/expression in a block into the de facto return value of the block, without needing it explicitly returned.  Like in Scala and other languages.  Then that final default case could be written as:

No need for any keyword then... but that would be confusing for Java programmers not used to that.  And what if there's more than one possible value to return?  E.g.

Those numbers just floating there look wrong to a java programmer... having some keyword there to like return, break or yield does help readability, I think.  Or maybe it's all just a question of what we're used to seeing...
 
Author
Posts: 53
15
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here are the highlights of changes to switch:
  • It was added in Java 12 as a preview feature.
  • It stayed as a preview feature in Java 13 with a minor change – the break with value in a switch expression in Java 12 was replaced with a yield statement in Java 13.
  • switch has received new syntax. The new switch syntax allows you to use an arrow (->) instead of a colon (:) to separate the case label from its corresponding code. In my book, I call them as switch-with-colon and switch-with-arrow.
  • Now you can also use multiple constants in one case label.
  • You can use both switch-with-colon and switch-with-arrow as a statement and an expression. Before this change, you had only switch-with-colon and you could use it only as a statement.
  • To support enhancements to switch, there is a new yield statement, which can be used in a switch expression. This may break your existing code, which would be easy to fix though. More details on this in a separate section below.

  • Let me give you an example of all changes with a little explanation. Some people do not know what a preview feature is, so I will start with explaining it first.

    What Is a Preview Feature?
    A preview feature of the Java SE Platform is a fully specified and fully implemented language or virtual machine feature, which is available in a JDK feature release, but is not a permanent feature of the JDK yet. A preview feature is provided to solicit developers feedback. Developers are expected to experiment with the features in real world use-cases. Based on the feedback, a preview feature may become permanent (standard feature) in a future release with or without modifications or it may be removed altogether. A preview feature is not meant to be used in production. Refer to JEP 12 at https://openjdk.java.net/jeps/12 for more details on preview features.

    A preview feature is not backward compatible. You cannot run class files that contain preview features from Java 12 using Java 13 runtime.
    Since a preview feature is not meant to be used in production, it is not enabled in the compiler and runtime by default. You must use the --enable-preview option with the compiler and runtime to use a preview feature.  You will need to use the --release or -source option when you use the --enable-preview option to compile the source code. To compile source code with preview features in JDK 13, you would use:

    If you do not use the --enable-preview option to compile the source code with preview features, you receive compile-time errors similar to the following:

    If you enable preview features at compile-time, the compiler prints notes suggesting you to compile with a -Xlint:preview option, so you can see the warnings.
    To run compiled classes with preview features, you specify the --enable-preview option with the java command:

    If you want to use JShell to explore preview features, you need to start it with the --enable-preview option:
    Enhancements to Traditional Switch
    Java has always been backward compatible. Adding breaking changes to the traditional switch was not an option to the language designers. The preview feature provides you new ways of using the traditional switch without breaking your old code. Here are the changes to the traditional switch:
  • You can have multiple constants in a case label.
  • You can use switch as an expression.

  • Previously, you had to use one case label per constant. The new switch syntax allows you to use a comma-separated list of constants in a case label. The following snippet of code uses the traditional switch with multiple constants in a case label to match a letter against a vowel and consonant:


    With the new switch syntax, you have collapsed five case labels into one. You still need to use a break statement because the traditional switch statement still uses default fall-through semantics.
    The preview feature allows you to use the traditional switch as an expression. An expression evaluates to a value (or yields a value). Now you can write code like:

    Notice the use of a semicolon at the end of the switch expression. The switch expression is part of the variable declaration for the str variable, so the entire variable declaration must end with a semicolon. Think of the previous variable declaration as shown:

    The traditional switch allowed you to use only statements for a switch label. The preview feature has introduced a new yield statement. Its syntax is:

    yield expression;

    The yield statement evaluates its expression and transfers control to the enclosing switch expression. The value of the expression becomes the value of the switch expression.

    Tip The yield statement can only be used inside a switch expression. You cannot use the break statement inside a switch expression.

    Here is an example of a switch expression using the traditional switch:

    This is a simple example where each switch label contains only one yield statement. You can have multiple statements in a switch label. However, each switch label must contain one yield statement that will represent the value of the switch expression. Typically, you will not print something from an expression. Let us do it just for the demonstration purpose to show that you can have multiple statements in a switch label for a switch expression. The following snippet of code prints a message when "case 1:" is executed:

    Recall that you cannot use the break statement inside a switch expression. The yield statement completes a switch expression. In this statement, when count is 1, a message is printed, and the yield statement completes the switch expression by yielding "One" and other case labels below "case 1:" are not executed.
    Here is a challenge for you. Let me switch the two statements in the previous snippet of code as follows. Now, the yield statement is first and the System.out.println() is second. Will the following snippet of code compile?

    If your answer is no, you are correct. The yield statement completes the switch expression making the System.out.println() statement unreachable. Java does not allow unreachable statements. This snippet of code generates the following compile-time error:



    New Switch Syntax
    The new switch retains most of the syntax from the traditional switch, except the character to separate a switch label from its code. It uses an arrow (->) instead of a colon (:). The traditional "case label:" becomes "case label->". This is the only syntactic difference you have for the new switch. There are several semantic differences that I explain in this section.
    Often, I need to distinguish which switch I am talking about–the new one or the old new. I refer to the old switch as traditional switch, switch-with-colon, or switch with "case label:". I refer to the new one as new switch, switch-with-arrow, or switch with "case label->". Java Language Specification refers to the switch block associated with the traditional switch as switch labeled statement groups and the switch block associated with the new switch as switch labeled rules. Whichever name you use to refer to the new switch, here is its syntax:

    The syntax allows for one or more constants in a case label. The code associated with a switch label is restricted to one of the following: an expression, a block statement, and a throw statement. I will explain the rationale behind this rule shortly.
    Let us look at the rules used to process the new switch followed with examples of each rule:
  • The default is no fall-through in the new switch. This means, you no longer need to use a break statement to stop executing the switch labels following the matched switch label.
  • Only one "thing" can be executed as part of a matched switch label. That "thing" can be an expression, a block statement, or a throwstatement. In traditional switch, a group of statements was allowed causing the scoping issue where the entire switch block was executed in one scope. Using these constraints, if you have more than one statement to execute, you are forced to use a block statement that will have a new scope for the switch label. This allows you to have the same functionality as the traditional switch, but code is less error-prone.
  • The new switch can be used as a statement or as an expression.

  • The following snippet of code rewrites the previous example, which used the traditional switch statement, using the new switch statement:

    Notice the use of the System.out.println() in each switch label. Didn't I say that each switch label can have an expression, a block statement, or a throw statement?  I did say that. In Java, a method call (in this case, System.out.println()) is an expression. When you add a semicolon after the method call, it becomes an expression statement. Here are the detailed rules about using an expression in a switch label with arrow:
  • In a switch statement, the expression must be an expression statement–an expression, which can be converted to a statement by adding a semicolon to it.
  • In a switch expression, the expression may be any valid Java expression.

  • The following snippet of code rewrites the previous example using a switch expression:
     

    This time, "One", "Two", etc. are expressions. You cannot convert them to expression statements by adding a semicolon. When the switch expression (count) matches one of the case labels, the corresponding expression ("One", "Two", etc.) becomes the value for the switch expression.
    If you have to compute the value in a switch label using some logic, you will need to use the yield statement to return the value as the value for the switch expression. Consider the following snippet of code that uses a switch expression to compute a value:

    The case label uses a simple expression "Vowel" when the character is a vowel. The default label uses a block statement to use logic to determine whether it is a consonant or not a letter. Note the use of the yield statements inside the if and else blocks. The default label does not use very complex logic. You can replace it with an expression as shown:

    Consider the following snippet of code that uses the new switch statement:

    The code uses one case label and one default label. Both contain more than one statement, so you are forced to use a block statement ({}) in each label. Notice that you have used the same variable name upperChar inside the code for both labels. Declaring duplicate variables in a switch block like this was also possible with traditional switch, but you had to remember to use a block statement, whereas the new switch forces you to use a block statement.

    Does New switch Replace the Old One?
    Once the new switch becomes a standard feature in Java SE (maybe in Java SE 14), you are encouraged to use it in place of the traditional switch when it fits your needs. However, it is not a complete replacement for the traditional switch statement. Remember that the traditional switch offers fall-through by default and you have a way (using the break statement) to override the default behavior. Consider the following trivial example that uses the fall-through feature of the traditional switch statement:

    If the value of count is 1, it prints "One Two Three"; for 2, it prints "Two Three"; for 3, it prints "Three"; and, for any other values, it prints "Over-My-Head". Implementing this logic is simple because of the fall-through feature of the traditional switch statement. There is no straightforward way to implement this logic using the new switch syntax because the new switch does not provide the fall-through feature. You got the point–use the new syntax whenever possible and use the traditional switch when fall-through is needed.
    I was curious to get a bit more insight into the new switch features and how the compiler handles them. So, I tried to decompile all my examples, which were written using new switch syntax. You can use http://www.javadecompilers.com to decompile your Java code. When I decompiled my code, I did not see any new switch syntax. I found out that in all cases, the code using new switch syntax was translated to the traditional switch. Even though the new switch uses the old switch behind the scene, as a developer you gain a lot of benefits using the new syntax. You get compact and less error-prone code, and a new big feature, which is using switch as an expression!

    A Switch Expression is a Poly Expression
    A poly expression in Java is an expression whose type depends on the context. Therefore, the same poly expression can take on different types in different contexts. A switch expression is a poly expression. If its target type is known, its type is the type of its target type. If its target type is unknown, its type is computed by combining the types of each switch labels. Consider the following snippet of code:

    This switch expression has a target type of double, which is the type of the value variable. Therefore, the type of the switch expression is double. The compiler also checks that the type of the value yielded from each switch label is assignment compatible to the target type of the switch expression. In this case, the switch labels yields an int (10), a double (20.4) and a float (1.5F). All three types, int, double, and float, are assignment compatible to the target type double.
    Consider the following snippet of code. Will it compile?

    This snippet of code does not compile. The target type of the switch expression is int, which is the declared type of the value variable. The double and float values yielded from the two switch labels are not assignment compatible to int. This is the reason why this code does not compile.
    Consider the following snippet of code. Will it compile?

    The code compiles fine. Notice the use of var to declare the value variable. This time, the target type of the switch expression is unknown. The compiler has to compute the type of the switch expression by looking at each switch label. The switch labels yield values of int, double, and float type. The compiler uses the type-widening rules and computes double as the type of the switch expression. Remember that the compiler has to infer the type of the value variable because of var. The type value will be inferred as double, which is the same as the computed type of the switch expression.
    Consider the following snippet of code. Will it compile?

    If you guessed that this snippet of code won't compile, you are wrong. It compiles fine. Now you might be curious to know the computed type of the switch expression. The compiler uses the following steps:
  • There are three types of values yielded from switch labels: int, double, and String.
  • The types are mixed–two primitive types and one reference type.
  • The primitive types are promoted to reference types Integer and Double.
  • The compiler looks at the common types among Integer, Double, and String. The compiler computes a type that is the union of all common types of these three types. All three types implement four interfaces: Serializable, Comparable, Constable, and ConstantDesc. The computed type of the switch expression is a combination of these four interfaces.

  • So, what is the type of the switch expression in the previous snippet of code? Here it is:

    This is a non-denotable type. That is, only the compiler can use this type in bytecode. You cannot use (or denote) this type in your source code. To see this for yourself, you can use JShell to run this snippet of code. Make sure to use the --enable-preview option to start Jshell and set the feedback mode to verbose, as shown:


    The yield Statement
    The new switch expression has introduced a new statement called the yield statement. Making yield a statement has some implications on the existing code. It might break existing code if you had a yield() method, which was invoked using unqualified syntax. Let us take an example to understand this rule. Consider the followings yield statement:

    Before yield being a statement, this was definitely a method call. That is, it will call a method named yield by passing a value 10.
    After the introduction of the switch expressions, this statement will be interpreted as a yield statement that yields a value 10 and it is only permitted to be used in switch expressions. Note that using parenthesis around 10 does not make this a method call because now yield is a statement and (10) is its value. All of the following variants will be treated as a yield statement–whitespaces and parenthesis making no difference:

    If you have unqualified yield() method calls in your existing code, you will need to modify it to make them qualified method calls. That is, if you have yield(x) in your existing code, you will need to change it to this.yield(x) or C.yield(x) depending on the context.
    With the introduction of the switch expressions, yield is a restricted identifier.  Its use is restricted in certain contexts. You cannot use yield as a type name such as a class name or an interface name. However, you can use yield as a method name and a variable name. Using yield as a method is allowed for backward compatibility because the Thread class in Java contains a yield method and, in rare cases, you might have named your methods as yield.
    The following is a complete program to show how to use yield as a method/variable names and how to call such methods. You must use the NoYieldAsTypeName.yield() syntax to call the yield() method.



    Output:


    Mixing Switch Label Syntax
    You have two syntax to declare switch labels–one uses a colon (:) and one uses an arrow (->). In one switch, you cannot mix the two syntax. The following snippet of code does not compile:

     
    Campbell Ritchie
    Marshal
    Posts: 66135
    250
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    ...but what about old uses of yield? Have they shot themselves in the foot by breaking old code? I know the only place plain simple yield appears in the standard API is Thread#yield(), and they say it is rarely useful, but what about other uses of yield in old code? Will previously compiled code still work? Or might there be a different version of switch in Java14?
     
    Kishori Sharan
    Author
    Posts: 53
    15
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    The unqualified use of yield in already compiled code works in JDK 13. That is, if you have used an yield() as a method call compiled in JDK8, the same compiled code can be used (I mean, it can be run using JDK13 runtime) in JDK13 without forcing you to make any changes. You will need to make changes only if you try to re-compile your existing source code using JDK13.  
     
    Campbell Ritchie
    Marshal
    Posts: 66135
    250
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    That sounds like the situation with deprecated code; I think old code will continue to execute as long as you don't recompile it.

    Thank you for your detailed responses in this discussion
     
    Carey Brown
    Saloon Keeper
    Posts: 6398
    60
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    For most  projects it's a given that you're going to recompile it. So, poof, broken. I'd prefer that they'd come up with a new operation from special characters then to come up with a new keyword, especially one already known to be used.
     
    Campbell Ritchie
    Marshal
    Posts: 66135
    250
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Surely they know that breaking old code will take 10% off their market share immediately? But I agree that <- or -> or similar would have been much better than a new keyword.
     
    salvin francis
    Bartender
    Posts: 2401
    106
    Google Web Toolkit Eclipse IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Why are they after the good old switch statement !?!  
    The only change I love about it was introducing strings to it in Java 7. I am still not able to grasp my mind yet over a switch returning a value instead of just comparing. In my head, a switch was a very elegant  way of writing if - else if - else  statements.
     
    Kishori Sharan
    Author
    Posts: 53
    15
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    They are preparing for a big new feature called pattern-matching. Enhancing old switch is a tiny part of the pattern-matching feature, which is still in proposal phase. Of course, new switch expressions and new switch without fall-through will help developers write concise and less error-prone code.
     
    Mike Simmons
    Master Rancher
    Posts: 3396
    33
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    salvin francis wrote:The only change I love about it was introducing strings to it in Java 7.


    Hey, what about switching on enums?  Also a good change, I think.

    salvin francis wrote: I am still not able to grasp my mind yet over a switch returning a value instead of just comparing.


    I think it's a bit like replacing a traditional if / else with a ternary operator.  Consider how code like this:

    can be replaced with a ternary:


    Similarly, a traditional switch like

    can now be replaced with:


    salvin francis wrote:In my head, a switch was a very elegant  way of writing if - else if - else  statements.


    It still is - but now, there's a more elegant, more compact form.
     
    expectation is the root of all heartache - shakespeare. tiny ad:
    Java file APIs (DOC, XLS, PDF, and many more)
    https://products.aspose.com/total/java
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!