我正在为学校项目开发Java Web应用程序,并且我将尽可能地遵循MVC架构模式。为此,我创建了一组JavaBean类,并使用Gson对这些实例的序列化和反序列化。我遇到的问题表明,我还没有完全理解Java中继承和泛型的工作原理,因此我希望通过这个问题来阐明这些论点。
我有两个抽象类Item
和ItemVariant
,分别由两个CatalogItem
,ArchivedItem
和CatalogItemVariant
,{{ 1}}。
ArchivedItemVariant
的一个实例可以引用Item
的集合,反之亦然,ItemVariant
的一个实例可以引用其父项(我知道这会导致序列化过程中的循环,但是这不是我遇到的问题)。因此,理想情况下,ItemVariant
的实例应始终引用集合CatalogItem
,而CatalogItemVariant
的实例应始终引用CatalogItemVariant
中的一个,并且对于{{ 1}}和CatalogItem
。但是,我对强迫这种关系不感兴趣。例如,允许将ArchivedItem
的实例引用为ArchivedItemVariant
的实例。
当前,这两个抽象类的代码如下:
CatalogItemVariant
这会产生未经检查的强制警告,我知道这可能不是最优雅的解决方案。但是,这不是我遇到的主要问题。
扩展这两个类的bean类只需添加几个属性以及它们的getter和setter,这些具体类的实例就是整个应用程序中实际使用的类。现在是真正的问题:例如,考虑以下必须反序列化为ArchivedItem
实例的JSON字符串。
public abstract class Item implements Serializable {
...
protected Collection<ItemVariant> variants;
...
public <T extends ItemVariant> Collection<T> getVariants() {
return (Collection<T>) variants;
}
...
public <T extends ItemVariant> void setVariants(Collection<T> variants) {
this.variants = (Collection<ItemVariant>) variants;
}
}
public abstract class ItemVariant implements Serializable {
...
protected Item parentItem;
...
public <T extends Item> T getParentItem() {
return (T) parentItem;
}
...
public <T extends Item> void setParentItem(T parentItem) {
this.parentItem = parentItem;
}
...
}
理想情况下,CatalogItemVariant
应该反序列化为{"parentItem":{"name":"Sample name","category":"Sample category","color":"Sample color"},"size":"Sample size"}
的形式,但是考虑到这些类当前的设计方式,Gson尝试创建parentItem
的实例,该实例是抽象的,因此导致以下异常:
CatalogItem
要解决此问题,我想到了Item
中的两个方法java.lang.RuntimeException: Failed to invoke public model.transfer.catalog.Item() with no args
和setVariants
中的Item
的抽象,从而迫使它们的两个子类覆盖它们。像这样:
setParentItem
但这无法正常工作,因为类型ItemVariant
与public abstract class ItemVariant implements Serializable {
...
protected Item parentItem;
...
public abstract <T extends Item> void setParentItem(T parentItem);
...
}
public class CatalogItemVariant extends ItemVariant {
...
@Override
public void setParentItem(CatalogItem parentItem) {
this.parentItem = parentItem;
}
...
}
不匹配,从而使CatalogItem
注释无效。
一种解决方法是向servlet发送反序列化对象的两个单独的JSON字符串,一个用于item变量,一个用于其父项,然后使用正确的类将它们都反序列化为两个不同的对象({{ }}(第一个),T
(第二个),然后使用@Override
手动设置新CatalogItem
实例的属性CatalogItemVariant
。当然,在应用此解决方案时,item变体的JSON字符串必须丢失其parentItem
字段。有更好的解决方案吗?如果是这样,我应该如何重新设计受此问题影响的类和方法?
编辑:由于系统要求我提供实际代码,因此这是我正在使用的类的简化版本:
CatalogItemVariant
我遇到的错误可以通过运行以下代码段进行模拟,并将其抛出到最后一行:
setParentItem()
为澄清起见,我完全理解错误是由于这些类的设计方式引起的,并且我不希望程序的行为有所不同。我只想了解是否有一种方法可以使用泛型和继承来重新设计这些类,如果可以,那是什么方法。