Le magasin d'infrastructure étudiera à nouveau Java (1er: conception de classe)

L'histoire d'une société d'infrastructure qui n'a appris Java que pendant environ 3 mois en formation il y a plus de 10 ans, visant Java Gold. [Ce livre](https://books.google.co.jp/books?id=N0ktDQAAQBAJ&printsec=frontcover&dq=java+gold&hl=ja&sa=X&ved=0ahUKEwjO7_LEv5PZAhXFKZQKHeI-AIQQ6EI-Q Sur la base de v = onepage & q = java% 20gold & f = false), je vais résumer les principaux points à ma manière. Le premier est la conception de classe.

Encapsulation

Exemple


class Hoge {
    private int hoge;
    public Hoge(int hoge) { this.hoge = hoge; }

    /*accessor*/
    //setter
    public void setHoge(int hoge) {
        //check
        if(check) this.hoge = hoge;
    }
    //getter
    public int getHoge() { return hoge; }
}

Ce qui suit est un résumé des modificateurs d'accès autres que «private» et de leurs effets.

Accéder aux modificateurs et à la portée

Modificateurs d'accès classe paquet Sous-classe Autre (tous)
public o o o o
protected o o o x
Non spécifié (par défaut) o o x x
private o x x x

Document de référence

Class Modifiers Résumé des modificateurs (Class).

abstract Indique une classe incomplète (pensable). Erreur de compilation lors de la tentative de création d'une instance à partir de la classe abstraite. S'il est donné à la méthode, cela signifie qu'il n'est pas implémenté. La méthode abstraite ne peut être définie (déclarée) que dans la classe abstraite (erreur de compilation (a) si la méthode abstraite est écrite dans une classe ordinaire). Au contraire, si vous héritez d'une classe abstraite qui a une méthode abstraite et ne remplacez pas (implémentez) cette méthode abstraite, vous devez toujours utiliser la classe abstraite (erreur de compilation (b)). ~~ De plus, même si vous déclarez une méthode abstraite qui a la même signature de méthode que celle déclarée dans l'interface dans la classe abstraite qui implémente l'interface, une erreur de compilation ~~ [saka1029-sama Comme indiqué dans le commentaire, 2018.02.11 [Correctif] Dans la classe abstraite qui implémente l'interface, il est possible de la laisser comme abstraite sans implémenter la méthode (@Override), mais puisque la visibilité ne peut pas être réduite, si vous oubliez d'entrer public, une erreur de compilation (c).

Erreur de compilation(a)


abstract class Hoge {
    abstract void doHoge();
}
class Hoge2  {
    public void doHoge2() {
        Hoge hoge = new Hoge();  //Erreur de compilation car vous essayez d'instancier une classe abstraite
    }
}

Erreur de compilation(b)


abstract class abstractHoge {
    abstract void doHoge();
}
class Hoge extends abstractHoge {
    public void hoge() { } //méthode abstraite (doHoge()) Reste, mais ce n'est pas abstrait, donc une erreur de compilation
}

Erreur de compilation(c)


interface HogeInterface {
    void doHoge(int hoge);
}
abstract class abstractHoge implements HogeInterface {
    abstract void doHoge(int hoge);    //Puisque la méthode d'interface et la méthode abstraite couverte par la signature sont déclarées, une erreur de compilation → signalée dans le commentaire de saka1029[2018.02.11 Correction]Même si la signature est couverte, il s'agit simplement d'une déclaration qui est simplement mets mais toujours abstraite et qui peut être compilée. Erreur de compilation selon laquelle la méthode déclarée dans l'interface ne peut pas être réduite en visibilité car elle est implicitement publique et n'a pas de public ici.
}

final Cela montre que presque toutes sont des classes qui ne peuvent plus être héritées. Erreur de compilation (a) lors de la tentative d'extension de la classe finale. Erreur de compilation lors de l'utilisation simultanée de abstract et final (clairement incohérent lors de l'utilisation de abstract qui est censé s'étendre et final qui ne peut pas être étendu en même temps) (b).

Erreur de compilation(a)


final class finalHoge { }
class SubHoge extends finalHoge { } //Erreur de compilation car nous étendons la classe finale

Erreur de compilation(b)


abstract final class OmaenanishitekuretennoHoge { } //résumé et final!?Alors compilez l'erreur

strictfp FP strict (Floating Poing). C'est une virgule flottante stricte. Qu'est-ce que c'est? Je ne suis pas bon en maths, donc si je l'arrondis grossièrement, la gestion du point décimal est définie par l'IEEE, mais dans le monde strictfp, float est float et double est double, y compris les valeurs intermédiaires. Il semble qu'il soit traité comme (pas de conversion de type implicite), mais dans un contexte qui n'est pas strictfp, l'erreur d'arrondi (sous-dépassement) et la perte de chiffres (débordement) sont tolérées dans une certaine mesure (Référence /javase/specs/jls/se8/html/jls-15.html#jls-15.4)). Apparemment, cela fonctionne pour éliminer la différence de résultats due à la différence du nombre de chiffres effectifs de virgule flottante entre le calcul 32 bits et 64 bits. .. .. Je ne suis pas sûr parce que je ne l'ai pas vu.

Héritage

En étendant la classe, il hérite de ce qui suit.

L'héritage simultané multiple n'est pas possible en Java. Il semble que cela puisse être appelé C ++.

est-une relation et a-une relation

Si B étend A, c'est juste B "est-a". En Java, toutes les classes sont des classes d'objets car les parents de toutes les classes sont des objets. has-a signifie simplement qu'une classe en contient une autre comme variable d'instance. Il existe deux autres types, et dans le cas de "l'agrégation", les objets associés ne partagent pas un cycle de vie. Dans le cas de la "composition", le cycle de vie est partagé (en bref, lorsque B a a, si B est détruit, a est également détruit).

aggregation


package net.mognet.java8gold;
class A {
	public A() {
		System.out.println("A is created.");
	}
	@Override
	protected void finalize() throws Throwable {
		System.out.println("A is finalized.");
	}
}
class B {
	private A a;
    public B(A a) {
    		this.a = a;
    		System.out.println("B is created.");
    }
    
    @Override
    protected void finalize() throws Throwable {
    		System.out.println("B is finalyzed.");
    }
}
public class Test {
	public static void main(String[] args) throws InterruptedException {
		A a = new A();
		B b = new B(a);
		b = null;
		System.gc();  //b est finalisé mais a n'est pas finalisé
	}
}

composition


class A {
	public A() {
		System.out.println("A is created.");
	}
	@Override
	protected void finalize() throws Throwable {
		System.out.println("A is finalized.");
	}
}
class B {
    A a = new A();
    public B() {
    		System.out.println("B is created.");
    }
    
    @Override
    protected void finalize() throws Throwable {
    		System.out.println("B is finalyzed.");
    }
}
public class Test {
	public static void main(String[] args) throws InterruptedException {
		B b = new B();
		b = null;
		System.gc();   //Maintenant, A et B sont finalisés
	}
}

Polymorphisme

En gros, vous pouvez créer un objet enfant en utilisant le type parent.

class A {}
class B extends A {}
class C {
    private A a = new B(); //OK
}

Dans le plus extrême, toutes les superclasses sont des objets, alors faites-le également.

class A {}
class B extends A {}
class C extends B {}
class Test {
    private Object a = new A(); //OK
    private Object b = new B(); //OK
    private Object c = new C(); //OK
}

Même si vous ne connaissez pas le type spécifique au moment de la compilation, si vous connaissez la méthode courante à fournir, vous pouvez en faire le type de la classe parente et écrire le code pour appeler cette méthode. Le comportement réel (implémentation de la méthode) est déterminé lors de l'exécution.

Méthode de la classe Object

Méthode Contenu
boolean equals(Object obj) Renvoie si l'objet et l'objet passé sont égaux
protected void finalize() Appelé lors de l'exécution de gc
Class<?> getClass() Renvoie une classe d'exécution
int hashCode() Renvoie la valeur de hachage de l'objet
void notify() 1 Reprendre le fil
void notifyAll() Reprendre tous les threads
String toString() Renvoie l'objet sous forme de chaîne
void wait() notify()Attendre jusqu'à

gars statiques

static fields Il n'y a qu'une seule variable statique physiquement (en mémoire), quel que soit le nombre d'instances dont elle dispose.

staticFields


class A {
    private static int i = 0;
    public static void add(int a) { i = i + a; }
    public static int getI() { return i; }
} 
public class Test {
	public static void main(String[] args) {
		A[] a = { new A(), new A(), new A(), new A() }; //Peu importe le nombre d'instances que vous créez
		a[0].add(3);
		System.out.println(a[1].getI());  //3 retours
		a[2].add(4);
		System.out.println(a[3].getI());  //7 retours
	}
}

Seules les personnes statiques peuvent accéder aux champs statiques. Ne faites pas cela même si vous faites une erreur (erreur de compilation (a)).

Erreur de compilation(a)


class A {
    private static int i;
    public A(int i) {
        this.i = i;    //non dans un champ statique-Erreur de compilation avec accès statique
    }
}

Comme il est également appelé un alias ou une variable de classe, ce n'est pas une variable d'instance, donc il n'est pas accessible comme "this.i". Au contraire, il peut être utilisé sans instanciation.

staticFields2


class A {
    private static int i = 0;
    public static void add(int a) { i = i + a; }
    public static int getI() { return i; }
} 
public class Test {
	public static void main(String[] args) {
		System.out.println(A.getI());  //0 est retourné
	}
}

static methods Méthode de classe Alias. Si vous utilisez des mots-clés tels que this ou super qui sont supposés être des instances, vous obtiendrez une erreur de compilation (a). Bien sûr, le contraire est OK.

Erreur de compilation(a)


class A {
    private static int i = 0;
    private int memberField = 0;
    public void memberMethod() { //do something with i } //OK
    public static void classMethod() { //do something with this.memberField } //Erreur de compilation car la variable membre est référencée à partir de la méthode statique
}

static initializer Code qui s'exécute lorsque la classe est chargée, c'est-à-dire lorsque la machine virtuelle Java est lancée. Il peut être utilisé principalement pour initialiser des champs statiques, mais il peut également écrire un comportement. Erreur de compilation (a) si vous accédez à un champ déclaré en dehors du bloc de l'initialiseur statique, ou si vous commencez à utiliser this ou super, ce qui est légal dans le contexte statique.

Erreur de compilation(a)


clss A() {
    private int i;
    private static int j;
    static {
        this.i = 1;    //Erreur de compilation car vous accédez à une variable d'instance
        j = 1;         //OK
        static int k = 1;  //Erreur de compilation (difficile!) Parce que statique est ajouté dans l'initialiseur statique.
    }
}

Motif singleton

Un modèle de conception basé sur la garantie qu'il n'y a qu'une seule instance d'une classe.

Singleton


public class SingletonHoge {
    private static SingletonHoge shoge = new SingletonHoge();
    private SingletonHoge() {}
    public static SingletonHoge getInstance() { return shoge; }
}

Classe immuable

Une classe conçue pour que le contenu (champs) d'un objet une fois instancié ne soit pas mis à jour.

Immutable


public final class ImmutableHoge {
    private final int hoge;
    private final int[] hogearray = { 1, 2, 3 };
    public ImmutableHoge(int hoge) { this.hoge = hoge; }
    public int getHoge() { return this.hoge; }
    public ImmutableHoge add(int hoge) { new ImmutableHoge(this.hoge + hoge); }
}

abstract, static, and default methods Depuis Java 8, vous pouvez écrire des méthodes d'implémentation dans l'interface.

Interface


interface Hoge {
    void doHoge(); //abstract
    static void staticDoHoge() {
        //do something in static context
    }
    default void defaultDoHoge() {
        //do something
    }
}

Cependant, la méthode statique d'une interface ne peut être appelée qu'à partir d'une référence à l'interface.

staticMethod


interface InterfaceHoge {
    static void doHoge() { System.out.println("hoge"); }
}
class ClassHoge implements InterfaceHoge {
    ClassHoge choge = new ClassHoge();
    InterfaceHoge.doHoge();    //OK
    choge.doHoge();            //Erreur de compilation car elle est appelée à partir de l'instance de classe d'implémentation
    ClassHoge.doHoge();        //Erreur de compilation car elle est appelée à partir d'une référence à la classe d'implémentation
}

Classe imbriquée

Une classe déclarée dans un bloc.

  1. Classe imbriquée de membres de classe (classe interne)
  1. classe membre statique: une classe imbriquée déclarée statique comme membre de classe

Notez que toutes les classes membres de l'interface sont traitées comme statiques, elles ne sont donc pas traitées comme des classes internes (deviennent des classes membres statiques).

NestedClass


public class OuterHoge {
    static class InnerStaticHoge { }   //classe de membre statique
    private class InnerPrivateHoge { } //Classe de membre (classe de membre non statique)
    void doHoge() {
        class HogeInMethod { }         //Classe locale
    }
}

Voici comment l'appeler.

public class OuterHoge {
    public void doHoge() {
        InnerHoge ih = new InnerHoge();
        ih.doInnerHoge();
    }
    public class InnerHoge {            //Classe de membre
        public void doInnerHoge() { }
    }
}

L'appel à partir du contexte statique est déroutant, mais après avoir créé une instance de la classe Outer, nouvelle à partir de cette référence d'objet.

public class OuterHoge {
    public static void doHoge() {
        OuterHoge oh = new OuterHoge();    //Instanciez-vous (classe externe)
        InnerHoge ih = oh.new InnerHoge(); //Nouveau d'une référence à la classe Outer
        ih.doInnerHoge();
        //InnerHoge ih = new OugerHoge().new InnerHoge(); //Si vous le mettez sur une seule ligne, ce sera comme ça
    }
    public class InnerHoge {
        public void doInnerHoge() { }
    }
}

Appels d'autres classes.

public class AnotherHoge {
    public void doAnotherHoge() {
        OuterHoge oh = new OuterHoge();
        OuterHoge.InnerHoge ih = oh.new InnerHoge();
        ih.doInnerHoge();
    }
}

Classe anonyme (https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.9.5)

Créé automatiquement par le compilateur lorsque la classe est instanciée. Les classes anonymes sont des classes internes non abstraites, implicitement finales et toujours non statiques. Utilisé en fait pour fournir une implémentation d'interface (c'est-à-dire qu'il n'est plus nécessaire maintenant que la méthode par défaut puisse être définie pour l'interface? Je me demande si elle est réellement utilisée dans divers endroits où diverses implémentations légères sont effectuées. utilisation).

interface Hoge {
    public void doHoge(); //méthode abstraite
}
class HogeClass {
	void hogeMain() {
            Hoge hoge = new Hoge() {
        	@Override
        	public void doHoge() { }
        };
        hoge.doHoge();
	}
}

Le fait est que vous pouvez implémenter une méthode en créant un objet de type interface sur place et en y créant une classe anonyme, sans avoir à créer une classe qui implémente l'interface et remplace la méthode.

Si vous écrivez avec une seule doublure, ce sera comme ça.

new Hoge() {
    public void doHoge() {}
}.doHoge();

Je me demande si cela arrive à ce point. .. .. Quand je regardais la propriété DataSource de MySQL, quand je lisais le code source du pilote, je me souviens que la classe interne apparaissait partout et que j'étais confus sur comment appeler et comment l'appeler, mais ce n'est qu'en maîtrisant ce domaine. peut être.

Type d'énumération

Utilisé pour combiner des constantes liées (implicitement «public static final») en une seule. La syntaxe est modificateur enum Name {Const1, Const2, ...}.

public enum DogType {
    BORDER_COLLIE, GOLDEN_RETRIEVER, AKITA; //Si vous déclarez d'autres champs et méthodes, écrivez une constante avant cela.
    private int hoge;        //Les champs peuvent également être déclarés
    public void doHoge() { } //Vous pouvez également déclarer des méthodes
}

Comme les classes et les interfaces, il peut être déclaré comme un type de niveau supérieur ou imbriqué et est implicitement compilé comme une classe finale (non extensible). Contrairement aux classes imbriquées, il ne peut pas être déclaré à l'intérieur d'une méthode. Tous les types d'énumération sont implicitement compilés en tant que sous-classes de java.lang.Enum, il n'est donc pas possible d'étendre quoi que ce soit, mais il est possible d'implémenter des interfaces. Les types d'énumération imbriqués sont implicitement «statiques» (peuvent être explicites). Une méthode fournie par la classe java.lang.Enum.

`String final name()`
Renvoie le nom de la constante d'énumération sous forme de chaîne
`int ordinal()`
Renvoie l'ordre des constantes d'énumération
`static > valueOf(Class type, String name)`
Renvoie un objet de constante d'énumération qui correspond à la constante d'énumération avec le nom spécifié dans le deuxième argument du type d'énumération spécifié dans le premier argument
`static E valueOf(String name)`
Renvoie une constante d'énumération qui correspond à la constante d'énumération avec le nom spécifié
`static E[] values()`
Renvoie un tableau de types d'énumération

EnumTest


enum DogTypes {
	BORDER_COLLIE, BULL_DOG, GOLDEN_RETRIEVER;
	private int i = 0;
	public void printField() { System.out.println(i); }
}
public class EnumTest {
	public static void main(String[] args) {
		System.out.println(DogTypes.BORDER_COLLIE);
		for(DogTypes dt : DogTypes.values()) {
			dt.printField();
			System.out.println(dt + ": " + dt.name());
		}
		System.out.println(DogTypes.valueOf("BORDER_COLLIE"));
	}
}

Résultat d'exécution


BORDER_COLLIE
0
BORDER_COLLIE: BORDER_COLLIE
0
BULL_DOG: BULL_DOG
0
GOLDEN_RETRIEVER: GOLDEN_RETRIEVER
BORDER_COLLIE

constructeur

Seuls les constructeurs privés sont autorisés. Aucun argument n'est possible. Puisqu'il est nécessaire d'en faire un objet singleton et immuable, spécifiez la valeur du champ lors de la création de l'objet (le setter n'est pas fourni, seulement getter).

enum DogTypes {
    NA, SMALL(5), MEDIUM(10), LARGE(20);      //Constructeur sans argument, 5 arguments chacun, 10,Pour appeler 20 constructeurs
    private int weight;
    private DogTypes() { this.weight = 1; }
    private DogTypes(int weight) { this.weight = weight; }
    public int getWeight() { return this.weight: }
}
class Hoge {
    public void doHoge() {
        DogTypes dt = DogTypes.MEDIUM;
        System.out.println(dt.getWeight());
    }
}

Jusqu'à ici pour cette fois.

Recommended Posts

Le magasin d'infrastructure étudiera à nouveau Java (1er: conception de classe)
Comparaison Java et Swift (3) Implémentation de classe / héritage de classe / conception de classe
Méthodes de classe Java
[Java] Héritage de classe
Étudions Java
classe Scanner java
Classe Java HashMap
Modèle de conception Java
java (classe abstraite)
[Java] Classe imbriquée
Classe anonyme Java
Modèles de conception Java
À propos de la classe Java
[Java] Notes d'étude
Étudier Java 8 (répétable)
Mémorandum d'étude Java
[java] Classe abstraite
[Java] Classe d'objets
Classe locale Java
Étudier Java Silver 1