猿问

用于修改值的 Java 框架/模式

我有一个对象人


public class Person {

    private String name;

    private Integer age ;

    private String address;

    private String group;

    private String id;


    public Person(String name, Integer age, String address, String group, String id) {

        this.name = name;

        this.age = age;

        this.address = address;

        this.group = group;

        this.id = id;

    }


    @Override

    public String toString() {

        return "Person{" +

                "name='" + name + '\'' +

                ", age=" + age +

                ", address='" + address + '\'' +

                ", group='" + group + '\'' +

                ", id='" + id + '\'' +

                '}';

    }


    public void setName(String name) {

        this.name = name;

    }


    public void setAge(Integer age) {

        this.age = age;

    }


    public void setAddress(String address) {

        this.address = address;

    }


    public void setGroup(String group) {

        this.group = group;

    }


    public void setId(String id) {

        this.id = id;

    }


    public String getName() {

        return name;

    }


    public Integer getAge() {

        return age;

    }


    public String getAddress() {

        return address;

    }


    public String getGroup() {

        return group;

    }


    public String getId() {

        return id;

    }

}

如上所述,它将非常笨拙,因为将有更多的比较运算符和更多的字段。

是否有我可以使用的表达语言框架或 JAva 库或任何开源框架来使其成为通用解决方案


心有法竹
浏览 195回答 2
2回答

拉莫斯之舞

假设您对稍微不太方便的形式感到满意import com.google.common.base.Equivalence;...metaData.add(new MetaData(Person.class, Equivalence.equals(), "name", "John", "group", "SIGMA"));最简单的基于 Java 的解决方案是将内省实例的类添加到元数据中,参数化比较对象的方式(我在这里使用了 Guava,你也可以使用普通的 Java 8 BiPredicate<T super Person>)并指定属性的名称。执行时,您可以利用它java.beans.Introspector#getBeanInfo()来发现 getter 和 setter 名称(这是克服各种 Java Beans 怪胎的最安全方法,例如布尔属性、完全大写的属性名称等。 - 我建议更喜欢它而不是基于字符串替换的半生不熟的工具)并相应地调用它们。您可以使用以下方法进一步缩短通话时间metaData.add(new MetaData<Person>(Equivalence.equals(), "name", "John", "group", "SIGMA"));(类可以使用称为类型标记或类型文字的反射黑客派生)或创建自己的子类,例如EqualsMetadataor PersonMetadata,您就明白了。或者,您可以完全避免(普通的)反射并使用方法引用定义所有内容:metaData.add(new MetaData(Equivalence.equals(), Person::getName, Person::setName, "John", Person::getGroup, Person::setGroup, "SIGMA"));它更长但类型更安全 - 您可以确保参数John并SIGMA与 getter 和 setter 类型相对应。要使用外部工具实现它,我建议查看 mapstruct.org。Dozer 也是可能的,但是在我们的项目中,由于基于生成代码的性能和哲学,我们迁移到 mapstruct,恕我直言,它可以更好地了解转换过程中真正发生的情况。

慕虎7371278

主要有以下三个坑:首先,您需要某种从字段名称到 getter/setter 方法的映射,以从 POJO 模型类访问字段值。其次,各个字段的数据类型不同。因此,如果字段值没有实现,您需要一个不同的比较器Comparable。你使用的类型实现了Comparable,所以你很好。第三,Java 不能Object以泛型的方式来转换内置值类型;即 getter 方法的签名通常不匹配。您已经通过为诸如 int 之类的琐碎数据类型选择盒装类型来避免这种情况。要使所有这些工作正常运行,您需要执行以下步骤:因此,在第一步中,您需要构建一个 getter 方法的存储库。即类似的东西HashMap<String, Function<Person, Object>> map1。您可以通过map1.put("name", Person::getName)或通过反射显式添加所有 getter 来静态执行此操作。接下来,您需要为 setter 构建一个存储库。即类似的东西HashMap<String, BiConsumer<Person, Object>> map2。同样,您可以使用反射或显式初始化。在后一种情况下,还有另一个陷阱,因为 setter 的泛型类型转换不再是协变的。这可以通过双重未经检查的强制转换来处理:map2.put("name",&nbsp;(BiConsumer)(BiConsumer<Person,&nbsp;String>)Person::setName);由于 Java 的类型擦除,所有 setter 实际上都具有相同的匹配方法签名。假设您的所有值类型都实现Comparable了下一步是非常简单的。调用您的getter从存储库,比较值(注意空的),并应用所需要的比较操作符(= 0,< 0,> 0或其他) -顺便说一句:你真的应该使用enum的MetaData::comparator,而不是字符串。如果需要,通过从存储库调用 setter 来分配结果值。如果您不需要字符串作为字段名称的键,您可以加入步骤 1 和步骤 2。只需使用 getter 方法引用作为(强类型)键而不是名称。现在您只需要一个从 getter 映射到 setter 的存储库。IE:HashMap<Function<Person,&nbsp;Object>,&nbsp;BiConsumer<Person,&nbsp;Object>>&nbsp;map;这从 getter(用作键)映射到匹配的 setter 方法。如果需要,我更喜欢这种方式,因为强类型值不易出错且重构更安全。
随时随地看视频慕课网APP

相关分类

Java
我要回答