Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.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_Generics_Architecture - Fatal编程技术网

Java 泛型/使用泛型的系统架构的问题

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

也许我在理解泛型时遇到了一些问题,但我不能做一些看起来合乎逻辑的事情。也许你能帮我澄清一下

我正在开发一个Java库,其中有一个函数将调用一个平台,该平台将以JSON格式返回信息。我想创建一个名称空间,负责检索JSON信息并将其解析为业务对象。为此,我创建了以下内容:

JSON类-有2个方法:

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型