【问题标题】:Java: generic Method - add elements to varargJava:泛型方法 - 向可变参数添加元素
【发布时间】:2016-07-12 12:56:25
【问题描述】:

我想在这里这样做,它确实有效,但不知何故我认为这不是一个好的解决方案:

class A5<T> implements A4<T> {

    private final T[] elements;

    A5(T... elements) {
        this.elements = elements;
    }


    public <R> A5<R> map(Function<T, R> function) {
        List<R> liste = new LinkedList<>();
        for (T element : elements) {
            liste.add(function.apply(element));
        }
        Object[] objects = new Object[liste.size()];
        int counter = 0;
        for (R element : liste) {
            objects[counter] = liste.get(counter++);
        }
        return new A5(objects);
    }
}

Object[] 对我来说是个问题,但我无法创建 R[] 数组。有没有人有解决方案?更改 CTOR 和 map 的签名不是我想要的。只有身体可以改变。

【问题讨论】:

  • 旁注:你明白你用的A4、A5的名字真的有点什么都没说吗?为什么要声明 A5 是泛型的,然后在不提供类型参数的情况下实例化 A5 的对象并直接使用 Object ?
  • 不改变CTOR,是说它的主体不能改变吗?还是签名?还是两者兼而有之?
  • explv both Jägermeister 我只是不允许在这里提供原始源代码。
  • @N-rG 在这种情况下,您需要使用Object[],请参阅我的回答
  • 泛型数组通常不好。使用List

标签: java generics methods


【解决方案1】:

您不能创建一个通用数组,因此除非您将 A5 类中的 T[] 更改为 List&lt;T&gt;,否则您将需要创建一个 Object[]

您的代码可以稍微简化一下。您可以使用 Java 8 Stream 映射元素并将它们收集到 Object[],然后将此 Object[] 转换为 R[]@SuppressWarnings("unchecked") 隐藏了未经检查的演员产生的警告:

class A5<T> implements A4<T> {

    private final T[] elements;

    A5(T... elements) {
        this.elements = elements;
    }

    @SuppressWarnings("unchecked")
    public <R> A5<R> map(Function<T, R> function) {
        return new A5<>((R[]) Arrays.stream(elements).map(function).toArray());
    }
}

【讨论】:

    【解决方案2】:

    如果你被允许添加一个ctor,你可以将你的数据存储在一个列表中,这样就可以了

    class A5<T> implements A4<T> {
    
        private final List<T> elements;
    
        A5(T... elements) {
            this.elements = Arrays.asList(elements);
        }
    
        private A5(List<T> elements) {
            this.elements = elements;
        }
    
    
        public <R> A5<R> map(Function<T, R> function) {
            List<R> list = elements.stream().map(function)
                .collect(Collectors.toList());
            return new A5(list);
        }
    }
    

    【讨论】:

    • 这还需要更改 OP 指定他无法执行的初始构造函数。 (当然除非他只是表示不能更改签名,在这种情况下他应该更具体。)
    • @explv 我是这么理解的。
    【解决方案3】:

    你可以试试:

    public <R> A5<R> map(Function<T, R> function) {
        List<R> liste = new LinkedList<>();
        for (T element : elements) {
            liste.add(function.apply(element));
        }
    
        Object[] objects = liste.toArray();
    
        return new A5(objects);
    }
    

    【讨论】:

      【解决方案4】:

      不可能。

      你能做的最好的事情是获取函数返回的最不特定类型的对象,并使用它来创建一个新数组。显然,当数组为空或函数仅返回 null 时,这将不起作用。

          Set<Class<?>> types = new HashSet<>();
          List<R> liste = new LinkedList<>();
          for (T element : elements) {
              R mapped = function.apply(element);
              types.add(mapped.getClass());
              liste.add(mapped);
          }
      
          Class<?> elementType = getMostUnspecifc(types);
      
          return new A5<R>(liste.toArray((R[]) Array.newInstance(elementType, liste.size()));
      

      使用辅助方法

      static Class<?> getMostUnspecifc(Set<Class<?>> types) {
          if (types.isEmpty()) {
              return Object.class;
          }
          Class<?> unspecific = types.iterator().next();
          for (Class<?> type : types) {
              if (!unspecific.isAssignableFrom(type)) {
                  unspecific = type;
              }
          }
          return unspecific;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-27
        • 1970-01-01
        相关资源
        最近更新 更多