Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

super class のインジェクションってどうやるんすか?

public class A implements Serializable {
   private int a;

   private void readObject(ObjectInputStream s) {
       synchronized(PrivateUtil.lock) {
           this.a = PrivateUtil.getInt("a");
       }
   }
}

public class B extends A {
   int b;
}


B クラスの b は Method.setAccessible() と
Method.set() を使えばできる。

A クラスの a を インスタンスBが作成された時点で書
き換えたいのですが、シリアライズで PrivateUtil な
るユーティリティ経由で synchronized ロックしてごに
ょごにょすれば出来そうな予感があるのですが、
public class PrivateUtil {
   public static Object lock = new Object();
   private static Object obj;

   public static void setVal(Object o) {
      synchronized(lock) {
          obj = o;
      }
   }
   public static int getInt() {
      if (obj instanceof Number) return 
((Number)obj).intValue();
      throw new RuntimeException("dame;;");
   }
}
出来そうな予感だけで実際に試してないのです。試した
くないくらい嫌な予感しかしないので、なんとか、シリ
アライズ以外で何か方法ありませんか?

3

回答

12054

閲覧

3件の回答

評価

0

どういう状況で何をしたいかが全然分からん。
PrivateUtilとやらも、定義と実使用が合ってないし。

とりあえず、親のprivateを子が書き換えるのが「おかしい」
のは明らかだが。
親のコンストラクタではだめなんだろうか。

評価

0

super クラスの private 変数を書き換えたいって話です。

public class A {
   private int a;
}
public class B extends A {

}
A a = new B();

Field f = a.getClass().getField("a");
f.setAccessible(true);
f.set(a, "OK");
が出来ないから、別の手段は無いのか?ということです。

インジェクション関連の(通常の手順では出来ない、というか普
通そんなのやることに何の意味があるのか?という疑問しか沸か
ない)話題なので、実利用用途とかそんな次元の話ではないのが
残念なんですが・・・

強いて用途と言えば、

public class FormBean {
   @In
   private Logger logger;
}
@Form("ScreenXX")
public class ScreenXXForm extends FormBean {
   
}

サーブレットで、
Object form = 
Class.forName("xxx.xxx.xxx.ScreenXXForm").newInstance();

ReflectUtil.injectSuper("logger", 
LogUtil.getLogger(session.getSessionId()));

こんな用途を想定してます。

「ログにそのスレッド固有のプロパティを固定表示させたいなん
てとき」に限ればもっと一般的な方法もあるでしょうけど、
super クラスの injecition ができるなら、用途の可能性は未知
数ですが、これもまた一般解のひとつになりえませんか、という
程度の疑問です。


最初の書き込みのシリアライズの話は、
newIsntance() したクラスを ObjectOutputStream 経由でシリア
ライズして byte[] データにしたものを、ObjectInputStream で
復元する際に、readObject() が正常な復元に+αの復元操作が
出来るのでこれを 「super クラスに inject すること」の代用
手段として考えたわけです。ですが、super クラス個々に同じ実
装を入れなくちゃならないコストと、派生クラスが巨大なときの
シリアル・デシリアルに掛かる時間コストを考慮するとあまり現
実的ではないのと、PrivateUtil みたいに、どこかに静的な資源
を置いてデシリアライズ時に間接参照させるときに、
synchronized しなくちゃならいのでロックのコストも含めて出
来たとしても課題が多すぎてこれまた現実的ではないと思った次
第です。

評価

0

出来ないと提示されたコードですが、
以下のようにすれば出来ますけど、何を問題にしているのか
イマイチ要点が分かりません。

A a = new B();

Field f = A.class.getDeclaredField("a");
f.setAccessible(true);
f.set(a, 100);

難しい言葉が並んでますが、要はリフレクションしたいだけなのかな

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。