Java 序列化动态生成的类
假设我有一个抽象类Java 序列化动态生成的类,java,serialization,dynamic-class-loaders,Java,Serialization,Dynamic Class Loaders,假设我有一个抽象类 public abstract class Base implements Serializable { static final long serialVersionUID = 1; public Base(int x) { ... } public abstract void baseMethod(); } 然后我动态地创建这个类 public class Temp { public Base getBase() { re
public abstract class Base implements Serializable {
static final long serialVersionUID = 1;
public Base(int x) { ... }
public abstract void baseMethod();
}
然后我动态地创建这个类
public class Temp {
public Base getBase() {
return new Base(2) {
static final long serialVersionUID = 1;
@Override
public void baseMethod() { .... }
};
}
}
我能够从字符串动态生成类Temp,调用一个新实例,提取基对象,并像任何其他扩展基对象的实例一样使用它。当我序列化时,问题就出现了。我可以序列化从动态Temp类中提取的基本对象,但随后无法在其他会话中反序列化,因为Temp不再位于类路径上
你们能想办法解决这个问题吗?必须有一种方法可以从Temp类中分离出有问题的基本对象(在从Temp类中提取基类之后,我从不关心这个问题)。基本对象不依赖于Temp类中的任何内容。尝试在
Temp
对象上实现writeReplace
,以便写入Base
,并在Base
对象上实现readResolve
,从而创建一个包装它的Temp
。看
代码看起来像这样。请注意,我并没有实际测试这个,但它应该是相当接近
public class Base implements Serializable {
// Existing members here
private Object readResolve() throws ObjectStreamException {
return new Temp(this);
}
}
public class Temp implements Serializable {
Base base;
public Temp(Base base) {
this.base = base;
}
// Other existing methods here
private Object writeReplace() throws ObjectStreamException {
return base;
}
}
我意识到这在这两个类之间引入了一个令人讨厌的循环依赖,但我看不到另一个很好的方法,除了其他人建议的外部读写器方法。此方法的优点是它支持将
Temp
作为较大对象图的一部分写入。请尝试在Temp
对象上实现writeReplace
,以便它写入基
,并在Base
对象上实现readResolve
,以便它创建一个包装它的Temp
。看
代码看起来像这样。请注意,我并没有实际测试这个,但它应该是相当接近
public class Base implements Serializable {
// Existing members here
private Object readResolve() throws ObjectStreamException {
return new Temp(this);
}
}
public class Temp implements Serializable {
Base base;
public Temp(Base base) {
this.base = base;
}
// Other existing methods here
private Object writeReplace() throws ObjectStreamException {
return base;
}
}
我意识到这在这两个类之间引入了一个令人讨厌的循环依赖,但我看不到另一个很好的方法,除了其他人建议的外部读写器方法。这种方法的优点是它支持将
Temp
作为更大对象图的一部分来编写。首先,Richard,这是我第一次看到这种特殊情况,谢谢你的介绍;)
在这里,我找到了一些解决你问题的方法。我希望这对你有帮助
import java.io.*;
abstract class Base implements Serializable
{
protected int x ;
private static final long serialVersionUID = 1L;
public Base(int x) { this.x = x; }
public abstract void baseMethod();
}
class Temp implements Serializable
{
private static final long serialVersionUID = 2L;//Make Temp serializable also.
public Base getBase(int i)
{
Base base = new Base(i)
{
static final long serialVersionUID = 1L;
@Override
public void baseMethod() { System.out.println(x); }
};
return base;
}
}
public class ReadWriteBaseObject
{
public static Base createBaseObject(int i)
{
Temp temp = new Temp();//You might be creating your Temp object here Dynamically..
Base base = temp.getBase(i);
return base;
}
public static Base read()
{
ObjectInputStream oin = null;
try
{
FileInputStream fin = new FileInputStream("BASE.ser");
oin = new ObjectInputStream(fin);
Base base = (Base)oin.readObject();
return base;
}
catch (Exception ex)
{
ex.printStackTrace();
return null;
}
finally
{
if (oin!=null)
{
try
{
oin.close();
}
catch (Exception ex){}
}
}
}
public static void write(Base base)
{
if (base == null)
{
System.out.println("Can't write null");
return;
}
ObjectOutputStream os = null;
try
{
FileOutputStream fos = new FileOutputStream("BASE.ser");
os = new ObjectOutputStream(fos);
os.writeObject(base);
System.out.println("Wrote to file");
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
if (os!=null)
{
try
{
os.close();
}
catch (Exception ex){}
}
}
}
public static void main(String st[])
{
Base base = createBaseObject(45);
write(base);
Base obj = read();
obj.baseMethod();
}
}
编辑虽然匿名类实例可以成功地序列化,但由于一些复杂因素,Java仍然强烈反对匿名类实例。是java官方网站的声明: 注意-内部类的序列化(即 非静态成员类),包括本地类和匿名类, 由于以下几个原因,强烈不鼓励使用此选项。因为内部阶级 在非静态上下文中声明包含隐式非瞬态 引用封闭类实例,序列化此类内部 类实例将导致其关联外部对象的序列化 类实例。由javac生成的合成字段(或 用于实现内部类的其他JavaTM编译器包括 取决于实现,并且可能因编译器而异;分歧 在这些字段中,可能会破坏兼容性并导致
冲突的默认SerialVersionId值。分配给某人的名字 本地和匿名内部类也依赖于实现 编译器之间可能会有所不同。因为内部类不能声明 除了编译时常量字段以外的静态成员,它们不能 使用serialPersistentFields机制指定serializable 领域。最后,因为内部类与外部类关联 实例没有零参数构造函数(的构造函数 这样的内部类隐式地接受封闭实例作为 前置参数),它们无法实现外部化。都不 但是,上面列出的问题适用于静态成员类
要了解更多关于java序列化的信息,您可以观看首先,Richard这是我第一次看到这种特殊情况,谢谢您的介绍;) 在这里,我找到了一些解决你问题的方法。我希望这对你有帮助
import java.io.*;
abstract class Base implements Serializable
{
protected int x ;
private static final long serialVersionUID = 1L;
public Base(int x) { this.x = x; }
public abstract void baseMethod();
}
class Temp implements Serializable
{
private static final long serialVersionUID = 2L;//Make Temp serializable also.
public Base getBase(int i)
{
Base base = new Base(i)
{
static final long serialVersionUID = 1L;
@Override
public void baseMethod() { System.out.println(x); }
};
return base;
}
}
public class ReadWriteBaseObject
{
public static Base createBaseObject(int i)
{
Temp temp = new Temp();//You might be creating your Temp object here Dynamically..
Base base = temp.getBase(i);
return base;
}
public static Base read()
{
ObjectInputStream oin = null;
try
{
FileInputStream fin = new FileInputStream("BASE.ser");
oin = new ObjectInputStream(fin);
Base base = (Base)oin.readObject();
return base;
}
catch (Exception ex)
{
ex.printStackTrace();
return null;
}
finally
{
if (oin!=null)
{
try
{
oin.close();
}
catch (Exception ex){}
}
}
}
public static void write(Base base)
{
if (base == null)
{
System.out.println("Can't write null");
return;
}
ObjectOutputStream os = null;
try
{
FileOutputStream fos = new FileOutputStream("BASE.ser");
os = new ObjectOutputStream(fos);
os.writeObject(base);
System.out.println("Wrote to file");
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
if (os!=null)
{
try
{
os.close();
}
catch (Exception ex){}
}
}
}
public static void main(String st[])
{
Base base = createBaseObject(45);
write(base);
Base obj = read();
obj.baseMethod();
}
}
编辑虽然匿名类实例可以成功地序列化,但由于一些复杂因素,Java仍然强烈反对匿名类实例。是java官方网站的声明: 注意-内部类的序列化(即 非静态成员类),包括本地类和匿名类, 由于以下几个原因,强烈不鼓励使用此选项。因为内部阶级 在非静态上下文中声明包含隐式非瞬态 引用封闭类实例,序列化此类内部 类实例将导致其关联外部对象的序列化 类实例。由javac生成的合成字段(或 用于实现内部类的其他JavaTM编译器包括 取决于实现,并且可能因编译器而异;分歧 在这些字段中,可能会破坏兼容性并导致
冲突的默认SerialVersionId值。分配给某人的名字 本地和匿名内部类也依赖于实现 编译器之间可能会有所不同。因为内部类不能声明 除了编译时常量字段以外的静态成员,它们不能 使用serialPersistentFields机制指定serializable 领域。最后,因为内部类与外部类关联 实例没有零参数构造函数(的构造函数 这样的内部类隐式地接受封闭实例作为 前置参数),它们无法实现外部化。都不 但是,上面列出的问题适用于静态成员类<