{"id":4057,"date":"2018-02-06T10:34:05","date_gmt":"2018-02-06T08:34:05","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=4057"},"modified":"2018-02-06T10:34:24","modified_gmt":"2018-02-06T08:34:24","slug":"inselupdate-switch-hat-ohne-unterbrechung-durchfall","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2018\/02\/inselupdate-switch-hat-ohne-unterbrechung-durchfall\/","title":{"rendered":"Inselupdate: switch hat ohne Unterbrechung Durchfall"},"content":{"rendered":"<p>Bisher haben wir in die letzte Zeile eine break-Anweisung gesetzt. Ohne ein break w\u00fcrden nach einer \u00dcbereinstimmung alle nachfolgenden Anweisungen ausgef\u00fchrt. Sie laufen somit in einen neuen Abschnitt herein, bis ein break oder das Ende von switch erreicht ist. Da dies vergleichbar mit einem Spielzeug ist, bei dem Kugeln von oben nach unten durchfallen, nennt sich dieses auch Fall-through. Ein h\u00e4ufiger Programmierfehler ist, das break zu vergessen, und daher sollte ein beabsichtigter Fall-through immer als Kommentar angegeben werden.<\/p>\n<p>\u00dcber dieses Durchfallen ist es m\u00f6glich, bei unterschiedlichen Werten immer die gleiche Anweisung ausf\u00fchren zu lassen. Das nutzt auch das n\u00e4chste Beispiel, das einen kleinen Parser f\u00fcr einfache Datumswerte realisiert. Der Parser soll mit drei unterschiedlichen Datumsangeben umgehen k\u00f6nnen, je ein Beispiel:<\/p>\n<ul>\n<li>&#8222;18 12&#8220;: Jahr in Kurzform, Monat<\/li>\n<li>&#8222;2018 12&#8220;: Jahr, Monat<\/li>\n<li>&#8222;12&#8220;: Nur Monat, es soll das aktuelle Jahr implizit gelten<\/li>\n<\/ul>\n<pre>public class SimpleYearMonthParser {\r\n\r\n@SuppressWarnings( \"resource\" )\r\n\r\npublic static void main( String[] args ) {\r\n\r\nString date = \"17 12\";\r\n\r\nint month = 0, year = 0;\r\n\r\njava.util.Scanner scanner = new java.util.Scanner( date );\r\n\r\nswitch ( date.length() ) {\r\n\r\n<strong>case 5<\/strong>:\u00a0 \/\/ YY MM\r\n\r\nyear = 2000;\r\n\r\n\/\/ Fall-through\r\n\r\n<strong>case 7<\/strong>: \/\/ YYYY MM\r\n\r\nyear += scanner.nextInt();\r\n\r\n\/\/ Fall-through\r\n\r\n<strong>case 2<\/strong>: \/\/ MM\r\n\r\nmonth = scanner.nextInt();\r\n\r\nif ( year == 0 )\r\n\r\nyear = java.time.Year.now().getValue();\r\n\r\nbreak;\r\n\r\ndefault :\r\n\r\nSystem.err.println( \"Falsches Format\" );\r\n\r\n}\r\n\r\nSystem.out.println( \"Monat=\" + month + \", Jahr=\" + year );\r\n\r\n}\r\n\r\n}\r\n\r\n<\/pre>\n<p>In dem Beispiel bestimmt eine case-Anweisung \u00fcber die L\u00e4nge, wie der Aufbau ist. Ist die L\u00e4nge 5, so ist die Angabe des Jahres verk\u00fcrzt und wir initialisieren das Jahr mit 2000, um im folgenden Schritt mit Hilfe vom Scanner das Jahr einzulesen. Zu diesem Schritt w\u00e4ren wir auch direkt gekommen, wenn die L\u00e4nge der Eingabe 7 gewesen w\u00e4re, also das Jahr vierstellig gewesen w\u00e4re. Damit ist der Jahresanteil gekl\u00e4rt, es bleibt die Monate zu parsen. Kommen wir direkt \u00fcber einen String der L\u00e4nge 2, ist vorher kein Jahr gesetzt, wir bekommen \u00fcber java.time.Year.now().getValue() das aktuelle Jahr, andernfalls \u00fcberschreiben wir die Variable nicht.<\/p>\n<p>Was sollte der Leser von diesem Beispiel mitnehmen? Eigentlich nur Kopfsch\u00fctteln f\u00fcr eine schwer zu verstehende L\u00f6sung. Das Durchfallen ist eigentlich nur zur Zusammenfassung mehrerer case-Bl\u00f6cke sinnvoll zu verwenden.<\/p>\n<p>Sprachvergleich *<\/p>\n<p>Obwohl ein fehlendes break zu l\u00e4stigen Programmierfehlern f\u00fchrt, haben die Entwickler von Java dieses Verhalten vom syntaktischen Vorg\u00e4nger C \u00fcbernommen. Eine interessante andere L\u00f6sung w\u00e4re gewesen, das Verhalten genau umzudrehen und das Durchfallen explizit einzufordern, zum Beispiel mit einem Schl\u00fcsselwort. Dazu gibt es eine interessante Entwicklung: Java \u00bberbt\u00ab diese Eigenschaft von C(++), die wiederum erbt sie von der Programmiersprache B. Einer der \u00bbErfinder\u00ab von B ist Ken Thompson, der heute bei Google arbeitet und an der neuen Programmiersprache Go beteiligt ist. In Go m\u00fcssen Entwickler ausdr\u00fccklich die fallthrough-Anweisung verwenden, wenn ein case-Block zum n\u00e4chsten weiterleiten soll. Das gleiche gilt f\u00fcr die neue Programmiersprache Swift; auch hier gibt es die Anweisung fallthrough. Selbst in C++ gibt es seit dem Standard C++17 das Standard-Attribut [[fallthrough]]<a href=\"#_ftn1\" name=\"_ftnref1\">[1]<\/a> \u2013 Attribute sind mit Java-Annotationen vergleichbar ist; es steuert den Compiler, bei einem Durchfallen keine Warnung anzuzeigen.<\/p>\n<p>Stack-Case-Labels<\/p>\n<p>Stehen mehrere case-Bl\u00f6cke untereinander, um damit Bereiche abzubilden, nennt sich das auch Stack-Case-Labels. Nehmen wir an, eine Variable hour steht f\u00fcr eine Stunde am Tag und wir wollen herausfinden, ob Mittagsruhe, Nachtruhe oder Arbeitszeit ist:<\/p>\n<pre>int hour = 12;\r\n\r\nswitch ( hour ) {\r\n\r\n\/\/ Nachtruhe von 22 Uhr bis 6 Uhr\r\n\r\n<strong>\u00a0 case 22:<\/strong>\r\n\r\n<strong>\u00a0 <\/strong><strong>case 23:<\/strong>\r\n\r\n<strong>\u00a0 case 24: case 0:<\/strong>\r\n\r\n<strong>\u00a0 case 1: <\/strong>\r\n\r\n<strong>\u00a0 case 2: <\/strong>\r\n\r\n<strong>\u00a0 case 3: <\/strong>\r\n\r\n<strong>\u00a0 case 4:<\/strong>\r\n\r\n<strong>\u00a0 case 5: <\/strong>\r\n\r\nSystem.out.println( \"Nachtruhe\" );\r\n\r\nbreak;\r\n\r\n\/\/ Mittagsruhe von 13 bis 15 Uhr\r\n\r\n<strong>\u00a0 case 13:<\/strong>\r\n\r\n<strong>\u00a0 case 14:\u00a0 <\/strong>\r\n\r\nSystem.out.println( \"Mittagsruhe\" );\r\n\r\nbreak;\r\n\r\ndefault :\r\n\r\nSystem.out.println( \"Arbeiten\" );\r\n\r\nbreak;\r\n\r\n}<\/pre>\n<p><a href=\"#_ftnref1\" name=\"_ftn1\">[1]<\/a> \u00a0\u00a0\u00a0\u00a0 http:\/\/en.cppreference.com\/w\/cpp\/language\/attributes<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bisher haben wir in die letzte Zeile eine break-Anweisung gesetzt. Ohne ein break w\u00fcrden nach einer \u00dcbereinstimmung alle nachfolgenden Anweisungen ausgef\u00fchrt. Sie laufen somit in einen neuen Abschnitt herein, bis ein break oder das Ende von switch erreicht ist. Da dies vergleichbar mit einem Spielzeug ist, bei dem Kugeln von oben nach unten durchfallen, nennt [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[11],"tags":[],"class_list":["post-4057","post","type-post","status-publish","format-standard","hentry","category-insel"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/4057","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=4057"}],"version-history":[{"count":2,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/4057\/revisions"}],"predecessor-version":[{"id":4059,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/4057\/revisions\/4059"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=4057"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=4057"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=4057"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}