Java 泛型 - 类型转换问题

标签 java generics reflection

我有一个通用方法,它接受要更新的类类型和该类的字段。 例如:

class A {
  private int a;
  private int b;
}

class B {
 private int c;
 private int d;
}

在运行时,如果我们将类类型作为“A.class”传递,并将 fieldstoBeUpdated 作为“b”传递,访问该特定类的字段的 getter/setter 的最佳方式是什么,以便我们可以修改字段。

public <T> void find(T clazz, List<String> fieldsToBeUpdated) {
List<T> collectionList = findAll((Class<T>) clazz);
collectionList.parallelStream().forEach(p -> {
        if (clazz instanceof A) {
            fieldsToBeUpdated.parallelStream().forEach(classFieldName -> {
                switch(classFieldName) {
                case "a":((A)p).setA(10);
                break;
                case "b":((A)p).setB(20);
                break;
                }
            });
        }

        if (clazz instanceof B) {
            fieldsToBeUpdated.parallelStream().forEach(classFieldName -> {
                switch(classFieldName) {
                case "c":((B)p).setC(30);
                break;
                case "d":((B)p).setD(40);
                break;
                }
            });
        }
    });
}

我已经编写了上面的代码来实现相同的目的。

但问题是我有 30 个这样的类作为参数传递给这个通用方法,其中包含要更新/修改的类的字段列表。

编写 30 个这样的 if 语句检查类类型然后将对象类型转换为该类是不正确的实现。

有没有更好的方法来达到同样的效果?

提前致谢。

最佳答案

您的AB 类似乎都提供了set/getCreatedTimeset/getUpdatedTime 方法。

如果其他 28 个左右的类也提供这些方法(正如您的问题所暗示的那样),则只需拥有一个具有这些方法的通用接口(interface),供所有类实现。

然后您可以将方法的泛型类型绑定(bind)到该接口(interface),并放弃所有 instanceof 语句和后续的显式转换。

唯一的缺点是,如果您的 List 中有一个与传递给方法的具体类无关的字段名称。

如果你想强制执行这一点,你可以在对象上使用反射来发现该字段是否按名称存在。然后,您可以使用记录的警告(或您认为合适的任何机制)轻松处理任何缺失的字段。

注意

thijs-steel 所述,如果你的“时间”方法共享相同的实现,你可以让你的 30 个类扩展一个只实现“时间”方法的公共(public)抽象父类。

或者,您可以使用 default 方法,因为您显然使用的是 Java 8。

示例

interface I {
    // assuming parameters and return types here
    public void setCreatedTime(ZonedDateTime z);
    public void setUpdatedTime(ZonedDateTime z);
    public ZonedDateTime getCreatedTime();
    public ZonedDateTime getUpdatedTime();
}

// A, B etc. all implement I

public <T extends I> void find(T object, List<String> fieldsToBeUpdated) {
    fieldsToBeUpdated
    .parallelStream()
    .forEach(
        field -> {
            switch(field) {
                case "a": {
                    try {
                        object.getClass().getDeclaredField("a");
                        // we're good
                        object.setCreatedTime(...);
                    }
                    catch (NoSuchFieldException e) {
                        // TODO something
                    }
                    break;
                }
                // ...
            }
        });
}

更新

如果您的类根本不共享公共(public)字段,您可能想要完全改变整个方法。

您可能希望使用继承并在每个类中实现自己的 find 方法,而不是拥有“一个通用的方法适合所有人”的逻辑实现范例。

这将允许在每个实现中使用更小的 switch 语句,并在 default 情况下执行错误处理。

您仍然可以通过仍然采用 T extends Findablefind 方法来概括行为(其中 Findable 声明“时间”方法(现在是find 方法),并简单地在给定的T 对象上调用find

或者甚至将 FindableTimed 之间的关注点分开,并让您的类实现两者。

关于Java 泛型 - 类型转换问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44242647/

相关文章:

c# - "Method is not declared within generic type definition"错误

运行 Solr 需要 Java 1.7 或更高版本,但已安装 1.8

java - 使用 JAXB 插入/删除/搜索 XML 元素

c# - 在泛型集合的泛型方法上使用表达式lambda

swift - 具有可选、泛型和可比较性的函数确实满足编译器要求

c# - 使用 C++ 调试器作为反射替代

objective-c - 为什么 NSDictionary 会报告一个不寻常的类名?

java - DecimalFormat 和 Double 异常

java - 目前是否可以通过 Maven 构建 Eclipse 插件并具有良好的 IDE 集成?

java - 需要一些关于这个通用 Java 的帮助