Java 泛型/使用泛型的系统架构的问题
也许我在理解泛型时遇到了一些问题,但我不能做一些看起来合乎逻辑的事情。也许你能帮我澄清一下 我正在开发一个Java库,其中有一个函数将调用一个平台,该平台将以JSON格式返回信息。我想创建一个名称空间,负责检索JSON信息并将其解析为业务对象。为此,我创建了以下内容: JSON类-有2个方法:Java 泛型/使用泛型的系统架构的问题,java,generics,architecture,Java,Generics,Architecture,也许我在理解泛型时遇到了一些问题,但我不能做一些看起来合乎逻辑的事情。也许你能帮我澄清一下 我正在开发一个Java库,其中有一个函数将调用一个平台,该平台将以JSON格式返回信息。我想创建一个名称空间,负责检索JSON信息并将其解析为业务对象。为此,我创建了以下内容: JSON类-有2个方法: protected JSONObject readJsonFromUrl(String url) 打开流并下载JSON文件 public <T, U extends Parser> T re
protected JSONObject readJsonFromUrl(String url)
打开流并下载JSON文件
public <T, U extends Parser> T readObjectFromUrl(String url, U parser)
public T readObjectFromUrl(字符串url,U解析器)
是“入口点”。将调用readJsonFromUrl,并将返回的值调用到解析器
解析器类是一个抽象类,具有以下接口
public abstract class Parser {
public abstract <T> T parse(JSONObject jsonObject);
}
公共抽象类解析器{
公共抽象T-parse(JSONObject-JSONObject);
}
我想做的是创建一个子类来覆盖parse方法,每个子类将返回不同的类型。
例如,联系人列表解析器如下所示:
public <T> T parse(JSONObject jsonObject) {
ContactList contactList = new ContactList();
//Simplified for clearness
contactList = parse(jsonObject);
return contactList;
}
ContactList contactList = parser.parse(jsonObject, ContactList.class);
publictparse(JSONObject-JSONObject){
ContactList ContactList=新建ContactList();
//为清晰起见简化
contactList=parse(jsonObject);
返回联系人列表;
}
问题是:我得到一个编译器错误,因为它需要一个T,而不是一个联系人列表。
如果更改为,则新方法的签名与父类的签名不匹配。
如果我将联系人列表的声明更改为T contactList代码>,我无法调用我需要的某些方法(例如addContact)
我的泛型错了吗?在这种情况下,它们适合我想要的吗?
如果不是,您将如何实现类似的功能
谢谢,
奥斯卡
编辑:使用对象而不是泛型是最好的解决方案吗?它看起来不那么漂亮:(您可能想看看Google Guice是如何实现.getInstance方法的:
<T> T getInstance(Class<T> type);
将此模式应用于您的解析器,我认为您可以避免为要解析的每种类型创建不同的解析器类。相反,您可以只创建一个解析器类,并调用如下方法:
public <T> T parse(JSONObject jsonObject) {
ContactList contactList = new ContactList();
//Simplified for clearness
contactList = parse(jsonObject);
return contactList;
}
ContactList contactList = parser.parse(jsonObject, ContactList.class);
您可能希望了解Google Guice如何实现.getInstance方法:
<T> T getInstance(Class<T> type);
将此模式应用于您的解析器,我认为您可以避免为要解析的每种类型创建不同的解析器类。相反,您可以只创建一个解析器类,并调用如下方法:
public <T> T parse(JSONObject jsonObject) {
ContactList contactList = new ContactList();
//Simplified for clearness
contactList = parse(jsonObject);
return contactList;
}
ContactList contactList = parser.parse(jsonObject, ContactList.class);
您在一个方法上使用泛型,该方法总是返回相同类型的对象,并且该类型可能会根据方法的实现而有所不同
那么我想您应该将泛型声明移动到类中
public abstract class Parser<T> {
public abstract T parse(JSONObject jsonObject);
}
公共抽象类解析器{
公共抽象T-parse(JSONObject-JSONObject);
}
您的实现将如下所示:
public class Impl extends Parser<ContactList>{
public abstract ContactList parse(JSONObject jsonObject){
ContactList contactList = new ContactList();
//Simplified for clearness
contactList = parse(jsonObject);
return contactList;
}
}
public类Impl扩展解析器{
公共抽象联系人列表解析(JSONObject JSONObject){
ContactList ContactList=新建ContactList();
//为清晰起见简化
contactList=parse(jsonObject);
返回联系人列表;
}
}
您在一个方法上使用泛型,该方法总是返回相同类型的对象,并且该类型可能会根据方法的实现而有所不同
那么我想您应该将泛型声明移动到类中
public abstract class Parser<T> {
public abstract T parse(JSONObject jsonObject);
}
公共抽象类解析器{
公共抽象T-parse(JSONObject-JSONObject);
}
您的实现将如下所示:
public class Impl extends Parser<ContactList>{
public abstract ContactList parse(JSONObject jsonObject){
ContactList contactList = new ContactList();
//Simplified for clearness
contactList = parse(jsonObject);
return contactList;
}
}
public类Impl扩展解析器{
公共抽象联系人列表解析(JSONObject JSONObject){
ContactList ContactList=新建ContactList();
//为清晰起见简化
contactList=parse(jsonObject);
返回联系人列表;
}
}
这看起来是一个非常有趣的方法,但我必须先了解注射,然后再进行操作,)谢谢您的回答@奥斯卡:你不必担心注射方面的问题。只需使用反射来实例化作为参数提供的类型的对象。(当然,这是假设类型有一个“default”(无参数)构造函数。)关键是方法签名的设置方式不必进行任何转换。它使用泛型,应该可以帮助您消除当前策略使用的大量样板样式代码。在我的JSON类(readObjectFromUrl mthod)中,我将调用Parser.Parser方法。目前,我在readObjectFromUrl中收到一个解析器参数,该解析器返回预期的对象类型。我很抱歉,但是我看不出这个改变会带来什么大的不同,我想我不明白you@Oscar:当前解决方案要求您为每种类型的对象创建新的解析器实现(例如,ContactListParser
)。此解析器的代码似乎只是创建对象的实例(newcontactlist()
),调用其他一些“parse”方法,然后返回对象。然而,所有这三个步骤都可以通过使用反射来构造对象来完成。因此,可以避免为每种类型编写不同的实现。也许我误解了,你的“解析”方法只是挥手示意你将在那里编写一堆其他代码?@Oscar:google的gson
库正是我想要描述的。请参见此处的示例:()。您是否考虑过使用它,而不是为每种对象类型编写自己的自定义解析实现?这看起来是一种非常有趣的方法,但在这样做之前,我必须先了解注入,谢谢您的回答@奥斯卡:你不必担心注射方面的问题。只需使用反射来实例化作为参数提供的类型的对象。(当然,这是假设h型