JavaSE

http://www.oracle.com/technetwork/java/javase/documentation/index.html

Java SE 7 2011/07/28

Java SE 8 2014/03/18

Java SE 9 2017/09/21

Java SE 7(本家サイトを参照)

Java SE 8(本家サイトを参照)

記法順番

Annotations

public / protected / private

abstract

static

final

transient

volatile

synchronized

native

strictfp

Java 初期化

原則

public class Initializer {

static {

// Step 1 クラスのロード時に実行

}

{

// Step 2 コンストラクタ前に実行

}

public Initializer() {

// Step 3 インスタンスの生成時に実行

}

}

継承の場合

public Parent(){}

public Child(String name){

super(); // 省略可

}

public Parent(String name){}

public Child(String name){

super(name);

}

サンプル

public class Parent {

static {

System.out.println("parent static block");

}

{

System.out.println("parent block");

}

public Parent() {

System.out.println("parent constructor");

}

}

class Child extends Parent {

static {

System.out.println("child static block");

}

{

System.out.println("child block");

}

public Child() {

System.out.println("child constructor");

}

}

// テスト

new Child();

System.out.println("==============");

new Child();

出力:

parent static block

child static block

parent block

parent constructor

child block

child constructor

==============

parent block

parent constructor

child block

child constructor

インスタンス作成

1.new コンストラクタを呼び出す

Employee emp = new Employee();

2.Class#newInstance コンストラクタ(引数なし)を呼び出す

Employee emp = (Employee) Class.forName("xxx.Employee").newInstance();

或いは

Employee emp = Employee.class.newInstance();

3.Constructor#newInstance コンストラクタ(private可)を呼び出す

Constructor<Employee> constructor = Employee.class.getConstructor();

Employee emp = constructor.newInstance();

4.clone (implements Cloneable)

Employee emp = (Employee) emp.clone();

5.Deserialize (implements Serializable)

ObjectInputStream in = new ObjectInputStream(new FileInputStream("data"));

Employee emp = (Employee) in.readObject();

Javaで擬似的な多重継承

interface Father{

public int strong();

}

interface Mother{

public int kind();

}

class FatherImpl implements Father{

public int strong(){

return 8;

}

}

class MotherImpl implements Mother{

public int kind(){

return 8;

}

}

class Son extends FatherImpl implements Mother{

@Override

public int strong{

return super.strong() + 1;

}

@Override

public int kind(){

// ★書き方1

return new MotherSpecial().kind();

}

private class MotherSpecial extends MotherImpl{

@Override

public int kind(){

return super.kind() - 1;

}

}

}

class Daughter extends MotherImpl implements Father{

@Override

public int kind{

return super.kind() + 1;

}

@Override

public int strong(){

// ★書き方2

return new FatherImpl(){

@Override

public int strong(){

return super.strong() - 1;

}

}.strong();

}

}

一般クラス作成フォーマット

import java.io.Serializable;

public class Test implements Comparable<Test>, Cloneable, Serializable {

private static final long serialVersionUID = 1L;

@Override

public int hashCode() {

// do something

}

@Override

public boolean equals(Object obj) {

// do something ※判断基準はcompareToと一致

}

@Override

public String toString() {

// do something

}

@Override

public Object clone() {

// do something

}

@Override

public int compareTo(Test t) {

// do something ※判断基準はequalsと一致

}

}

※ソート後、位置が同じ = 値が同じ

メソッド名、行目、ファイル名を取得

String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();

或いは

String methodName = new Throwable().getStackTrace()[0].getMethodName();

String lineNumber = Thread.currentThread().getStackTrace()[2].getLineNumber();

String fileName = Thread.currentThread().getStackTrace()[2].getFileName();

ラベルの用法

複数ループから脱出

label:

for (int i = 0; i < 10; i++) {

for ( int j = 0; j < 10; j++) {

System.out.println("i=" + i + ",j=" + j + "\t");

if(i == j) {

break label;

}

}

}

System.out.println("次の処理");

★Null Pointer Exception対策

対策1

if (target.equalsIgnoreCase("xxx")) { ×

if ("xxx".equalsIgnoreCase(target)) {

...

}

String str = target.toString(); ×

String str = String.valueOf(target);

対策2

public static T getXXX() {

return null; ×

return Collections.EMPTY_LIST;

return Collections.EMPTY_SET;

return Collections.EMPTY_MAP;

}

対策3:チェック

boolean isExist = list.contains(target);

int index = list.indexOf(target);

boolean isEmpty = list.isEmpty();

boolean isExist = map.containsKey(target);

boolean isExist = map.containsValue(target);

boolean isEmpty = map.isEmpty();

boolean isExist = set.contains(target);

boolean isEmpty = set.isEmpty();

boolean isExist = iterator.hasNext();

対策4:ApacheのStringUtils

StringUtils.isEmpty()

StringUtils.isBlank()

StringUtils.equals()

対策5:

Annotation@NotNullと@Nullableを利用し、IDEが管理してくれる

対策6:

Null Object Pattern

・nullの判断が不要

interface Log {

void write(String msg);

public static final Log NULL = new Log() {

@Override

public void write(String msg) {} // do nothing

};

}

class FileLog implements Log {

private final FileWriter out;

public FileLog(String fileName) throws IOException {

out = new FileWriter(fileName, true);

}

@Override

public void write(String msg) {

// do something

}

}

class ConsoleLog implements Log {

@Override

public void write(String msg) {

System.out.println(msg);

}

}

class Service {

private final Log log;

Service() {

this.log = Log.NULL;

}

Service(Log log) {

this.log = log;

}

public void handle() {

log.write("xxx");

}

}

★C#のFuncと似るJavaコード(Guava)

import com.google.common.base.Function;

Function<K, T> func = new Function<K, T>() {

@Override

public T apply(K arg0) {

...

}

};

func.applay(xxx);

★ComparableとComparator

class Employee implements Comparable<Employee>{

private int id;

private String name;

private Position position;

// constructor

// getter/setter

@Override

public int compareTo(Employee o){

return this.id - o.getId(); // 昇順+

return o.getId() - this.id; // 降順-

}

}

List<Employee> list = new ArrayList<Employee>(3);

...

Collections.sort(list);

Collections.reverse(list); // 逆に並び替える

TreeSet<Employee> set = new TreeSet<Employee>();

class IdComparator implements Comparator<Employee>{

@Override

public int compare(Employee o1, Employee o2){

return o1.getId() - o2.getId(); // 昇順+

return o2.getId() - o1.getId(); // 降順-

}

}

List<Employee> list = new ArrayList<Employee>(3);

...

Collections.sort(list, new IdComparator());

Collections.sort(list, Collections.reverseOrder(new IdComparator())); // 逆に

TreeSet<Employee> set = new TreeSet<Employee>(new IdComparator());

複数の条件でソート

class XXXComparator implements Comparator<Employee>{

@Override

public int compare(Employee o1, Employee o2){

if( o1.getPosition().compareTo(o2.getPosition()) == 0 ){

return o1.getId() - o2.getId(); // IDでソート

}else{

return o1.getPosition().compareTo(o2.getPosition()); // Posでソート

}

}

}

結論

・Comparable:デフォルトソート用

・Comparator:拡張ソート用

Utilsクラスの作り方

public final class Utils{

private Utils(){

throw new Error("インスタンス化できない"); //Reflectionを防ぐ

}

//implementation

}

理想なequals(), hashCodeの書き方

public class Person {

private String name;

private double salary;

public Person(String name) {

this.name = name;

}

// getter・setter

/**

* List中に比べる

*/

@Override

public boolean equals(Object obj) {

if (obj == this) {

return true;

}

if (!(obj instanceof Person)) { // 親子関係を考慮

return false;

}

Person p = (Person) obj;

return p.name == this.name && Double.compare(p.salary, this.salary);

return Objects.equal(p.name, this.name); // Guava

}

@Override

public boolean equals(Object obj) {

if(obj != null && obj.getClass() == this.getClass()){ // 親子関係を考慮せず

Person p = (Person)obj;

if(p.getName() == null || name == null){

return false;

}else{

return name.equalsIgnoreCase(p.getName());

}

}

return false;

}

/**

* Map中に比べる

* 1.hashCode()が同じかどうか 2.equals()が同じかどうか

*/

@Override

public int hashCode() {

// org.apache.commons.lang.builder

return new HashCodeBuilder().append(name).toHashCode();

return Objects.hashCode(getX(), getY(), getZ()); // Guava

}

@Override

public String toString() {

return String.format("%s.name=%s", this.getClass(), name);

}

}

equals()が同じ⇒hashCode()が同じ ○

hashCode()が同じ⇒equals()が同じ ×

Code Block用法

public class Client extends SuperClient{

{

// インスタンス変数を初期化

// インスタンス環境を構築

}

public Client(){

// do something

}

public Client(String str){

// do something

}

public Client(int i){

this();

}

public Client(float f){

super();

}

}

下記と同じ

public class Client extends SuperClient{

public Client(){

// インスタンス変数を初期化

// インスタンス環境を構築

// do something

}

public Client(String str){

// インスタンス変数を初期化

// インスタンス環境を構築

// do something

}

public Client(int i){

this();

// ※ここはCode Block処理がない

}

public Client(float f){

super();

// インスタンス変数を初期化

// インスタンス環境を構築

}

}

他のプログラムを実行

Process pr = null;

try {

pr = Runtime.getRuntime().exec("C:\\temp\\xxx.exe");

int result = pr.waitFor();

if(result == 0){

System.out.println("Success");

}else{

System.out.println("Failure");

}

} catch (IOException e) {

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}

OSのコマンドを実行

List<String> cmdList = new ArrayList<String>();

cmdList.add("C:\\temp\\xxx.exe");

ProcessBuilder builder = new ProcessBuilder(cmdList);

List<String> list = builder.command();

for (String str : list) {

System.out.println(str);

}

System.out.println(builder.directory());

try {

Process pr = builder.start();

int result = pr.waitFor();

if(result == 0){

System.out.println("Success");

}else{

System.out.println("Failure");

}

} catch (IOException e) {

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}

信頼できないオブジェクト

1.可変なメンバ

class Dummy {

private Date date;

public Dummy() {

date = new Date();

}

public Date getDate() {

//return date;

return (Date) date.clone();

}

}

2.可変な配列メンバ

class Dummy {

private Date[] date;

public Dummy() {

date = new Date[10];

for (int i = 0; i < date.length; i++) {

date[i] = new Date();

}

}

public Date[] getDate() {

//return date;

//return date.clone(); shallow clone

Date[] dates = new Date[date.length];

for (int i = 0; i < date.length; i++) {

dates[i] = (Date) date[i].clone(); // deep clone

}

return dates;

}

}

3.不変オブジェクトを持つ可変メンバ

class Dummy {

private HashMap<Integer, String> values = new HashMap<Integer, String>();

public Dummy() {

values.put(1, "aaa");

}

public HashMap<Integer, String> getValues() {

//return values;

return (HashMap<Integer, String>) values.clone();

}

}

4.java.nioパッケージのバッファクラス

ケース1

class Dummy {

private char[] dateArray;

public Dummy() {

dateArray = new char[10];

}

public CharBuffer getBufferCopy() {

方法1

return CharBuffer.wrap(dateArray); ×

return CharBuffer.wrap(dateArray).asReadOnlyBuffer(); 〇

方法2

CharBuffer cb = CharBuffer.allocate(dateArray.length);

cb.put(dateArray);

return cb;

}

}

ケース2

class Dummy {

private CharBuffer cb;

public Dummy() {

cb = CharBuffer.allocate(10);

}

public CharBuffer getBufferCopy() {

return cb.duplicate(); ×

return cb.asReadOnlyBuffer(); 〇

}

}

※IntBuffer、ByteBufferも同様

Immutable class

Pattern 1

public final class ImmutableClass {

@Getter

private final int id;

@Getter

private final String name;

private final Date date;

public Date getDate() {

return new Date(date.getTime());

}

private final HashMap map;

public HashMap getTestMap() {

return (HashMap) map.clone();

}

private final List<String> list;

public List<String> getList() {

return Collections.unmodifiableList(list);

}

// deep copy

private ImmutableClass(int id, String name, Date date, HashMap map){

this.id = id;

this.name = name;

this.date = new Date(date.getTime());

HashMap tempMap = new HashMap();

String key;

Iterator it = map.keySet().iterator();

while(it.hasNext()){

key = it.next();

tempMap.put(key, map.get(key));

}

this.map = tempMap;

}

public static ImmutableClass createNewInstance(

int id, String name, Date date, HashMap map) {

return new ImmutableClass(id, name, date, map);

}

}

Pattern 2 (Builder Pattern)

public class ImmutableClass {

//required fields

@Getter

private int id;

@Getter

private String name;

//optional fields

@Getter

private String company;

private HashMap properties;

public HashMap getProperties() {

return (HashMap) properties.clone();

}

private ImmutableClass(ImmutableClassBuilder builder) {

this.id = builder.id;

this.name = builder.name;

this.properties = builder.properties;

this.company = builder.company;

}

public static class ImmutableClassBuilder{

private int id;

private String name;

private HashMap properties;

private String company;

public ImmutableClassBuilder(int id, String name){

this.id = id;

this.name = name;

}

public ImmutableClassBuilder setProperties(HashMap map){

this.properties = (HashMap) map.clone();

return this;

}

public ImmutableClassBuilder setCompany(String company){

this.company = company;

return this;

}

public ImmutableClass build(){

return new ImmutableClass(this);

}

}

}

ImmutableClass immutableClass = new ImmutableClass

.ImmutableClassBuilder(101, "Andy")

.setCompany("XXX")

.setProperties(map)

.build();

Covariant return types

class Grain {}

class Wheat extends Grain {}

class Mill {

Grain process() {

return new Grain();

}

}

class WheatMill extends Mill {

@Override

Wheat process() {

return new Wheat();

}

}

Mill m = new Mill();

Grain g = m.process(); // Grain

m = new WheatMill();

g = m.process(); // Wheat