Enum et annotations du chapitre 6 de Java 3rd Edition efficace

[Effective Java 3rd Edition](https://www.amazon.co.jp/Effective-Java-%E7%AC%AC3%E7%89%88-%E3%], qui est un livre indispensable pour les utilisateurs Java intermédiaires et supérieurs. 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) a une version Kindle, donc je vais le résumer.

Précédent: Génériques du chapitre 5 de Java 3ème édition efficaces Suivant: Effective Java 3rd Edition Chapter 7 Lambda and Stream

Item 34 Utiliser enum au lieu de int

--enum est une classe qui expose une instance pour chaque constante d'énumération via le champ final statique public. --enum n'a pas de constructeur accessible, il est donc effectivement définitif. --Le type enum est une version généralisée de singleton, qui est essentiellement une énumération à un seul élément.

Type d'énumération avec données et comportement


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);
    //réduction

    private final double mass; //Masse
    private final double radius; //rayon
    private final double surfaceGravity; //Gravité de surface

    private static final double G = 6.67300E-11; //Constante gravitationnelle universelle
    //Constructeur qui associe des données à la constante enum
    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
    }
    //Exemple d'appel
    public static void main(String[] args) {
     //Combien pèsent 60 kg sur terre sur les autres planètes?
        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));
        }
    }
}

//résultat
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 type avec corps de classe spécifique à la constante et données spécifiques à la constante

Type enum avec corps de classe spécifique à la constante et données spécifiques à la constante


public enum Operation {
    PLUS("+") {
        //Remplacer appliquer
        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;
    }
    //constructeur
    Operation(String symbol) {
        this.symbol = symbol;
    }
    //Si vous définissez une méthode de manière abstraite, chaque constante euum est requise pour remplacer la méthode
    public abstract double apply(double x, double y);

    //Exemple d'appel
    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));
        }
    }
}

Élément 35 Utiliser des champs d'instance au lieu de numéros de commande

Enregistrez la valeur dans le repli de l'instance


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;

    //Si vous souhaitez avoir une valeur numérique, définissez-la dans le constructeur
    Ensemble(int size) {
        this.numberOfMusicians = size;
    }

    public int getNumberOfMusicians() {
        return numberOfMusicians;
    }

    //Exemple d'appel
    public static void main(String[] args) {
        for (Ensemble e : Ensemble.values()) {
            System.out.printf("%s %s %n",e.name(), e.numberOfMusicians);
        }
    }
}
//Résultat d'exécution
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 

Élément 36 Utiliser EnumSet au lieu du champ de bits

--Bitfield est un moyen d'exprimer abc comme 1 + 2 + 4 = 7 quand a = 1, b = 2, c = 4, d = 8. --EnumSet est un ensemble qui peut avoir plusieurs types d'énumération.

Exemple EnumSet


public class Text {
  public enum Style { BOLD, ITALIC, UNDERLINE STRIKETHROUGH }
  //Recevoir EnumSet avec Set
  public void applyStyles(Set<Style> styles) { ... }
}
//Exemple d'utilisation d'EnumSet
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC);

Élément 37 Utiliser EnumMap au lieu de l'index ordinal

--EnumSet est une implémentation de carte à grande vitesse conçue pour utiliser enum comme clé.

Exemple d'utilisation d'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;
    }

    //Exemple d'appel
    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));
        //Créer une instance d'EnumMap
        Map<LifeCycle, Set<Plant>> plantsByLifeCycle =
                new EnumMap<>(Plant.LifeCycle.class);
        //Clé: Enum type LifeCycle, ajoutez Map avec HashSet avec une valeur vide
        for (Plant.LifeCycle lc : Plant.LifeCycle.values()) {
            plantsByLifeCycle.put(lc, new HashSet<>());
        }
        //Ajoutez une valeur au HashSet de la carte.
        for (Plant p : garden) {
            plantsByLifeCycle.get(p.lifeCycle).add(p);
        }
        System.out.println(plantsByLifeCycle);
    }
}
//Résultat de sortie
{ANNUAL=[annual], PERENNIAL=[], BIENNIAL=[biennial1, biennial2]}

Point 38: imiter l'énumération extensible avec une interface

--Le type enum ne peut pas être étendu, mais il est possible d'implémenter l'interface avec le type enum.

Implémenter l'interface avec enum


//Définition d'interface
public interface Operation {
    double apply(double x, double y);
}
//Implémenter l'interface
enum BasicOperation implements Operation {
    PLUS("+") {
        //Mettre en œuvre appliquer
        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;

    //constructeur
    BasicOperation(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public String toString() {
        return symbol;
    }
}

//Type d'énumération étendu
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;

    //constructeur
    ExtendedOperation(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public String toString() {
        return symbol;
    }
}

//Exemple d'appel
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);
    }

    //Passer comme énumération et sous-type d'opération
    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));
        }
    }

    //Comment passer en utilisant le type générique de bordure
    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));
        }
    }
}
//Résultat d'exécution
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

Élément 39 Sélectionnez une annotation plutôt qu'un modèle de dénomination


// @Tester la définition de l'annotation
@Retention(RetentionPolicy.RUNTIME) //L'annotation de test doit être conservée lors de l'exécution
@Target(ElementType.METHOD) //Uniquement autorisé pour les déclarations de méthode
@interface Test {
}

//Classe testée
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() {
    }
}

///Classe de traitement des annotations de test
class RunTests {
    public static void main(String[] args) throws Exception {
        int tests = 0;
        int passed = 0;
        Class<?> testClass = Class.forName("sec39.Sample");
        //Parcourez toutes les méthodes du test
        for (Method m : testClass.getDeclaredMethods()) {
            // @Est-ce avec une annotation Test?
            if (m.isAnnotationPresent(Test.class)) {
                tests++;
                try {
                    //Appel de méthode testée
                    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);
    }
}

//Résultat d'exécution
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

Élément 40 Toujours utiliser l'annotation de remplacement

Élément 41 Utilisez l'interface des marqueurs pour définir le type

Recommended Posts

Enum et annotations du chapitre 6 de Java 3rd Edition efficace
Efficacité de Java 3rd Edition Chapitre 4 Classes et interfaces
Efficace Java 3e édition Chapitre 7 Lambda et Stream
Efficacité de Java 3rd Edition Chapitre 5 Génériques
Méthodes efficaces du chapitre 8 de Java 3rd Edition
Effective Java 3rd Edition Chapitre 2 Création et disparition d'objets
Effective Java 3rd Edition Chapitre 9 Programme Général
Efficace Java 3rd Edition Chapitre 3 Méthodes communes à tous les objets
Ce qui a changé entre la 2e édition effective de Java et la 3e édition
Efficace Java Chapitre 2
Effective Java Chapitre 6 34-35
Effective Java Chapitre 4 15-22
Java efficace Chapitre 3
3ème résumé efficace de Java
Efficacité de Java 3rd Edition Section 85 Choix d'une alternative à la sérialisation Java
[Lire Java efficace] Chapitre 2 Item 7 "Eviter les finaliseurs"
Discrimination d'énum dans Java 7 et supérieur
Traitement parallèle et parallèle dans divers langages (édition Java)
Résumé de l'enquête sur les questions relatives à Java 2e édition efficace
[Lire Java efficace] Chapitre 3 Item 10 "Always Override toString"
J'ai essayé d'expliquer Effective Java 3rd Edition "presque tous les chapitres" en "japonais facile à lire".
Java et JavaScript
XXE et Java
Convertir l'énumération Java et JSON vers et depuis Jackson
[Lire Java efficace] Chapitre 3 Point 12 "Considérer l'implémentation de Comparable"
Résumé du comportement de ToString avec les annotations Java et Groovy
La comparaison d'énumération est ==, et equals est bonne [Java]
[Lire Java efficace] Chapitre 2 Item 6 "Supprimer les références d'objets obsolètes"
Mises à jour des notes personnelles en vigueur de Java Third Edition 2nd Edition
J'écrirai un extrait de ce que j'ai trouvé intéressant en lisant Effective Java 3rd Edition