Effektive Java 3rd Edition Kapitel 4 Klassen und Schnittstellen
[Effektive Java 3rd Edition](https://www.amazon.co.jp/Effective-Java-%E7%AC%AC3%E7%89%88-%E3%] 82% B8% E3% 83% A7% E3% 82% B7% E3% 83% A5% E3% 82% A2% E3% 83% BB% E3% 83% 96% E3% 83% AD% E3% 83% 83% E3% 82% AF-ebook / dp / B07RHX1K53) hat eine Kindle-Version, daher werde ich sie zusammenfassen.
Zurück: Effektive Java 3rd Edition, Kapitel 3, allen Objekten gemeinsame Methoden
Weiter: Effektive Java 3rd Edition Kapitel 5 Generika
Punkt 15 Minimieren Sie die Zugänglichkeit für Klassen und Mitglieder
- Jede Klasse oder jedes Mitglied sollte so unzugänglich wie möglich sein.
Klassen und Schnittstellen der obersten Ebene
- Es gibt öffentliche und private Pakete, und es sollte so weit wie möglich paketprivat sein. Weil es keine öffentliche API mehr für Pakete ist.
- Wenn eine private Klasse oder Schnittstelle eines Pakets der obersten Ebene nur von einer Klasse verwendet wird, sollten Sie sie zu einer privaten verschachtelten Klasse innerhalb dieser Klasse machen.
Mitglieder (Felder, Methoden, verschachtelte Klassen, verschachtelte Schnittstellen)
- Alles sollte zuerst privat und das Paket nur privat sein, wenn Sie auf andere Klassen im selben Paket zugreifen müssen.
- In Bezug auf Mitglieder der öffentlichen Klasse wird die Zugänglichkeit erheblich verbessert, wenn das Paket von privat zu geschützt geändert wird.
- Der Bedarf an geschützten Mitgliedern sollte relativ selten sein.
--Wenn eine Methode einer Superklasse überschrieben wird, darf die Zugriffsebene der Methode in der Superklasse in der Unterklasse (Java-Spezifikation) nicht eingegrenzt werden.
- Bis zu einem gewissen Grad kann das Lösen von Zugriffsbeschränkungen für Klassen, Schnittstellen und Mitglieder das Testen erleichtern. Von privat bis privat verpackend. Es wird nicht mehr akzeptiert.
- Das Instanzfeld sollte nicht öffentlich sein. Wenn es sich um eine nicht endgültige, variable Objektreferenz handelt, wird die Begrenzung der Werte, die in diesem Feld gespeichert werden können, aufgegeben. Daher sind Klassen mit öffentlichen Variablenfeldern im Allgemeinen nicht threadsicher.
--Verwenden Sie public static final, um Konstanten verfügbar zu machen. Es ist üblich, großgeschriebene, durch Unterstriche getrennte Namen zu verwenden. Es ist unbedingt erforderlich, entweder einen Basisdatentyp oder einen Verweis auf ein unveränderliches Objekt zu haben. Weil sich der Wert ändert. Beachten Sie, dass Arrays ungleich Null immer variabel sind.
//Mögliche Sicherheitslücke (der Inhalt des Arrays kann geändert werden)
public static final Thing[] VALUES = { ... };
//Lösung 1. Gibt eine öffentliche unveränderliche Liste zurück
private static final Thing[] PRIVATE_VALUES = { ... };
public static final List<Thing> VALUES =
Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
//Lösung 2. Gibt eine Kopie des Arrays in der öffentlichen Methode zurück
private static final Thing[] PRIVATE_VALUES = { ... };
public static final Thing[] values() {
return PRIVATE_VALUES.clone();
}
Punkt 16 Verwenden Sie in der öffentlichen Klasse die Zugriffsmethode anstelle des öffentlichen Felds.
- Öffentliche Klassen sollten keine variablen Felder verfügbar machen. Es sollte ein privates Feld und eine öffentliche Zugriffsmethode (Getter) sowie einen Mutator (Setter) für Variablenklassen haben.
- Für paketprivate oder privat verschachtelte Klassen ist es im Wesentlichen in Ordnung, ihre Datenfelder direkt verfügbar zu machen.
Punkt 17 Variabilität minimieren
- Das unveränderliche Objekt ist einfach. Im Wesentlichen threadsicher.
- Für unveränderliche Klassen ist es nicht erforderlich, eine Klonmethode oder einen Kopierkonstruktor anzugeben, und dies sollte nicht angegeben werden.
- Um eine Klasse unveränderlich zu machen, befolgen Sie die folgenden fünf Prinzipien.
- Bietet keine Methode zum Ändern des Status eines Objekts.
- Klassen nicht erweitern.
- Machen Sie alle Falten endgültig.
- Machen Sie alle Falten privat.
- Gewährleisten Sie den exklusiven Zugriff auf variable Komponenten.
- Der praktische Nachteil unveränderlicher Objekte besteht darin, dass sie separate Objekte für unterschiedliche Einzelwerte benötigen.
--Klassen sollten unveränderlich sein, es sei denn, es gibt einen guten Grund, sie variabel zu machen.
- Wenn Sie eine Klasse nicht unveränderlich machen können, sollten Sie ihre Variabilität so weit wie möglich einschränken.
Punkt 18 Wählen Sie die Komposition aus der Vererbung aus
- Vererbung führt bei unsachgemäßer Verwendung zu spröder Software. Durch Vererbung wird die Kapselung unterbrochen. Das ordnungsgemäße Funktionieren von Unterklassen hängt von der Implementierung von Oberklassen ab.
- Geben Sie der neuen Klasse anstelle der Erweiterung einer vorhandenen Klasse ein privates Feld, das auf eine Instanz der vorhandenen Klasse verweist. Dieser Entwurf wird Zusammensetzung genannt.
- Jede Instanzmethode der neuen Klasse ruft die Methode auf, die der vorhandenen Klasseninstanz entspricht, die sie enthält, und gibt das Ergebnis zurück. Dies wird als Übertragung bezeichnet, und die neue Methodenklasse wird als Übertragungsmethode bezeichnet.
- Die Kombination aus Zusammensetzung und Übertragung wird manchmal lose als Delegation bezeichnet. Technisch gesehen handelt es sich nicht um eine Delegierung, es sei denn, das Wrapper-Objekt übergibt sich selbst an das umschlossene Objekt.
Punkt 19 Entwurf und Dokument für die Vererbung, andernfalls die Vererbung verbieten
--Das Entwerfen einer Klasse für die Vererbung führt zu erheblichen Einschränkungen für diese Klasse. Jeder Eigenverbrauch der Klasse muss dokumentiert werden, und sobald er dokumentiert ist, muss er befolgt werden, solange die Klasse existiert.
--Verwenden Sie das Javadoc-Tag von "@ implSpec", um die Vererbung zu dokumentieren.
- Die beste Lösung besteht darin, Unterklassen von Klassen zu verbieten, die weder für eine sichere Unterklasse ausgelegt noch dokumentiert sind. Es gibt zwei Möglichkeiten, Unterklassen zu verbieten.
- Erklären Sie das Klassenfinale.
- Machen Sie den Klassenkonstruktor privat oder das Paket privat und fügen Sie als Alternative zum Konstruktor eine öffentliche statische Factory-Methode hinzu.
Punkt 20 Wählen Sie eine Schnittstelle über einer abstrakten Klasse aus
--Wenn eine Methode mit einer Schnittstelle offensichtlich implementiert ist, sollten Sie Implementierungsunterstützung im Standardmethodenformat bereitstellen. Das Bereitstellen von Standardmethoden für Objektmethoden wie equals und hashCode ist nicht zulässig.
- Die Schnittstelle darf keine Instanzfelder oder nicht öffentlichen statischen Elemente enthalten (außer privaten statischen Methoden).
- Indem Sie die Implementierungsklasse für das abstrakte Skelett bereitstellen, die der Schnittstelle beiliegt, können Sie die Vorteile der Schnittstelle und der abstrakten Klasse kombinieren. Die Skeleton-Implementierung basiert auf den grundlegenden Methoden der Schnittstelle und implementiert die verbleibenden nicht grundlegenden Methoden der Schnittstelle. Durch die Erweiterung der Skeleton-Implementierung wird der größte Teil der Schnittstellenimplementierung durchgeführt. (* Vorlagenmethode * Muster)
- Gemäß der Konvention heißt die Skeleton-Implementierungsklasse Abstract * Interface *.
- Zum Beispiel bietet das Sammlungsframework Skelettimplementierungen, die jeder wichtigen Sammlungsschnittstelle beiliegen, wie z. B. AbstractCollection, AbstractSet, AbstractList und AbstractMap.
- Das Tolle an der Skeleton-Implementierung ist, dass sie Implementierungsunterstützung bietet, bei der es sich um eine abstrakte Klasse handelt, ohne die Rolle der abstrakten Klasse als Typdefinition ernsthaft einzuschränken.
- Eine Klasse, die eine Schnittstelle implementiert, kann eine Instanz einer privaten inneren Klasse enthalten, die die Skelettimplementierung erweitert und Schnittstellenaufrufe an diese Instanz überträgt. Diese Technik wird als Pseudo-Multiple-Vererbung bezeichnet.
Punkt 21 Entwerfen Sie die Schnittstelle für die Zukunft
- Wenn Sie vor Java8 einer Schnittstelle eine neue Methode hinzufügen, verfügt die vorhandene Implementierung noch nicht über diese Methode, und es wird ein Kompilierungsfehler angezeigt. Java 8 hat die Standardmethodensyntax hinzugefügt, das Hinzufügen von Methoden zu vorhandenen Schnittstellen ist jedoch riskant.
- Die Standardmethode kann die Schnittstellenimplementierung möglicherweise ohne Fehler oder Warnungen kompilieren, schlägt jedoch möglicherweise zur Laufzeit fehl.
- Auch wenn die Standardmethoden Teil der Java-Plattform sind, bleibt ein sorgfältiges Interface-Design wichtig. Das Hinzufügen einer Methode birgt ein hohes Risiko.
- Es ist wichtig, eine neue Schnittstelle zu testen, bevor Sie sie freigeben. Es sollten mindestens drei verschiedene Implementierungen implementiert und getestet werden. Es ist schwierig, Schnittstellenfehler nach der Freigabe zu beheben.
Punkt 22 Verwenden Sie die Schnittstelle nur, um den Typ zu definieren
- Die in einer Klasse implementierte Schnittstelle fungiert als Typ, mit dem auf diese Instanz verwiesen werden kann.
- Sie sollten nicht die Konstantenschnittstelle verwenden, die nur eine Schnittstelle zum Definieren von Konstanten ist.
--Konstanten sollten in Aufzählungstypen oder nicht individualisierbaren Dienstprogrammklassen bereitgestellt werden.
Punkt 23 Wählen Sie eine Klassenhierarchie anstelle einer markierten Klasse aus
- Eine Klasse, die zwei oder mehr Merkmale aufweist und mit enum zwischen ihnen wechselt, wird als markierte Klasse bezeichnet und weist viele Nachteile auf. Schwer zu lesen, mehr Speicher, redundant, entschuldigend und ineffizient.
--Subtyp, um einen einzelnen Datentyp zu definieren, der Objekte mit mehreren Merkmalen darstellen kann.
- Definieren Sie eine abstrakte Klasse, die abstrakte Methoden für einzelne Operationen enthält. Wenn es allgemeines Verhalten oder Daten gibt, ordnen Sie sie einer abstrakten Klasse zu.
- Definieren Sie für jedes Merkmal eine Realisierungsunterklasse der Stammklasse.
Punkt 24 Wählen Sie eine statische Elementklasse gegenüber einer nicht statischen Elementklasse aus
――Vier Arten verschachtelter Klassen
- Statische Mitgliedsklasse (innere Klasse)
- Nicht statische Mitgliedsklasse
- Anonyme Klasse
- Lokale Klasse
- Der einzige syntaktische Unterschied zwischen statischen und nicht statischen Elementklassen besteht darin, dass statische Elementklassen einen statischen Modifikator in ihrer Deklaration haben. Diese beiden Arten verschachtelter Klassen sind unterschiedlich.
- Jede Instanz einer nicht statischen Mitgliedsklasse ist implizit der einschließenden Instanz der Klasse zugeordnet, die sie enthält. Innerhalb einer Instanzmethode einer nicht statischen Elementklasse kann die Methode für die einschließende Instanz aufgerufen werden, oder es kann ein Verweis auf die einschließende Instanz unter Verwendung der qualifizierten Syntax dieser erhalten werden.
- (Geplant, hinzugefügt zu werden)
statische Mitgliedsklasse
class Outer {
private int outerField;
private static int a;
//statische Mitgliedsklasse
static class Inner {
void innerMethod() {
//Nur für statische externe Klassenmitglieder verfügbar
a = 10;
}
}
//Methoden innerhalb der äußeren Klasse
void outerMethod() {
Inner ic = new Inner();
}
}
class Main {
public static void main(String[] args) {
// Outer.Wird in Inner verwendet
Outer.Inner ic = new Outer.Inner();
ic.innerMethod();
}
}
Nicht statische Mitgliedsklasse
class Outer {
private static int outerField;
private int b;
//Nicht statische Mitgliedsklasse
class Inner {
void innerMethod() {
outerField = 10;
b = 5;
}
}
//Methoden innerhalb der äußeren Klasse
void outerMethod() {
Inner ic = new Inner();
}
}
class Main {
public static void main(String[] args) {
Outer o = new Outer();
// o.Gebraucht in neu
Outer.Inner in = o.new Inner();
}
}
Punkt 25 Beschränken Sie Quelldateien auf eine einzelne Klasse der obersten Ebene
- Fügen Sie nicht mehrere Klassen der obersten Ebene in eine einzige Quelldatei ein. Der Grund ist, dass der Compiler die Klasse möglicherweise nicht richtig erkennt.