[Effective Java 3rd Edition](https://www.amazon.co.jp/Effective-Java-%E7%AC%AC3%E7%89%88-%E3%], ein Muss für fortgeschrittene Java-Benutzer und höher. 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 5 Generika Weiter: Effektive Java 3rd Edition, Kapitel 7, Lambda und Stream
--enum ist eine Klasse, die eine Instanz für jede Aufzählungskonstante über das öffentliche statische Endfeld verfügbar macht. --enum hat keinen zugänglichen Konstruktor, daher ist es effektiv endgültig.
Aufzählungstyp mit Daten und Verhalten
public enum Planet {
MERCURY(3.302e+23, 2.439e6),
VENUS(4.869e+24, 6.052e6),
EARTH(5.975e+24, 6.378e6),
MARS(6.419e+23, 3.393e6);
//Kürzung
private final double mass; //Masse
private final double radius; //Radius
private final double surfaceGravity; //Oberflächengravitation
private static final double G = 6.67300E-11; //Universelle Gravitationskonstante
//Konstruktor, der Daten mit der Enum-Konstante verknüpft
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
surfaceGravity = G * mass / (radius * radius);
}
public double mass() {
return mass;
}
public double radius() {
return radius;
}
public double surfaceGravity() {
return surfaceGravity;
}
//
public double getSurfaceWeight(double mass) {
return mass * surfaceGravity; // F = ma
}
//Beispiel aufrufen
public static void main(String[] args) {
//Wie viel wiegen 60 kg auf der Erde auf anderen Planeten?
double earthWeight = Double.parseDouble("60.0");
double mass = earthWeight / Planet.EARTH.surfaceGravity();
for (Planet p: Planet.values()) {
System.out.printf("Weight on %s is %f%n", p, p.getSurfaceWeight(mass));
}
}
}
//Ergebnis
Weight on MERCURY is 22.674402
Weight on VENUS is 54.303060
Weight on EARTH is 60.000000
Weight on MARS is 22.776240
--Enum-Typ mit konstantem Klassenkörper und konstanten spezifischen Daten
Aufzählungstyp mit konstantenspezifischem Klassenkörper und konstantenspezifischen Daten
public enum Operation {
PLUS("+") {
//Überschreiben anwenden
public double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
public double apply(double x, double y) {
return x - y;
}
},
TIMES("*") {
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE("/") {
public double apply(double x, double y) {
return x / y;
}
};
private final String symbol;
@Override
public String toString() {
return symbol;
}
//Konstrukteur
Operation(String symbol) {
this.symbol = symbol;
}
//Wenn Sie eine Methode abstrakt definieren, ist jede Vakuumkonstante erforderlich, um die Methode zu überschreiben
public abstract double apply(double x, double y);
//Beispiel aufrufen
public static void main(String[] args) {
double x = 2.0;
double y = 4.0;
for (Operation op : Operation.values()) {
System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
}
}
}
Speichern Sie den Wert in der Instanzfalte
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),
SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8),
NONET(0), DECTET(10), TRIPLE_QUARTET(12);
private final int numberOfMusicians;
//Wenn Sie einen numerischen Wert haben möchten, definieren Sie ihn im Konstruktor
Ensemble(int size) {
this.numberOfMusicians = size;
}
public int getNumberOfMusicians() {
return numberOfMusicians;
}
//Beispiel aufrufen
public static void main(String[] args) {
for (Ensemble e : Ensemble.values()) {
System.out.printf("%s %s %n",e.name(), e.numberOfMusicians);
}
}
}
//Ausführungsergebnis
SOLO 1
DUET 2
TRIO 3
QUARTET 4
QUINTET 5
SEXTET 6
SEPTET 7
OCTET 8
DOUBLE_QUARTET 8
NONET 0
DECTET 10
TRIPLE_QUARTET 12
EnumSet-Beispiel
public class Text {
public enum Style { BOLD, ITALIC, UNDERLINE STRIKETHROUGH }
//Empfangen Sie EnumSet mit Set
public void applyStyles(Set<Style> styles) { ... }
}
//Beispiel für die Verwendung von EnumSet
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC);
--EnumSet ist eine Hochgeschwindigkeits-Map-Implementierung, die Enum als Schlüssel verwendet.
Beispiel für die Verwendung von EnumSet
public class Plant {
enum LifeCycle {ANNUAL, PERENNIAL, BIENNIAL;}
final String name;
final LifeCycle lifeCycle;
Plant(String name, LifeCycle lifeCycle) {
this.name = name;
this.lifeCycle = lifeCycle;
}
@Override
public String toString() {
return name;
}
//Beispiel aufrufen
public static void main(String[] args) {
var garden = List.of(new Plant("annual", LifeCycle.ANNUAL),
new Plant("biennial1", LifeCycle.BIENNIAL),
new Plant("biennial2", LifeCycle.BIENNIAL));
//Erstellen Sie eine Instanz von EnumMap
Map<LifeCycle, Set<Plant>> plantsByLifeCycle =
new EnumMap<>(Plant.LifeCycle.class);
//Schlüssel: Aufzählungstyp LifeCycle, Map mit HashSet mit leerem Wert hinzufügen
for (Plant.LifeCycle lc : Plant.LifeCycle.values()) {
plantsByLifeCycle.put(lc, new HashSet<>());
}
//Fügen Sie dem HashSet der Karte einen Wert hinzu.
for (Plant p : garden) {
plantsByLifeCycle.get(p.lifeCycle).add(p);
}
System.out.println(plantsByLifeCycle);
}
}
//Ausgabeergebnis
{ANNUAL=[annual], PERENNIAL=[], BIENNIAL=[biennial1, biennial2]}
Implementieren Sie die Schnittstelle mit enum
//Schnittstellendefinition
public interface Operation {
double apply(double x, double y);
}
//Implementieren Sie die Schnittstelle
enum BasicOperation implements Operation {
PLUS("+") {
//Implementieren anwenden
public double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
public double apply(double x, double y) {
return x - y;
}
},
TIMES("*") {
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE("/") {
public double apply(double x, double y) {
return x / y;
}
};
private final String symbol;
//Konstrukteur
BasicOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
//Erweiterter Aufzählungstyp
enum ExtendedOperation implements Operation {
EXP("^") {
public double apply(double x, double y) {
return Math.pow(x, y);
}
},
REMAINDER("%") {
public double apply(double x, double y) {
return x % y;
}
};
private final String symbol;
//Konstrukteur
ExtendedOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
//Beispiel aufrufen
class Main {
public static void main(String[] args) {
double x = 2.0;
double y = 4.0;
text1(BasicOperation.class, x, y);
text1(ExtendedOperation.class, x, y);
text2(Arrays.asList(BasicOperation.values()), x, y);
text2(Arrays.asList(ExtendedOperation.values()), x, y);
}
//Als Aufzählung und Operationstyp übergeben
private static <T extends Enum<T> & Operation> void text1(Class<T> opEnumType, double x, double y) {
for (Operation op : opEnumType.getEnumConstants()) {
System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
}
}
//Übergeben mit dem Rahmen-Platzhaltertyp
private static void text2(Collection<? extends Operation> opSet, double x, double y) {
for (Operation op : opSet) {
System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
}
}
}
//Ausführungsergebnis
2.000000 + 4.000000 = 6.000000
2.000000 - 4.000000 = -2.000000
2.000000 * 4.000000 = 8.000000
2.000000 / 4.000000 = 0.500000
2.000000 ^ 4.000000 = 16.000000
2.000000 % 4.000000 = 2.000000
2.000000 + 4.000000 = 6.000000
2.000000 - 4.000000 = -2.000000
2.000000 * 4.000000 = 8.000000
2.000000 / 4.000000 = 0.500000
2.000000 ^ 4.000000 = 16.000000
2.000000 % 4.000000 = 2.000000
--Anmerkungen sollten verwendet werden, da es ein Nachteil ist, Methodennamen usw. aufgrund von Namensmustern besondere Eigenschaften zu geben. (Beispiel: testSafetyOverride beginnt mit test, daher ist test med ein schlechtes Beispiel.)
// @Test Annotation Definition
@Retention(RetentionPolicy.RUNTIME) //Testanmerkungen sollten zur Laufzeit beibehalten werden
@Target(ElementType.METHOD) //Nur für Methodendeklarationen zulässig
@interface Test {
}
//Getestete Klasse
class Sample {
@Test
public static void m1() {
}
public static void m2() {
}
@Test
public static void m3() {
throw new RuntimeException("Boom");
}
public static void m4() {
}
@Test
public static void m5() {
}
public static void m6() {
}
@Test
public static void m7() {
throw new RuntimeException("Crash");
}
public static void m8() {
}
}
///Test Annotation Processing Class
class RunTests {
public static void main(String[] args) throws Exception {
int tests = 0;
int passed = 0;
Class<?> testClass = Class.forName("sec39.Sample");
//Durchlaufen Sie alle Methoden im Test
for (Method m : testClass.getDeclaredMethods()) {
// @Ist es mit einer Testanmerkung?
if (m.isAnnotationPresent(Test.class)) {
tests++;
try {
//Getesteter Methodenaufruf
m.invoke(null);
passed++;
} catch (InvocationTargetException wrappedExc) {
Throwable exc = wrappedExc.getCause();
System.out.println(m + " failed: " + exc);
} catch (Exception e) {
System.out.println("Invalid @Test: " + m);
}
}
}
System.out.printf("Passed: %d, Failed: %d%n", passed, tests - passed);
}
}
//Ausführungsergebnis
public static void sec39.Sample.m7() failed: java.lang.RuntimeException: Crash
public static void sec39.Sample.m3() failed: java.lang.RuntimeException: Boom
Passed: 2, Failed: 2
Recommended Posts