{"id":1643,"date":"2012-12-30T08:25:37","date_gmt":"2012-12-30T06:25:37","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=1643"},"modified":"2012-12-30T08:26:01","modified_gmt":"2012-12-30T06:26:01","slug":"konstruktor-referenz-in-java-8","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2012\/12\/konstruktor-referenz-in-java-8\/","title":{"rendered":"Konstruktor-Referenz in Java 8"},"content":{"rendered":"<p>Um ein Objekt aufzubauen, nutzen wir den new-Operator. Wenn wir new nutzen, dann wird ein Konstruktor aufgerufen, und optional lassen sich Argumente an den Konstruktor \u00fcbergeben. Die Java-API deklariert aber auch Typen, von denen sich keine Exemplare mit new aufbauen lassen. Stattdessen gibt es statische (oder nicht-statische) Erzeuger, deren Aufgabe es ist, Objekte aufzubauen.   <\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"204\">\n<p><strong>Konstruktor \u2026<\/strong><\/p>\n<\/td>\n<td valign=\"top\" width=\"97\">\n<p><strong>\u2026 erzeugt<\/strong><\/p>\n<\/td>\n<td valign=\"top\" width=\"199\">\n<p><strong>Erzeuger \u2026<\/strong><\/p>\n<\/td>\n<td valign=\"top\" width=\"97\">\n<p><strong>\u2026 baut<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"204\">\n<p>new Integer( &quot;1&quot; )<\/p>\n<\/td>\n<td valign=\"top\" width=\"97\">\n<p>Integer<\/p>\n<\/td>\n<td valign=\"top\" width=\"199\">\n<p>Integer.valueOf( &quot;1&quot; )<\/p>\n<\/td>\n<td valign=\"top\" width=\"97\">\n<p>Integer<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"204\">\n<p>new File( &quot;dir&quot; )<\/p>\n<\/td>\n<td valign=\"top\" width=\"97\">\n<p>File<\/p>\n<\/td>\n<td valign=\"top\" width=\"199\">\n<p>Paths.get( &quot;dir&quot; )<\/p>\n<\/td>\n<td valign=\"top\" width=\"97\">\n<p>Path<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"204\">\n<p>new BigInteger( val )<\/p>\n<\/td>\n<td valign=\"top\" width=\"97\">\n<p>BigInteger<\/p>\n<\/td>\n<td valign=\"top\" width=\"199\">\n<p>BigInteger.valueOf( val )<\/p>\n<\/td>\n<td valign=\"top\" width=\"97\">\n<p>BigInteger<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Beispiele f\u00fcr Konstruktoren und Erzeuger-Methoden<\/p>\n<p>Beide, Konstruktoren und Erzeugen, lassen sich als spezielle Funktionen sehen, den von einem Typ in einem anderen Typ konvertieren. Damit eignen sie sich perfekt f\u00fcr Transformationen und in einem Beispiel haben wir das schon eingesetzt:<\/p>\n<pre class=\"csharpcode\">Arrays.stream( words )\n      . \u2026\n      .map( Integer::parseInt )\n      . \u2026<\/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>Integer.parseInt(string) ist eine Methode, die sich einfach mit einer Methoden-Referenz fassen l\u00e4sst, und zwar als Integer::parseInt. Aber was ist mit Konstruktoren? Auch sie transformieren! Statt Integer.parseInt(string) h\u00e4tte ja auch new Integer(string) eingesetzt werden k\u00f6nnen.<\/p>\n<p>Wo Methoden-Referenzen statische und Objekt-Methoden angeben k\u00f6nnen, so bieten Konstruktor-Referenzen die M\u00f6glichkeit, Konstruktoren anzugeben, sodass diese als Erzeuger an anderer Stelle \u00fcbergeben werden k\u00f6nnen. Damit lassen sich elegant Erzeuger angeben, auch wenn diese nicht \u00fcber Erzeuger-Methoden verf\u00fcgen. Wie auch bei Methoden-Referenzen spielt eine funktionale Schnittstelle eine entschiedene Rolle, doch dieses Mal ist es die Methode der funktionalen Schnittstelle, die aufgerufen zum Konstruktor-Aufruf f\u00fchrt. Wo syntaktisch bei Methoden-Referenzen rechts vom Doppelpunkt ein Methodenname steht, steht bei Konstruktor-Referenzen new.<a href=\"file:\/\/\/C:\/Users\/Christian\/Dropbox\/Insel\/todo\/#_ftn1_3086\" name=\"_ftnref1_3086\">[1]<\/a><\/p>\n<p><b>Beispiel:<\/b> Die funktionale Schnittstelle sei:<\/p>\n<p>interface DateFactory { Date <b>create()<\/b>; }<\/p>\n<p>Die Konstruktor-Referenz bindet den Konstruktor an die Methode create() der funktionalen Schnittstelle.<\/p>\n<p>DateFactory factory = <b>Date::new<\/b>;<\/p>\n<p>System.out.print( factory.<b>create()<\/b> ); \/\/ z.B. Sat Dec 29 09:56:35 CET 2012<\/p>\n<p>Bzw. die letzten beiden Zeilen zusammengefasst:<\/p>\n<p>System.out.println( ((DateFactory)(Date::new)).create() );<\/p>\n<p>Soll nur der Standard-Konstruktor aufgerufen werden, muss die funktionale Schnittstelle nur eine Methode besitzen, die keinen Parameter besitzt und etwas zur\u00fcckliefert. Der R\u00fcckgabetyp der Methode muss nat\u00fcrlich mit dem Klassentyp zusammen. Das gilt f\u00fcr unseren eigenen Typ DateFactory, doch es geht noch etwas generischer, zum Beispiel mit der vorhandenen funktionalen Schnittstelle Supplier, wie wir gleich sehen werden.<\/p>\n<p>In der API finden sich oftmals Parameter vom Typ Class, die als Typ-Angabe dazu verwendet werden, dass die Methode mit newInstance() Exemplare bilden kann. Class l\u00e4sst sich durch eine funktionale Schnittstelle ersetzen und Konstruktor-Referenzen lassen sich anstelle von Class-Objekten \u00fcbergeben. <\/p>\n<p><strong>Standard- und parametrisierte Konstruktoren<\/strong><\/p>\n<p>Beim Standard-Konstruktor hat die Methode nur eine R\u00fcckgabe, bei einem parametrisierten Konstruktor muss die Methode der funktionalen Schnittstelle nat\u00fcrlich \u00fcber eine kompatible Parameterliste verf\u00fcgen.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"16%\">\n<p>Konstruktor<\/p>\n<\/td>\n<td valign=\"top\" width=\"39%\">\n<p>Date()<\/p>\n<\/td>\n<td valign=\"top\" width=\"44%\">\n<p>Date(<b>long<\/b> t)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"16%\">\n<p>Kompatible funktionale Schnittstelle<\/p>\n<\/td>\n<td valign=\"top\" width=\"39%\">\n<p>interface DateFactory {<\/p>\n<p> Date create();<\/p>\n<p>}<\/p>\n<\/td>\n<td valign=\"top\" width=\"44%\">\n<p>interface DateFactory {<\/p>\n<p> Date create(<b>long<\/b> t);<\/p>\n<p>}<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"16%\">\n<p>Konstruktor-Referenz<\/p>\n<\/td>\n<td valign=\"top\" width=\"39%\">\n<p>DateFactory factory = Date::new;<\/p>\n<\/td>\n<td valign=\"top\" width=\"44%\">\n<p>DateFactory factory = Date::new;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"16%\">\n<p>Aufruf<\/p>\n<\/td>\n<td valign=\"top\" width=\"39%\">\n<p>factory.create();<\/p>\n<\/td>\n<td valign=\"top\" width=\"44%\">\n<p>Factory.create(1);<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Standard- und parametrisierter Konstruktor mit korrespondierenden funktionalen Schnittstellen<\/p>\n<p><b>Hinweis<\/b>: Kommt die Typ-Inferenz des Compilers an ihre Grenzen, sind zus\u00e4tzliche Typinformationen gefordert. In dem Fall werden hinter dem Doppelpunkt in eckigen Klammen weitere Angaben gemacht, etwa Klasse::&lt;Typ1, Typ2&gt;new.<\/p>\n<p><strong>N\u00fctzliche vordefinierte Schnittstellen f\u00fcr Konstruktor-Referenzen<\/strong><\/p>\n<p>Die funktionale Schnittstelle passend f\u00fcr einen Standard-Konstruktor muss eine R\u00fcckgabe besitzen und keinen Parameter annehmen; die funktionale Schnittstelle f\u00fcr parametrisierten Konstruktor muss eine entsprechende Parameterliste haben. Es kommt nun h\u00e4ufig vor, dass der Konstruktor ein Standard-Konstruktor ist oder genau einen Parameter annimmt. Hier kommt es entgegen, dass f\u00fcr diesen beiden F\u00e4lle die Java API zwei praktische (generische deklarierte) funktionale Schnittstellen mitbringt:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"20%\">\n<p>Funktionale <strong>Schnittstelle<\/strong><\/p>\n<\/td>\n<td valign=\"top\" width=\"26%\">\n<p><strong>Funktions-Deskriptor<\/strong><\/p>\n<\/td>\n<td valign=\"top\" width=\"13%\">\n<p><strong>Abbildung<\/strong><\/p>\n<\/td>\n<td valign=\"top\" width=\"39%\">\n<p><strong>Passt auf<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"20%\">\n<p>Supplier&lt;T&gt;<b><\/b><\/p>\n<\/td>\n<td valign=\"top\" width=\"26%\">\n<p>T get()<\/p>\n<\/td>\n<td valign=\"top\" width=\"13%\">\n<p>() -&gt; T<\/p>\n<\/td>\n<td valign=\"top\" width=\"39%\">\n<p>Standard-Konstruktor<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"20%\">\n<p>Function&lt;T, R&gt;<\/p>\n<\/td>\n<td valign=\"top\" width=\"26%\">\n<p>R apply(T t)<\/p>\n<\/td>\n<td valign=\"top\" width=\"13%\">\n<p>(T) -&gt; R<\/p>\n<\/td>\n<td valign=\"top\" width=\"39%\">\n<p>einfachen parametrisierter Konstruktor<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b>Beispiel<\/b>: Die funktionale Schnittstelle Supplier&lt;T&gt; hat eine T get()-Methode, die wir mit dem Standard-Konstruktor von Date verbinden k\u00f6nnen:<\/p>\n<p>Supplier&lt;Date&gt; factory = Date::new;<\/p>\n<p>System.out.print( factory.get() ); <\/p>\n<p>Wir nutzen Supplier mit dem Typparameter Date, was den parametrisierten Typ Supplier&lt;Date&gt; ergibt, und get() liefert folglich den Typ Date. Der Aufruf factory.get() f\u00fchrt zum Aufruf des Konstruktors.<\/p>\n<p><strong>Ausblick *<\/strong><\/p>\n<p>Interessant werden die Konstruktor-Referenzen wieder mit den M\u00f6glichkeiten von Java 8. Nehmen wir eine Liste von Zeitstempel an. Der Konstruktor Date(long) nimmt einen solchen Zeitstempel an und mit einem Date-Objekt k\u00f6nnen wir Vergleiche vornehmen, etwa, ob ein Datum hinter einem anderen Datum liegt. Folgendes Beispiel listet alle Datumswerte auf, die nach dem 1.1.2012 liegen:<\/p>\n<pre class=\"csharpcode\">Long[] timestamps = { 2432558632L, 1455872986345L };\nDate thisYear = <span class=\"kwrd\">new<\/span> GregorianCalendar( 2012, Calendar.JANUARY, 1 ).getTime();\nArrays.stream( timestamps )\n      .map( Date::<span class=\"kwrd\">new<\/span> )\n      .filter( thisYear::before )\n      .forEach( System.<span class=\"kwrd\">out<\/span>::println );  \/\/ Fri Feb 19 10:09:46 CET 2016<\/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<hr size=\"1\" width=\"33%\" \/>\n<p><a href=\"file:\/\/\/C:\/Users\/Christian\/Dropbox\/Insel\/todo\/#_ftnref1_3086\" name=\"_ftn1_3086\">[1]<\/a> Da new ein Schl\u00fcsselwort ist, kann keine Methode so hei\u00dfen; der Identifizierer ist also sicher.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Um ein Objekt aufzubauen, nutzen wir den new-Operator. Wenn wir new nutzen, dann wird ein Konstruktor aufgerufen, und optional lassen sich Argumente an den Konstruktor \u00fcbergeben. Die Java-API deklariert aber auch Typen, von denen sich keine Exemplare mit new aufbauen lassen. Stattdessen gibt es statische (oder nicht-statische) Erzeuger, deren Aufgabe es ist, Objekte aufzubauen. Konstruktor [&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-1643","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\/1643","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=1643"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1643\/revisions"}],"predecessor-version":[{"id":1644,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1643\/revisions\/1644"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=1643"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=1643"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=1643"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}