Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 您能在运行时使对象可序列化吗?_Java_Serialization_Runtime - Fatal编程技术网

Java 您能在运行时使对象可序列化吗?

Java 您能在运行时使对象可序列化吗?,java,serialization,runtime,Java,Serialization,Runtime,正如标题所说,有没有办法检查对象是否可序列化,如果没有,请在运行时进行序列化?正如其他人所说。。。简而言之,答案是否定的 您完全可以在运行时使用代理对象向任何旧对象添加接口,如中所述。这也包括java.io.Serializable。但是,为了使代理对象有用,它必须维护对原始对象的内部引用,在您的情况下,该引用不实现可序列化。唯一可以序列化代理对象的方法是将原始对象的内部引用设置为临时字段,这对您没有多大好处 此外,在检查您的注释之后,看起来java序列化肯定不是您想要的,您真的只是想序列化为某

正如标题所说,有没有办法检查对象是否可序列化,如果没有,请在运行时进行序列化?

正如其他人所说。。。简而言之,答案是否定的

您完全可以在运行时使用代理对象向任何旧对象添加接口,如中所述。这也包括java.io.Serializable。但是,为了使代理对象有用,它必须维护对原始对象的内部引用,在您的情况下,该引用不实现可序列化。唯一可以序列化代理对象的方法是将原始对象的内部引用设置为临时字段,这对您没有多大好处

此外,在检查您的注释之后,看起来java序列化肯定不是您想要的,您真的只是想序列化为某种字符串格式。其他人提出了各种各样的解决方案,但我认为,如果你想尽量少惹麻烦,可以选择XStream:。

简短回答-不

回答更长-是,使用字节码操作,例如asm。但你真的应该考虑这是否是必要的。序列化是一件严肃的事情(有效的Java有一整章关于序列化的内容)

顺便说一句,二进制序列化还有一些替代方法,它们不需要对象实现
serializeble
(正如Jacob在注释中指出的):

  • XML-
    java.beans.XMLEncoder.encode(..)
    ObjectOutputStream的XML版本
  • JSON-Jacskon、Gson等框架允许您用一行代码序列化对象

    • 哇。为什么需要在运行时检查它?在编译时确保它不是更容易吗?使用这样的代码

      public void someMethod(Serializable serializable){
      }
      
      或者你可以让它更复杂

      public interface SerializableInterface implements Serializable{
      // bla-bla
      }
      
      public void someMethod(SerializableInterface serializable){
      }
      

      除了现有的好答案外,另一个问题是您是否特别需要针对特定框架的Java Serializable,还是只需要能够序列化对象。 对于后者,有比JDK默认选项多得多的选择;对于许多用例来说,替代方案都比JDK好得多


      如果您不特别需要JDK one,那么使用JSON或基于XML的序列化通常是一个不错的选择。

      在运行时检查?当然“如果(可序列化的someObject实例)


      是否要在运行时更改对象的定义?很少有好的理由这样做。也许有一种方法可以通过反思来做到这一点,但我从来没有理由想做这样的事情。你想做什么?

      如果有人真的需要在运行时使用字节码进行操作。使用库可以执行以下操作:

      ClassPool pool = ClassPool.getDefault();
      CtClass cc = pool.get("mypackage.MyClass");
      cc.addInterface(pool.get("java.io.Serializable"))
      

      您可以创建一个带有对象字段的Serizlize包装类,然后将对象分配给该字段。序列化包装器类时,它将存储对象,您可以从字段中反序列化和强制转换对象

      public class SerialWrap implements Serializable{
      public Object obj;
      }
      
      HashMap<String, String> hm = new HashMap<>();
          hm.put("great preacher", "Apostle Winston George Baker King Jesus Pentecostal Fellowship Negril, Jamaica");
         hm.put("Miracles","Sick healed, cancer healed,God is moving");
          SerialWrap wrap = new SerialWrap();
          wrap.obj = hm;
      
      ObjectOutputStream.write(wrap)
      
      SerialWrap wrap2 =(SerialWrap)ObjectInputStream.readObject();
      hm =(HashMap<String, String>) wrap2.obj;
      
      public类SerialWrap实现可序列化{
      公共对象对象;
      }
      HashMap hm=新的HashMap();
      hm.put(“伟大的传教士”,“使徒温斯顿·乔治·贝克国王耶稣五旬节联谊会”,牙买加内格里尔);
      hm.put(“奇迹”,“病愈,癌症痊愈,上帝在移动”);
      SerialWrap=新的SerialWrap();
      wrap.obj=hm;
      ObjectOutputStream.write(wrap)
      SerialWrap wrap2=(SerialWrap)ObjectInputStream.readObject();
      hm=(HashMap)wrap2.obj;
      
      如果对象不可序列化,可能是因为一个很好的原因:例如,序列化数据库连接没有什么意义。非Java对象序列化的序列化格式可以工作吗?我正在考虑一种使用反射和JSON或XML来序列化对象的解决方案。从其他评论来看,您的要求似乎是将对象变成字符串,这将实现这一点。这个问题非常广泛,主要是因为它没有提到所有的设计约束。(例如,您需要字符串序列化格式。)代理由接口生成,而不是在类上。@Bozho-我链接到的文档中详细介绍了这一部分。如果他还没有使用接口以多态方式(sp?)引用他的对象,则需要在他的代码库中进行一些更改。他的原始对象将是InvocationHandler的成员,该调用处理程序也被序列化,这将失败。@Bozho-你是对的,它将失败。他可以使原始物体成为一个瞬态场。。。但就序列化而言,这并没有多大好处:D(除非在代理对象本身中对对象状态进行一些奇特的重新创建+加上使原始对象暂时化,这远远超出fugly)。通常,使用代理对象是向对象动态添加接口的方式,但在可序列化的情况下,这没有任何好处。我将修改我的答案。我之所以考虑序列化,是因为我想将一个对象转换为字符串(通过字节数组)以进行存储和传输,而由于外部因素,该对象必须是字符串。我看过几个例子,说明了如何使用序列化转换为字节流,最终将对象捕获为字符串,但没有说明如果对象不可序列化该怎么办。我理解某些对象不需要序列化,但在这种情况下,这将由开发人员自行决定。好的,那么您肯定不想使用JDK Serializable。我建议使用JSON序列化(如Jackson,请参阅)。结果更具可读性,更不脆弱。Serializable的主要问题是版本控制非常困难,因此持久化结果是一种反模式(例如,阅读Josh Bloch的解释)。它也不可读(与xml或json不同)。序列化事物本身并没有错,但序列化很少是正确的方式。