# Java Rätsel



## Thomas Darimont (11. Juni 2008)

Hallo,

bei unseren Kollegen vom java-forum.org gibts nen interessanten Thread wo die User immer wieder neue Java Rätsel posten und lösen.

Hier mal eine Beispiel-Aufgabe:
http://www.java-forum.org/de/viewtopic.php?t=24333&postdays=0&postorder=asc&start=780


> ...
> *Aufgabe:* Die Methode "get" ist so umzuschreiben, dass: In den geschweiften Klammern gibt es nur noch das return-Statement, mit einem mehr oder weniger komplizierten Ausdruck hinter dem "return". "get" setzt weiterhin "a" auf null und gibt den alten Wert von "a" zurück (anders gesagt: es gibt noch ein Semikolon ';' in "get" und "get" macht dasselbe wie vor der Änderung).
> ...



Als Lösungsvorschlag kam dann:

```
public Object get( Object... schummel ){
return ((schummel = new Object[]{ a }) != null ) ?
(((a = null) == null ) ? schummel[0] : null) : null;
}
```

Mein Vorschlag wäre hier: 

```
public Object get2() {
return (System.getProperties().put("XXX", a) == (a = null)) ? System
					.getProperty("XXX")
					: null;
        }
```

Jemand ein neues Rätsel parat?

Gruß Tom


----------



## zeja (14. Juni 2008)

Okay, was ist die Ausgabe von folgendem Codestück wenn man die main ausführt? Bitte nicht einfach ausführen 


```
package de.tutorials;

public class Instantiation {
	
	private interface InnerClass {}

	private static final InnerClass[] inner = { new Inner0() };

	private static final Singleton singleton1 = Singleton.getInstance();

	private static final class Inner0 implements InnerClass {
		public Inner0() {
			System.out.println(singleton1.getName());
		}
	}

	private static final class Singleton {
		private static final Singleton singleton = new Singleton();

		private Singleton() {
			System.out.println("Create SingletonInstance");
		}

		public String getName() {
			return "Name";
		}

		public static final Singleton getInstance() {
			return singleton;
		}
	}
	
	public static void main(String[] args) {
		System.out.println(inner.length);
	}
}
```


Lösungen bitte in [spoiler]...[/spoiler] einschließen. Dann können mehr mitraten


----------



## Thomas Darimont (14. Juni 2008)

Spoiler



Tja bei static Membern kommt es halt auf die Initialisierungsreihenfolge an ;-)


----------



## zerix (16. Juni 2008)

Spoiler



Es wird eine Exception geworfen.



Natürlich kann man noch weiter Antworten für zejas Rätsel posten. 
Ich hätte aber auch mal eins.

Wie lautet die Ausgabe und warum?


```
public class AusgabeParent
{

  public AusgabeParent()
  {
    initialize();
  }
  
  protected void initialize(){
    System.out.println("Initialize");
  }
}
```


```
public class AusgabeChild extends AusgabeParent
{

  private String ausgabeString = "Wird man dieses lesen?";
 
  public AusgabeChild()
  {
    super();
    System.out.println(ausgabeString);
  }
  
  protected void initialize()
  {
    super.initialize();
    ausgabeString = "Oder wird man doch dieses lesen?";
  }
  
  public static void main(String[] args)
  {
    new AusgabeChild();
  }
}
```

Bei mir gilt natürlich das gleiche wie bei zeja. Nicht die main-Methode ausführen und auch mit Spoiler antworten.

MFG

Sascha


----------



## Thomas Darimont (16. Juni 2008)

Hallo,

was wird hier ausgegeben?

```
/**
 * 
 */
package de.tutorials;

import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * @author Tom
 * 
 */
public class IdentiyHashMapExample {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Map<String, Integer> m = new IdentityHashMap<String, Integer>();
        m.put("a", 1);
        m.put("b", 2);
        m.put("c", 3);
        m.put("a", 4);

        System.out
                .println(new HashSet<Map.Entry<String, Integer>>(m.entrySet()));
    }

}
```

Gruß Tom


----------



## Clash (17. Juni 2008)

Zu Sascha's Rätsel


Spoiler



es erfolgt die Ausgabe von "Wird man dies Lesen" da mit dem super() aufruf im Konstruktor lediglich der Konstruktor der der Vaterklasse aufgerufen wird der wiederum seine! initialize() Methode aufruft. Das überschreiben von initialize() in der Kindklasse ist somit keinen Effekt (zumindest in diesem Beispiel  )


----------



## zerix (17. Juni 2008)

Das ist so nicht korrekt. Ein Prinzip der objectorientierten Programmierung ist ja Polimorphie und dieses garantiert ja, dass die überschriebene initialize-Methode aufgerufen wird. Kannst du gerne mit einer weiteren Ausgabe prüfen. ;-)

MFG

Sascha


----------



## Dario Linsky (17. Juni 2008)

Spoiler



Hmm? Ich hätte auch gedacht, dass die Methode von AusgabeChild ausgeführt wird und der Ausgabe-String überschrieben wird. Aber Java sagt mir was anderes, warum weiß ich allerdings nicht... 



Nebenbei: Wäre es nicht sinnvoller, der Übersicht wegen die Rätsel nacheinander hier einzustellen?

Grüße, D.


----------



## zerix (17. Juni 2008)

@Dario
Es war ja nicht ganz Sinn der Sache, das Programm auszuführen und die Ausgabe zu posten. ;-)

MFG

Sascha

EDIT: Wenn bis Morgen keiner die richtige Lösung gepostet hat, werde ich es auflösen.


----------



## Dario Linsky (17. Juni 2008)

Ich weiß, ich dachte nur, es wäre ja sowieso schon gelöst... hab's weg editiert. 

Ich wollte ja eigentlich auch gestern schon meine Gedanken dazu posten - aber als ichs zur Kontrolle mal ausgeführt hab, hat es mich stutzig gemacht, weil was anderes raus kam, als ich erwartet hatte und hätte begründen können. Deswegen hab ichs sein lassen.


----------



## zerix (17. Juni 2008)

Wenn es so leicht wäre, wäre es ja kein Rätsel. ;-)

Ich hatte vor einiger Zeit mal so ein Konstrukt programmiert und war dann ebenso verblüfft, als ich nen Fehler hatte.


----------



## Dario Linsky (17. Juni 2008)

Naja... Fehler? Würde mich aber mal interessieren, woran's liegt.


----------



## zerix (17. Juni 2008)

Naja, ich hatte nen Fehler, weil ich halt ne Variable mit null initialisiert hatte. Also kam da dann eine NullPointerException. Das passiert hier ja nicht.

Morgen wirst du es spätestens Erfahren. Es sei Tom sagt vielleicht heute noch was oder jemand anderes. ;-)

MFG

Sascha


----------



## Dario Linsky (17. Juni 2008)

Gut, wenn ich eh noch Zeit hab, dann rate ich schnell nochmal. 



Spoiler



Java führt die Initialisierung von ausgabeString genau genommen erst im Konstruktor von AusgabeChild aus. Evtl. erst nach dem Aufruf von super()?



Klingt für mich zwar irgendwie weit hergeholt, aber ein anderer Grund fällt mir nicht ein. :suspekt:

Grüße, D.


----------



## hammet (17. Juni 2008)

Hmmm Wo ist da das Rätsel? Die Ausgabe ist "Initialize" mit einem nachfolgendem "wird man dieses lesen?".
Durch das "super();" wird doch nur der Konstruktor der Vaterklasse aufgerufen, in dem die Ausgabe von "Initialize" erfolgt. Und dann eben das Syso aus dem Konstruktor von AusgabeChild.
Oder hab ich da was nicht mitbekommen


----------



## Dario Linsky (17. Juni 2008)

@hammet:


> Ein Prinzip der objectorientierten Programmierung ist ja Polimorphie und dieses garantiert ja, dass die überschriebene initialize-Methode aufgerufen wird.


Danach sollte man eigentlich was anderes erwarten, weil die aufgerufene initialize-Methode des Childs den String überschreibt.

Grüße, D.


----------



## hammet (17. Juni 2008)

Wird sie ja. Nur Initialisiert Java den AusgabeString als null und führt die Wertzuweisung erst nach den Init-Methoden durch. Die Zuweisung in der Child-Initialize-Methode ändert den Wert vom AusgabeString von null in den den gewünschten Text. Aber wie schon gesagt, wird die Wertzuweisung global erst nach den Initalisierungen vorgenommen.


----------



## zerix (17. Juni 2008)

Hammet hat es ganz genau getroffen. Da brauche ich gar nicht mehr aufzulösen. 

Ich hätte im Konstruktor nicht mal super aufrufen müssen, da der Standard-Kontruktor (wenn vorhanden) der Parent-Klasse sowieso aufgerufen werden würde.

MFG

Sascha


----------



## Thomas Darimont (17. Juni 2008)

Hallo,



> Es ist so, dass erst der super-Aufruf ausgeführt wird, bevor die Varialben der Klasse AusgabeChild deklariert werden.


deklariert ist hier IMHO falsch. Initialisiert wäre richtig.

Gruß Tom


----------



## zerix (17. Juni 2008)

Falsch ausgedrückt.  Sorry, aber hab ich ja schon gelöscht.


----------



## Thomas Darimont (17. Juni 2008)

Hallo,

verdeutlichen kann man sich das wie folgt:

```
/**
 * 
 */
package de.tutorials;

/**
 * @author Thomas.Darimont
 *
 */
public class InitializationExample {

    /**
     * @param args
     */
    public static void main(String[] args) {
        new B();
    }
    
    static class A{
        A(){
            System.out.println("Constructor A");
            intialize();
        }
        
        void intialize(){
            System.out.println("Initialize A");
        }
    }
    
    static class B extends A{
        
        String value =init("yyy");
   
       B(){
            System.out.println("Constructor B");
            System.out.println(value);
        }
        
        void intialize(){
            super.intialize();
            value = init("xxx");
        }
    }
    
    static String init(String string){
        System.out.println("Init: " + string);
        return string;
    }
}
```

Ausgabe:

```
Constructor A
Initialize A
Init: xxx
Init: yyy
Constructor B
yyy
```

Die Instanzvariablen einer Instanz werden erst (automatisch) initialisiert, nachdem der Konstruktor der Basisklasse aufgerufen worden ist. Ebenso werden auch Instanz Initialisierer Blocks nach dem Aufruf des Basisklassen Konstruktors ausgeführt, in der Reihenfolge in der Sie im Code auftauchen. Anschließend wird der eigentliche Konstruktor ausgeführt. 


```
/**
 * 
 */
package de.tutorials;

/**
 * @author Thomas.Darimont
 *
 */
public class InitializationExample {

    /**
     * @param args
     */
    public static void main(String[] args) {
        new B();
    }
    
    static class A{
        A(){
            System.out.println("Constructor A");
            intialize();
        }
        
        void intialize(){
            System.out.println("Initialize A");
        }
    }
    
    static class B extends A{
        {
            System.out.println("Instance Initializer B 0");
        }
        
        B(){
            System.out.println("Constructor B");
            System.out.println(value);
        }
        
        String value =init("yyy");
        
        {
            System.out.println("Instance Initializer B 1");
        }

        
        void intialize(){
            super.intialize();
            value = init("xxx");
        }
    }
    
    static String init(String string){
        System.out.println("Init: " + string);
        return string;
    }
}
```

Ausgabe:

```
Constructor A
Initialize A
Init: xxx
Instance Initializer B 0
Init: yyy
Instance Initializer B 1
Constructor B
yyy
```

Weitere Beispiele zur Initialisierung:
http://www.tutorials.de/forum/1040519-post3.html

Gruß Tom


----------



## zeja (22. Juni 2008)

Dann mach ich nochmal eins 


```
public class Finally {

	public static String methodB() {
		try {
			return "methodB";
		} finally {
			System.out.println("finally block");
		}
	}

	public static void main(String[] args) {
		System.out.println(methodB());
	}
}
```

Was ist davon die Ausgabe?


----------



## maesi (24. Juni 2008)

Spoiler



finally block
methodB


----------



## AAF (29. Juni 2008)

bin auch für mäsis antwort ;-)


----------



## Kai008 (29. Juni 2008)

Spoiler



"methodB"?
Weiß zwar nicht was finally genau bewirkt, aber soweit ich weiß kommt bei einer static jedes mal der selbe Returnwert oder so, was auch immer das für einen Sinn haben mag.



€: Ups, auf Spoiler vergessen.
@AAF: Danke, aber editiere bitte das Zitat raus.


----------



## AAF (29. Juni 2008)

Spoiler



@Kai0008

finally wird nach try-catch *immer *ausgeführt, auch dann wenn catch in kraft tritt.


----------



## zeja (4. Juli 2008)

Spoiler



@Kai008
"aber soweit ich weiß kommt bei einer static jedes mal der selbe Returnwert oder so, was auch immer das für einen Sinn haben mag."
Wo hast du dass denn aufgeschnappt? static an einer Methode bedeutet nur dass es nicht abhängig von einer Instanz der Klasse ist sondern direkt mit Klasse.methode aufgerufen werden kann. Kann man für Methoden nutzen die auf keinen Zustand angewiesen sind.


----------



## limago (10. Juli 2008)

Wer weiss Vorrangregeln von Operatoren auswendig?

Was erzeugt der folgende Code?

```
package de.tutorials;

public class PlusPlus {

	public static void main(String[] args) {
		int a,b,c;
		
		a = b = 1;
		c = a+++b;
		
		System.out.println("a=" + a);
		System.out.println("b=" + b);
		System.out.println("c=" + c);

	}

}
```

Preincrement von b, oder Postincrement von a. Das ist für die Werte entscheidend.


----------



## Thomas Darimont (10. Juli 2008)

Hallo,



Spoiler






> Was erzeugt der folgende Code?


Eine Ausgabe auf stdout. scnr ... Fragen bitte ein wenig eindeutiger Formulieren ;-)

a+++b -> (a++) + b
a++ gibt a zurück und erhöht a im nächsten Schritt um 1 
also wird
c = 1 + 1 = 2 

Hab richtig geraten
a=2
b=1
c=2



Was ist die Ausgabe des Beispielcodes unter:
http://www.tutorials.de/forum/1630760-post5.html
und warum?

Hätte wohl noch ein wenig länger warten sollen... aber es juckte mich gerade so in den Fingern... vielleicht sollten wir eine Antwortfrist für Mods einführen. Erst nachdem ein Rätsel 2 Tage nicht korrekt beantowrtet wurde darf ein mod sich offiziell daran versuchen....

Gruß Tom


----------



## limago (10. Juli 2008)

Du hast recht. Dein Rätsel ist knifflig. Werde knobeln....


----------



## limago (10. Juli 2008)

> Was ist die Ausgabe des Beispielcodes unter:
> http://www.tutorials.de/forum/1630760-post5.html
> und warum?





Spoiler



Einträge in einem Set müssen immutable sein, sonst können Duplikate entstehen. Offensichtlich ist das bei der konkreten Map.Entry Klasse nicht der Fall. Die IdentityHashMap scheint immer das selbe interne Objekt zu recyceln. So zeigen alle Referenzen auf das selbe Objekt. Würde man die HashMap in einer Schleife sequenziell befüllen, müsste man das sehen können. Warum die Add-Methode die Duplikate nicht erkennt ist mir jedoch noch ein Rätsel. Ich bleibe dran.

Ich weiss, dass die Erklärung noch etwas wage ist. Bin ich auf dem richtigen Weg?


----------



## zeja (10. Juli 2008)

@limago: Ja bist du.


----------



## limago (10. Juli 2008)

Spoiler



Ich glaube ich habe habe es. Die Add-Methode ermittelt den HashCode des zu speichernden Objektes. Dieser wird als Key für die Referenz benutzt. Der nächste Aufruf von Add ermittelt einen anderen Hashcode aus den Objektdaten, also wird die Referenz mit dem anderen Hashcode in das Set eingetragen. Beide Refenzen zeigen nun aber auf das one and only Objekt. Das ist es oder?


----------



## limago (10. Juli 2008)

@tom: Nicht nur den Code lesen, sondern auch was drunter steht. Dann wird die Frage klarer ;-)


----------



## Kai008 (12. Juli 2008)

zeja hat gesagt.:


> Spoiler
> 
> 
> 
> ...





Spoiler



Ach sooooooo, danke. Jetzt verstehe ich auch warum die Main static ist: Weil keine Instanz eines Überobjekt's intialisiert ist was sie aufrufen könnte kann sie nur aufgerufen werden wenn sie unabhängig eines anderen Objekts ist.
Die Frage kommt aus der Zeit als ich mich mit OOP auseinandergesetzt habe. Damals hat die Main noch alles erledigt (anderst als jetzt wo nur ein "new" drinnensteht), und ich habe der Klasse "Soldat" ein Static verpasst weil es in der Paint dadurch verlangt wurde, und ein Bekannter hat "wenn die variablen static sind, dann sind se für alle soldaten gleich
" als ich ihm nach einen Fehler gefragt habe geschrieben.
Deshalb bin ich davon ausgegangen dass ein return() auch immer den selben Wert zurückliefert.


----------



## limago (12. Juli 2008)

Ich habe eine Abstrakte Klasse, von dieser erben 2 Kindklassen. Beide haben identische codierte Methoden. Könnte diese nicht besser in der in der abstrakten Klasse implementiert werden. kann es Gründe für folgende Lösung geben?


```
package de.tutorials;

public abstract class AbstractParent {
	
	public abstract void doSomeThingWithWorker(Worker worker);

}
```


```
package de.tutorials;

public class ConcreteChild1 extends AbstractParent {

	@Override
	public void doSomeThingWithWorker(Worker worker) {
		
		worker.work(this);
	}

}
```


```
package de.tutorials;

public class ConcreteChild2 extends AbstractParent {

	@Override
	public void doSomeThingWithWorker(Worker worker) {
		
		worker.work(this);
	}

}
```

Sieht doch ziemlich redundant aus. Oder ist es das nicht?


----------



## Kai008 (12. Juli 2008)

Spoiler



Da "this" zur Funktion "work" mitgeliefert wird, kann die Klasse "Worker" auf beide erbenden Klassen individuell "eingehen", falls du das gemeint hast. Denke zwar eher nicht weil das wohl zu einfach ging, aber will mal mein Glück versuchen. =)


----------



## limago (13. Juli 2008)

@kai008

Du hast im Prinzip recht. Aber warum kann ich die Methode nicht in der abstrakten Klasse implementieren? Diese ist selbst ja nicht instanziierbar. Also würde der this-Zeiger der abstrakten Klasse ja sowieso immer auf eine der Childinstanz zeigen.

Schlimmstenfalls passiert dies :


```
package de.tutorials;

public class Main {
	
	public static void main(String[] args) {
		
		AbstractParent referenz = new ConcreteChild1();
		
		referenz.doSomeThingWithWorker(new Worker());
	}

}
```


Könnte ich da nicht einfacher und besser auf die "doSomeThingWithWorker"-Methode verzichten und gleich folgenden Aufruf ausführen?


```
package de.tutorials;

public class Main {
	
	public static void main(String[] args) {
		
		AbstractParent referenz = new ConcreteChild1();
		
		new Worker().work(referenz);
	}

}
```


----------



## Thomas Darimont (23. Juli 2008)

Hallo,

was ist die Ausgabe hiervon und warum:

```
/**
 * 
 */
package de.tutorials;
/**
 * @author Tom
 */
public class Main {
    public static void main(String[] args) {
        System.out.println("null".equals(String.valueOf((Object)null)));
        System.out.println("null".equals(String.valueOf(null)));
    }
}
```

Gruß Tom


----------



## Thomas Darimont (25. Juli 2008)

Hallo,

die Ausgabe:

```
true
Exception in thread "main" java.lang.NullPointerException
    at java.lang.String.<init>(Unknown Source)
    at java.lang.String.valueOf(Unknown Source)
    at de.tutorials.NullStringEqualsNull.main(NullStringEqualsNull.java:17)
```

Erklärung:
Beim ersten Aufruf wird die Überladung mit String(Object value) Signatur der valueOf Methode aufgerufen.

```
public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
    }
```

Beim zweiten Aufruf wird jedoch auf die String (char[] data) Variante gegangen. Da hier davon ausgegegan wird, dass das char[] nicht null ist, kommt hier im weiteren Verlauf eine NullPointerException zu stande.

```
public static String valueOf(char data[]) {
    return new String(data);
    }
```

Tja, nur warum wird hier beim zweiten Aufruf die String (char[] data)? Weil diese nach Java Language Specification die am besten passende Variante für die Eingabe ist. Warum? - Das wird durch eine ganze Menge von ziemlich komplizierten Regeln in der JLS beschrieben, wie ihr hier nachlesen könnt: 

15.12 Method Invocation Expressions
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#292575

Gruß Tom


----------



## Thomas Darimont (25. Juli 2008)

Hallo,

hier mal noch ein neues Rätsel:

Eine Zahl soll in ein Zahlenwort umgewandelt werden. Beispiel 2147483647 in "zwei Milliarden hundertsiebenundvierzig Millionen vierhundertdreiundachtzigtausendsechshundertsiebenundvierzig".
Wie macht man das möglichst schnell, einfach und elegant? 
(Man darf auch zusatzlibs verwenden, aus dem Eclipse Project, Tomcat, Spring, Hibernate, etc.)

Keiner Hint als zusäzliche Anforderung: Man soll die Zahl auch auf "englisch" und "französisch" ausgeben können also bei 2147483647 : 
englisch: two billion, one hundred and forty-seven million, four hundred and eighty-three thousand, six hundred and forty-seven
französisch: deux milliard cent quarante-sept million quatre cents quatre-vingt-trois mille six cents quarante-sept

Gruß Tom


----------



## Kai008 (25. Juli 2008)

Ich habs mal versucht, weiß aber nicht ob es gut funktioniert, oder noch mehr ob es sauber ist, habe es schnell runtergeschrieben, und nur ein mal am Ende ausprobiert.

Ach ja, habe es fürs erste nur bis Tausend gemacht, sollte aber einfach so erweiterbar sein.


----------



## Thomas Darimont (27. Juli 2008)

Hallo,

danke Kai008 das du dich daran versucht hast  Dein Ansatz funktioniert natürlich auch, jedoch muss man hier noch relativ viel "selber machen". Wie wärs denn damit?

```
/**
 * 
 */
package de.tutorials;

import java.util.Locale;

import com.ibm.icu.text.RuleBasedNumberFormat;

/**
 * @author Tom
 * 
 */
public class NumberSpelling {

    /**
     * @param args
     */
    public static void main(String[] args) {
        int number = Integer.MAX_VALUE;
        System.out.println(number);
        System.out.println(new RuleBasedNumberFormat(Locale.GERMANY,
                RuleBasedNumberFormat.SPELLOUT).format(number));
        System.out.println(new RuleBasedNumberFormat(Locale.US,
                RuleBasedNumberFormat.SPELLOUT).format(number));
        System.out.println(new RuleBasedNumberFormat(Locale.FRANCE,
                RuleBasedNumberFormat.SPELLOUT).format(number));
    }
}
```

Ausgabe:

```
2147483647
zwei Milliarden hundertsiebenundvierzig Millionen vierhundertdreiundachtzigtausendsechshundertsiebenundvierzig
two billion, one hundred and forty-seven million, four hundred and eighty-three thousand, six hundred and forty-seven
deux milliard cent quarante-sept million quatre cents quatre-vingt-trois mille six cents quarante-sept
```

Kommt mir bekannt vor? Das kann sein, denn:
http://www.tutorials.de/forum/java/...ke-zahlenwort-zu-zahl-zahl-zu-zahlenwort.html

Gruß Tom


----------



## thomy800 (31. Juli 2008)

Letztendlich macht die RuleBasedNumberFormat-Version aber auch nicht viel anders als Kai008s Version, nur dass Kai008 die Funktionen selber geschrieben hat


----------



## java123 (27. August 2009)

*Thread ausgrab* 

Was wird ausgegeben wenn man folgendes Programm ausführt? Es dürfte zwar relativ klar sein, aber die Idee kam mir gerade heute und wunderte mich ob auch wirklich das "Gedachte" auf der Konsole ausgegeben wird.
Achja, das *Warum* könnt ihr auch noch angeben.


```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Foo implements ActionListener {
	public Foo() {
		new Foobar().a(this);
	}
	public static void main(String[] args) {
		new Foo();
	}
	public void actionPerformed(ActionEvent e) {}
}

class Foobar {
	public void a(ActionListener a) {
		System.out.println("actionlistener");
	}
	public void a(Foo foo) {
		System.out.println("foo");
	}
}
```


----------



## zeja (28. August 2009)

Spoiler



foo, da Java eine statisch getypte Sprache ist.


----------



## Kai008 (28. August 2009)

Ich denke


Spoiler



'foo'


, da Klassen wohl gegen Interface'e Vorrang haben.
Aber interessante Frage, eine genaue Erklärung ect. würde mich schon interessieren.


----------



## limago (28. August 2009)

Hi,

ich tippe es wird "Foo" ausgegeben. Die übergebene Referenz ist vom Typ "Foo". Es verhält sich als würde "Foo" von "ActionListener" erben. Der Compiler prüft bei der überladenen Funktion erst ob Foo passt. Nur wenn das nicht passt, steigt er die Vererbungshierachie auf. Nicht auflösen könnte der Compiler dies:

```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;

public class Foo implements ActionListener, Serializable {
	public Foo() {
		new Foobar().a(this);
	}
	public static void main(String[] args) {
		new Foo();
	}
	public void actionPerformed(ActionEvent e) {} }

class Foobar {
	public void a(ActionListener a) {
		System.out.println("actionlistener");
	}
	public void a(Serializable foo) {
		System.out.println("Serializable");
	}
}
```

Gruß

Jo


----------



## Technoblade (15. November 2009)

> *Achtung Spoiler*



Ich würde tippen, dass Foo ausgegeben wird.
Das warjm ist auch recht simpel. gehen wir davon aus die Klasse würde noch 5 weitere Interfaces implementieren, udn es gäbe nicht nur die Methode a mit einem ActionListener und Foo als Parameter, sondern auch noch die 5 weiteren Interfaces als Parameter. In diesem fall wäre es auf jeden Fall einfacher, wenn Foo genommen würde. Der einzige Knackpunkt der mir einfällt wäre, was dann passieren sollte wenn es die Methode mit Foo als Parameter nicht geben würde. Hier stehe ich dann auch auf dem Schlach. In diesem fall würde ich tippen entweder die Interfaces (mit Packageangabe!!) alphabetisch geordnet, oder in der Reihenfolge wie sie bei der Klassensignatur angegeben sind.

Edit:

Mir ist noch eingefallen, dass es auch sein könnte, dass danach geurteilt wird wie die Methoden im Quelltext auftauchen, in diesem fall, würde natürlich ActionListener ausgegeben, ich denke ich bleibe trotz dem bei meiner ersten Vermutung (siehe oben).


----------



## w0ddes (2. Dezember 2009)

schade, dass dieser Thread schon wieder eingeschlafen ist. Ich hab jetzt alles mal durchgelesen und finde es sehr spannend


----------



## Thomas Darimont (3. Dezember 2009)

Hallo,

gegeben sei folgender Code:

```
package de.tutorials;

public class WhatsGoingOn {
  public static void main(String[] args) {
    //?
    System.out.println(new String("xxx"));
  }
}
```

Was kann man an Stelle von "?" schreiben damit das Programm folgende Ausgabe erzeugt?
Die Aufgabe ist auf mehrere verschiedene Arten lösbar.

Ausgabe:

```
huch?
```

Aufrufe von System.exit(...) / Reflection-Calls sowie Verwendung von AspectJ oder anderen AOP Frameworks sind nicht erlaubt!

Gruß Tom


----------



## Technoblade (3. Dezember 2009)

Hier meine Lösung, die zumindest bei mir wunderbar funktioniert hat:


```
Achtung Spoiler:
package de.tutorials;

public class WhatsGoingOn {
  public static void main(String[] args) {
    System.setOut(new java.io.PrintStream(System.out) {
                                                        public void println(String x) {
                                                            super.println(x.equals("xxx") ? 
                                                            "huch?" : x);
                                                        }});
    System.out.println(new String("xxx"));
  }
}
```


----------



## zeja (4. Dezember 2009)

Noch ne Möglichkeit:



Spoiler



public class WhatsGoingOn {
	public static void main(String[] args) {
		class String {

			public String(java.lang.String s) {
			}

			@Override
			public java.lang.String toString() {
				return "huch?";
			}
		}
		System.out.println(new String("xxx"));
	}
}


----------



## Nagsor (21. Dezember 2009)

So gehts auch:



Spoiler





```
public class WhatsGoingOn {
  public static void main(String[] args) {
    System.out.println(new String("huch?"));
    if (false)
    System.out.println(new String("xxx"));
  }
}
```




/duck


----------



## zeja (21. Dezember 2009)

*g* Auch nett


----------



## limago (22. Dezember 2009)

ich hätte auch noch einen.... Ähnliche Idee wie Zeja


Spoiler



import java.io.PrintStream;

public class WhatsGoingOn {
  public static void main(String[] args) {

	System.setOut(new PrintStream(System.out){

		@Override
		public void println(String x) {

			super.println("Huch");
		}

	});

	System.out.println(new String("xxx"));
  }
}


----------



## Technoblade (25. Dezember 2009)

Ist zwar ähnlicher zu meiner Idee, aber dennoch gut


----------



## limago (28. Dezember 2009)

@technoblade

Stimmt, habe Deinen Beitrag leider übersehen....


----------



## Thomas Darimont (29. Dezember 2009)

Hallo,

da für das letzte Rätsel schon so ziemlich jede Lösungsvariante gepostet wurde gibts hiermit ein neues Rätsel:

Folgendes Programm läuft mit 48MB Heap (-Xmx48m) bricht kurz nach dem Start mit einem (java.lang.OutOfMemoryError: Java heap space) ab.


```
package de.tutorials;

import java.util.ArrayList;
import java.util.List;

public class MemoryLeakExample {
    public static void main(String[] args) {
        List<List<?>> lists = new ArrayList<List<?>>();
        
        for(int i = 0; i < 100;i++){
            List<Integer> list = new ArrayList<Integer>();
            
            for(int j = 0; j < 1000000;j++){
                list.add(j);
            }
            lists.add(list);
            
            System.out.println(i);
            list.clear();
 //+
           ?
//-
        }
        
        System.out.println(lists);
    }
}
```

Was könnte man noch bei ? aufrufen um den OOME abzuwenden?

Regeln:
1) lists darf nicht null gesetzt / neu initialisiert oder mit clear() geleert werden.
2) Kein Thread Sleep 
3) Kein System.gc() etc.
4) lists soll am Ende noch die ursprünglich hinzugefügten List Instanzen beinhalten
Edit: 
5) -Xmx48m (Heap Size auf 48 MB beschränken)
6) Es dürfen nur beliebig viele Zeilen zwischen //+ und //- eingefügt werden

Gruß Tom


----------



## limago (29. Dezember 2009)

Also bei mir ist das Programm unter Java 6 32-bit version und Windows 7 64-bit Version durchgelaufen. Daraufhin habe ich den Heapsize auf 256 gesetzt um den Effekt zu bekommen.

Nachfolgende Lösung läuft dann bei mir durch:



Spoiler



package de.tutorials;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MemoryLeakExample {
    public static void main(String[] args) {
        List<List<?>> lists = new ArrayList<List<?>>();

        for(int i = 0; i < 100;i++){
            List<Integer> list = new ArrayList<Integer>();

            for(int j = 0; j < 1000000;j++){
                list.add(j);
            }
            lists.add(list);

            System.out.println(i);
            list.clear();
            //?
            lists.remove(list);
            // lists.add(Collections.unmodifiableList(list));
           lists.add(list);
        }

        System.out.println(lists);
    }
}


----------



## Thomas Darimont (29. Dezember 2009)

Hallo,

okay, habs mit dem unter Ubuntu 64 Bit mit dem Open JDK 1.6.0_0 laufen lassen.

Damit das Problem auf jeden Fall auftritt reduzieren wir die Heap Size mal auf 48 MB. -Xmx48m

@limago:


Spoiler



Die Liste zu entfernen und nachträglich wieder hinzuzufügen ist keine zuverlässige Lösung... ->  mit kleineren Heap Konfiguration gibt es trotzdem OOMEs. Ich bekomme auch mit 256 MB OOME's bei deiner Lösung.



@All


Spoiler



die Ursache für den OOME liegt in der Implementierung der Liste...
Vielleicht machen ja manche Methoden nicht ganz das was man von ihnen erwartet...



Gruß Tom


----------



## limago (29. Dezember 2009)

Das hier ist sicher nicht in Toms Sinn ;-) erfüllt aber alle Foderungen  * grins *



Spoiler



package de.tutorials;


import java.util.List;

public class MemoryLeakExample {
    public static void main(String[] args) {
        List<List<?>> lists = new ArrayList<List<?>>();

        for(int i = 0; i < 100;i++){
            List<Integer> list = new ArrayList<Integer>();

            for(int j = 0; j < 1000000;j++){
                list.add(j);
            }
            lists.add(list);

            System.out.println(i);
            list.clear();
            //?


        }

        System.out.println(lists);
    }

    static class ArrayList<T> extends java.util.ArrayList<T> {
    	public boolean add( T element) {
    		if (element instanceof List)
    			super.add(element);
    		return true;}
    }
}


----------



## Thomas Darimont (29. Dezember 2009)

Hallo,



> Das hier ist sicher nicht in Toms Sinn ;-) erfüllt aber alle Foderungen  * grins *



Ist auch nicht wirklich gültig, da der Code nicht an der Stelle des ? eingefügt wurde... ;-)  -> Regeln erweitert / klarer gemacht

Gruß Tom


----------



## zeja (29. Dezember 2009)

Hmm...



Spoiler



i = 100;



Ich denke richtig ist:


Spoiler



((ArrayList<Integer>)list).trimToSize( );
clear() setzt nur die Elemente im Array der ArrayList auf null und die Größe auf 0, aber behält die Größe des Arrays bei. Daher bleibt der Speicher auch reserviert.


----------



## Technoblade (29. Dezember 2009)

Hat zwar nen bisschen gedauert bis ich drauf gekommen, aber wohl eher weil ich das Problem überschätzt habe. Hier meine Lösung:


```
import java.util.ArrayList;
import java.util.List;
 
public class MemoryLeakExample {
    public static void main(String[] args) {
        List<List<?>> lists = new ArrayList<List<?>>();
       
        for(int i = 0; i < 100;i++){
            List<Integer> list = new ArrayList<Integer>();
           
            for(int j = 0; j < 1000000;j++){
                list.add(j);
            }
            lists.add(list);
           
            System.out.println(i);
            list.clear();
            i = 100;
        }
       
        System.out.println(lists);
    }
}
```


----------



## Thomas Darimont (30. Dezember 2009)

Hallo,

die Schleifenvariablen zu manipulieren ist nicht wirklich eine Lösung... oder würdet ihr etwa so ein Speicherproblem in production code lösen? Durch verändern der Business Logic? In den meisten Fällen wird das wohl keine so gute Idee sein... ;-)

Gruß Tom


----------



## Anime-Otaku (30. Dezember 2009)

Spoiler



Habe die Liste die geleert wurde wieder auch von der array size gestaucht. Bei mir gehts mit 48MB heap(und weniger) auf Windows 7 & sun jre 6-17 auf x86_64 bit Maschine

package de.tutorials;

import java.util.ArrayList;
import java.util.List;

public class MemoryLeakExample {
    public static void main(String[] args) {
        List<List<?>> lists = new ArrayList<List<?>>();

        for(int i = 0; i < 100;i++){
            List<Integer> list = new ArrayList<Integer>();

            for(int j = 0; j < 1000000;j++){
                list.add(j);
            }
            lists.add(list);

            System.out.println(i);
            list.clear();
 //+
           ArrayList<?> ar = (ArrayList<?>) list;
           ar.trimToSize();
//-
        }

        System.out.println(lists);
    }
}


----------



## Thomas Darimont (31. Dezember 2009)

Hallo,

ein Aufruf von trimToSize() war natürlich des Rätsels Lösung.


```
package de.tutorials;

import java.util.ArrayList;
import java.util.List;

public class MemoryLeakExample {
    public static void main(String[] args) {
        List<List<?>> lists = new ArrayList<List<?>>();
        for(int i = 0; i < 100;i++){
            List<Integer> list = new ArrayList<Integer>();
            
            for(int j = 0; j < 1000000;j++){
                list.add(j);
            }
            lists.add(list);
            
            System.out.println(i);
            list.clear();
            ((ArrayList<?>)list).trimToSize();
        }
        System.out.println(lists);
    }
}
```

Das Beispiel sollte nochmal vor Augen führen, dass auch in Code der auf den ersten Blick sauber ausschaut üble Memory Leaks verborgen sein können die man nur durch genaue Kenntnisse der Implementierungsdetails der Java API auflösen kann.

Andere Collection Klassen wie HashMap, LinkedHashMap, ConcurrentHashMap etc. haben dieses Problem auch, bieten jedch keine Möglichkeit nachträglich die internen Strukturen (hier Hash-Buckets / Segments) zu stutzen.

TreeMap hat dieses Problem IMHO nicht. Dort wird beim clear() die Referenz auf den zugrundeliegenden RB-Tree (RedBlack) null gesetzt, so dass die internen Strukturen, soweit nicht mehr sonstwie referenziert, vom GC aufgesammelt werden können.


```
package de.tutorials;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

public class MemoryLeakExample {
    public static void main(String[] args) {
        List<Map<?,?>> maps = new ArrayList<Map<?,?>>();
        for(int i = 0; i < 100;i++){
            Map<Integer, Integer> map = 
                new TreeMap<Integer, Integer>(); //Läuft durch
                //new HashMap<Integer, Integer>(); //OOME
                //new LinkedHashMap<Integer, Integer>(); //OOME
                //new ConcurrentHashMap<Integer, Integer>(); //OOME
            
            for(int j = 0; j < 100000;j++){
                map.put(j,j);
            }
            maps.add(map);
            
            System.out.println(i);
            map.clear();
            System.out.println(map);
        }
        System.out.println(maps);
    }
}
```

Gruß Tom


----------



## Thomas Darimont (1. Januar 2010)

Hallo,

zum Jahres auftakt gibts dann mal ein neues (einfaches) Rätsel:

Gegeben:

```
package de.tutorials;

import java.util.LinkedHashMap;
import java.util.Map;

public class LRUMapExample {
    public static void main(String[] args) {
        int maxEntriesToKeep = 10;
        
        Map<Integer, Integer> lruMap = new LinkedHashMap<Integer, Integer>();

        for (int i = 0; i < 1000; i++) {
            lruMap.put(i, i);
        }

        System.out.println(lruMap);
    }
}
```

Wie macht man hier am einfachsten aus einer LinkedHashMap eine LRU Map (Last Recently Used) welche sich nur die letzten 10 hinzugefügten Elemente merkt?

Um dann folgende Ausgabe zu erzeugen:

```
{990=990, 991=991, 992=992, 993=993, 994=994, 995=995, 996=996, 997=997, 998=998, 999=999}
```
?

Viel Spaß und ein frohes neues Jahr allerseits 

Gruß Tom


----------



## zeja (1. Januar 2010)

Nice...



Spoiler



import java.util.LinkedHashMap;
import java.util.Map;

public class LRUMapExample {

	public static void main(String[] args) {
		final int maxEntriesToKeep = 10;

		Map<Integer, Integer> lruMap = new LinkedHashMap<Integer, Integer>( ) {
			@Override
			protected boolean removeEldestEntry(
					java.util.Map.Entry<Integer, Integer> eldest) {
				return this.size( ) > maxEntriesToKeep;
			}
		};

		for (int i = 0; i < 1000; i++) {
			lruMap.put(i, i);
		}

		System.out.println(lruMap);
	}

}


----------



## DEV (6. Dezember 2010)

Hallo,

bin mir nicht ganz sicher ob ich deine Aufgabenstellung richtig verstehe *schäm*, aber wie wärs mit:


```
for (int i = 1000-maxEntriesToKeep; i < 1000; i++) {
            lruMap.put(i, i);
        }
```

?

Gruß
DEV


----------



## AAF (6. Dezember 2010)

Dann kannst du gleich folgendes verwenden^^:

```
for (int i = 990; i < 1000; i++) {
	lruMap.put(i, i);
}
```

PS: Die Frage ist schon knapp ein Jahr alt..


----------



## DEV (6. Dezember 2010)

> PS: Die Frage ist schon knapp ein Jahr alt..



Oh mann, das passiert mir heute schon das zweite mal :-(

Das passiert, weil unter den Threads immer so komische Vorschläge mit ähnlichen Threads kommen; leider sind die wohl größtenteils alt ....

Gruß
DEV


----------



## MAN (20. März 2011)

Auch wenn es jetzt schon ein Jahr her ist: was spricht gegen ein neues Rätsel? 

Thema: *Annotations*

Gegeben ist die folgende Klasse:


```
package de.tutorials;

import java.util.Date;

public class AnnotationExample {
	private static String supUnused1 = "unused";
	private static String supDeprecation1 = "deprecation";
	private static final String supUnused2 = "unused";
	private static final String supDeprecation2 = "deprecation";
	private static final String[] suppressArray = { "unused", "deprecation" };

	public static void main(String[] args) {
		// Test 1
		@SuppressWarnings( { "unused", "deprecation" })
		new Date().getDay();

		// Test 2
		@SuppressWarnings( { "unused", "deprecation" })
		int a = new Date().getDay();

		// Test 3
		@SuppressWarnings( { supUnused1, supDeprecation1 })
		int b = new Date().getDay();

		// Test 4
		@SuppressWarnings( { supUnused2, supDeprecation2 })
		int c = new Date().getDay();

		// Test 5
		@SuppressWarnings(suppressArray)
		int d = new Date().getDay();
	}
}
```

Die Fragen sind:
- wie reagiert der Compiler mit Java 1.6?
- welche Tests funktionieren, welche nicht und warum nicht?
Der Code sollte wenns geht nicht vorher ausgeführt werden 

Viel Spaß beim Knobeln (oder Wissen )!

Viele Grüße,
MAN


----------



## Thomas Darimont (22. März 2011)

Hallo,

wie sollen wir denn die Lösung angeben...?
Hier kommen mehere Dinge zusammen die man aber IMHO etzten endes aber alle unter der Kategorie Syntaxfehler abtun kann, wobei einige Fehler offensichtlich sind und andere eher subtil daher kommen ;-)

Gruß Tom


----------



## MAN (22. März 2011)

Okay, im Prinzip hast du vollkommen Recht dass es ausschließlich Syntaxfehler sind 
Vielleicht ist es als Rätsel etwas unsinnig, aber dennoch eine gute Frage, warum der Compiler reagiert, wie er reagiert 

Gerade beim ersten und fünften Test reagiert der Compiler meiner Meinung nach einfach falsch. Und wenn es richtig wäre, mit welcher genauen Erklärung?

Viele Grüße,
MAN


----------



## Kai008 (29. März 2011)

Bei 5 vielleicht aus den selben Grund, warum byte a = 5; byte b = 3; byte c = (byte)(a + b); gecastet werden muss: Weil der Wert zur Kompilerzeit noch nicht eindeutig bekannt ist. Vielleicht will er deshalb auch final's, und kein Array, da dessen Felder ja auch zwischen Intialisation und Verwendung auch verändert werden können.

:/


----------



## Thomas Darimont (3. Mai 2011)

Hallo,

hier noch ein neues Rätsel für euch:

Wie erstellt man eine Instanz der Klasse X ohne den Code der Klasse X zu ändern (weder auf Sourcecode noch auf Bytecode Ebene)?


```
package de.tutorials.training;

import java.lang.reflect.Constructor;

public class SneakyObjectConstruction {
  
  public static void main(String[] args) throws Exception {

    try {
      System.out.println(X.class.newInstance());
    } catch (Throwable t) {
      System.out.println(t);
    }

    try {
      Constructor<?> ctor = X.class.getDeclaredConstructor();
      ctor.setAccessible(true);
      System.out.println(ctor.newInstance());
    } catch (Throwable t) {
      System.out.println(t);
    }
    
    //TODO insert your approach here :)
  }

  static class X {
    
    private int i = 1;
    
    private X() {
      if(i == 1){
        throw new IllegalStateException("i is 1");
      }
    }
  }
}
```

Viel Spaß,
Gruß Tom


----------



## Thomas Darimont (9. Mai 2011)

Hallo zusammen,

hier die Äuflösung des Java Rätsels:

```
package de.tutorials.training;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;


// Our test driver
public class SneakyObjectConstruction {

  public static void main(String[] args) throws Exception {

    try {
      System.out.println(X.class.newInstance());
    } catch (Throwable t) {
      System.out.println(t);
    }

    try {
      Constructor<?> ctor = X.class.getDeclaredConstructor();
      ctor.setAccessible(true);
      System.out.println(ctor.newInstance());
    } catch (Throwable t) {
      System.out.println(((InvocationTargetException)t).getTargetException());
    }

    // Some working approaches :)

    //ReflectionFactory
    try {
      sun.reflect.ReflectionFactory reflectionFactory = sun.reflect.ReflectionFactory.getReflectionFactory();
      Constructor<X> ctor = reflectionFactory.newConstructorForSerialization(X.class, Object.class.getDeclaredConstructor());
      System.out.println("ReflectionFactory: " + ctor.newInstance());
    } catch (Throwable t) { 
      System.out.println(t);
    }

    //Unsafe
    Field f = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
    f.setAccessible(true);
    sun.misc.Unsafe u = (sun.misc.Unsafe)f.get(null);
    System.out.println("Unsafe: " +  u.allocateInstance(X.class));

    //Method by Dr. Heinz Kabuts :)
    //See http://www.javaspecialists.eu/archive/Issue032.html
    System.out.println("Heinz Kabutz: " + Y.make());
  }
  
  static class X {

    private int i = 1;


    private X() {
       if(i == 1){
       throw new IllegalStateException("i is 1");
       }
    }
  }

  static class Y extends X {
    private static Y y;


    static Y make() {
      try {
        new Y();
      } catch (Exception ex) {
        try {
          synchronized (Y.class) {
            while (y == null) {
              System.gc();
              Y.class.wait(100);
            }
          }
        } catch (InterruptedException ie) {
          return null;
        }
      }
      return y;
    }


    @Override
    protected void finalize() throws Throwable {
      synchronized (Y.class) {
        y = this;
        Y.class.notify();
      }
    }
  }
}
```

Ausgabe:

```
java.lang.IllegalAccessException: Class de.tutorials.training.SneakyObjectConstruction can not access a member of class de.tutorials.training.SneakyObjectConstruction$X with modifiers "private"
java.lang.IllegalStateException: i is 1
ReflectionFactory: de.tutorials.training.SneakyObjectConstruction$X@459189e1
Unsafe: de.tutorials.training.SneakyObjectConstruction$X@2f9ee1ac
Heinz Kabutz: de.tutorials.training.SneakyObjectConstruction$Y@24c21495
```


Gruß Tom


----------



## MAN (30. November 2011)

"10, 20", da *int* ein atomarer Datentyp ist und byValue und nicht byReference der Funktion swap übergeben wird!


----------



## slowfly (18. Januar 2012)

Da es hier schon lange kein Rätse mehr gab; hier ein kleines von meiner Seite,...

Es geht um die Berechnung einer Kreditkarten-Quersumme nach dem Module-10-Algorithmus. Wir hatten mal die Anforderung, eine Karte unseres Loyaltysystems zu validieren. Das war ja eher ein ge-copy-paste aus dem Internet. Die nächste Anforderung war, die nächste gültige Nummer zu bekommen.

Die Aufgabe darin besteht eine möglichst elegante/einfache Möglichkeit zur Berechnung der nächsten gültigen Nummer zu formulieren

Hier die Source:

```
package test;

public class CheckSum {
	public static boolean validateCheckSum(String inData) {
		char[] c = null;
		char[] d = null;
		int sum = 0;
		int checksum = 0;
		StringBuffer digits = new StringBuffer();

		// isolate digits
		c = inData.toCharArray();
		for (int i = 0; i < c.length; i++) {
			if (Character.isDigit(c[i])) {
				digits.append(c[i]);
			}
		}

		// calculate sum
		int nr = 0;
		d = digits.toString().toCharArray();
		for (int i = 0; i < d.length - 1; i++) {
			nr = i + 1;
			if (nr % 2 == 0) {
				sum += Character.digit(d[i], 10) * 3;
			} else {
				sum += Character.digit(d[i], 10);
			}
		}

		// validate check sum
		if ((10 - (sum % 10)) == 10) {
			checksum = 0;
		} else {
			checksum = 10 - (sum % 10);
		}

		if (checksum == Character.digit(c[(d.length - 1)], 10)) {
			return true;
		}

		return false;
	}

	public static String getNextNumber(String inLatest) {
		// your approach here
		return null;
	}

	public static void main(String[] args) {
		String latestNumber = "1009";
		System.out.println("Is " + latestNumber + " valid? " + validateCheckSum(latestNumber));
		System.out.println("Is 1018 the next number? " + "1018".equals(getNextNumber(latestNumber)));
	}
}
```

Ausgabe:
Is 1009 valid? true
Is 1018 the next number? false

Und wehe, es macht jemand einfach return "1018" 

hf
slowy


----------



## Thomas Darimont (18. Januar 2012)

Hallo,

danke für das Rätsel 

Ich nehme mal an, dass die Aufgabe darin besteht eine möglichst elegante/einfache Möglichkeit zur Berechnung der nächsten gültigen Nummer zu formulieren, oder? Das steht leider nicht soooo explizit drin ;-)

Gruß Tom


----------



## slowfly (18. Januar 2012)

kopf->tisch
ty, ge-edited.


----------



## j2se (8. März 2012)

Angenommen es gibt die Klassen Othello, welche das Interface Comparator wie folgt implementiert:


```
public class Othello implements Comparator<String> {
	public int compare(String s1, String s2) {
		return s2.compareTo(s1);
	}
}
```

Was ergibt demnach folgender System.out.println und weshalb:


```
String[] s = {"map", "pen", "marble", "key"};
		Arrays.sort(s, new Othello());
		System.out.println(Arrays.binarySearch(s, "key"));
```


----------



## genodeftest (8. März 2012)

Die Ausgabe lautet 
	
	
	



```
-1
```
weil das Array falsch herum sortiert wurde.


----------



## j2se (8. März 2012)

genodeftest hat gesagt.:


> Die Ausgabe lautet
> 
> 
> 
> ...



richtig analysiert!

Um eine richtige Antwort zu erhalten, müsste der Aufruf

System.out.println(Arrays.binarySearch(s, "key", new Othello()));

lauten.


----------



## MAN (12. März 2013)

Hallo zusammen,

ich hätte mal wieder ein neues Rätsel.

Gegeben ist folgender Java Code:


```
public static void main(String args[]) {
	Integer a1 = 50;
	Integer b1 = 50;
	Integer a2 = 500;
	Integer b2 = 500;

	System.out.println(a1 == b1);
	System.out.println(a2 == b2);
}
```

Und die folgende zugehörige Ausgabe:


```
true
false
```

*Erkläre, wie es zu dieser Ausgabe kommt!* 

Viele Grüße,
MAN


----------



## slowfly (12. März 2013)

Habe folgendes rausgefunden:

```
Integer a1 = 127;
		Integer b1 = 127;
		Integer a2 = 128;
		Integer b2 = 128;

		System.out.println(a1 == b1);
		System.out.println(a2 == b2);

		a1 = new Integer(127);
		b1 = new Integer(127);
		a2 = new Integer(128);
		b2 = new Integer(128);

		System.out.println(a1 == b1);
		System.out.println(a2 == b2);
		
		a1 = Integer.valueOf(127);
		b1 = Integer.valueOf(127);
		a2 = Integer.valueOf(128);
		b2 = Integer.valueOf(128);
		
		System.out.println(a1 == b1);
		System.out.println(a2 == b2);

true
false
false
false
true
false
```
Ab 128 inklusive wird's auf einmal false. Gleich verhält es sich, wenn ich mit "valueOf" arbeite, verwende ich den Konstruktor, ist es immer false.
Erklärung habe ich aber keine dazu - und finde, das ist gemein-gefährlich 

Gruss
slowy


----------



## Yaslaw (12. März 2013)

slowfly hat gesagt.:


> Erklärung habe ich aber keine dazu - und finde, das ist gemein-gefährlich





Gemeingefährlich ists nicht. Grad bei Nicht Nativ-Typen solltest du über equals() testen.

```
Integer a2 = 500;
Integer b2 = 500;

System.out.println(a2.equals(b2));
```


----------



## slowfly (12. März 2013)

Ja, das ist schon klar. Mit gemeingefährlich meine ich vorallem: wenn ich eine TestCase schreibe mit Werten unter 128, ist der TestCase grün. Das kann dann in der Produktion ziemlich nerven kosten. Jetzt könnte man sagen, man muss halt auch mit mehreren Werten testen, aber dieser "Switch" könnte ja auch erst ab 65k auftreten... naja, bin gespannt auf die Antwort, dann wird alles Sinn machen


----------



## Thomas Darimont (12. März 2013)

Hallo,



Spoiler



Der Java Compiler erkennt, dass ein primitiver Typ als ein Referenztyp benötigt wird und fügt automatisch eine entsprechende Auto-Boxing Operation durch. Dabei wird die statische valueOf(...) Methode der entsprechenden Wrapper-Klasse verwendet. 
Die folgenden Wrapper-Typen verwenden in der valueOf- Methode einen zum Teil konfigurierbaren (*) Cache (Standard Werte Bereiche in [...] angegeben) :Byte[-128,+127], Short[-128,+127], Integer[-128,+127], Long[-128,+127], Character[0,+128], (Boolean[TRUE,FALSE])
Diese Caches bilden die primitiven Werte auf entsprechende Wrapper Typ Instanzen ab.
Wird die valueOf Methode mit einem Argument aufgerufen, dass innerhalb der Cache-Grenzen so wird
immer die selbe Wrapper-Instanz zurückgegeben.

Hierbei handelt es sich im Prinzip um das Flyweight-Design Pattern. Hierbei handelt es sich also um eine Optimierung um die Objekt-Erzeugung von Wrapper-Typen in Standardfällen zu reduzieren und somit weniger "GC-Pressure" zu erzeugen und auch "weniger" Speicher zu verbrauchen, da die entsprechenden Wrapper Instanzen im Idealfall ja nur 1-Mal vorhanden sind. 
Die Wrapper-Klassen Double und Float haben keine solche Cache-Mechanismen eingebaut.

System.out.println(Integer.valueOf(1) == Integer.valueOf(1));
System.out.println(System.identityHashCode(Integer.valueOf(1))  + " = " + System.identityHashCode(Integer.valueOf(1)));

Da der Cache im Falle von Integer standardmäßig auf den Wertebereich [-128,+127] beschränkt ist, liefert die valueOf Methode ab einem Wert ober- oder unterhalb der Cache grenzen dann neue Integer Instanzen.

System.out.println(Integer.valueOf(128) == Integer.valueOf(128));
System.out.println(System.identityHashCode(Integer.valueOf(128))  + " != " + System.identityHashCode(Integer.valueOf(128)));

(*)
versuchs mal mit -Djava.lang.Integer.IntegerCache.high=1000000 oder-XX:+AggressiveOpts laufen zu lassen ;-)



Gruß Tom


----------



## Akeshihiro (12. März 2013)

Das ist eigentlich nicht so sehr schwer. Der code sieht nach dem Kompilieren eigentlich so aus:

```
public static void main(String args[]) {
    Integer a1 = Integer.valueOf(50); // irgend eine Instanz
    Integer b1 = Integer.valueOf(50); // die selbe Instanz wie a1
    Integer a2 = Integer.valueOf(500); // neue Instanz, da > 127 -> new Integer(500)
    Integer b2 = Integer.valueOf(500); // neue Instanz, da > 127 -> new Integer(500)
 
    System.out.println(a1 == b1);
    System.out.println(a2 == b2);
}
```

Die Sache ist die. Integer arbeitet mit einem Cache, der von -128 bis 127 reicht. Wird eine Zahl innerhlab dieses Bereiches "angefordert", wird eine gecachte Instanz zurück gegeben. Alles, was außerhalb dieses Bereiches ist, wird neu instanziiert und somit sind das dann beim Vergleich mittels Vergleichsoperator unterschiedliche Instanzen, daher auch ein false als Ergebnis.

EDIT:
Mist, Thomas war schneller


----------



## MAN (12. März 2013)

@Tom: perfekte Erklärung! Ist alles dabei was man wissen muss 
Dass man das ganze noch per VM-Argument beeinflussen kann ist sehr interessant. Da hab auch ich noch was dazugelernt 

@Akeshihiro: ebenfalls die richtige Erklärung!


----------



## Thomas Darimont (12. März 2013)

Hallo,

dann habe ich auch mal ein einfaches neues Rätsel:

Für welche Argumente gibt Math#abs(..) einen negativen Wert zurück?

Gruß Tom


----------



## slowfly (12. März 2013)

```
System.out.println(Math.abs(Integer.MIN_VALUE));
```
Erklärung JavaDoc

```
Note that if the argument is equal to the value of Integer.MIN_VALUE, 
the most negative representable int value, the result is that same value, 
which is negative.
```
Vermutlich weil der MIN_VALUE ohne Vorzeichen ins eins grösser ist als MAX_VALUE...?

Gruss
slowy


----------



## Thomas Darimont (12. März 2013)

Hallo,

Stimmt zum Teil ;-) aber deine Erklärung passt IMHO nicht bzw. entspricht nicht die aus dem JavaDoc Fragment. Dies enthält jedoch die Antwort: -Integer.MIN_VALUE ==  Integer.MIN_VALUE und --Long.MIN_VALUE == Long.MIN_VALUE. Das sind zwei explizite Sonderfälle 
Math.signum(Math.abs(Integer.MIN_VALUE)) und Math.signum(Math.abs(Long.MIN_VALUE)) geben beide -1 zurück.



> Vermutlich weil der MIN_VALUE ohne Vorzeichen ins eins grösser ist als MAX_VALUE...?


 ... fast ;-) 

```
Integer.MIN_VALUE-1  == Integer.MAX_VALUE
```

Math#abs ist für Fließkommawerte anders definiert als die Ganzzahl-Varianten, deshalb tritt das Verhalten von #abs dort nicht so auf -> Math.signum(Math.abs(Float.MIN_VALUE)) und Math.signum(Math.abs(Double.MIN_VALUE)) geben beide "+1" zurück.


```
System.out.printf("-(%s) => %s%n",Byte.MIN_VALUE, -Byte.MIN_VALUE);
        System.out.printf("-(%s) => %s%n",Short.MIN_VALUE, -Short.MIN_VALUE);
        System.out.printf("-(%s) => %s%n",Integer.MIN_VALUE, -Integer.MIN_VALUE);
        System.out.printf("-(%s) => %s%n",Long.MIN_VALUE, -Long.MIN_VALUE);
        System.out.printf("-(%s) => %s%n",Float.MIN_VALUE, -Float.MIN_VALUE);
        System.out.printf("-(%s) => %s%n",Double.MIN_VALUE, -Double.MIN_VALUE);
```

Ausgabe:

```
-(-128) => 128
-(-32768) => 32768
-(-2147483648) => -2147483648  ******
-(-9223372036854775808) => -9223372036854775808 ******
-(1.4E-45) => -1.4E-45 ******
-(4.9E-324) => -4.9E-324  ******
```
 
... habe dieses Beispiel gewählt, weil dies wieder mal eine der Stellen zeigt, wo die API nicht ganz das zu machen scheint, was man auf den ersten Blick erwartet ;-)

... und die Moral von der Geschicht - vergiss ins JavaDoc zu schauen nicht 

Gruß Tom


----------



## MAN (12. März 2013)

Für folgende Argumente wird ein negativer Wert zurückgeliefert:


```
Integer.MIN_VALUE // bzw. Integer.MAX_VALUE + 1
Long.MIN_VALUE // bzw. Long.MAX_VALUE + 1
```

*MAX_VALUE + 1* hat im Prinzip genau den gleichen Wert wie *MIN_VALUE* wegen dem internen "RollOver", siehe auch Zweierkomplement

Daher auch:


```
(Integer.MAX_VALUE + 1) == Integer.MIN_VALUE == -Integer.MIN_VALUE
(Long.MAX_VALUE + 1) == Long.MIN_VALUE == -Long.MIN_VALUE
```


----- Oh, zu langsam


----------



## Thomas Darimont (12. März 2013)

Hallo,

MAN passt!

Gruß Tom


----------



## Fasibio (6. November 2013)

So dann schau ich mal ob ich ein Rätsel zur Verfügung stellen kann. 

Folgende Klasse ist gegeben und bekannt: 

```
public class KnackMich{
       private String geheim = "Ich bin privat";
       private String privat = "Ich bin geheim";
}
```
Diese Klasse ist in in sich geschlossen und kann nicht verändert werden. 
Aufgabe: Erstelle ein Object der Klasse und gebe den Inhalt der Variabeln geheim und private aus.


----------



## slowfly (6. November 2013)

Huhu =) 


```
import java.lang.reflect.Field;

public class Knacker {
	public static void main(String[] args) {
		try {
			KnackMich knackMich = new KnackMich();

			Field[] fields = KnackMich.class.getDeclaredFields();

			for (Field field : fields) {
				field.setAccessible(true);
				System.out.println(field.get(knackMich));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}
```

Ausgabe:

```
Ich bin privat
Ich bin geheim
```

Ohne die Zeile
field.setAccessible(true);
wird eine IllegalAccessException geworfen.

Grüsse, slowy


----------



## Fasibio (6. November 2013)

genau ! 
So man könnte ja eine Rätsel kette machen ....


----------



## slowfly (6. November 2013)

Hab noch einen. PI nach dem Zufallsprinzip "ausrechnen". Haben vermutlich viele von euch schon mal in der Schule gemacht, aber ich fand die Übung ziemlich cool =)

Vorgabe

```
Random random = new Random();
		// kleiner tipp... was wird wohl "gehittet"
		int hits = 0;

		int runs = 999999;

		for (int i = 0; i < runs; i++) {
		// hier Code einfügen 
		}

		double myPI = // und hier Code einfügen

		System.out.println(Math.PI);
		System.out.println(myPI);
		System.out.println("difference = " + (Math.PI - myPI));
```

Ausgabe soll ungefähr gleich wie PI sein, je mehr runs, desto genauer.

Beispielausgabe:

```
3.141592653589793
3.1416427141642713
difference = -5.0060574478205666E-5
```
Gruss,
slowy


----------



## Thomas Darimont (6. November 2013)

Kleine Alternative zum KnackMich "Rätsel":

```
package de.tutorials.training;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicLong;

class KnackMich{
    private String geheim = "Ich bin privat";
    private String privat = "Ich bin geheim";
}

public class PrivateInformationStealingExample {

    static Unsafe getUnsafe() throws Exception{
        Field field = AtomicLong.class.getDeclaredField("unsafe");
        field.setAccessible(true);
        return (Unsafe)field.get(null);
    }

    public static void main(String[] args) throws Exception{
        KnackMich k = new KnackMich();
        Unsafe u = getUnsafe();

        for(Field f : k.getClass().getDeclaredFields()){
            System.out.printf("%s=%s%n", f.getName(), u.getObject(k, u.objectFieldOffset(f)));
        }
    }
}
```

Gruß Tom


----------



## Thomas Darimont (7. November 2013)

Zum RandomPI


Spoiler



package de.tutorials.training;

import static java.lang.Math.*;

public class RandomPI {

    public static void main(String[] args) {
        int inQuarterCircle = 0;
        int iterations = 999999;

        for (int i = 0; i < iterations; i++) {
            inQuarterCircle += sqrt(pow(random(),2)+pow(random(),2)) <= 1 ? 1 : 0;
        }

        double myPI = inQuarterCircle*4.0/iterations;

        System.out.println(Math.PI);
        System.out.println(myPI);
        System.out.println("difference = " + (Math.PI - myPI));
    }
}



Sample output:

```
3.141592653589793
3.142155142155142
difference = -5.624885653490175E-4
```


----------



## slowfly (7. November 2013)

Jo, Thomas stimmt, aber etwas unleserlich, der Einzeiler *duck-zisch-und-weg* 

Hier wird das Prinzip erklärt (für jene, bei welchen der letzte Mathematikunterricht doch schon eine Weile her ist, so wie bei mir )
http://www.mathcs.emory.edu/~cheung/Courses/170/Syllabus/07/compute-pi.html

Gruss,
slowy


----------



## Bratkartoffel (7. November 2013)

Hier meine Lösung zu der Pi-Berechnung:


```
package de.tutorials.bratkartoffel;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.concurrent.ThreadLocalRandom;

public class MonteCarloPi {
	public static final int THREADS = 6;

	static class MonteCarloPiWorker extends Thread {
		private int hits = 0;
		private final int rounds;

		public MonteCarloPiWorker(ThreadGroup group, int rounds) {
			super(group, "MonteCarloPiWorker");
			this.rounds = rounds;
		}

		@Override
		public void run() {
			int hits = 0, rounds = this.rounds;
			double x, y;
			ThreadLocalRandom rnd = ThreadLocalRandom.current();

			for (long i = 0; i < rounds; i++) {
				x = rnd.nextDouble();
				y = rnd.nextDouble();

				if (Math.sqrt((x * x) + (y * y)) < 1.0) {
					hits++;
				}
			}

			this.hits = hits;
		}

		public int getHits() {
			return hits;
		}
	}

	private final int iRounds;

	public MonteCarloPi(int rounds) {
		iRounds = rounds - (rounds % THREADS);
	}

	public void doWork() throws InterruptedException {
		int hits = 0;
		if (Integer.valueOf(1).equals(THREADS)) {
			System.out.println("Not threading.");
			MonteCarloPiWorker worker = new MonteCarloPiWorker(null, iRounds);
			worker.run();
			hits = worker.getHits();
		} else {
			System.out.println("Using " + THREADS + " threads.");
			ThreadGroup group = new ThreadGroup("MonteCarloPi");
			for (int i = 0; i < THREADS; i++) {
				new MonteCarloPiWorker(group, iRounds / THREADS).start();
			}

			MonteCarloPiWorker[] threadArray = new MonteCarloPiWorker[THREADS];
			group.enumerate(threadArray);

			synchronized (group) {
				group.wait();
			}

			for (MonteCarloPiWorker thread : threadArray) {
				hits += thread.getHits();
			}
		}

		BigDecimal result = null;
		{
			BigDecimal dQuarter = new BigDecimal(4.0);
			BigDecimal dHits = new BigDecimal(hits);
			BigDecimal dRounds = new BigDecimal(iRounds);

			BigDecimal dParts = dHits.divide(dRounds, MathContext.DECIMAL64);
			result = dQuarter.multiply(dParts);
		}

		System.out.println("Rounds:  " + iRounds);
		System.out.println("Math.PI: " + Math.PI);
		System.out.println("Calc.PI: " + result);
		System.out.println("difference = " + (Math.PI - result.doubleValue()));
		System.out.println();
	}

	public static void main(String[] args) throws InterruptedException {
		long start = System.currentTimeMillis();
		new MonteCarloPi(100000000).doWork();
		long end = System.currentTimeMillis();

		System.out.println("Dauer: " + (end - start) + " ms.");
	}
}
```

Ausgabe:

```
Using 6 threads.
Rounds:  100000002
Math.PI: 3.141592653589793
Calc.PI: 3.1416844971663100
difference = -9.184357651692565E-5

Dauer: 340 ms.

Using 6 threads.
Rounds:  100000002
Math.PI: 3.141592653589793
Calc.PI: 3.1416984171660316
difference = -1.0576357623870436E-4

Dauer: 339 ms.

Using 6 threads.
Rounds:  100000002
Math.PI: 3.141592653589793
Calc.PI: 3.1415952571680948
difference = -2.60357830184077E-6

Dauer: 277 ms.
```

Ich weiß, etwas overkill und übers Ziel hinausgeschossen, aber was solls 

Grüße,
BK


----------



## Thomas Darimont (7. November 2013)

Hallo,

schick 
... zum Thema Einzeiler ;-)

```
package de.tutorials.training.java8.lambda;
 
import java.util.stream.IntStream;
 
import static java.lang.Math.*;
import static java.util.concurrent.ThreadLocalRandom.*;
 
/**
 * Author: Thomas Darimont
 */
public class LambdaPi {
 
    public static void main(String[] args) {
        int n = 9999999;
        double pi = IntStream.range(0, n)
                             .mapToDouble((a) -> 4.0 * 1.0 / n * (sqrt(pow(current().nextDouble(),2)+pow(current().nextDouble(),2)) <= 1 ? 1 : 0))
                             .sum();
        System.out.printf("%s delta-abs: %s",pi, PI-pi);
    }
}
```


Gruß Tom


----------



## Bratkartoffel (7. November 2013)

Hi Thomas,

schick, Java 8 wird interessant 

Grüße,
BK


----------



## Thomas Darimont (7. November 2013)

Hallo,

auf jeden Fall 

Ich hab noch ein paar Varianten in nem github gist zusammengetragen:
https://gist.github.com/thomasdarimont/7351740

Gruß Tom


----------



## Bratkartoffel (8. November 2013)

So, ich hab auch noch ein kleines Rätsel:

Gegeben sind folgende Interfaces:

```
interface A {
  int getA();
}

interface B {
  int getB();
}
```

Wie würde eine generische Methode aussehen, bei denen der Parameter sowohl A, als auch B implementieren muss?

Und noch gleich eins:
Was ist die Ausgabe von folgendem Programm?

```
class Test {
    public static void main(String[] args) {
        int big = 1234567890;
        float approx = big;
        System.out.println(big - (int)approx);
    }
}
```

Grüße,
BK


----------



## Thomas Darimont (11. November 2013)

Hallo,

hier das Beispiel für eine generische Methoden Deklaration, welche einen zu zwei Typen A(,B) kompatiblen Argumenttyp verlangt:

```
package de.tutorials.training;

public class MultipleInheritanceGenericsExample {

    interface A {
        int getA();
    }

    interface B {
        int getB();
    }

    static class C implements A, B{

        @Override
        public int getA() {
            return 42;
        }

        @Override
        public int getB() {
            return 43;
        }
    }

    public static void main(String[] args) {
        op(new C());
    }

    public static <Arg extends A & B> void op(Arg arg){
        System.out.println("A: " + arg.getA());
        System.out.println("B: " + arg.getB());
    }
}
```

Gruß Tom


----------



## Thomas Darimont (11. November 2013)

Hallo,

was soll uns dein zweites Rätsel sagen, außer dass bei int und float wahrscheinlich wg. Ungenauigkeiten eine Differenz != 0 raus kommt.

Das von Hand nachzuvollziehen finde ich aber ziemlich mühsam... ;-)

Anyway hier noch ein "hands-on" Rätsel für euch:

```
package de.thomasdarimont.labs;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SerializableLockExample {

    static class BusinessObject implements Serializable{

        Object lock = new Object();

        public void buisinessMethod(){
            synchronized (lock){
                //...
            }
        }
    }

    public static void main(String[] args) throws Exception{
        new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(new BusinessObject());
    }
}
```

Wenn man obiges Programm ausführt bekommt man folgende Exception:

```
de.thomasdarimont.labs.SerializableLockExample
Exception in thread "main" java.io.NotSerializableException: java.lang.Object
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
	at de.thomasdarimont.labs.SerializableLockExample.main(SerializableLockExample.java:21)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
```

Wie bekommt man eine BusinessObject Instanz trotzdem serialisiert ohne Code in der main-Methode, der buisinessMethod-Methode oder den Typ des lock Feldes zu ändern? Was ist die minimale Codeänderung die das Problem löst? Das lock als transient zu deklarieren oder über serialPersistentFields auszuschließen gilt natürlich nicht ;-)

Gruß Tom


----------



## ComFreek (12. November 2013)

Ich gebe zu, eher ein wenig geraten zu haben und einen Volltreffer gelandet zu haben, als konzentriert nachgedacht zu haben, aber hier die Lösung:


Spoiler



Folgende Methode zu BusinessObject hinzufügen:

```
private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
}
```

Ideone-Link: http://ideone.com/xI8ZpQ


----------



## Thomas Darimont (13. November 2013)

Hallo ComFreek,

deine Lösung funktioniert, ist aber nicht das auf was ich mit dem Rätsel hinaus wollte... ;-)
... als Erweiterung der Regeln gilt: Es dürfen keine Methoden zu BusinessObject hinzugefügt und auch keine Klassen durch lokale Definitionen überlagert / geshadowed werden. 

Fällt dir unter den Bedingungen noch eine andere Lösung ein?

Gruß Tom


----------



## ComFreek (13. November 2013)

Thomas Darimont hat gesagt.:


> Fällt dir unter den Bedingungen noch eine andere Lösung ein?


Mir ist gerade eingefallen, eine lokale Klasse zu erstellen, die die anderen "shadowed". Aber das hast du ja leider auch verboten 

Die Lösung würde mich echt interessieren!


----------



## Thomas Darimont (13. November 2013)

Hallo,

die Lösung auf die ich hinaus wollte schaut so aus:

```
package de.thomasdarimont.labs;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
public class SerializableLockExample {
 
    static class BusinessObject implements Serializable{

        Object lock = new Object[0];
 
        public void buisinessMethod(){
            synchronized (lock){
                //...
            }
        }
    }
 
    public static void main(String[] args) throws Exception{
        new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(new BusinessObject());
    }
}
```

... d.h. aus

```
Object lock = new Object();
```
wird:

```
Object lock = new Object[0];
```

Object ist nicht serialisierbar, leere Object Arrays schon ;-)

Gruß Tom


----------



## ComFreek (13. November 2013)

Danke für die Lösung!

Kannst du mir erklären bzw. den Namen vom Feature nennen, dass du einfach Code in die Klassendeklaration schreiben darfst?
Object lock = ... steht ja nicht innerhalb einer Methode o.Ä. Wann wird dann der Code ausgeführt?
Ich kenne static-Blöcke, ist das das gleiche?


----------



## sheel (13. November 2013)

Ich lass mich gern über Sonderfälle/Unterschiede(?) etc. aufklären,
aber im Wesentlichen hätte es den selben Effekt,
die Zuweisung vom new-irgendwas im Konstruktor zu machen.
Nur an einen anderen Ort geschrieben.


----------



## Thomas Darimont (4. Februar 2014)

Hallo,

es wird mal wieder Zeit für ein neues Java Rätsel:

Gegeben sei folgendes Java Programm mit vielen unterschiedlichen Arten von Klassendefinitionen:

```
import java.io.Serializable;

class F{} //1

public class ClassNameConventionTests { //2

    class A{} //3
    static class B{} //4

    public ClassNameConventionTests(){
        class C{} //5

        new Serializable(){ //6
            class D{} //7

            void foo(){
                class E{} //8
            }

            void bar(){
                class E{} //9
            }
        };
    }
   
    static{
        class X{} //10
    }

    static{
        class X{} //11
    }
}
```

Frage: Welche .class-Filenames resultieren aus den jeweiligen Class-Definitions?

Gruß Tom


----------

