Java基于泛型类型执行不同的操作

Cob*_*urn 5 java generics

截至目前,我有一个看起来类似于下面的对象.

public class DataField implements JSONable
{
    public final String name;
    public final Class<?> typeClass;
    private Object data;

    public <T> DataField(String name, Class<T> typeClass)
    {
        this.name = name;
        this.typeClass = typeClass;

        data = null;
    }
    public <T> T getData(Class<T> passClass)
    {
        if(!typeClass.equals(passClass))
            throw new TypeMismatchException("Type mismatch");
        return passClass.cast(data);
    }
    public <T> T setData(T obj, Class<T> passClass)
    {
        if(!typeClass.equals(passClass))
            throw new TypeMismatchException("Type mismatch");
        data = (Object) obj;
    }
    public String toJSON()
    {
        //The part that bugs me
        StringBuilder sb = new StringBuilder();
        switch(type)
        {
        case "myPackage.DataField":
            if(isArray)
                return TakesADataObjOrCollectionOfDataObjs(sb,Arrays.asList(get(DataObj[].class)));
            else
                return TakesADataObjOrCollectionOfDataObjs(sb,get(DataObj.class));
        break;
        default:
            if(isArray)
                TakesAnObjectOrCollection(sb,Arrays.asList(get(Object[].class)));
            else
               TakesAnObjectOrCollection(sb,get(Object.class));
        break;
        }
        return sb.toString();
    }
}
//I did not include code for DataObj but it has a HashMap<String,DataField>
//fields on it and two functions for getting and setting field data 
//without actually divulging the field objects themselves.
Run Code Online (Sandbox Code Playgroud)

背景:问题在于最后一个toJSON功能.我有两个不同的函数(在这里列为TakesADataObjOrCollectionOfDataObjsTakesAnObjectOrCollection),它们根据对象是否实现来执行不同的操作JSONable.现在,我不能简化这些都源于一个功能,让编译器选择因为类型擦除,我不能有一个函数,它都Collection<?>Collection<? extends JSONable>他们有相同的函数签名.
很简单,当我只需要区分just ObjectDataObjtypes(这是一个非常简单的检查,我所要做的就是传递Class<?>我们正在使用的类型),但现在我需要开始存储List<?>List<? extends JSONable>.

当前解决方案:我确实为此解决方案提供了一些代码,但它与上图所示的不同.目前的解决方案是只包括我正在使用的通用类型,以及有typeClass和a genericTypeClass.这个问题是它开始变得非常混乱,因为:

  • 所有适当的方法是采取只typeClass需要现在两种方法,一种采用既typeClassgenericTypeClass,而另一种typeClass却设置genericTypeClass为null.
  • 如果我甚至可以在某些情况下完成它,那么我在执行类型检查(获取和设置)方面会遇到更多麻烦.
  • toJSON开关语句将充满更多的情况下,每一个支持通用的,然后在每个那些,检查genericTypeClass,看它是否是一个DataObj与否.


问题:有没有其他方法可以创建此类来执行我想要的操作(存储不同的数据但仍然能够根据DataField保留的类型输出不同的JSON )?

希望只是解释情况而不是询问3或4个其他相关问题,只会问这个问题,这将阻止我成为XY问题的牺牲品.

ccj*_*mne 2

我建议您使用Jackson将对象转换为JSON Strings

它真的很容易开始工作(说真的),它可以节省你大量的时间和潜在的错误...它还支持一些你可以使用的功能,List例如我正在考虑 s 的序列化:)

这是一个有趣博客的链接,可帮助您了解 Jackson Json这里是Jackson Json 下载页面
的链接。


下面是我刚刚制作的一个小示例,旨在向您展示如何使用它:

public class Main {
    public final String mainStr = "Hello";
    
    public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {
        final ObjectMapper om = new ObjectMapper();
        System.out.println("Serialized Main: " + om.writeValueAsString(new Main()));
        System.out.println("Serialized A: " + om.writeValueAsString(new A()));
        System.out.println("Serialized AA: " + om.writeValueAsString(new AA()));
        System.out.println("Serialized B: " + om.writeValueAsString(new B()));
        System.out.println("Serialized List of A: " + om.writeValueAsString(Collections.singletonList(new A())));
    }
    
    static class A extends Main {
        public final String aStr = "World";
        public final int aInt = 42;
    }
    
    static class AA extends A {
        public final String aaStr = "Foo";
    }

    static class B {
        public final String bStr = "Bar";
        public final boolean bBool = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Serialized Main: {"mainStr":"Hello"}
Serialized A: {"mainStr":"Hello","aStr":"World","aInt":42}
Serialized AA: {"mainStr":"Hello","aStr":"World","aInt":42,"aaStr":"Foo"}
Serialized B: {"bStr":"Bar","bBool":true}
Serialized List of A: [{"mainStr":"Hello","aStr":"World","aInt":42}]
Run Code Online (Sandbox Code Playgroud)

如果您在使用时遇到困难,我们可以在聊天中进行讨论,我可以在那里为您提供更多帮助。

干杯!