- PR -

JSPで別クラスのpublic static finalフィールドを使用した場合のデプロイ作業について

投稿者投稿内容
YOU@IT
ぬし
会議室デビュー日: 2002/03/29
投稿数: 284
お住まい・勤務地: 大阪
投稿日時: 2004-09-21 17:38

定数のインラインについては、以前以下のようにして対応したことがあります。

public static final String STRING_VALUE = new String("VALUE");
public static final int INT_VALUE = new Integer(100).intValue();

たしかこれでインライン展開されなくなったと記憶しています。
# 随分前のことなので少々自信がないのですが。

Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2004-09-21 18:01
引用:

YOU@ITさんの書き込み (2004-09-21 17:38) より:

定数のインラインについては、以前以下のようにして対応したことがあります。

public static final String STRING_VALUE = new String("VALUE");
public static final int INT_VALUE = new Integer(100).intValue();

たしかこれでインライン展開されなくなったと記憶しています。
# 随分前のことなので少々自信がないのですが。


確かに展開されなくなりますね。ただし、INT_VALUEはcase文にも使えなくなりますけど
まあ、どうせswitch文なんてプリミティブの数値型にしか使えないし、みつけたら片っ端から
ポリモフィズムを使って置き換えてしまった方がいいような代物なので、問題ないかな?

ただし、ソースには「インライン展開抑止のため」ってコメントに書いておいた方がよさそうですね。
torakiyojp
常連さん
会議室デビュー日: 2004/08/04
投稿数: 23
投稿日時: 2004-09-21 18:16
皆様、ご回答ありがとうございます。
皆様のご意見を参考に他の者とも相談した結果、とりあえず次回のデプロイからはプリコンパイル機能を使ってみることとなりました。
プリコンパイル機能で何か問題があった場合はキャッシュ、CLASSファイルの削除等の対応をするかと思います。
public static finalフィールドのみの宣言を行っているクラスをいじって(アクセサ追加や初期化の工夫等)の対応は今のところしないこととなりました。
皆様、多くの意見ありがとうございました。


おばけ
ぬし
会議室デビュー日: 2002/11/14
投稿数: 609
お住まい・勤務地: 東京都江東区
投稿日時: 2004-09-21 18:27
引用:

と、私も思っていたのですが、念のため調べてみるとそうではないようです。
「Java言語仕様第2版」の§13.4.8「finalフィールドと定数」によると、
・・・略・・・


ま、マジですか・・・ことごとく嘘を言ってしまった・・・orz
発言するのが怖いです(ToT)

引用:

言語仕様には、「final定数は"本当に変わらない値"にだけ使うのが良い」
なんてことも書いてあります。円周率とか光速とかですかね。


そ、そりゃあないっしょ・・・って感じですね
何のための定数なんだか。

でも、言語仕様でデフォルトでインライン化しちゃうっていうのはどうもなあ。
インライン化っていうのは、オプティマイズの一種だと思うんですが。。。
私が頭が固いだけ??

[ メッセージ編集済み 編集者: おばけ 編集日時 2004-09-21 18:28 ]
でゅうく
大ベテラン
会議室デビュー日: 2003/11/30
投稿数: 129
投稿日時: 2004-09-21 19:52
引用:

おばけさんの書き込み (2004-09-21 18:27) より:
でも、言語仕様でデフォルトでインライン化しちゃうっていうのはどうもなあ。
インライン化っていうのは、オプティマイズの一種だと思うんですが。。。
私が頭が固いだけ??


コンパイラ実装ごとに挙動が変わるのも何なんで、言語仕様で規定しちゃえってことですかね。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-09-21 20:10
unibon です。こんにちわ。

引用:

YOU@ITさんの書き込み (2004-09-21 17:38) より:
public static final String STRING_VALUE = new String("VALUE");
public static final int INT_VALUE = new Integer(100).intValue();

たしかこれでインライン展開されなくなったと記憶しています。


こんな姑息な、もとい、すごいワザがあったとは。これを知らなかったので、私は今まで、フィールドにせずにメソッドにして対処していました。

コード:
public static int intValue() {
    return 100;
}


のように。

引用:

Wataさんの書き込み (2004-09-21 18:01) より:
確かに展開されなくなりますね。ただし、INT_VALUEはcase文にも使えなくなりますけど


これもすごいですね。これを逆手に取れば、定数がインライン展開されるかどうかをすぐに知りたい時には、たとえば Eclipse 上で switch に書いてエラーになるかどうかを試せば良いわけですよね。
じゃばら
会議室デビュー日: 2004/05/24
投稿数: 10
お住まい・勤務地: 福岡
投稿日時: 2004-09-21 22:23
私が「コンパイラに依るかも」と書いてしまった張本人です。
調査せずにてきとうなことを言ってしまって、申し訳ないです。

私がインライン展開防止によく使う手は、列挙用途の int 値定数を
SafeEnum パターンの列挙型クラスに置き換えることです。

最初の方でぼんさんが書かれてますね。

引用:

ぽんさんの書き込み (2004-09-21 15:14) より:
[参考]
「Effective Java」のSafeEnumパターンを調べて見ると良いと思います



この手法は他にもたくさんメリットがあり、おすすめです。
J2SE 5.0 では言語仕様に盛り込まれていますね!
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-09-24 01:52
この現象、実感したことはないので一応実験。
・元のコード
コード:
-------------Constants.java
public interface Constants{
  int INT_VALUE=10;
   int ADDED_VALUE = 5+5;
  int INTEGER_INT_VALUE = new Integer(10).intValue();    String STRING_VALUE = "string";
   String STRING_TOSTRING_VALUE = "string".toString();
}
-------------ConstantsTest.java
public class ConstantsTest implements Constants{
  public static void main(String args[]){
    System.out.println(INT_VALUE);
    System.out.println(ADDED_VALUE);
    System.out.println(INTEGER_INT_VALUE);
    System.out.println(STRING_VALUE);
    System.out.println(STRING_TOSTRING_VALUE);
  }  
}


・コンパイル、実行
$ javac *.java
$ java ConstantsTest
10
10
10
string
string

・コンパイル後、jad で ConstantsTest.class を逆コンパイル
コード:
// Decompiled by Jad v1.5.8c. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   ConstantTest.java

import java.io.PrintStream;

public class ConstantsTest
    implements Constants
{

    public ConstantsTest()
    {
    }

    public static void main(String args[])
    {
        System.out.println(10);
        System.out.println(10);
        System.out.println(Constants.INTEGER_INT_VALUE);
        System.out.println("string");
        System.out.println(Constants.STRING_TOSTRING_VALUE);
    }
}


なるほど、確かにインライン展開されていますね。

※MacOSX10.3.5 / JDK1.4.2_05 にてテストしました
$ java -version
java version "1.4.2_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_05-141.3)
Java HotSpot(TM) Client VM (build 1.4.2-38, mixed mode)

スキルアップ/キャリアアップ(JOB@IT)