{"id":1640,"date":"2012-12-29T12:32:32","date_gmt":"2012-12-29T10:32:32","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=1640"},"modified":"2012-12-29T12:34:15","modified_gmt":"2012-12-29T10:34:15","slug":"methoden-referenzen-in-java-8","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2012\/12\/methoden-referenzen-in-java-8\/","title":{"rendered":"Methoden-Referenzen in Java 8"},"content":{"rendered":"<p>Je gr\u00f6\u00dfer Software-Systeme werden, desto wichtiger werden Aspekte wie Klarheit, Wiederverwendbarkeit und Dokumentation. Wir haben in f\u00fcr unseren String-Comparator eine Implementierung geschrieben, anfangs \u00fcber eine innere Klasse, sp\u00e4ter \u00fcber einen Lambda-Ausdruck, in jedem Fall haben wir Code geschrieben. Doch was w\u00e4re, wenn eine Utility-Klasse schon eine Implementierung h\u00e4tte? Kann k\u00f6nnte der Lambda-Ausdruck nat\u00fcrlich an die vorhandene Implementierung delegieren.<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">class<\/span> StringUtils {\n  <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">int<\/span> compareTrimmed( String s1, String s2 ) {\n    <span class=\"kwrd\">return<\/span> s1.trim().compareTo( s2.trim() );\n  }     \n}\n\n<span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> CompareIgnoreCase {\n  <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">void<\/span> main( String[] args ) throws Exception {\n    String[] words = { <span class=\"str\">&quot;A&quot;<\/span>, <span class=\"str\">&quot;B&quot;<\/span>, <span class=\"str\">&quot;a&quot;<\/span> };\n      Arrays.sort( words, (String s1, String s2) -&gt; StringUtils.compareTrimmed(s1, s2) );\n      System.<span class=\"kwrd\">out<\/span>.println( Arrays.toString( words ) );\n  }\n}<\/pre>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n<p>Auff\u00e4llig bei dem Beispiel ist, dass die referenzierte Methode compareTrimmed(String,String) von den Parametertypen und vom R\u00fcckgabetyp genau auf die compare(\u2026)-Methode eines Comparator passt. F\u00fcr genau solche F\u00e4lle gibt es eine weitere syntaktische Verk\u00fcrzung, dass Entwickler im Code kein Lambda-Ausdruck mehr schreiben m\u00fcssen.<\/p>\n<p><b>Definition<\/b>: Methoden-Referenzen identifizieren Methoden ohne sie aufzurufen. Syntaktisch trennen zwei Doppelpunkte den Klassenamen bzw. die Referenz auf der linken Seite von einem Methodennamen auf der rechten.<\/p>\n<p>Die Zeile<\/p>\n<p>Arrays.sort( words, <b>(String s1, String s2) -&gt; StringUtils.compareTrimmed(s1, s2)<\/b> );<\/p>\n<p>l\u00e4sst sich mit Methoden-Referenzen abk\u00fcrzen zu:<\/p>\n<p>Arrays.sort( words, <b>StringUtils::compareTrimmed<\/b> );<\/p>\n<p>Die Sortiermethode erwartet vom Comparator eine Methode, die zwei Strings annimmt und eine Ganzzahl zur\u00fcckgibt. Der Name der Klasse und der Name der Methode ist unerheblich, weshalb Methoden-Referenzen eingesetzt werden k\u00f6nnen.<\/p>\n<p>Eine Methoden-Referenz ist wie ein Lambda-Ausdruck ein Exemplar einer funktionalen Schnittstelle, jedoch f\u00fcr eine existierende Methode einer bekannten Klasse. Wie \u00fcblich bestimmt der Kontext von welchem Typ genau der Ausdruck ist.<\/p>\n<p><b>Beispiel<\/b>: Gleicher Code f\u00fcr eine Methoden-Referenz kann zu komplett unterschiedlichen Typen f\u00fchren \u2013 der Kontext macht den Unterschied:<\/p>\n<p>Comparator&lt;String&gt; c = <b>StringUtils::compareTrimmed<\/b>;<\/p>\n<p>BiFunction&lt;String, String, Integer&gt; c = <b>StringUtils::compareTrimmed<\/b>;<\/p>\n<p>Im Beispiel war die Methode compareTrimmed(\u2026) statisch, und links vom Doppeltpunkt steht der Name einer Klasse stehen. Doch kann links auch eine Referenz stehen, was dann eine Objektmethode referenziert.<\/p>\n<p><b>Beispiel<\/b>: Die statische Variable String.CASE_INSENSITIVE_ORDER enth\u00e4lt eine Referenz auf ein Comparator-Objekt:<\/p>\n<p>Comparator&lt;String&gt; c = String.CASE_INSENSITIVE_ORDER;<\/p>\n<p>Wir k\u00f6nnen auch mit Methoden-Referenzen arbeiten:<\/p>\n<p>Comparator&lt;String&gt; c = String.CASE_INSENSITIVE_ORDER::compare;<\/p>\n<p>Statt dass der Name einer Referenzvariablen gew\u00e4hlt wird, kann auch this das Objekt beschreiben.<\/p>\n<p><strong>Was soll das alles?<\/strong><\/p>\n<p>F\u00fcr Einsteiger in die Sprache Java wird dieses Sprache-Feature wie der gr\u00f6\u00dfte Zauber auf Erden vorkommen und auch Java-Profis bekommen hier zittrige Finger, entweder vor Angst oder Freunde\u2026 In der Vergangenheit musste in Java sehr viel explizit geschrieben werden, aber mit diesen neuen Methoden-Referenzen sieht und macht der Compiler vieles von selbst.<\/p>\n<p>N\u00fctzlich wird diese Eigenschaft mit den funktionalen Bibliotheken aus Java 8, die ein eigenes Kapitel einnehmen. Nur kurz:<\/p>\n<pre class=\"csharpcode\">String[] words = { <span class=\"str\">&quot;3&quot;<\/span>, <span class=\"str\">&quot;2&quot;<\/span>, <span class=\"str\">&quot; 1&quot;<\/span>, <span class=\"str\">&quot;&quot;<\/span> };\nArrays.stream( words )\n      .map( String::trim )\n      .filter( (s) -&gt; s != <span class=\"kwrd\">null<\/span> &amp;&amp; ! s.isEmpty() )\n      .map( Integer::parseInt )\n      .sorted()\n      .forEach( System.<span class=\"kwrd\">out<\/span>::println );   \/\/ 1 2 3<\/pre>\n<style type=\"text\/css\">\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/style>\n","protected":false},"excerpt":{"rendered":"<p>Je gr\u00f6\u00dfer Software-Systeme werden, desto wichtiger werden Aspekte wie Klarheit, Wiederverwendbarkeit und Dokumentation. Wir haben in f\u00fcr unseren String-Comparator eine Implementierung geschrieben, anfangs \u00fcber eine innere Klasse, sp\u00e4ter \u00fcber einen Lambda-Ausdruck, in jedem Fall haben wir Code geschrieben. Doch was w\u00e4re, wenn eine Utility-Klasse schon eine Implementierung h\u00e4tte? Kann k\u00f6nnte der Lambda-Ausdruck nat\u00fcrlich an die [&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,66],"tags":[],"class_list":["post-1640","post","type-post","status-publish","format-standard","hentry","category-insel","category-java-8"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1640","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=1640"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1640\/revisions"}],"predecessor-version":[{"id":1641,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1640\/revisions\/1641"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=1640"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=1640"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=1640"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}