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