Infrastructure shop study Java again (1st: Class design)

A story about an infrastructure company who only learned Java for about 3 months in training more than 10 years ago, aiming for Java Gold. [This book] purchased with the points given by the long-term contract benefit of mobile phone [https://books.google.co.jp/books?id=N0ktDQAAQBAJ&printsec=frontcover&dq=java+gold&hl=ja&sa=X&ved=0ahUKEwjO7_LEv5PZAhXFKZQKHeI-AIQQ6 Based on v = onepage & q = java% 20gold & f = false), I will summarize the main points in my own way. The first is class design.

Encapsulation

Example


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; }
}

The following is a summary of access modifiers other than private and their effects.

Access modifiers and scope

Modifiers (Access Modifiers) class package Subclass Other (all)
public o o o o
protected o o o x
Not specified (default) o o x x
private o x x x

Reference Document

Class Modifiers Summary of (Class) modifiers.

abstract Indicates an incomplete (thinkable) class. Compile error when trying to instantiate from abstract class. If it is given to the method, it means that it is not implemented. The abstract method can only be defined (declared) in the abstract class (compilation error (a) if you write the abstract method in an ordinary class). On the contrary, if you inherit the abstract class that has the abstract method and do not override (implement) the abstract method, you must always use the abstract class (compile error (b)). ~~ In addition, even if you declare an abstract method that has the same method signature as the one declared in the interface in the abstract class that implements the interface, a compilation error ~~ [saka1029-sama As pointed out in the comment, 2018.02.11 [Fix] In the abstract class that implements the interface, it is possible to leave the abstract as it is without implementing the method (@Override), but since visibility cannot be reduced, if you forget to enter public, a compilation error (c) will occur.

Compile error(a)


abstract class Hoge {
    abstract void doHoge();
}
class Hoge2  {
    public void doHoge2() {
        Hoge hoge = new Hoge();  //Compile error because you are trying to instantiate an abstract class
    }
}

Compile error(b)


abstract class abstractHoge {
    abstract void doHoge();
}
class Hoge extends abstractHoge {
    public void hoge() { } //abstract method (doHoge()) Remains, but it is not abstract, so a compile error
}

Compile error(c)


interface HogeInterface {
    void doHoge(int hoge);
}
abstract class abstractHoge implements HogeInterface {
    abstract void doHoge(int hoge);    //Since the interface method and the abstract method covered by the signature are declared, a compile error → pointed out in the comment from saka1029[2018.02.11 Correction]Even if the signature is covered, it's just a declaration that is simply met but still abstract, and is compileable. A compile error that the method declared in the interface cannot be less visible because the method declared in the interface is implicitly public and does not have public here.
}

final It shows that almost all of them are classes that cannot be inherited anymore. Compile error (a) when trying to extend the final class. Compile error when using abstract and final at the same time (clearly inconsistent when using abstract which is supposed to extend and final which cannot be extended at the same time) (b).

Compile error(a)


final class finalHoge { }
class SubHoge extends finalHoge { } //Compile error because we are extending the final class

Compile error(b)


abstract final class OmaenanishitekuretennoHoge { } //abstract and final!?So compile error

strictfp strict FP (Floating Poing). That is a strict floating point. what is that? I'm not good at arithmetic systems, so to summarize it roughly, the handling of decimal points is standardized around IEEE, but in the strictfp world, float is float, double is double, and it is strict including intermediate values. It seems that it is treated as (not implicit type conversion), but it allows rounding error (underflow) and digit loss (overflow) to some extent in non-strictfp contexts (Reference /javase/specs/jls/se8/html/jls-15.html#jls-15.4)). Apparently, it works to eliminate the difference in results due to the difference in the number of effective digits of floating point between 32-bit and 64-bit calculations. .. .. I'm not sure because I haven't seen it.

Inheritance

By extending the class, it inherits the following.

Multiple simultaneous inheritance is not possible in Java. It seems that it can be said that it is C ++.

is-a relationship and has-a relationship

If B extends A, it's just B "is-a". In Java, all classes are Object classes because the parents of all classes are Objects. has-a just says that one class contains another as an instance variable. There are two more types, and in the case of "aggregation", the related objects do not share a life cycle. In the case of "composition", the life cycle is shared (in short, when B has a, if B is destroyed, a is also destroyed).

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 is finalized but a is not finalized
	}
}

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();   //Now both A and B are finalize
	}
}

Polymorphism

Roughly speaking, you can create a child object using the parent type.

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

To be more extreme, since all superclasses are Objects, we also do this.

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
}

Even if you don't know the specific type at compile time, if you know the common method to provide, you can make it the type of the parent class and write the code that calls that method. The actual behavior (method implementation) is determined at run time.

Method of Object class

Method Contents
boolean equals(Object obj) Returns whether the object and the passed obj are equal
protected void finalize() Called when gc is run
Class<?> getClass() Returns a runtime class
int hashCode() Returns the hash value of the object
void notify() 1 Resume thread
void notifyAll() Resume all threads
String toString() Returns the object as a string
void wait() notify()Wait until

static guys

static fields There is only one static variable physically (in memory), no matter how many instances it has.

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() }; //No matter how many instances you create
		a[0].add(3);
		System.out.println(a[1].getI());  //3 returns
		a[2].add(4);
		System.out.println(a[3].getI());  //7 returns
	}
}

Only static people can access static fields. Even if you make a mistake, do not do this (compile error (a)).

Compile error(a)


class A {
    private static int i;
    public A(int i) {
        this.i = i;    //non in static field-Compile error with static access
    }
}

As it is also called an alias or class variable, it is not an instance variable, so you cannot access it like "this.i". Rather, it can be used without instantiation.

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 is returned
	}
}

static methods Alias class method. If you use keywords such as this or super that are supposed to be instances, you will get a compile error (a). Of course, the opposite is OK.

Compile error(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 } //Compile error because the member variable is referenced from the static method
}

static initializer Code that runs when the class is loaded, that is, when the JVM is launched. It can be used mainly for initializing static fields, but you can also write behavior. Compile error (a) if you access a field declared outside the block of static initializer, or if you start using this or super, which is legal in the static context.

Compile error(a)


clss A() {
    private int i;
    private static int j;
    static {
        this.i = 1;    //Compile error because you are accessing an instance variable
        j = 1;         //OK
        static int k = 1;  //A compile error (difficult!) Because static is added in the static initializer.
    }
}

Singleton pattern

A design pattern based on the guarantee that there is only one instance of a class.

Singleton


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

Immutable Class

A class designed so that the contents (fields) of an object once instantiated are not updated.

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 From Java 8, you can write implementation methods in the interface.

Interface


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

However, the static methods of an interface can only be called from a reference to the interface.

staticMethod


interface InterfaceHoge {
    static void doHoge() { System.out.println("hoge"); }
}
class ClassHoge implements InterfaceHoge {
    ClassHoge choge = new ClassHoge();
    InterfaceHoge.doHoge();    //OK
    choge.doHoge();            //Compile error because it is called from the implementation class instance
    ClassHoge.doHoge();        //Compile error because it is called from a reference to the implementation class
}

Nested class

A class declared within a block.

  1. Nested class of class members (Inner Class)
  1. static member class: a nested class declared static as a class member

Note that all member classes in the interface are treated as static, so they are not treated as internal classes (become static member classes).

NestedClass


public class OuterHoge {
    static class InnerStaticHoge { }   //static member class
    private class InnerPrivateHoge { } //Member class (non-static member class)
    void doHoge() {
        class HogeInMethod { }         //Local class
    }
}

Here's how to call it.

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

Calling from the static context is confusing, but after creating an instance of the Outer class, new from the object reference.

public class OuterHoge {
    public static void doHoge() {
        OuterHoge oh = new OuterHoge();    //Instantiate yourself (Outer class)
        InnerHoge ih = oh.new InnerHoge(); //New from a reference to the Outer class
        ih.doInnerHoge();
        //InnerHoge ih = new OugerHoge().new InnerHoge(); //If you put it in one line, it will be like this
    }
    public class InnerHoge {
        public void doInnerHoge() { }
    }
}

Calls from other classes.

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

Anonymous Class

Created automatically by the compiler when the class is instantiated. Anonymous classes are non-abstractable, implicitly final, and are always non-static inner classes. Actually used to provide an implementation of interface (that is, it is unnecessary now that you can define a default method for interface? I wonder if it is actually a case where various light implementations are done in various places. use).

interface Hoge {
    public void doHoge(); //abstract method
}
class HogeClass {
	void hogeMain() {
            Hoge hoge = new Hoge() {
        	@Override
        	public void doHoge() { }
        };
        hoge.doHoge();
	}
}

The point is that you can implement a method by creating an interface type object on the spot and creating an anonymous class in it, without having to create a class that implements interface and override the method.

Writing with one liner looks like this.

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

I wonder if it comes to this point. .. .. When I was looking at the DataSource property of MySQL, when I was reading the source code of the driver, I remember that the inner class appeared everywhere and I was confused about what to call and how to call it, but it is only by mastering this area maybe.

Enumeration

Used to combine related constants (implicitly public static final) into one. The syntax is modifier enum Name {Const1, Const2, ...}.

public enum DogType {
    BORDER_COLLIE, GOLDEN_RETRIEVER, AKITA; //If you declare other fields and methods, write constants before that.
    private int hoge;        //Fields can also be declared
    public void doHoge() { } //Methods can also be declared
}

Like classes and interfaces, it can be declared as a top-level or nested type and is implicitly compiled as a final class (not extendable). Unlike nested classes, it cannot be declared inside a method. All enums are implicitly compiled as a subclass of java.lang.Enum, so you can't extend anything, but you can implement interfaces. Nested enums are implicitly static (may be explicit). Methods provided by the java.lang.Enum class.

`String final name()`
Returns the enumeration constant name as a string
`int ordinal()`
Returns the ordinal of an enumeration constant
`static > valueOf(Class type, String name)`
Returns an enumeration constant object that matches the enumeration constant with the name specified in the second argument from the enumeration type specified in the first argument
`static E valueOf(String name)`
Returns an enumeration constant that matches the enumeration constant with the specified name
`static E[] values()`
Returns an array of enums

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"));
	}
}

Execution result


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

constructor

Only private constructors are allowed. No argument is possible. Since it is a requirement to make it a Singleton and immutable object, specify the field value when creating the object (setter is not provided, getter only).

enum DogTypes {
    NA, SMALL(5), MEDIUM(10), LARGE(20);      //No-argument constructor, 5 arguments each, 10,For calling 20 constructors
    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());
    }
}

Up to here for this time.

Recommended Posts

Infrastructure shop study Java again (1st: Class design)
Java and Swift comparison (3) Class implementation / Class inheritance / Class design
Java class methods
[Java] Class inheritance
Let's study Java
java Scanner class
Java HashMap class
Java design pattern
java (abstract class)
[Java] Nested class
Java anonymous class
Java Design Patterns
About Java class
[Java] Study notes
Java 8 study (repeatable)
Java study memorandum
[java] abstract class
[Java] Object class
Java local class
Study Java Silver 1