Java 您可以重命名泛型类中的变量吗?

Java 您可以重命名泛型类中的变量吗?,java,json,generics,Java,Json,Generics,我有一个类PagedResult。这个类是用来帮助我实现一个JSON输出,它以页面格式包含不同的对象。E是包装在列表中的对象。这一切都很好,但有一件事仍然困扰着我。我希望包含对象的列表不总是具有相同的名称。我想使名称适应相应的对象 类PagedResult: public class PagedResult<E> { Long totalItems; Integer totalPages; Integer currentPage; List<E> elements;

我有一个类
PagedResult
。这个类是用来帮助我实现一个JSON输出,它以页面格式包含不同的对象。
E
是包装在列表中的对象。这一切都很好,但有一件事仍然困扰着我。我希望包含对象的列表不总是具有相同的名称。我想使名称适应相应的对象

PagedResult

public class PagedResult<E> {

Long totalItems;
Integer totalPages;
Integer currentPage;
List<E> elements;

[... Getter & Setter ...] 
}
因此,对于每个响应,无论是哪个对象,数组都被命名为“elements”。我不想在JSON响应中使用难看的名称,因为
PagedResult
-类中的对象不断变化。当我用
MyPojo
这样的对象得到响应时,JSON数组的名称应该是“myPojos”,当我想用
MyWin
这样的对象得到响应时,名称应该是“myWins”


我用
@JsonProperty
做了很多尝试,但我找不到一种方法来实现这个同样通用的“对象数组名”。有人能帮我解决这个问题吗?提前谢谢。

不,你不能那样做。泛型类型具有类型参数,而不是标识符参数。另外,Java语言中没有任何东西允许您在生成类型时将Java标识符作为参数。(当然,在这种情况下,您不能使用任何东西!)

备选方案:

  • 不要这样做。(仔细看看您希望JSON属性名称变化的原因。它实际上实现了什么?值得付出努力吗?)

  • 不要使用泛型类型。为每种“分页结果”定义不同的类。(笨重,不推荐。)

  • 使用映射,并为每种“分页结果”的元素属性填充不同的映射键。(缺点是您会丢失静态类型检查,并会对性能和存储造成较小的损失。但这些损失不太可能很大。)

  • 编写一个自定义映射程序,根据您的要求序列化和反序列化
    PagedResult



就其价值而言,标识符作为参数是您可以使用宏预处理器来做的事情。那种Java语言没有对这种事情的标准支持。

不,你不能这样做。泛型类型具有类型参数,而不是标识符参数。另外,Java语言中没有任何东西允许您在生成类型时将Java标识符作为参数。(当然,在这种情况下,您不能使用任何东西!)

备选方案:

  • 不要这样做。(仔细看看您希望JSON属性名称变化的原因。它实际上实现了什么?值得付出努力吗?)

  • 不要使用泛型类型。为每种“分页结果”定义不同的类。(笨重,不推荐。)

  • 使用映射,并为每种“分页结果”的元素属性填充不同的映射键。(缺点是您会丢失静态类型检查,并会对性能和存储造成较小的损失。但这些损失不太可能很大。)

  • 编写一个自定义映射程序,根据您的要求序列化和反序列化
    PagedResult



就其价值而言,标识符作为参数是您可以使用宏预处理器来做的事情。该Java语言没有对此类内容的标准支持。

是的,可以使用自定义序列化程序。但即使使用自定义序列化程序,您仍然存在一个问题:泛型在编译时被删除。因此,我们需要在运行时以某种方式获取类型

下面是一个示例,它只检查
elements
列表中第一个元素的类型。这显然不是最干净的方法,但您不必调整
PagedResult

public class PagedResultSerializer<T> extends JsonSerializer<PagedResult<Object>> {

    @Override
    public void serialize(PagedResult<Object> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeNumberField("totalItems", value.getTotalItems());
        // Your other attributes
        if (!value.getElements().isEmpty()) {
            Object firstElement = value.getElements().get(0);
            String elementsFieldName;
            if (firstElement instanceof MyPojo) {
                elementsFieldName = "myPojos";
            } else if (firstElement instanceof MyWin) {
                elementsFieldName = "myWins";
            } else {
                throw new IllegalArumentException("Unknown type");
            }
            serializers.defaultSerializeField(elementsFieldName, value.getElements(), gen);
        }
        gen.writeEndObject();
    }
}
公共类PagedResultSerializer扩展JsonSerializer{
@凌驾
public void serialize(PagedResult值、JsonGenerator gen、SerializerProvider提供程序)引发IOException{
gen.writeStartObject();
gen.writeNumberField(“totalItems”,value.getTotalItems());
//你的其他属性
如果(!value.getElements().isEmpty()){
Object firstElement=value.getElements().get(0);
字符串元素字段名;
if(MyPojo的第一个元素实例){
elementsFieldName=“myPojos”;
}else if(MyWin的第一个元素实例){
elementsFieldName=“myWins”;
}否则{
抛出新的IllegalRumentException(“未知类型”);
}
serializers.defaultSerializeField(elementsFieldName,value.getElements(),gen);
}
writeEndObject将军();
}
}
现在你只需要告诉Jackson使用这个序列化程序而不是默认的

@JsonSerialize(using = PagedResultSerializer.class)
public class PagedResult<T> {
    // Your code
}
@JsonSerialize(使用=PagedResultSerializer.class)
公共类PagedResult{
//你的代码
}


改进:向您的
PagedResult
添加
Class elementsType
属性,并在序列化程序中使用此属性,而不是检查列表中的第一个元素。

是的,可以使用自定义序列化程序。但即使使用自定义序列化程序,您仍然存在一个问题:泛型在编译时被删除。因此,我们需要在运行时以某种方式获取类型

下面是一个示例,它只检查
elements
列表中第一个元素的类型。这显然不是最干净的方法,但您不必调整
PagedResult

public class PagedResultSerializer<T> extends JsonSerializer<PagedResult<Object>> {

    @Override
    public void serialize(PagedResult<Object> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeNumberField("totalItems", value.getTotalItems());
        // Your other attributes
        if (!value.getElements().isEmpty()) {
            Object firstElement = value.getElements().get(0);
            String elementsFieldName;
            if (firstElement instanceof MyPojo) {
                elementsFieldName = "myPojos";
            } else if (firstElement instanceof MyWin) {
                elementsFieldName = "myWins";
            } else {
                throw new IllegalArumentException("Unknown type");
            }
            serializers.defaultSerializeField(elementsFieldName, value.getElements(), gen);
        }
        gen.writeEndObject();
    }
}
公共类PagedResultSerializer扩展JsonSerializer{
@凌驾
public void serialize(PagedResult值、JsonGenerator gen、SerializerProvider提供程序)引发IOException{
gen.writeStartObject();
gen.writeNumberField(“totalItems”,value.getTotalItems());
//你的ot