Wenn meine IDE so intelligent ist, warum muss ich dann "clone ()" umwandeln?

13

Mein IDE ( NetBeans ) -Typ überprüft meinen CollectionsCode, während ich ihn eingebe. Aber warum muss ich dann das zurückgegebene Objekt von werfen Object.clone()? Welches ist in Ordnung. Kein Schaden kein Foul. Aber ich verstehe es immer noch nicht.

Ist eine Typprüfung ohne Casting des zurückgegebenen Objekts Object.clone()nicht möglich? Das generische Framework lässt mich glauben, dass die IDE den Typ der Objektreferenzen auf der rechten Seite der Markierung " = " überprüfen könnte, ohne sie während des Tippens umzusetzen. Ich verstehe es nicht.

Nachtrag
Mein Anwendungsfall war nur, dass ich ein privates CalendarFeld hatte, pubdate . Ich wollte schreiben:

Calendar getPubdate() {
    return pubdate;
}

Es besteht jedoch die Gefahr, dass der Aufrufer mein Pubdate ändert , sodass ich eine Kopie zurücksende :

Calendar getPubdate() {
    return (Calendar) pubdate.clone();
}

Dann fragte ich mich, warum ich besetzen musste pubdate.clone(). Die Methodensignatur hat genau dort den Typ. NetBeans sollte dies herausfinden können. Und NetBeans schien etwas Ähnliches in Bezug auf zu tun Collections.

konishiki
quelle
5
Ein kurzes (!) Codebeispiel wäre hilfreich.
Doc Brown
78
Die IDE ist nicht mit der Sprache selbst identisch. Daher hat das Verhalten von Smart Netbeans keine Auswirkung auf die Funktionsweise von Java.
JacquesB
7
Hinweis aufgrund Typ Kovarianz zurückzukehren, ist es empfehlenswert , zurückzukehren MyObjectvon clone()nicht Object- dies entfernt das gesamte Problem. Es wird weiterhin empfohlen, niemals clone()Java (Effective Java Item # 11) zu verwenden.
Boris die Spinne
Liegt der Schwerpunkt Ihrer Frage auf I oder auf "cast" clone () " ? Weil die Frage, die sich aus der ersteren ergibt, tatsächlich eine viel bessere Frage sein könnte als die letztere.
Benutzer541686
Wenn ich den Fragentitel lese, denke ich nur this.clone()an einen Programmer-Gegenstand, besonders in der Nacht nach der Veröffentlichung von Di. Entschuldigung, aber ich muss diesen Kommentar schreiben. Warum kann Smart IDE nicht einfach alle Fehler für uns beheben? LOL
Mai

Antworten:

53

warum muss ich den zurückgegebenen gegenstand von werfen Object.clone()?

Weil es zurückkehrt Object.

Das generische Framework lässt mich glauben, dass die IDE den Typ der Objektreferenzen auf der rechten Seite der Markierung " = " überprüfen könnte, ohne sie während des Tippens umzusetzen. Ich verstehe es nicht.

Object.clone ist nicht generisch.

Wenn es Generika gegeben hätte, als sie cloneentworfen wurden, hätte sie wahrscheinlich so ausgesehen (unter Verwendung des F-Bounded Polymorphism):

interface Cloneable<T extends Cloneable<T>> {
  T clone();
}

Wenn Java eine MyType-Funktion hätte, würde sie möglicherweise so aussehen:

interface Cloneable {
  this clone();
}

Generics gab es jedoch nicht, als Object.clonees entworfen wurde, und Java hat keine MyTypes. Daher müssen wir mit der typunabhängigen Version von Object.clonearbeiten.

Jörg W. Mittag
quelle
Ich habe gerade festgestellt, dass die IDE-Funktion, die mich verwirrte, eine Hintergrundkompilierung war. Ich meine, das ermöglicht die Codevervollständigung und die automatische Typprüfung mit Generika? Persönlich würde ich es vorziehen, die Typprüfung bis zu einer expliziten Kompilierung zu verzögern. Aber ich liebe die Code-Vervollständigung.
Konishiki
1
@konishiki mit Java 8 (und in gewissem Maße Java 7) Typinferenz , um Unterstützung zu bieten, muss die IDE Typen ableiten. Dies erfordert eine teilweise Kompilierung. Vor der Typinferenz ist keine Kompilierung für die automatische Vervollständigung erforderlich.
Boris die Spinne
@ BoristheSpider Vielen Dank für das Feedback! Ich muss definitiv noch mehr testen / nachdenken. sehr geschätzt.
Konishiki
Warum müsstest du bestehen original?
Clashsoft
@Clashsoft: Dummes Denken beim Anpassen der offensichtlichen Functional Programming-Version. Vielen Dank.
Jörg W Mittag
26

Dies ist kein Merkmal einer IDE, sondern der Sprachdefinition.

Eine IDE hilft Ihnen dabei, eine Programmiersprache effizienter zu nutzen, und ändert die Semantik dieser Sprache nicht. Das bedeutet, dass ein Editor-Helfer möglicherweise automatisch eine Besetzung einfügt, wenn klar ist, welche Sie möchten, aber nicht einfach die Regeln der Sprache brechen und so tun kann, als wäre der Code, der nicht kompiliert wurde, gültig.

Bearbeiten Es ist richtig, dass eine IDE ihren eigenen Compiler bündeln kann, und tatsächlich tun viele genau das, z. B. für eine bessere Fehlerberichterstattung mit mehr Insiderinformationen in den partiellen Analysebaum. Es wäre jedoch eine sehr schlechte Idee, diesen internen Compiler eine andere Sprachsemantik als das offizielle SDK implementieren zu lassen, da dies bedeuten würde, dass Code, der in der Entwicklung arbeitet, bei der Installation in der Produktion auf mysteriöse Weise zu Fehlern führen kann. debuggbar!

Kilian Foth
quelle
Folgendes ist passiert: Ich bin mir ziemlich sicher, dass die Codevervollständigung eine IDE-Funktion ist (über Reflection). Und die automatische Typprüfung, über die ich gesprochen habe, findet in der IDE statt (über die Hintergrundkompilierung). Ich hoffe das ist was los ist.
Konishiki
1
Die IDE kann sehr leicht alle Regeln der Sprachspezifikation brechen und den Code trotzdem kompilieren. Ich weiß, dass sowohl NetBeans als auch Eclipse zum Beispiel ihre eigenen Compiler verwenden. In diesen Fällen sind IDE und Compiler praktisch dasselbe. Nicht, dass es eine gute Idee wäre, aber C-Compiler tun es auf jeden Fall die ganze Zeit.
MichaelS
@MichaelS Die C-Sprachspezifikation ermöglicht erhebliche Unterschiede zwischen den Implementierungen, sodass verschiedene Anbieter zwischen verschiedenen möglichen Ansätzen wählen und zusätzliche Funktionen hinzufügen können. Dies schafft verschiedene Bereiche der Mehrdeutigkeit in der Spezifikation, die notwendig sind, um diese Variationen zuzulassen. Der Name "C" ist kein Warenzeichen, daher kontrolliert niemand die Verwendung des Begriffs. Die Java-Spezifikation wurde so konzipiert, dass möglichst viele Unklarheiten beseitigt werden. Java ist eine Marke, und der Markeninhaber macht geltend, dass es nur in kompatiblen Implementierungen verwendet werden kann.
Jules
Moderne IDEs brauchen sowieso einen Compiler. Code-Vervollständigungshinweise erfordern, dass der Code vor dem Cursor analysiert wird. Und sicherlich bei Generika (oder C ++ - Vorlagen), für die ein vollständiger Compiler erforderlich ist, nicht nur ein Parser.
MSalters
3

Dies liegt an der Typensignatur der Object.clone-Methode. Die Typensignatur gibt an, dass die Methode ein Objekt vom Typ Object zurückgibt.

protected Object clone() throws CloneNotSupportedException

Die Sammlungen verwenden sogenannte generische Typen, um die Art des Castings automatisch zu ersetzen.

Also, wenn Sie diesen Code haben:

List<Integer> ints = Arrays.asList(1,2,3);
int x = ints.get(0);`

Der Compiler fügt die Casts für Sie hinter den Kulissen hinzu. Der Code wäre also tatsächlich:

List ints = Arrays.asList(1,2,3);
int x = (Integer)ints.get(0);
Miro
quelle
0

Der Vollständigkeit halber sind seit Java 5 kovariante Rückgabetypen zulässig . Sie können also Folgendes schreiben:

public MyObject implements Cloneable {
  @Override
  public MyObject clone() {
    try {
      return (MyObject)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new AssertionError();
    }
  }
}

Damit ist der folgende Code legal:

MyObject original = new MyObject();
MyObject clone = original.clone();
Olivier Grégoire
quelle