首页 > 解决方案 > 在 Java 中表示匿名交集类型

问题描述

这些都不能编译,但是......我想在 Java中表达匿名 交集类型,这意味着任何实现/扩展 A 和 B 接口的类型,但通过使用某些语法(如. 特别是我想在以下情况下使用它们:(A & B)&

  1. 方法参数,例如public void foo((A & B) x) { ... }
  2. 方法返回类型,例如public (A & B) foo() { ... }
  3. 局部变量,例如(A & B) foo = ...
  4. 通配符泛型,例如List<? extends A & B)> foo = ...

我是否认为到目前为止(Java 13)对我来说的选项如下?

  1. 方法参数- 使用泛型:public static <T extends A & B> void foo(T x) { ... }
  2. 方法返回类型- 使用泛型:public static <T extends A & B> T foo() { ... }
  3. 局部变量- 使用 varvar foo = (A & B) bar
  4. 通配符泛型- 没有当前选项

以下文章深入探讨了这些类型何时/为何有用。这篇文章很好地涵盖了 1。这篇文章涵盖了 1. 2. 和 3。这个SO 问题涵盖了 4. 以及 Java 对此没有语法是多么好奇。

---根据要求进行了编辑以解释我的用例---

我经常使用仅包含信息项的 Value 对象。这些信息项相对独立地可重用,但通常只是为了方便而将它们放在一起,并在其他应用实际逻辑的类中传递。我发现以一种长期稳定且可重用的方式命名 getter 接口非常容易。getCustomerForename()关于返回什么和 将返回什么的争论很少getCustomerId(),定义这些几乎是为您的业务定义一个“数据模型”。但是一旦你尝试将它们固定在一起Customer接口,该接口通常变得非常特殊,并且被不恰当地重用,因为在某些情况下您需要所有客户信息,而在其他情况下您只需要一些信息,或者混入其他数据。很难命名,无论是否需要都会产生耦合'不是任何并创建额外的代码。相反,我想避免创建/命名任何新接口,而是使用匿名交集类型从现有的类型中动态创建一个新类型,这些类型一次只公开一个 getter。所以上面的接口AB上面将是如下接口:

interface CustomerId {
  Long getCustomerId();
}

interface CustomerForename {
  String getCustomerForename();
}

...如果我有一份报告只是显示了这两个项目,我将只创建具有“类型”的对象,(CustomerId & CustomerForename)而不是命名和创建CustomerIdAndCustomerForename接口/类,但收益甚微。

标签: javagenericstypes

解决方案


如果您指定了类型参数,则<T extends A&B>可以在通配符类型中使用它,如下例中使用Optional<? extends T>. 这是相似的,但我想和你想做的不一样,虽然现在我的大脑太疼了,无法解释有什么区别。


public class GenericsTest {

    public static void main(String[] args) {

        System.out.println(generateCombination().get().getB());
        System.out.println(generateCombination().get().getA());
    }

    static <T extends A&B> Optional<? extends T> generateCombination() {
        return (Optional<? extends T>) Optional.of(new Both());
    }

     interface A {
        String getA();
    }

     interface B {
        Number getB();
    }

    static class Both implements A, B {
        @Override
        public String getA() {
            return "Hello";
        }

        @Override
        public Number getB() {
            return 23;
        }
    }
}

无论如何,如您的问题中所述,其他变体似乎是正确的。


推荐阅读