2013-03-01 4 views
8

Ich bespreche die Sun-Zertifizierung Studienführer und es gibt eine Passage, die den endgültigen Modifikator beschreibt. Es sagtJava-Vererbung, wie wirkt sich eine Erweiterung einer Klasse auf die tatsächliche Klasse aus?

„Wenn Programmierer die String-Klasse Zivilisation zu erweitern frei waren, wie wir sie kennen kollabieren könnte“

Was bedeutet er? Wenn es möglich wäre, String Class zu erweitern ... würde ich einfach nicht eine Klasse namens MyString haben, die alle Strings Eigenschaften erbt. Wie wäre es möglich, die tatsächliche String-Klasse in irgendeiner Weise zu ändern, indem Sie sie nur erweitern?

Vielen Dank für Ihre Antworten

+2

klingt ein wenig hyperbolisch – mre

+0

@mre ja, aber ziemlich awesomely so gegeben, es ist in der Zertifizierungsprüfung! – sharakan

+2

@drlobo Ich denke, Sie sollten den Titel dieser Frage wie folgt ändern: "Warum denkt die Sun-Zertifizierung, dass die Erweiterung der String-Klasse dazu führen wird, dass die Zivilisation zusammenbricht?" – sharakan

Antwort

4

eine Klasse Erweiterung der Basisklasse nicht beeinflusst. Es kann sich jedoch auf die Consumer der Basisklasse auswirken.

So lassen Sie uns sagen, dass Sie konnten String verlängern, könnten Sie so etwas wie das schreiben folgendes:

class MyString extends String { 

    @Override 
    public int length() { 
     System.exit(); 
    } 
} 

Jetzt übergeben Sie diese Klasse alles, was eine Zeichenfolge verwendet, und die Chancen sind, dass Sie würde das Programm schnell beenden. Nicht das Ende der Zivilisation, aber es gibt etwas unheimlichere Dinge, die Sie tun könnten.

6

Nun, ein Problem ist, dass Sie wahrscheinlich die Sicherheit des jvm in einer Vielzahl von Möglichkeiten untergraben können, wenn Sie die String-Klasse unterklassifizieren können. Viele der Berechtigungen überprüfen verschiedene String-Werte, um festzustellen, ob eine bestimmte Aktion zulässig ist. Wenn Ihr Code die Zeichenfolgenwerte bereitstellt, können Sie eine String-Instanz zurückgeben, die "auscheckt", wenn der Sicherheitsmanager sie betrachtet, aber später wie ein ganz anderer Wert wirkt.

Beispiel, sagen Sie einige sensible Jvm weite Konfiguration haben:

public static void registerProvider(String providerName, Provider impl) { 
    SecurityManager sm = ...; 
    if(sm != null) { 
    // say the check provider method doesn't allow strings starting with "com.sun." 
    sm.checkProvider(providerName); 
    } 
    _providerMap.put(providerName, impl); 
} 

Nun, ich einen benutzerdefinierten String implementieren, die die startsWith() Methode überschreibt false zurück, wenn der Wert "com.sun." vergangen, aber der tatsächliche Wert meiner String tut starten mit com.sun..

Ganz zu schweigen von der allgemeinen Erwartung von Strings, die unveränderlich sind und die, wenn sie kaputt gehen, alle Arten von allgemeiner Verwüstung verursachen könnten (wie in anderen Antworten ausführlicher erwähnt).

+0

Würdest du das 'ChuckNorrisString' nennen? :-) – kdgregory

+0

Obwohl, wie ich darüber nachdenke, "ChuckNorrisString" würde 'hashCode()' überschreiben: Sie legen es in eine Karte, und wenn Sie später zurückgehen, um danach zu suchen, ist es nicht da. – kdgregory

+0

@ kdgregory - ein ChuckNorrisString wäre nicht sehr nützlich, weil er niemals gleich sein würde. und das Sortieren wäre schwierig, weil es immer größer als alles andere wäre. – jtahlborn

2

Bedenken Sie, dass in der gesamten Java API, Sie Konstrukte wie sehen:

HashMap<String, Object> map; 

die Strings verwenden für die Indizierung. Eine sehr übliche Sache, z.B. für Immobilien und - und das ist wahrscheinlich am schlechtesten in sicherheitsrelevanten Orten. Dieser Code basiert auf einem unveränderten String, um sicher zu bleiben.

Aber lassen Sie jetzt Ihre modifizierte String Klasse ermöglichen z. Umkehren von Saiten an Ort und Stelle.

Dann würde die Welt, wie wir wissen, zusammenbrechen, weil überall Karten zu einem verrückten Durcheinander werden würden. Protokollierung würde zusammenbrechen usw.

Viele Code auf der String Klasse verlässt sich auf sein unveränderlich, und gut, wenn es wirklich unveränderlich ist, welche Funktionalität will man trotzdem, um es hinzuzufügen auf?

+0

Das Ändern des Verhaltens darf eine Integritätsbedingung nicht ungültig machen. Stellen Sie sich eine Klasse "ReversedString" mit einem praktischen Konstruktor vor. –

+0

@jeppi könnte man dies mit einer statischen Methode trivial machen, ohne überhaupt eine neue Klasse zu benötigen. –

+0

In einigen Szenarien bevorzugen Sie Konstruktoren gegenüber statischen Fabrikmethoden. Vielleicht ist ReversedString nicht das realistischste Beispiel dafür. Es war nur da, um über unveränderliche Objekte zu sprechen ... –

1

Das Erweitern einer Klasse wirkt sich nicht auf die Klasse aus. Da es sich bei jeder geerbten Klasse jedoch auch um eine Basisklasse handelt, sollte sie sich an die Verhaltensregeln der Basisklasse halten. Wenn Programmierer gängige Framework-Typen ändern sollten, konnte man sich nicht darauf verlassen, dass diese Klassen wie erwartet funktionieren. Sie wollen also verhindern, dass solche Klassen missbraucht werden - das geschieht über die endgültige Schlüsselwort

0

Die Übertreibung der Katastrophe ist wahrscheinlich eine Anspielung auf Sicherheitsaspekte der (Un) Veränderlichkeit von String. Eine Zeichenfolge wird oft als Parameter an verschiedene E/A-Ressourcenverbindungs-APIs (z. B. JDBC und Datei-E/A) übergeben. Solch eine Zeichenfolge, wenn oft entweder eine Verkettung von Ressourcen-Locators und Authentifizierungs-Credentials und diese API eine Überprüfung durchführen, um sicherzustellen, dass die Credentials für die angeforderte Ressource gültig sind, bevor die Verbindung zurückgegeben wird. Wenn String änderbar wäre, würde es Gateway für alle Arten von Sicherheitsverletzungen öffnen als Ressourcenzeiger/Adresse (wie zum Beispiel ein Datenbankname für DB-Verbindung oder Dateiname mit sensiblen Informationen für einen Benutzer) könnte nach dem geändert werden Die Authentifizierung war erfolgreich, aber bevor die Ressourcenverbindung für die ursprünglich angeforderte Ressource hergestellt wurde, führte dies zu unbefugtem Zugriff und untergräbt die Zugriffssteuerung.

Ein weiterer Grund dafür, String unveränderlich zu machen, ist, es threadsicher zu machen.

0

Eigentlich ist das Problem nichts, nur mit der Erweiterung String oder einer anderen Klasse zu tun.

Das Problem ist eigentlich mit Java selbst. Das Problem ist, dass Sie den Vertrag, den ein bestimmtes Objekt implementiert, in seinem Code nicht wirklich definieren können. Es ist im Code für String nicht wirklich angegeben, dass es unveränderlich ist, weil die Unveränderlichkeit nicht spezifiziert werden kann, es kann nur codiert werden. Dieser Vertrag ergibt sich nur aus der tatsächlichen Umsetzung von String.

Wenn es möglich war, in der Java-Sprache dass String und Number und Integer usw. sind unveränderlich zu erklären, dann würden wir diese Klassen final nicht machen müssen. Meiner Meinung nach ist dies eine schwächende Krankheit von Java, dass Sie den Vertrag nicht im Code definieren können. Sie können es nur codieren und dokumentieren.

Ich würde gerne in der Lage sein Zeichenfolge zu erweitern und definieren, vielleicht ein UppercaseString extends String aber es ist keine contract(immutable,interned) Schlüsselwort in Java, so kann ich nicht so tun, weil am nächsten zu diesem Vertrag zu bekommen, das einzige Schlüsselwort vorhanden ist final statt immutable wie es sein sollte.

Verwandte Themen