在Java中是否可以将对象完全转换为其基类型?

时间:2014-03-25 21:34:48

标签: java

如果我有两个相关的类AB这样的class B extends A,然后创建一个B的实例,有没有办法完全向上播放它,以便它是现在,实际上是A的实例?

B b = new B();
A a = full_upcast_to_A(b);
a.class.equals(A.class)

这是最后一行很重要。我不希望通过B变量引用A对象。它希望引用的A对象的外观和行为就像使用new A()创建一样。

如果我执行标准A a = (A) b;,如果您查看B或调用任何重写方法,则对象在内部仍为.class类型。我不希望这样。

将基类A副本添加到新的A对象中是可以接受的,但不是首选。

更新:为什么:

这是一个复杂的情况。我有一个POJO数据类(A),它是公共代码,但我无法从数据存储区加载,因为那些需要@Entity注释,所以我有一个派生类(B)除了那个注释因此允许存储。但是,我需要通过GWT RPC传递A,因为客户端不知道B。 GWT拒绝这样做,因为它只知道如何序列化A及其接收B

B未包含在可由此SerializationPolicy序列化的类型集中,或者无法加载其Class对象。出于安全考虑,此类型不会被序列化。

2 个答案:

答案 0 :(得分:0)

我认为,你所寻找的东西是不可能的。

我实现同样的方法是使用复制构造函数模式,如下所示:

public class A {
    public A(A copy) {
        // Copy the relevant state into new A instance here.
    }
}

然后你会这样使用:

B b = new B();
A a = new A(b);

编辑:

但托普·霍普金森是对的,我不确定你为什么要这样做。

答案 1 :(得分:0)

好的,我想我在这里理解根本问题。我不确定您使用的是哪个JPA提供程序,但是我遇到了与Hibernate相同的问题,它可能与您现在遇到的问题相同。

GWT是一个聪明的框架。只要您尝试序列化实现可序列化并且其所有成员也可序列化,它应该能够将对象发送到客户端。一些JPA提供程序在访问数据库时所做的是,它们提供了一些巧妙的缓存,只加载特定请求的数据和成员。例如,Hibernate通过提供一个与调用new B()时不完全相同的对象来实现这一点。它将为您提供一个具有B接口的对象,但在幕后,当调用getter方法时,它使用代理从数据库中获取数据。它将用类似PersistentBag的类替换标准java列表,当您访问它们时,它们也将使用数据库的代理。

当您尝试将此代理对象发送到客户端时,GWT会查看所有这些不可序列化的代理并拒绝它们,就像它应该的那样。无论如何,客户端都无法直接访问数据库。您可以通过查看调试器中的代码并在运行时查看对象的属性来测试这是否正在发生。在任何情况下,我解决它的方式是使用Dozer,一个设计用于采用一种形式的类并将其映射到另一种形式的库。您还可以使用复制构造函数。您甚至不需要将B转换为A.您可以使用new B(b)并且只要复制了所需的所有字段,就已经发生了数据库访问,并且您有一个B实例,即GWT能理解。

有关详细信息,请参阅GWT Project Homepage: Hibernate。特别是“为什么Hibernate对象到达浏览器世界时无法被理解”一节。