Java Quiz


#221

Korrekt. Die Interfaces fordern beide, dass equals von Listen/Sets dann true zurückliefern soll, wenn das andere auch eine Liste/Set ist und sie die gleichen Elemente (ggf. sogar in gleicher Reihenfolge) enthalten. Da man die Methoden bei enums nicht überschreiben kann, kann diese Forderung nicht erfüllt werden. Mir ist das übrigens nur mit sehr großer Verzögerung, also überhaupt nicht so spontan, aufgefallen :frowning:

Hier leider nicht richtig. Schau Dir mal die Javadocs von Set.equals und List.equals an. Und die diversen Implementierungen des JDK überschreiben sie doch. Die richtige Stelle ist nur etwas schwierig zu finden bei dem ganzen Vererbe mit AbstracList/Set/Collection und der Art und Weise, wie -recht intelligent- eigene Methoden aufgerufen werden.


#222

Tatsächlich… Ich hatte die geerbten Methoden ausgeblendet, aber natürlich nicht dran gedacht, dass die Listen ja nicht direkt List implementieren, sondern AbstractList und AbstractCollection erweitern :o


#223

[QUOTE=Marco13]Jupp, … so viele Möglichkeiten gäb’s dann ja auch nicht mehr.

Oder?

Was müßte dort stehen, um false zu erhalten, wenn man weder 0.0/-0.0 NOCH Double.NaN hinschreiben dürfte?
[/QUOTE]

Kommt da noch was oder ist das nur so in die Runde gefragt? Die Doku zu Double#equals() liefert nur diese beiden Ausnahmen. Oder meinst Du eine andere Schreibweise für Double.NaN? Das wäre dann 0/0 (so ist die Konstante auch definiert).


#224

Naja… im Endeffekt könnte man sagen: NaN ist NaN. Jede weitere Erklärung (a la “eine andere Bitfolge als die von NaN”) wäre schon praktisch die Antwort: Ich hatte da was mit Double#longBitsToDouble im Sinn…


#225
public class MyThrowable extends Throwable {}

public class MyThrowableTest {

    public static void main(String[] args) {
        try {
            doSomething();
        } catch (MyThrowable my) {
            System.out.println("hallo!");
        }
    }

    private static void doSomething() {
        throw new MyThrowable();
    }
}

Gibt obiger Code einen Compilerfehler, einen Laufzeitfehler oder läuft das Programm problemlos durch? Bitte ohne Mogeln und mit Begründung…


#226

Ich würde sagen: Es läuft problemlos durch. Das Throwable erbt nicht von Exception, und muss deswegen nicht declared werden, wird dann aber geworfen und gefangen. Aber sicher bin ich mir nicht, deswegen “mogele” ich jetzt, aber schreibe das Ergebnis NICHT hier hin :smiley:


#227

Wenn in der API nachschauen erlaubt ist, dann sage ich folgendes:

[SPOILER]
Es gibt einen Fehler beim Compilieren.
Die Api von Throwable sagt, dass Throwable und alle abgeleiteten Klassen, sofern sie nicht von Error oder RuntimeException abgeleitet sind als Checked Exceptions anzusehen sind.

Checked Exceptions müssen innerhalb einer Methode gefangen werden oder in der Methodensignatur deklariert werden. Dies ist hier offensichtlich nicht der Fall, da doSomething nicht auf die Exception hinweist.
[/SPOILER]


#228

Unser Gast hat recht.


#229

Ist an diesem Code etwas falsch, ja/nein

wenn ja, was? Was passiert und warum?

package test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

	
public class Test {
public static void main(String[] args) {
	SwingUtilities.invokeLater(new Runnable(){

		public void run(){
        		JFrame f = new JFrame();
        		f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        		f.setSize(new Dimension(300,300));
        		f.addWindowListener(new WindowAdapter() {
				@Override
				public void windowClosing(WindowEvent e) {
					JFrame f = (JFrame)e.getSource();
					f.setVisible(false);
				}

				@Override
				public void windowClosed(WindowEvent e) {
					JFrame f = (JFrame)e.getSource();
					f.dispose();
				}
			});
			f.setVisible(true);
		}
	});
}
}

#230

[SPOILER]Man macht das Fenster zu, dadurch wird die erste Listener-Methode aufgerufen und das Fenster auf nicht visible gesetzt. Auf den Closing-Listener hat visible vermutlich keinen Einfluss.
Anschließend wird die closed-Methode aufgerufen, in der das Fenster disposed wird, vermutlich gibt das dann eine Endlosschleife mit dem Listener. Ich bin mir aber nicht sicher, ob dispose closing und closed aufruft oder nur closed.[/SPOILER]


#231

Firephoenix’ antwort ist richtig
[spoiler]ja durch das dispose wird wird die windowClosed methode wieder aufgerufen. Bei mir hatte ich das leider übersehen und dachte schon ich haette ein Probelem mit meinem PC. Also der einzige Ort an einem WindowListener die dispose methode aufzurufen ist die windowClosing [/spoiler]


#232

Inspiriert von einer anderen Frage:

public class MethodInvocation 
{
    static void methodA(Number x, int ... y) { System.out.println("A Number"); } 
    static void methodA(byte x, int ... y)   { System.out.println("A byte  "); } 

    static void methodB(Number x, int y)     { System.out.println("B Number"); }
    static void methodB(byte x, int y)       { System.out.println("B byte  "); }
    
    public static void main(String[] args) 
    {
        Byte x = 12;
        methodA(x, 34);
        methodB(x, 34);
    }
}

Was passiert (ohne Ausprobieren, natürlich ;)) ?

[ol]
[li]Ausgabe “A Number”, “B Number”[/li][li]Ausgabe “A Number”, “B byte”[/li][li]Ausgabe “A byte”, “B Number”[/li][li]Ausgabe “A byte”, “B byte”[/li][li]Compilerfehler beim Aufruf von methodA (aber nicht bei methodB)[/li][li]Compilerfehler beim Aufruf von methodB (aber nicht bei methodA)[/li][li]Compilerfehler beim Aufruf von methodA und methodB[/li][/ol]

Auch gerne geraten (Vermutungen, oder Fälle, die man ausschließt) :smiley:


#233

wenn ich mal wild raten dürfte, würde ich sagen 1., weil wenn er nach der reihenfolge die
möglichen methoden durchlaufen würde, würde ja methodA nr 1 und methodB nr 2 “passen”…
aber ich probiers gleich mal aus ^^


#234

Nun, die Reihenfolge mit der die Methoden deklariert sind, spielt keine Rolle, falls du das meintest. Aber zugegeben, die Frage ist ziemlich fies, weil die Antwort tief in meinem Lieblingskapitel 15.12 der JLS versteckt ist … und sich das Verhalten dort zwischen Java 1.7 und Java 1.8 geändert hat (weswegen ich eigentlich noch dazusagen müßte, dass sich die Frage auf Java <= 1.7 bezieht).


#235

die Sysouts “B Number”, “B Byte” werden nicht ausgeführt, da sich diese nur in Geschwungenen Klammern befinden, aber nicht in einem Methodenrumpf. Dieser ist nämlich für die beiden Fälle von methodB(…) leer.

Kann aber auch ein schlichter Vertipper sein.


#236

In der Tat, ein Copy&Paste-Fehler - korrigiert.


#237

Würde auf 1 Tippen da ich denke, dass Vererbung mehr wiegt als die Möglichkeit zum Autounboxing (sozusagen Autounboxing als letzter Ausweg), bin mir aber sehr unsicher.


#238

Ich hätte ohne es auszuprobieren auch auf 1 getippt. Allerdings konnte ich kein unterschiedliches Verhalten zwischen einem jdk 7 und einem jdk 8 feststellen.


#239

naja, so ungefähr meinte ich das :smiley:
Reihenfolge wohl der falsche Begriff ^^


#240

Ehrlich gesagt hatte ich nicht selbst ausprobiert, ob sich das Verhalten in diesem Fall “spürbar” ändert (hab’ hier gerade kein JDK8), aber es gab einen Grund zu der Annahme. Zumindest die Spezifikation hat sich geändert, dewswegen sollte der Hinweis auf JDK <=7 sicherstellen, dass nicht jemand sich auf etwas falsches bezieht.

Wie auch immer: Die Lösung ist

5. Compilerfehler beim Aufruf von methodA (aber nicht bei methodB)

Der Grund dafür liegt darin, wie Java die “passende” Methode für einen bestimmten Aufruf mit bestimmten Parametern herausfindet. Das läuft grob in mehreren Phasen ab:

Phase 1: Identify Matching Arity Methods Applicable by Subtyping
Phase 2: Identify Matching Arity Methods Applicable by Method Invocation Conversion
Phase 3: Identify Applicable Variable Arity Methods

In Phase 1 wird geschaut, ob es eine Methode gibt, die so viele formale Parameter hat, wie beim Aufruf Argumente angegeben wurden, und die Typen der Argumente zu den Parametern passen, wenn man davon ausgeht dass man auch Subtypen übergeben kann. Wenn man eine Methode hat, die eine Number erwartet, und man die so eine Methode mit einem Byte aufruft, dann passt das.

In Phase 2 wird geschaut, ob es eine Methode gibt, die so viele formale Parameter hat, wie beim Aufruf Argumente angegeben wurden, und die Typen der Argumente zu den Parametern passen, wenn man davon ausgeht dass, dass es weitere Konvertierungen geben kann. Wenn man eine Methode hat, die einen int erwartet, und man die so eine Methode mit einem Integer aufruft, dann passt das, weil dafür eine Unboxing-Conversion von Integer nach int durchgeführt werden kann.

Diese beiden Phasen spielen für die methodA aber keine Rolle: Dort wird direkt bei Phase 3 gestartet, weil es eine “varargs”-Methode ist. Dann wird allerdings nicht mehr zwischen den Methoden unterschieden, die “per Subtyping” passen, und denen, die “per Method Invocation Conversion” passen, sondern nur letzteres. Das heißt, dort gibt es auf einen Schlag zwei passende Methoden - und da es dort keine “spezifischere” gibt, wird der Aufruf uneindeutig.