<div dir="ltr"><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Apr 20, 2024 at 3:01 AM Tagir Valeev <<a href="mailto:amaembo@gmail.com">amaembo@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Dear experts,<div><br></div><div>looking into this proposal, I'm really not convinced that Java needs it. We already have try-catch statements, and it sounds strange to provide another way to express the same semantics. I don't see what the new construct adds, aside from a bit of syntactic sugar. On the other hand, it creates a new source of subtle bugs, especially when exceptions are unchecked. E.g., consider:</div><div><br></div><div>switch(a.b().c().d()) {</div><div>case ...</div><div>case throws RuntimeException ex -> handle(ex);</div><div>}</div><div><br></div><div>Now, one may want to refactor the code, extracting a.b(), a.b().c(), or the whole a.b().c().d() to a separate variable for clarity, or to avoid a long line. </div><div>This action is usually safe, and it was totally safe in switches so far (even with patterns and case null). Now, it's not safe, as exceptions thrown from the extracted part are not handled by the 'case throws' branch. </div><div>I don't see a good way to perform this refactoring in a semantically equivalent way. The only possibility I see is to duplicate the exception handler in the external catch:</div><div><br></div><div>try {</div><div>  var ab = a.b();</div><div>  switch(ab.c().d()) {</div><div>  case ...</div><div>  case throws RuntimeException ex -> handle(ex);</div><div>  }</div><div>}<br></div><div>catch(RuntimeException ex) {</div><div>  handle(ex); // duplicated code</div><div>}</div><div><br></div></div></blockquote><div><br></div><div>There are some straightforward alternatives. To avoid long lines, wrap the switch expression across multiple lines. To refactor the switch expression across multiple statements for clarity, use a private method. I write this sort of thing all the time:<br></div><div><br><div>private D abcd(A a) {</div><div>  var b = a.b();</div><div>  var c = b.c();</div><div>  return c.d();</div><div>}</div><div><br></div><div>...</div><div><br></div><div>switch (abcd(a)) {</div><div>  case ...</div><div>  case throws RuntimeException ex -> handle(ex);</div><div>}<br></div><div><div> </div></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div>As switch selector does not allow using several expressions or to declare new variables, extract/inline refactorings can easily become very painful, or cause subtle bugs if not performed correctly. </div><div>Note that it's not a problem inside usual try-catch statement (*), as you can easily add or remove more statements inside the try-body.</div><div><br></div><div>(*) Except resource declaration, but it's rarely a problem, and in some cases it's still possible to extract parts as separate resources, because you can declare several of them<br></div><div><br></div><div>I think, instead of repurposing switch to be another form of try-catch we could add more love to try-catch allowing it to be an expression with yields in branches. The proposed JEP allows something like this:</div><div><br></div><div>Integer toIntOrNull(String s) {</div><div>  return switch(Integer.parseInt(s)) {</div><div>    case int i -> i;</div><div>    case throws NumberFormatException _ -> null;</div><div>  }</div><div>}</div><div><br></div><div>But we are still limited by a single expression in the selector. An alternative would be</div><div><div>Integer toIntOrNull(String s) {</div><div>  return try { yield Integer.parseInt(s); }</div><div>    catch(NumberFormatException _) { yield null; };</div><div>}<br></div><div>Here, all kinds of refactorings are possible. And we actually don't need to express pattern matching, because we essentially don't need any pattern matching.</div></div><div><br></div><div>Also, note that some of the situations which are usually solved with exception handling in modern Java (e.g. Pattern.compile -> PatternSyntaxException, or UUID.fromString -> IllegalArgumentException, or Integer.parseInt above) will be covered in future by member patterns. So probably if we concentrate more on member patterns, people will need much less exception handling in business logic, and such an enhancement will be not so useful anyway? Speaking about the sample from the JEP, can we imagine something like this in the future (sic!) Java?</div></div></blockquote><div><br></div><div>I agree *in part* with this sentiment. Many library methods that currently throw exceptions would be better written as member patterns. However, there will always be a need to handle exceptions thrown by code that works with the outside world (databases, network, filesystem). These are often libraries and frameworks we do not control. Having "case throws" available would be a significant improvement for those situations.<br></div><div><br></div><div>switch (getEntityFromNetworkDatabase(id)) {</div><div>  case SomeEntity entity -> ...<br></div><div>  case DatabaseException ex -> ...</div><div>  case NetworkException ex -> ...<br></div><div>}<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>switch(future) {</div><div>  case Future.cancelled() -> ...</div><div>  case Future.interrupted() -> ...</div><div>  case Future.failed(Exception ex) -> ... // no need to unwrap ExecutionException manually</div><div>  case Future.successful(Box b) -> ...</div><div>}</div><div><br></div><div>One more note about the JEP text. It's unclear for me whether 'case throw' branches could catch a residual result. More precisely, if MatchException happens, or NullPointerException happens (selector evaluated to null, but there's no 'case null'), can these exceptions be caught by the 'case throws' branches in the same switch?</div><div><br></div><div>With best regards,</div><div>Tagir Valeev.</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Apr 19, 2024 at 3:05 PM Angelos Bimpoudis <<a href="mailto:angelos.bimpoudis@oracle.com" target="_blank">angelos.bimpoudis@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>




<div dir="ltr">
<div style="font-size:11pt;color:rgb(0,0,0)">
Dear spec experts,</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
A while ago we discussed on this list about enhancing the <code>switch</code> construct to</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
support <code>case</code> labels that match exceptions thrown during evaluation of the</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
selector expression. A draft JEP for this feature is now available at:</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
<a href="https://bugs.openjdk.org/browse/JDK-8323658" target="_blank">https://bugs.openjdk.org/browse/JDK-8323658</a></div>
<div style="font-size:11pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
Please take a look at this new JEP and give us your feedback.</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
Thanks,</div>
<div style="font-size:11pt;color:rgb(0,0,0)">
Aggelos</div>
</div>

</div></blockquote></div>
</blockquote></div></div>