• 2019年5月1日水曜日
アリスト戦記
アリスト戦記 https://blog.aristo-solutions.net/2019/05/javatemplatebatchmain.html

mainクラスから自分自身のインスタンスを作成する

他人のソースを見ていて凄く疑問に思うことなんだが、もしかして、自分自身をnewしてインスタンスを作ることは出来ないとでも勘違いしていないか?

そんなこと無いからな!!

状況説明

Javaバッチの実行で最初に来るのは「mainメソッド」を持っているクラスだが、そのmainメソッドはstaticクラスである。

そして、staticクラスの中からメソッドを呼び出すには、呼び出される側もstaticである必要がある。

public class MyClazzInstanceExecuter {

 private static final Logger log = LoggerFactory.getLogger(MyClazzInstanceExecuter.class);

 /**
  * @param args
  */
 public static void main(String[] args) {

  /*
   * mainメソッドからの実行は、mainがstaticであるため、呼ばれる側もstaticメソッドしか出来ません。
   */
  start();

 }

 public static void start() {

  log.info("static実行しています。");

 }

}

これが既におかしくって!!

問題点

上記のソースの場合、「startメソッド」がstaticである意味なんて無いだろ!!

バッチを作っていると、クラス設計として、mainの入力パラメータやバッチの二重起動チェックはmainクラス内に書きたいと思うことがある。

それは正しいんだけど、ソースを見ると、何故かそれら全てがstaticメソッド……。
そりゃ動くことは動くだろうけど、汚ねぇなぁ……。

これはね、自分自身をnewしてインスタンスを作ることが出来るという着想が欠落しているとしか思えないんだよね。

  • newでインスタンスを作る対象は他クラスだけが対象ではない。
  • 自分自身のクラスを対象にインスタンスを作ることも出来る。

サンプルを見ればすぐに分かる。

サンプル

これがサンプルだ。

public class MyClazzInstanceExecuter {

 private static final Logger log = LoggerFactory.getLogger(MyClazzInstanceExecuter.class);

 /**
  * @param args
  */
 public static void main(String[] args) {

  /*
   * mainメソッドから直接メソッドを実行しようとすると、他のメソッドも全部staticにしなければならない。
   * しかし、自分自身をnewしてインスタンスを作成することは出来ますので、
   * それを使えばより自然に実装が出来るでしょう。
   */
  MyClazzInstanceExecuter exe = new MyClazzInstanceExecuter();
  exe.start();

 }

 public void start() {

  log.info("自分自身のクラスをnewしてインスタンスを作成することが出来ます。");

 }

}

「あっ!?」とか思う人もいるのではないだろうか?
コロンブスの玉子と言うか、全く普通の実装である。

staticの意味

これが分からん人は、単に「Eclipseが赤くなっちゃったぞ」とかそんなレベルの認識で実装している恐れがあるから、staticの意味を説明しておこう。


  • staticメソッドはクラスに紐づいているメソッドという意味だ。
  • 普通のメソッドはインスタンスに紐づいている。


どういうことかって言うと、普通のメソッドは一回newしてインスタンスを作成しないと実行できないでしょ?
対して、staticメソッドはクラスに紐づいているからnewしなくても使える。

ならば「だったら全部staticでも良いんじゃないか?」と思うかもしれないが、そうではない。

Javaにはガベージコレクションというものがあって、不要なインスタンスをガベージコレクションで消すことで、メモリが綺麗に掃除されていく。
しかし、staticにしてしまうと基本的にはガベージコレクションの対象にならない。

だから、ガベージコレクションを有効に機能させるため、処理はインスタンス配下に書くのが基本である。

では、基本に即さないでstaticに書く場合は何があるか?

それは、例えばインスタンスを作る負荷が勿体ないとかだな。

ApacheCommonsにStringUtilsというクラスがあるが、あの手のちょっとしたツール処理は呼び出す側で毎回newしてインスタンスを作ると、そのインスタンス作成の負荷が勿体ないじゃないか。
あっちこっちで何度も使うことも多いし、そういう使いまわしの意識がある処理はstaticでやるんだ。

処理負荷、チューニング観点の話なわけよ。

対して、上記サンプルのstartメソッドに使いまわしなんか無いでしょ?
今実行し、終わったら消えてくれれば良いんだ。
だからインスタンスにぶら下げる方が正解。

もちろんバッチ処理の場合、終わったら仮想マシン諸共全部消えるから、staticで書いたとしても現実として問題にはならない。

しかし、世の中ってのは何事も原理原則ってものがあって、特に理由が無ければ原理原則に従うものじゃないか。

staticで書く特別な理由が無いなら、インスタンスで書くのが原理原則である。

と言うわけで、Javaで実装していく場合は、staticの使いどころはなるべく意識して気を付けて欲しいと思う。

0 件のコメント:

コメントを投稿