あまりに寝苦しくて朝7時に起きるという快挙を成し遂げるも、12時くらいに睡魔に襲われて結局1時間ほど昼寝する。
そろそろタイ旅行の申込書を書かないとマズそうなので、わかる範囲で書いておく。明日もう一度見直してから送付しよう。
パスポートの交付に必要な葉書も送られてきたし、これで何とか旅行にいける最低限の条件は揃えることができそうだ。
今日から第二次設計変更の取り込み開始。のはずだったんだけど、設計変更に必要な資料が皆無ってのは一体何事だ。
今月第四週までに完全に終わらせないといけない上に、規模は前回の設計変更より大きそうだから、無駄な時間は使えない。
しかし、何をどう設計変更するのかの客先からの具体案が下りてこないと、開発サイドとしては全く着手できないっての。
さらに明日はパスポートの受け取りをしないといけないから早上がりしないといけないってのに、結構厳しい日々になりそうだ。
ここからはメモ書き。Javaでのオブジェクトのコピーがいまいちわかっていない人がいるから、その資料っぽいのを作ってみる。
import java.io.*;
public class test {
public static void main(String[] args) {
System.out.println("1.--------------------------------------------------\n");
try {
// インスタンスを別個に生成
test_1 t1A = new test_1();
test_1 t1B = new test_1();
// 情報設定
t1A.setString("t1A");
t1B.setString("t1B");
// 標準出力
// (t1A/t1B)
System.out.println("01:\tt1A.getString() = " + t1A.getString());
System.out.println("02:\tt1B.getString() = " + t1B.getString());
System.out.println("\n");
// 別個に生成したインスタンスの参照先を同じにする
t1A = t1B;
// 参照先が等しいため、オブジェクト比較でも等しいものとなる(true/true/true)
System.out.println("t1A == t1B -> " + (t1A == t1B));
System.out.println("t1A.equals(t1B) -> " + (t1A.equals(t1B)));
System.out.println("t1B.equals(t1A) -> " + (t1B.equals(t1A)));
System.out.println("\n");
// 標準出力
// (t1B/t1B)
System.out.println("03:\tt1A.getString() = " + t1A.getString());
System.out.println("04:\tt1B.getString() = " + t1B.getString());
System.out.println("\n");
// Aのインスタンスに情報設定
t1A.setString("t1AA");
// AとBの参照先が同じなので、Bを変えてなくてもAを変えると取得できる情報は同じ
// (t1AA/t1AA)
System.out.println("05:\tt1A.getString() = " + t1A.getString());
System.out.println("06:\tt1B.getString() = " + t1B.getString());
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("2.--------------------------------------------------\n");
try {
// Cloneableのインスタンスを別個に生成
test_2 t2A = new test_2();
test_2 t2B = new test_2();
// 情報設定
t2A.setString("t2A");
t2B.setString("t2B");
// 標準出力
// (t2A/t2B)
System.out.println("01:\tt2A.getString() = " + t2A.getString());
System.out.println("02:\tt2B.getString() = " + t2B.getString());
System.out.println("\n");
// Bの情報を元にAを作成
// implementsしたCloneableのclone()はExceptionをthrowするため、
// try - catch句内に記述が必須
t2A = t2B.cloneCopy();
// 参照先が異なるため、オブジェクト比較でも異なるものとなる(false/false/false)
System.out.println("t2A == t2B -> " + (t2A == t2B));
System.out.println("t2A.equals(t2B) -> " + (t2A.equals(t2B)));
System.out.println("t2B.equals(t2A) -> " + (t2B.equals(t2A)));
System.out.println("\n");
// 標準出力
// (t2B/t2B)
System.out.println("03:\tt2A.getString() = " + t2A.getString());
System.out.println("04:\tt2B.getString() = " + t2B.getString());
System.out.println("\n");
// Aのインスタンスに情報設定
t2A.setString("t2AA");
// AとBの参照先は別なので、取得できる情報は異なる
// (t2AA/t2B)
System.out.println("05:\tt2A.getString() = " + t2A.getString());
System.out.println("06:\tt2B.getString() = " + t2B.getString());
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("3.--------------------------------------------------\n");
try {
String[] s1 = null;
String[] s2 = new String[]{"1", "2", "3", "4", "5"};
// 参照先が同じになる
s1 = s2;
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
// s1の先頭を"0"にしただけで、s2の先頭も"0"になる
s1[0] = "0";
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("4.--------------------------------------------------\n");
try {
String[] s1 = null;
String[] s2 = new String[]{"1", "2", "3", "4", "5"};
// 配列はCloneableを実装
// この場合のclone()は例外を投げないため、try-catch句内である必要は無い
s1 = (String[])s2.clone();
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
// s1の先頭を"0"にしても、s2の先頭は"1"のままになる
s1[0] = "0";
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("5.--------------------------------------------------\n");
try {
String[][] s1 = null;
String[][] s2 = new String[][]{
{"1", "2", "3", "4", "5"},
{"A", "B", "C", "D", "E"},
{"あ", "い", "う", "え", "お"}};
// 配列はCloneableを実装
// この場合のclone()は例外を投げないため、try-catch句内である必要は無い
s1 = (String[][])s2.clone();
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
// s1の一次元目配列の先頭の二次元目配列の先頭を"0"にしても、
// s2の一次元目配列の先頭の二次元目配列の先頭は"0"になる
// (Object.clone()はShallow-Copyのため)
// コピー元とコピー先のインスタンス自体は別のものだが、
// そのインスタンスが内部で参照する構成要素は同じものとなる。
s1[0][0] = "0";
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("6.--------------------------------------------------\n");
try {
String[][] s1 = null;
String[][] s2 = new String[][]{
{"1", "2", "3", "4", "5"},
{"A", "B", "C", "D", "E"},
{"あ", "い", "う", "え", "お"}};
// 配列はCloneableを実装
// この場合のclone()は例外を投げないため、try-catch句内である必要は無い
s1 = (String[][])s2.clone();
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
// s1の一次元目配列の先頭を書き換えても、s2の一次元目配列は書き換わらない
s1[0] = new String[]{"0", "0", "0", "0", "0"};
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("7.--------------------------------------------------\n");
try {
String[][] s1 = null;
String[][] s2 = new String[][]{
{"1", "2", "3", "4", "5"},
{"A", "B", "C", "D", "E"},
{"あ", "い", "う", "え", "お"}};
// StringはSerializableを実装
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(s2);
ObjectInputStream ois =
new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
s1 = (String[][])ois.readObject();
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
// s1の一次元目配列の先頭の二次元目配列を書き換えても、
// s2の一次元目配列の先頭の二次元目配列は書き換えられず元の値を参照する
// 完全コピー(Deep-Copy)となる(完全に別物のインスタンス、参照先になる)
s1[0][0] = "0";
s1[0][4] = "9";
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("8.--------------------------------------------------\n");
try {
String[][] s2 = new String[][]{
{"1", "2", "3", "4", "5"},
{"A", "B", "C", "D", "E"},
{"あ", "い", "う", "え", "お"}};
String[][] s1 = new String[s2.length][s2[0].length];
// System.arraycopyを行う
System.arraycopy(s2, 0, s1, 0, s2.length);
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
// System.arraycopyはshallow-copyにつき、
// 別インスタンスの変数でも内部の参照先は同じになる
s1[0][0] = "0";
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("9.--------------------------------------------------\n");
try {
String[] s2 = new String[]{"1", "2", "3", "4", "5"};
String[] s1 = new String[s2.length];
// System.arraycopyを行う
System.arraycopy(s2, 0, s1, 0, s2.length);
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
// 一次元配列についてはshallow-copyでも問題ない
s1[0] = "9";
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("10.--------------------------------------------------\n");
try {
// System.arraycopyで二次元配列のdeep-copyを行う
String[][] s2 = new String[][]{
{"1", "2", "3", "4", "5"},
{"A", "B", "C", "D", "E"},
{"あ", "い", "う", "え", "お"}};
String[][] s1 = new String[s2.length][];
for (int i = 0; i < s2.length; i++) {
s1[i] = new String[s2[i].length];
System.arraycopy(s2[i], 0, s1[i], 0, s1[i].length);
}
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
// deep-copyにつき、全ての参照先が別個に保持される
s1[0][0] = "0";
s2[0][0] = "9";
s1[0][4] = "9";
s2[0][4] = "0";
new Utilities().printMessage(s1);
new Utilities().printMessage(s2);
System.out.println("\n");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class test_1 {
private String s = null;
public void setString(String _s) {
this.s = _s;
}
public String getString() {
return this.s;
}
}
class test_2 implements Cloneable {
private String s = null;
public void setString(String _s) {
this.s = _s;
}
public String getString() {
return this.s;
}
public test_2 cloneCopy() throws Exception {
return (test_2)super.clone();
}
}
UtilitiesクラスのprintMessage()は標準出力だと思って下さい。ってか、Arrays#deepToString()を使えばいいだけなんだが。
物凄い手抜きな資料だけど、これで意味わかってくれるかな。定数の定義についても講釈が必要そうな同期がいるしなあ。
public static final byte[] byteArrayCRLF = {0x0D, 0x0A};
こんな記述をしたところで、配列内の改行コードを示すバイトの値は変えられるっての。配列でfinal定義はあまり意味無い。
そもそも「FindBugs」でひっかかる記述をしている時点で、コーディングが間違っていると思うべき。何でこんなのを今さらねえ。
2015/12/31 追記
何でstaticメソッドでよさそうなものをnewして使ってたんだろう。この時ってJavaを始めて何年目だったっけかな。
予定は未定というヤツで、結局パスポートを取りに行けなかった。やる事が多すぎ、規模も大きいし今回はシャレにならん。
それにしても、java.math.BigIntegerを使ってビット計算なんかをする事になるとは思わなかった。勉強にはなったけどね。
明日からは自分の機能の設計変更要員で一人増えるんだけど、人が増えても手間が増えるだけだから作業効率は落ちる。
とりあえず今日一日で第二次設計変更の中の一つは結構消化できたから良しとしよう。まだ机上設計の段階なんだけど。
開発規模が致命的なまでにヤバい。明日で処理概要を固めないと月末のタイ旅行に行けなくなる可能性が出てきた。
末端機能の設計書は完成したのだが、それを実装する肝心の部分が不明のまま。検討用にサンプルソースを書きまくる。
水天宮で打ち合わせをしている人に電話で色々訊いてみたが、どうやらテーブルを使いたくないらしい。そんな無茶な。
そもそも明らかに新規機能だと思うのだが、何でそれが自分の受け持つ機能に実装されるのかすらも不明のままだったり。
とりあえず完成形が全く見えないままで他の設計も進めてはいるけど、月曜には決まってくれないと時間切れは必至だ。
クソ暑いのに何故かラーメンを食いたくなってしまい、34度の炎天下の中をラーメン目的で外出。5分後に後悔し始める。
昼飯を済ませてから帰宅して風呂入ってダラダラと。こんな暑い日に動けるはずがない。除湿の効いた部屋で本でも読む。
んで、読書中に買いたい本があったのを思い出すけど、既に22時を過ぎていたので諦める。タイの知識を用意しておかないと。