【Struts2】return SUCCESS;のSUCCESSが大文字で疑問だった話

- Java/Struts2 -
2019.11.09
struts2

こんにちは、ユーキです。

Struts2を学習し始めの時に地味に謎だったこと。

Struts2のActionクラス(xxxAction.java)って、途中の処理がどんなに複雑だとしても最後には

return SUCCESS;

return ERROR;

と成功した失敗したを喋るだけで単純なんだな〜と思っていたのですが、よく見たらこのSUCCESSとかERRORっておかしくないか?と。

僕の感じた謎ポイント"]

  1. なんでいきなり大文字で現れた?
  2. " "で囲まれてないから文字列じゃないな。かといってこんな変数を定義した覚えもない・・・じゃあ何なんだ?

結論:ActionSupportを継承してたのがミソ

結論から。

Q. SUCCESS / ERROR の正体は?

A. SUCCESS はString型の変数名で、中身は"success"という文字列。ERRORも同様。

Q. そんな変数はActionクラスで宣言してないけど?

A. Actionクラスで継承している"ActionSupportクラス"が実装している"Actionインタフェース"で宣言・初期化されてた

どういうことかというと

まず、以下のように自分で色々と処理を書いたActionクラスがActionSupportクラスを継承(extends)している前提のお話です。

Struts2 actionsupport

親であるActionSupportクラスを見てみると、以下の通りさらに"Action"というインターフェースを実装(implements)してます。

public class ActionSupport implements ★Action★, ...以下略

このActionSupportクラスでは、String SUCCESSという変数は宣言されていませんでした。

じゃあActionインターフェースで宣言されてんのかな?と思ったらやっぱりいました。

public interface Action {

    public static final ★String SUCCESS = "success";★

    public static final★String ERROR = "error";★

大元となるインターフェースで”success”という文字列が格納されたString型のSUCCESS変数が宣言済みだったので、そのインターフェースをimplementsしたActionSupportクラスをextendsしたLoginActionは、変数"SUCCESS"の宣言をすることなくいきなりSUCCESSを使える・・・というわけでした。

(インターフェースって?と疑問に思ったあなたはこのタイミングでググってみましょう。完璧に理解する必要はありません。とにかく疑問に思った瞬間に調べる癖をつけること)

これでいきなりActionクラスで"return SUCCESS"と書いてもOKな理由はスッキリしたのですが、SUCCESSという変数に"success"って文字列を入れるなんてなんでこんなワケわからんことするんだろ?staticとかfinalとか付いてるしという疑問が新たに浮かんできました。そして自信を持って答えられる回答が用意できていません。

がしかし、執筆時点での僕の一応の理解は以下。(ハードウェアとしてのメモリやstatic, final修飾子を知ってる必要ありです。ググってみましょう)

static修飾子をつけると変数はインスタンス間で1つだけ共有される。。。つまりActionインターフェースを実装したクラスが何個インスタンスを生成したとしてもSUCCESSというString変数用のメモリ領域は一箇所だけしか確保されずその一箇所が共有されるのでメモリの節約になる。もしstaticがつかない場合はインスタンス化されるたびに各インスタンス用に変数用メモリ領域が次々に消費されてしまう。

なぜそれぞれ別々の処理が実行されているであろうインスタンス間でString SUCCESS/ERRORという変数は共有しても大丈夫なのか?それは、SUCCESS/ERRORという変数の中身"success" "error"という文字列を途中で書き換える必要性はゼロだから。しかも間違えて変数の中身を書き換えられちゃったらstruts.xml側で表示用JSPの判断ができなくなって困るから、final修飾子を付けてSUCCESS, ERRORの中身は変更不可能にしちゃえ!(変数というか定数になってる)

(余計混乱させたらすみません)

そもそもfinal修飾子をつける場合は変数名を大文字にしましょう、っていう慣例があるんでしたね。完全に忘れてました。

これ、半年後とかに読み返したら「あの頃は青かったなぁ・・・」としょっぱい気持ちにかられるんだろうなぁ・・・。

豆知識:一瞬で宣言元のクラスファイルへワープする方法

Eclipseで開いているクラスファイルのextends ●●の「●●」をクリックしてマウスカーソルが当たった状態にして、Windowsならctrlキー、MacならCommandキーを押しながらマウスカーソルを下にずらすと

「宣言を開く」
「実装を開く」

という選択肢がポップアップするので、「宣言を開く」をクリックするとクラスファイルへ一瞬でひとっ飛びできます。

ちなみにメソッドでも一瞬で記載元のファイルへ飛べるので「このメソッドを書いてるファイルをわざわざ探して開く」という手間が省けてかなーり便利です。