- PR -

ObjectにSerializableが実装されていない理由

投稿者投稿内容
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-03-01 22:23
そういや話がそれますが、
ClassがSerializableを実装しているにもかかわらず、
Method/Field/ConstructorがSerializableを実装していなくて、
面倒だなと思った事がありました。

この辺のクラスはfinalクラスですが、以下のようなコードで回避しました。
コード:
private transient Method method;

private void readObject(ObjectInputStream in) throws 
IOException,ClassCastException{
    in.defaultReadObject();
    String name = in.readUTF();
    Class type = (Class)in.readObject();
    Class[] parameterTypes = (Class[])in.readObject(); 
    try{
        method = type.getDeclaredMethod(name, parameterTypes);
    }catch(Exception e){
        throw new IOException(e);
    }
}

private void writeObject(ObjectOutputStream out) throws IOException{
    out.defaultWriteObject();
    out.writeUTF(method.getName());    
    out.writeObject(method.getDeclaringClass());
    out.writeObject(method.getParameterTypes());
}


ただ、これだと毎度毎度面倒なので、
結局SerializableMethodというMethodのラッパーのようなクラスを作って、
直列化を意識しなくても済むようにしました。
コード:
public class SerializableMethod implements Serializable{

    private transient Method method;

    public SerializableMethod(Method method){
        this.method = method;
    }

    public Method getMethod(){
        return method;
    }

    private void readObject(ObjectInputStream in) throws IOException,ClassCastException{
        in.defaultReadObject();
        String name = in.readUTF();
        Class type = (Class)in.readObject();
        Class[] parameterTypes = (Class[])in.readObject(); 
        try{
            method = type.getDeclaredMethod(name, parameterTypes);
        }catch(Exception e){
            throw new IOException(e);
        }
    }

    private void writeObject(ObjectOutputStream out) throws IOException{
        out.defaultWriteObject();
        out.writeUTF(method.getName());    
        out.writeObject(method.getDeclaringClass());
        out.writeObject(method.getParameterTypes());
    }
}


これなら、利用する側はあまり直列化を意識する事がありません。
インターフェイスで提供されているものなら、
完全なラッパーも可能ですね。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-03-02 11:11
引用:

かつのりさんの書き込み (2007-03-01 22:23) より:
そういや話がそれますが、
ClassがSerializableを実装しているにもかかわらず、
Method/Field/ConstructorがSerializableを実装していなくて、
面倒だなと思った事がありました。



やっと意味が理解できました。
Method/Field/Constructorってのは、リフレクションでの
java.lang.reflect.Methodクラス、
java.lang.reflect.Fieldクラス、
java.lang.reflect.Constructorクラスのことですね。

引用:

引用:

そういえば、Map.Entryの実装クラスがSerializableになっていなくて
はまったことがありましたねぇ。TreeMapのときだったか。(JDK1.5)


こういうのに嵌りたくないですね。
差し支えなければ、どのように対処されたか教えて頂けませんか?



どうしたんだったかなぁ。
通信用のオブジェクトだったような気がするからデータ型をListにでも
したんだったかもしれません。実ははっきり覚えていない…。
Guri
会議室デビュー日: 2007/01/16
投稿数: 12
投稿日時: 2007-03-06 09:00
かつのりさん
実装例ありがとうございました。

実は、私もjava.awt.AlphaCompositeで似たようなラッパークラスを作って回避していました。
以下は参考までに。

当初、そのラッパークラスにjava.awt.Composite,java.io.Serializableを実装して、
AlphaCompositeをメンバーにして、Compositeインタフェイスメソッド自体は、
そのAlphaCompositeに委譲して、Graphics2Dにはこのラッパークラス自体を渡していました。
この方法だと、このクラスを利用する場合、直列化を意識しなくてよいのですが、
どうもパフォーマンスが落ちる気がしてjava.awt.AlphaComposite,SunのGraphics2D実装コードまで調べました。

するとinstanceof java.awt.AlphaCompositeの箇所があって特定の処理をしており、独自実装Compositeより有利な処理をするようです。

ですので、AlphaCompositeを直列化する場合、私のようなAlphaCompositeへの委譲はやめて、かつのりさんのように、Deserialize後にAlphaCompositeを取り出して、AlphaComposite自体をGraphics2Dに渡す方が良いかもしれません。

nagiseさん
回避策を教えていただきありがとうございました。

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