{"id":1144,"date":"2011-10-24T15:54:13","date_gmt":"2011-10-24T13:54:13","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/2011\/10\/ein-paar-faqs-teil-2\/"},"modified":"2011-10-24T15:54:13","modified_gmt":"2011-10-24T13:54:13","slug":"ein-paar-faqs-teil-2","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2011\/10\/ein-paar-faqs-teil-2\/","title":{"rendered":"Ein paar (F)AQs, Teil 2"},"content":{"rendered":"<p><b>Wie kann man in Java einzelne Strings de\/komprimieren. So wie man es in einem Zip-File machen kann nur eben ohne Zip.<\/b><\/p>\n<p>Nehme ein String und trage es in einen ByteArray[Output|Input]Stream ein. Dann nehme den GZIPOutputStream\/..InputStream und komprimiere den String in einen ByteArrayXXXStream. Diesen kannst du dann wieder zu einem Bytefeld konvertieren.<\/p>\n<p><b>Kennt jemand eine einfache M\u00f6glichkeit in Java Dateien zu k\u00fcrzen?<\/b><\/p>\n<p>Du kannst eine Datei k\u00fcrzen, indem du von RandomAccessFile die setLength() Methode nutzt. Leider kann man vorne keine Bl\u00f6cke ausschneiden (und das m\u00f6chte man ja eigentlich).<\/p>\n<p><b>Ich m\u00f6chte gerne mit JDOM ein XML-Dokument ohne Attribute ausgeben. Gibt es eine M\u00f6glichkeit, das mit dem Outputter einfach zu realisieren?<\/b><\/p>\n<p>Baue eine Unterklasse von XMLOutputter. Dann kann man sch\u00f6n das Template-Pattern in Anwendung sehen, in dem man die Methode printAttributes() leer l\u00e4sst:<\/p>\n<pre>protected void printAttributes( Writer out, List attributes,\n                                Element parent, NamespaceStack namespaces)\n  throws IOException { }<\/pre>\n<p>Anstatt dann den XMLOutputter einfach die eigene Klasse nehmen.<\/p>\n<p><b>Der SAX Parser parst doch sequentiell immer die folgende Reihenfolge 1. startDocument(), 2. startElement(), 3. characters(), 4. endElement(), 5. endDocument(), oder? <\/b><\/p>\n<p>Durch Character-Chunking kann characters() auch \u00f6fters hintereinander aufgerufen werden. Siehe dazu <a href=\"http:\/\/www.tutego.de\/blog\/javainsel\/2007\/01\/character-&bdquo;chunking&ldquo;-bei-sax\/\">http:\/\/www.tutego.de\/blog\/javainsel\/2007\/01\/character-%E2%80%9Echunking%E2%80%9C-bei-sax\/<\/a>. So etwas wie processingInstruction() kann nat\u00fcrlich auch noch kommen.<\/p>\n<p><b>Ich w\u00fcrde gerne aus einer MySQL-Datenbank jeweils eine Zeile auslesen, manche Spalten davon bearbeiten und letztendlich alles wieder in eine andere Datenbank schreiben. Im Moment sieht&#8217;s ungef\u00e4hr so aus: a) Verbindung zur Datenbank, b) ResultSet holen, c) Zeile verarbeiten und was machen. Jetzt hab ich aber beim Einlesen schon ein Problem. Ich bekomme&#160; bei dem ResultSet (mit &quot;SELECT * FROM DB&quot;) einen Speicher\u00fcberlauf. Die Datenbank besteht aus mehreren 100.000 Zeilen und ich wei\u00df leider nicht, wie ich das sonst l\u00f6sen sollte. Kann man zum Beispiel das ResultSet begrenzen? Also beispielsweise immer wieder 1000 Zeilen lesen oder so? Oder gibt&#8217;s noch eine elegantere L\u00f6sung?<\/b><\/p>\n<p>MySQL kennt leider kein echtes Cursor-Konzept (fr\u00fcherer jedenfalls), sodass der JDBC-Treiber alle Daten auf die Client-Seite \u00fcbertr\u00e4gt. Mit dieser Technik muss die Datenbank nicht gelockt werden und muss keine Transaktionen unterst\u00fctzten. Das l\u00f6st auf einfache Weise ein Problem wie: Der Abholer braucht 10 Stunden f\u00fcr das Lesen, die Tabelle wird aber beschrieben. Kopiert man alles, muss die Datenbank nur f\u00fcr die \u00dcbertragung gelockt werden. Sch\u00f6ne Optimierung-Parameter wie fetch-size oder so sind da v\u00f6llig wertlos. Hier helfen<\/p>\n<pre>Statement stmt = con.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE );\n\n\/\/ SENSITIVE ode INSENSITIVE gut \u00fcberlegen\n\nResultSet uprs = stmt.executeQuery( &quot;SELECT Bla FROM Blub&quot; );\n\n\/\/ Auf die passende Zeile steuern, dann etwa\n\nuprs.updateFloat( &quot;Groesse&quot;, 183f );\nuprs.updateRow();<\/pre>\n<p><b>Warum bekomme ich bei Hibernate mit session.load(clazz, x) bei Sammlungen ein PersistentSet und kein normales Set?<\/b><\/p>\n<p>Der Grund ist einfach: Hibernate verwaltet eine eigenes Set, um Lazy-Loading zu erm\u00f6glichen. Ist Lazy-Loading bei 1:n:-Assoziationen eingestellt (Standard), dann wird die Sammlung erst dann geladen, wenn es einen Zugriff auf die Sammlung gibt (Anfragen, add(), &#8230;). Der Punkt ist nun: Wie sollte ein Persistence-Provider mitbekommen, dass jmd. nun Daten aus der Sammlung lesen will? Daher f\u00e4ngt das PersistentSet (http:\/\/www.hibernate.org\/hib_docs\/v3\/api\/org\/hibernate\/collection\/PersistentSet.html) von Hibernate als Proxy die Anfragen ab (PersistentSet ist ein waschechtes java.util.Set) und kann so vor dem tats\u00e4chlichen Zugriff auf die Sammlung die Daten schnell laden.<\/p>\n<p>\u00dcbrigens hat man in der JPA auch nur die Basis-Collection-Schnittstellen wie Set, List, &#8230; aber keine konkreten Klassen wie HashSet, TreeSet,&#8230; Die PersistentSet-Doku schreibt aber: &quot;The underlying collection is a HashSet.&quot;<\/p>\n<p><b>Mit Hilfe des Parameters -exclude kann man bei Javadoc komplette Pakete von der Dokumentation ausschlie\u00dfen. Nun m\u00f6chte ich allerdings nur einzelne Klassen innerhalb eines Pakets ausschlie\u00dfen. Ist das irgendwie m\u00f6glich?<\/b><\/p>\n<p>Wenn du ant (http:\/\/ant.apache.org\/manual\/CoreTasks\/javadoc.html) benutzt, schau dir doch mal das FileSet (http:\/\/ant.apache.org\/manual\/CoreTypes\/fileset.html) an.<\/p>\n<pre>&lt;fileset dir=&quot;${server.src}&quot; casesensitive=&quot;yes&quot;&gt;\n  &lt;include name=&quot;**\/*.java&quot;\/&gt;\n  &lt;exclude name=&quot;**\/*Test*&quot;\/&gt;\n&lt;\/fileset&gt;<\/pre>\n<p>Damit sollte das gehen, etwa so:<\/p>\n<pre>&lt;javadoc\n packagenames=&quot;...&quot;\n destdir=&quot;...&quot;\n ...\n  &lt;fileset dir=&quot;...&quot;&gt;\n    &lt;include name=&quot;**\/*.java&quot; \/&gt;\n    &lt;exclude...&gt;\n  &lt;\/fileset&gt;\n&lt;\/javadoc&gt;<\/pre>\n<p><b>Java 5 hei\u00df ja lange Tiger. Gibt es auch f\u00fcr die anderen Java-Versionen solche Bezeichner?<\/b><\/p>\n<p>F\u00fcr fast jede Java-Version gibt es Code-Namen, etwa f\u00fcr 1.1.4 Sparkler (Diamant), 1.1.5 Pumpkin (K\u00fcrbis, auch Trottel), 1.1.6 Abigail (Zofe), 1.1.7 Brutus und 1.1.8 Chelsea . Java 1.2 hie\u00df Playground, und f\u00fcr die folgenden Versionen nutzte Sun Tiernamen (<a href=\"http:\/\/java.sun.com\/j2se\/codenames.html\">http:\/\/java.sun.com\/j2se\/codenames.html<\/a>): Cricket 1.2.2 (Grille), 1.3 Kestrel (Turmfalke), Ladybird 1.3.1 (Marienk\u00e4fer), 1.4.0 Merlin (Falke), 1.4.1 Hopper (Heuschrecke), 1.4.2 Mantis (Gottesanbeterin), 5 Tiger, 6 Mustang und 7 Dolphin (Delfin). Vielleicht finden wir demn\u00e4chst auch Java-Flugfrosch, Java-Nashorn und Javaneraffe (lat. Macaca fascicularis, eine krabbenfressende Affenart) \u2013 diese Tiere gibt\u2019s wirklich und einen Java-Tiger auch. (Der ist \u00fcbrigens vom Aussterben bedroht.)<\/p>\n<p><b>Ich ben\u00f6tige eine Routine zur Bestimmung aller Subklassen einer Klasse bzw. aller Klassen die ein Interface implementieren zur Laufzeit. Leider scheint mit Java Reflection (Class etc.) hier keine L\u00f6sung anzubieten (in SmallTalk-80 w\u00e4re das kein Problem gewesen \ud83d\ude09<\/b><\/p>\n<p>Das Problem l\u00e4sst sich allgemein auch in Java nicht l\u00f6sen. Eine (suboptimale) L\u00f6sung ist, sich eine Liste aller Klassen zu besorgen (auch das funktioniert nur im Spezialfall) und dann jede Klasse zu fragen, ob sie Unterklasse ist. Dabei muss jedes <b>Class<\/b>-Objekt auch geladen werden &#8212; die Performance ist nat\u00fcrlich richtig schlecht. Dieser Ansatz wird etwa hier realisiert: <a href=\"http:\/\/freerails.cvs.sourceforge.net\/freerails\/jfreerails\/src\/jfreerails\/util\/ClassLocater.java?revision=1.2&amp;view=markup\">http:\/\/freerails.cvs.sourceforge.net\/freerails\/jfreerails\/src\/jfreerails\/util\/ClassLocater.java?revision=1.2&amp;view=markup<\/a>. Die Idee ist, zu schauen, welcher Klassenlader die Klassen l\u00e4dt, und dann \u00fcber diesen an das Verzeichnis bzw. Jar-Archiv heranzukommen und das dann vollst\u00e4ndig zu durchsuchen.<\/p>\n<p>Eine andere L\u00f6sung, die oft vorgeschlagen wird, ist die, dass man jede Klasse in einem <b>static {}<\/b> Block an einer Zentrale anmeldet, sodass man sp\u00e4ter nur noch diese Zentrale als &quot;Liste aller Klassen&quot; durchsuchen muss. Wenn die Klassen \u00fcber ein Framework wie JPA oder Spring verwaltet werden ist das auch wieder einfacher. Bei JPA\/Hibernate kann zum Beispiel eine Anfrage auf Entity-Beans wie &quot;select o from java.lang.Object o&quot; helfen.<\/p>\n<p><b>Aus einem Buch unter dem Kapitel &quot;Sprachdesign und Compiler&quot; habe ich folgenden Satz gefunden und als Zitat in meiner Diplomarbeit verwendet: &quot;Variablen k\u00f6nnen bei der Initialisierung mit dem Schl\u00fcsselwort &quot;final&quot; gekennzeichnet werden, was bedeutet, dass sich der Wert dieser Variablen nicht mehr ver\u00e4ndern kann.&quot; Der Kommentar meines Prof. war: &quot;So einfach ist das nicht&quot;! Ist es nicht so, dass eine mit final deklarierte Variable nicht mehr ver\u00e4ndert werden kann?<\/b><\/p>\n<p>Worauf dein Prof anspielt ist, dass man final Variablen nicht zwingend bei der Deklaration einen Wert zuweisen muss. Dies kann man sp\u00e4ter machen, dann aber nur einmal. Nun muss der Compiler durch Flussanalyse verfolgen, ob schon jemand schreibend zugegriffen hat. Und da hat sich der Javac damals in die Nesseln mit gesetzt und das mach den Jikes heute immer noch so. Das Problem war ein switch(). Wenn man den durchfallen l\u00e4sst, kann man in beiden Teilen die Variable belegen. Ein Beispiel daf\u00fcr findest du in der FAQ.<\/p>\n<p>Das mit final Variablen und Zuweisungen f\u00fchrt manches mal zu sehr abgefahrenen L\u00f6sungen, etwa in der System Klasse. Dort sind die Konsolenstr\u00f6me (in,out,err) final und \u00fcber einen Hack werden sie nativ bei einer Systeminitialisierung wieder ge\u00e4ndert. Das musste man machen, da final Variablen prinzipiell inline gesetzt werden k\u00f6nnte. Das musste man verhindern.<\/p>\n<p><b>Kennt jemand eine bessere Methode, in Java Potenzen von (kleinen) ganzen Zahlen zu berechnen, als java.lang.Math.pow() zu benutzen und dann von double auf int zu casten?<\/b><\/p>\n<p>Wenn man nur 2^n braucht, dann tut es doch ein Shift. Man muss dann aber aufpassen, dass die Bits nicht rausrutschen.<\/p>\n<pre>int twoPow( long n )\n{\n  return 1 &lt;&lt; n;\n}<\/pre>\n<p><b>Kann mir jemand eine gute Erkl\u00e4rung geben warum ich eine abstrakte Methode nicht static deklarieren kann?<\/b><\/p>\n<p>Eine abstrakte Methode ist ja eine Methode, die nicht implementiert ist, also etwa so etwas<\/p>\n<pre>abstract class A\n{\n abstract void m();\n}<\/pre>\n<p>Sp\u00e4ter wird dann die abstrakte Klasse erweitert und die Implementierung nachgeliefert. Wenn die Methode m() aber in A keine Implementierung hat, dann kann Sie auch keine Klassenmethode sein, da Klassenmethoden (statische Methoden) ja nicht an ein Objekt gebunden ist, sondern an die Klasse. Wenn sie statisch w\u00e4re, dann k\u00f6nnte man ja etwa<\/p>\n<pre>A.m();<\/pre>\n<p>schreiben. Doch was soll hier passieren? Also geht das nicht. Eine \u00e4hnliche Begr\u00fcndung gilt f\u00fcr private. Wenn die Methode nicht f\u00fcr andere sichtbar ist, dann kann sich aber auch nicht \u00fcberschrieben werden, da sie keiner sieht. Auch mit final ist es das gleicht. final hei\u00dft ja, keiner darf \u00fcberschreiben. Aber abstract muss man \u00fcberschreiben.<\/p>\n<h4>Andere FAQs<\/h4>\n<ul>\n<li><a href=\"http:\/\/www.jguru.com\/faq\/index.jsp\">jGuru FAQ<\/a><\/li>\n<li><a href=\"http:\/\/www.cafeaulait.org\/javafaq.html\">comp.lang.java FAQ<\/a> (Elliotte Rusty Harold. Letzte \u00c4nderung 1997) <\/li>\n<li><a href=\"http:\/\/www.faqs.org\/faqs\/de\/comp-lang-java\/faq\/\">FAQ der Newsgroup de.comp.lang.java<\/a> (Letzte \u00c4nderung 2004) <\/li>\n<li><a href=\"http:\/\/java.sun.com\/products\/jdbc\/faq.html\">Frequently Asked Questions About JDBC<\/a> (Sun) <\/li>\n<li><a href=\"http:\/\/www.davidreilly.com\/java\/java_network_programming\/\">Java Network Programming FAQ<\/a> (David Reilly. Letzte \u00c4nderung 2000) <\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Wie kann man in Java einzelne Strings de\/komprimieren. So wie man es in einem Zip-File machen kann nur eben ohne Zip. Nehme ein String und trage es in einen ByteArray[Output|Input]Stream ein. Dann nehme den GZIPOutputStream\/..InputStream und komprimiere den String in einen ByteArrayXXXStream. Diesen kannst du dann wieder zu einem Bytefeld konvertieren. Kennt jemand eine einfache [&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":[1],"tags":[],"class_list":["post-1144","post","type-post","status-publish","format-standard","hentry","category-allgemein"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1144","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=1144"}],"version-history":[{"count":0,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1144\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=1144"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=1144"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=1144"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}