为什么 java.lang.Void 不可序列化?

发布于 2024-10-17 03:57:28 字数 419 浏览 2 评论 0原文

默认情况下可以序列化原始“void”,为什么对象“Void”不扩展可序列化?

添加示例:

RootImplementation 将出现编译错误,提示“Void 不在其范围内”,因为它不扩展 Serialized。 虽然“someMethod”会被声明为“void”,但这不会有问题。

public interface Root<R extends Serializable> extends Serializable {
  R someMethod();
}

public class RootImplementation implements Root<Void> {
  public Void someMethod() {
    return null;
  }
}

It is possible to serialize the primitive 'void' per default, why does not the object 'Void' extend Serializable?

Added example:

The RootImplementation will have a compilation error saying "Void is not within its bound" since it does not extend Serializable.
Though would 'someMethod' be declared with 'void' it would be no problem.

public interface Root<R extends Serializable> extends Serializable {
  R someMethod();
}

public class RootImplementation implements Root<Void> {
  public Void someMethod() {
    return null;
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

乱世争霸 2024-10-24 03:57:28

好的,根据您的示例,不,如果您将方法更改为 void ,它将不起作用,因为该方法必须具有返回类型(即使 Java 现在允许在重写方法中使用协变返回类型) 。对 void 的讨论使问题变得混乱。

您想要做的是将类型参数声明为“将仅返回 null”。 Void 通常是一个不错的选择,但要使 Void 正常工作,返回类型必须是 Object。 Void 不能仅仅因为有人可能想用它来指示类型参数的 null 返回而实现 API 中的每个接口。

可以通过三种方式来看待您的问题:

  1. Serialized 是一种限制过度的类型声明。你真的应该使用 Object.你真的需要它是可序列化的吗?
  2. 您可以将类型参数声明为 Serialized,并在实践中返回 null。这并不完全表明您每次都返回 null,但这可能就足够了。
  3. 您可以声明自己的名为 Null 的类,该类实现了 Serialized,可能作为 Root 接口的静态嵌套类,并在本例中将其用作类型参数。您会发现创建自己的 Null 对象并不罕见,即使在标准 JDK 中也有(私有)空对象。

OK, in response to your example, no if you changed the method to void it would not work, as the method has to have a return type (even if Java now allows covariant return types in overridden methods). The discussion of void confuses the issue.

What you want to do is declare a type parameter as a "will just return null." Void is generally a good choice for that, but for Void to work, the return type has to be Object. Void can't implement every interface in the API just because someone might want to use it to indicate a null return on a type parameter.

There are three ways to look at your problem:

  1. Serializable is an overly restrictive type declaration. You should really be using Object. Do you really need it to be Serializable?
  2. You can just declare the type parameter as Serializable, and in practice return null. This dosn't fully indicate that you are returning null every time, but it may be enough.
  3. You can declare your own class called Null which implements Serializable, perhaps as a static nested class of the Root interface, and use that as the type parameter in this case. You will find making your own Null object is not that uncommon, even in the standard JDK there is (a private) one.
鸵鸟症 2024-10-24 03:57:28

javadoc 很清楚:

Void类是一个不可实例化的类
用于保存引用的占位符类
到代表的类对象
Java关键字

因为你不能使用它,所以它不需要是可序列化的(除了反射的东西)。


对于第二个问题: void != Void (如果您在非 java 表达式中考虑 != )

是的, void 是一个关键字,而 Void 是一个类。

The javadoc is clear:

The Void class is an uninstantiable
placeholder class to hold a reference
to the Class object representing the
Java keyword

Because you can not use it, it does not need to be Serializable (except reflection stuff).


And for the second question: void != Void (if you are think about != in a not java expression)

Yes void is a keyword and Void a class.

甜点 2024-10-24 03:57:28

我将把它作为comminity-wiki 放在这里

你可以(反)序列化java.lang.Void b/c 你只能用null 来初始化它。如果类为 null,Java 并不关心该类是否实现了 java.io.Serialized

代码的结果

t1.VoidOut@19821f
t1.VoidOut@c17164

  public class VoidOut implements java.io.Serializable{
    int x=1;
    Void v = null;

    public static void main(String[] args) throws Throwable{
        VoidOut v = new VoidOut();
        System.out.println(v);
        ByteArrayOutputStream b =new ByteArrayOutputStream(256);
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(v);
        o.close();
        ObjectInputStream in =new ObjectInputStream(new ByteArrayInputStream(b.toByteArray()));
        System.out.println(in.readObject());        
    }
}

I will put it here as comminity-wiki

Thou can (de)serialize java.lang.Void b/c you can initialize it with null only. Java doesn't care if a class implements java.io.Serializable if it's null.

Result of the code

t1.VoidOut@19821f
t1.VoidOut@c17164

  public class VoidOut implements java.io.Serializable{
    int x=1;
    Void v = null;

    public static void main(String[] args) throws Throwable{
        VoidOut v = new VoidOut();
        System.out.println(v);
        ByteArrayOutputStream b =new ByteArrayOutputStream(256);
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(v);
        o.close();
        ObjectInputStream in =new ObjectInputStream(new ByteArrayInputStream(b.toByteArray()));
        System.out.println(in.readObject());        
    }
}
段念尘 2024-10-24 03:57:28

引用Javadoc:

Void 类是一个不可实例化的占位符类,用于保存对表示 Java 关键字 void 的 Class 对象的引用。

由于该类是不可实例化的,因此无法反序列化。因此不需要序列化支持。

To quote the Javadocs:

The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void.

Since the class is uninstantiable, it cannot be deserialized. Ergo no need for serialization support.

肥爪爪 2024-10-24 03:57:28

可以序列化
默认情况下原始“void”,为什么
不是对象“Void”扩展
可序列化吗?

Void 不携带值,因此序列化它是没有意义的。

这不是意味着 void != Void 吗?

是的,就像 int != Integer 一样。但是当你序列化和反序列化两个int时,newint==oldint(我的意思是int,而不是Integer!!!)。 void 不可能有这样的构造。序列化任何东西都是没有任何意义的。

It is possible to serialize the
primitive 'void' per default, why does
not the object 'Void' extend
Serializable?

Void doesn't carry a value, hence it makes no sense to serialize it.

Doesn't this mean that void != Void ?

True, just as int != Integer. But when you serialize and deserialize two ints, newint==oldint (I mean int, not Integer!!!). No such construct would be possible with void. It just doesn't make any sense to serialize nothing.

像你 2024-10-24 03:57:28

仅当您有一个 Void 类型的字段时它才有用,这确实没有意义。您还需要实际为其分配一个实例,这又没有意义。只要你不这样做,你就可以序列化包含Void字段的类的实例。为了创建 Void 的实例,您需要使用反射才能使用私有构造函数。

public class VoidSerializerDemo implements Serializable {
    private Void v;

    public static void main(String[] args) throws Exception {
        final VoidSerializerDemo instance = new VoidSerializerDemo();
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(instance);
        System.out.println("OK: null works");
        final Constructor<Void> constructor = Void.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        instance.v = constructor.newInstance();
        oos.reset();
        System.out.println("Going to throw");
        oos.writeObject(instance);
    }
}

所以你极不可能需要关心 Void 的可序列化性,不是吗?

It'd be only useful if you had a field of type Void, which really makes no sense. You'd also need to actually assign it an instance, which again makes no sense. As long as you don't do it, you can serialize the instance of class containing the Void field. In order to create an instance of Void, you need to use reflection in order to use the private constructor.

public class VoidSerializerDemo implements Serializable {
    private Void v;

    public static void main(String[] args) throws Exception {
        final VoidSerializerDemo instance = new VoidSerializerDemo();
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(instance);
        System.out.println("OK: null works");
        final Constructor<Void> constructor = Void.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        instance.v = constructor.newInstance();
        oos.reset();
        System.out.println("Going to throw");
        oos.writeObject(instance);
    }
}

So it's extremely improbably you ever need to care about the serializability of Void, isn't it?

雪若未夕 2024-10-24 03:57:28

其他人已经解释了为什么对于永远无法实例化的类型来实现 Serialized 没有意义,以及为什么 void 不是基元或可序列化的。

要解决编辑中的代码问题,我认为您应该将 R extends Serialized 更改为仅绑定到 R。大多数可序列化的泛型类型并不要求它们的类型参数是可序列化的...它们只是声明,如果您在其中放入不可序列化的内容,它们将不会也不能序列化。这通常是一个很好的实践,因为在编译器级别过于努力地强制执行可序列化可能会咬伤你(正如你在这里看到的)。

Others have explained why it doesn't make sense for a type that can never be instantiated to implement Serializable and why void isn't a primitive or serializable.

To address the code in your edit, I think you should just change the R extends Serializable bound to just R. Most generic types that are Serializable do not require that their type parameters be Serializable... they simply state that if you put something in them that isn't serializable, they won't be serializable either. This is generally a good practice, as trying too hard to enforce serializability at the compiler level can bite you (as you see here).

救赎№ 2024-10-24 03:57:28

Void 只是为了表明一个方法只能返回 null,遗憾的是没有办法直接声明 null 类型。对于 jvm Void 只是一个扩展 Object 的普通类,因此不能用于其他类或接口,这使得 Void 对于您的示例毫无用处。

由于您的方法不会返回除 null 之外的任何内容,因此您可以将 Void 替换为类似以下内容:

public final SerializebaleVoid extends Object implements Serializeable{
    private SerializeableVoid(){}
}

至于调用 void 基元,void 表明缺少值,返回 void 的方法不会返回 void 类型的值,而是实际上不返回返回任何东西。

Void is only intended to show that a method can only return null, sadly there is no way to declare the null-type directly. For the jvm Void is only a normal class extending Object and as such cannot be used in place for other classes or interfaces, this makes Void for your example useless.

Since your method wont return anything but null you could replace Void with something like the following:

public final SerializebaleVoid extends Object implements Serializeable{
    private SerializeableVoid(){}
}

As to calling void a primitive, void shows the absence of a value, a method returning void does not return a value of type void instead it literally does not return anything.

尸血腥色 2024-10-24 03:57:28

如果您使用 apache commons 库,则有一个 org.apache.commons.lang3.ObjectUtils.Null 扩展了 Serialized。

If you are using apache commons library, there's a org.apache.commons.lang3.ObjectUtils.Null which does extend Serializable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文