以任何 setter 作为参数的方法

Method that takes any setter as a parameter

我有一个项目class

public class Item {
    Long id;
    String name;
    Boolean isGood;

// getters and setters
}

我想声明一个方法,它可以将方法引用和一些值作为参数。

我试过的

public class Main {
    public static void main(String[] args) {
        Item item = new Item();
        
        setLong(item::setId, 123L);
        setBool(item::setGood, true);
        setString(item::setName, "Foo Bar");

   }

   static void setLong(Consumer<Long> setter, Long o) {
        setter.accept(o);
    }

    static void setBool(Consumer<Boolean> setter, Boolean o) {
        setter.accept(o);
    } 
    
    static void setString(Consumer<String> setter, String o) {
        setter.accept(o);
    }
}

但我想要类似的东西

set(Long.class, item::setId, 123L);
set(Boolean.class, item::setGood, true);
set(String.class, item::setName, "Foo Bar");

我该怎么做?

试试这个。

import java.util.function.Consumer;

public class SOQ_20220528
{

   public static class Example
   {
   
      private Short a;
      private Integer b;
      private Long c;
   
      public Example() {}
   
      public Short getA() {
         return this.a;}
      public Integer getB() {
         return this.b;}
      public Long getC() {
         return this.c;}
   
      public void setA(Short a) {this.a = a;}
      public void setB(Integer b) {this.b = b;}
      public void setC(Long c) {this.c = c;}
      
      public String toString() { 
         return this.a + " " + this.b + " " + this.c; }
   
   }
   
   public static void main(String[] args)
   {
   
      final Example instanceName= new Example();
      
      final Short tuv = 1;
   
      set(Short.class, instanceName::setA, Short.valueOf(tuv));
      set(Integer.class, instanceName::setB, Integer.valueOf(2));
      set(Long.class, instanceName::setC, Long.valueOf(3));
   
   }
   
   public static <T> void set(Class<T> clazz, Consumer<T> setter, T value)
   {
   
      setter.accept(value);
   
   }

}

我们把我们想要使用的类型的 Class 作为第一个参数,然后我们把 setter 作为我们的第二个参数,最后,我们把我们想要的字面值对象作为我们的第三个参数进行调整。

第一个参数是必需的,因为在运行时会进行类型擦除。 Java 根本不在运行时保留类型,所以我们只需要传入 Class,它作为我们的运行时类型。

第二个参数是必需的,因为你需要一个setter来执行。但是,请注意我做了 instanceName::setA 而不是 Example::setA。由于这是我们 提供 消费者使用的代码部分,因此我使用 instance 名称而不是 type 名称。很多时候它实际上是相反的(一个例子是静态方法)。

第三个参数是setter参数的实际值。我将 instanceName 的字段 a 设置为 Short11 部分是我所说的第三个参数。

EDIT - 事实证明,对于这个特定示例,Class<T> 参数不是必需的。为了修改的简单性,我将保留它,但是是的,你可以在技术上有一个这样的方法头 - public static <T> void set(Consumer<T> setter, T value),然后你会像以前一样向这个方法提供参数,只是没有 class.