その時に書きたいものを書きます

その時に書きたいものを書くんです

なぜVectorではなくArrayListなのか

おじいちゃんPGがVector使ってて頑なにArrayListを使わなかったので、まあどうせ時代についていけないだけなんだろうなと思ったけど一応ちゃんと調べてみた。レガシーで後方互換のために残ってるとは聞いてたけど実際どうなんだと。

同期のためにVectorは使わない(VectorとCollections.synchronizedList) - プログラマはサイコロを振らない

ここにだいたい書いてあった。

まとめ

  • Vectorは古いので基本使わない
  • Vectorはスレッドセーフ、ArrayListはスレッドセーフではないという違いはあるが、Collections.synchronizedListを使えばスレッドセーフなArrayListも作れる

ということでVectorのいいところ無いやんか!!!

staticファクトリーメソッド

オブジェクトの提供者は、コンストラクタだけではない。 staticなメソッドでオブジェクトを返すようにする方法もある。 コンストラクタでのオブジェクト提供を無意識に行わないよう注意。

StaticFactoryMethod.java

package test;

public class StaticFactoryMethod {
    
    private static StaticFactoryMethodImplA implA = new StaticFactoryMethodImplA();
    private static StaticFactoryMethodImplB implB = new StaticFactoryMethodImplB();
    
    public static IStaticFactoryMethod getStaticFactoryMethod(int num){
        if (num <= 64){
            return implA;
        }else{
            return implB;
        }
    }
    
    @Override
    public String toString(){
        return "StaticFactoryMethodクラスです";
    }
}

//インターフェイス
interface IStaticFactoryMethod {
    public String getName();
}

//実装クラス
class StaticFactoryMethodImplA implements IStaticFactoryMethod{
    @Override
    public String getName() {
        return "IStaticFactoryMethod実装クラスA";
    }
} 

//実装クラス
class StaticFactoryMethodImplB implements IStaticFactoryMethod{
    @Override
    public String getName(){
        return "IStaticFactoryMethod実装クラスB";
    }
}

Main.java

package test;

public class Main {

    public static void main(String[] args) {
        
        IStaticFactoryMethod impl = StaticFactoryMethod.getStaticFactoryMethod(63);
        
        System.out.println(impl.getName() + "デェス");

    }

}

staticファクトリーメソッドのメリット

デメリット

  • publicあるいはprotectedのコンストラクタを持たないクラスのサブクラスを作れない
  • それらが容易に他のstaticメソッドと区別がつかない

シリアライズ!!!

オブジェクトのシリアライズについて

参考:

上記リンクを見れば大体わかる。 シリアライズは直列化という日本語役らしい。ちょっとしっくりこないけど間違ってはいない模様。プカプカもやもや浮いてるオブジェクトを、受け渡しやすい一本の直線に整形するみたいなイメージやろか。

とにかくjava.io.Serializableインターフェイスを実装したオブジェクトはシリアライズが可能になる。このインターフェイスは特にメソッドの実装は要求しない(所謂マーカインターフェイス)。

serialVersionUID奴

eclipseでよく見る奴。これはいったい何なのか。
参考:

簡単に言うとシリアル状態からオブジェクトに戻す時の鍵みたいなもの。鍵というか照合するもの。
たとえばネットワーク越しにあるオブジェクトをシリアル化して受け渡すとき、受け渡し元と受け渡し先でそのクラスの構造が同じことが保証できない可能性がある。リリースのズレとかでね。
こういうことが起きた場合に復元しようとすると、InvalidClassExceptionが発生する。これで受け渡し元と先で差異が発生していることを検知することができる。
しかし、例えばあるオブジェクトをシリアライズしてファイルに永続化したとして、その時に指定してあったUIDが例えば123だったとして。その後そのクラスに変数が追加されたりした(なのでUIDも125に改めた)あと、改めてその永続化されたオブジェクトをデシリアライズして取り出そうとする場合。UIDが123と125で差があるので、Exceptionが発生してしまう。こういったことをする場合、たとえクラスに変更があったとしても、UIDは改めるべきではなく、123のままにしておく必要があると思われる。これは永続化したデータと最新のソースの間でオブジェクトの整合性を取ろうとするときに必要な考え方。ちなみにこの時UIDを定義しない(自動生成に任せる)方法をとっておいてしまうと、最初に自動生成されるUIDが843、最後に自動生成されるUIDが234みたいなことになり、やはり整合性が取れない。やはり明示的に123といったUIDをずっとつけておく必要があると思われる。

Webアプリケーションは基本的にマルチスレッド?

という結論でいいらしい。

VBでDesktopアプリケーションしか作ってなかったせいか、スレッドという概念が欠落していた模様。

ちまたでよく「スレッドセーフ」という言葉を耳にして「なんのこっちゃ?」状態でした。

JavaでWebをやり始めてやっと「スレッドセーフ」という言葉が腹落ちした。

サーバのVM上でPlayframeworkのアプリケーションが動いているとする。 Playframeworkのスレッド数は、

DEVモード - 1
PRODモード - 環境で利用可能なCPU数 + 1

らしい。 (参考:Playframeworkとスレッド数 - フレクトのHeroku Lab)

PRODモードで、利用可能なCPUが4だった場合、5スレッド用意されることになる。

2つのクライアントから同一のactionに同時にアクセスが来た場合、Framework側が「こっちのアクセスはこっちのスレッド、こっちのアクセスはこっちのスレッドでやってね」っていうことをやってくれる。結果、同じメソッドが別スレッドで実行されることになる。

スレッドは別とはいえ、その2つのスレッドは同じVM上で動いており、static変数などは共有されることとなる。

ここで2つのスレッドからこの共有財産にアクセスしようとすると、不整合が起きてしまう可能性が出てくる。

シングルスレッドで問題なく処理が完了するWindowsのDesktopアプリケーションを作っているときには働かなかった頭だ。

だがやっと理解できた。

これからは注意してマルチスレッドを見ていこう。

しかしこういう基本的なところをわかりやすく説明してくれてるページが意外となかなか見つからなくて困る。

StringBufferに文字追加していくのとStringに文字追加していくの違うの?

Stringは+=するたびにオブジェクトが作成されていく。

str +="a";
str +="b";
str +="c";

ってやるとオブジェクト3つできてしまうわけ。最終的にstrは"abc"だけども。

shallow copyについて

class Hoge implements Cloneable{
    public int intHoge = 0;
    public String[] arrHoge = new String[];
    public Hoge createClone(){
        Hoge hoge = null;
        try {
            hoge = (Hoge)clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return hoge;
    }
}

Hoge hoge = new Hoge();
Hoge fuga = hoge.createClone();

みたいなことをしたときにHoge型のオブジェクトは2個になるが、その中で定義されている配列arrHogeは1個しか存在しないことになる。それがshallow copy