【问题标题】:Java inferred generic typesJava 推断的泛型类型
【发布时间】:2018-04-01 21:44:03
【问题描述】:

我正在寻找一个类似的推断捕获的泛型类型的概念,类似于下面的方法 sn-p,但是代替捕获泛型类型的类:

public <X, Y, Z> static void someMethod(ObjectInterface<X, Y, Z> object) {
    // code that uses inferred generic type parameters X, Y and Z...
}

此 sn-p 中的代码将捕获类型并将它们分配给泛型参数类型 XYZ。这允许在代码主体内使用泛型类型变量,并使该方法在使用中更加灵活。在这个 sn-p 中,如果调用方法时没有指定类型(即没有参数化),那么 Java 会推断类型,即someMethod(instaceOfImplementedObject) 将起作用并推断类型。

我的问题是,我有以下(简化的)对象接口结构和实现该接口的对象:

public interface ObjectInterface<X, Y, Z> {
    //...
}

class ImplementedObject implements ObjectInterface<SomeType1, SomeType2, SomeType3> {
    //...
}

然后我有其他类必须捕获相当多的泛型类型变量,其中一个是实现ObjectInterface&lt;X, Y, Z&gt; 的对象。在这样一个类中,我还需要处理在捕获的对象中定义的类型(XYZ)。

以下(不理想,但非常简化)代码有效:

public class ClassWorks<X, Y, Z, N extends ObjectInterface<X, Y, Z>> {
    // code body uses X, Y, Z and N...
}

但是,这对于尝试使用/启动此类的人来说非常麻烦,即使在这个简化版本中也是如此,例如:

public class ImplementedObject implements ObjectInterface<Integer, Double, String> {
    //...
}

public class RandomExample {
    public static void main(String[] args) {
        ObjectInterface<Integer, Double, String> implementedObj = new ImplementedObject();
        ClassWorks<Integer, Double, String, ImplementedObject>> example = new ClassWorks<Integer, Double, String, ImplementedObject>(/* possible params */);
    }
}

有没有办法“提取”或捕获这些类型,以便推断它们而不是像工作示例中的 ClassWorks 那样显式地推断它们? 可能类似于以下内容(注意这不起作用):

pulic class WishfullClass<N extends ObjectInterface<X, Y, Z>> {
    // type N is captured; X, Y and Z is not explicitly captured.
    // code uses type N, as well as X, Y and Z
    // where, X, Y and Z is inferred somehow from N.
}

编辑: 所以 WishfullClass 的实现示例是:

public class ImplementedObject implements ObjectInterface<Integer, Double, String> {
    //...
}

public class WishfullExample {
    public static void main(String[] args) {
        ObjectInterface<Integer, Double, String> implementedObj = new ImplementedObject();
        WishFullClass<ImplementedObject> example = new WishfullClass<ImplementedObject>(/* possible params */);
    }
}

即。编译器应该从将ObjectInterface&lt;Integer, Double, String&gt; 实现为X、Y 和Z 的类的声明中知道ImplementedObject

请注意,上面的这些非常简化,在实际代码中并不是唯一需要捕获的参数,所以这三个额外的参数有很大的不同;实现的对象也捕获泛型类型,

因此,理想情况下,我只想集体捕获扩展ObjectInterface&lt;X, Y, Z&gt; 并推断出XYZ 的对象。有没有办法做到这一点?

即someMethod 的 sn-p 显示了如何推断方法范围的 X、Y 和 Z。我的问题是,有没有办法通过仅捕获扩展 ObjectInterface 的类型来推断类的整个范围的 X、Y 和 Z。

我在措辞/解释这个问题时遇到了一些问题,所以如果有任何不确定性,请要求澄清:)

【问题讨论】:

  • 使用类型变量(与任何其他变量一样)的唯一方法是让该类型变量在范围内。所以要么你必须声明它,要么必须有一个在包含范围内已经可见。
  • @AndyTurner 是的 :) 这就是问题的来源。所以我知道如何推断变量 X、Y、Z(无需明确指定变量 - 给对象extends ObjectInterface 就足够了),对于一个方法,在第一个小代码 sn-p 中显示并在问题的开头进行了解释。我的问题是,是否可以做一些类似于从扩展 ObjectInterface 的类型参数 N 推断 X、Y 和 Z 的事情,但适用于类的整个范围。

标签: java generics type-parameter inferred-type


【解决方案1】:
Map<String, List<String>> anagrams = new HashMap<>();

在 Java 7 及以后的版本中也会这样做。 &lt;&gt; 是钻石运营商。

【讨论】:

  • 昨天意识到了这一点。感谢您添加此内容。需要注意的一件事是,在左侧的声明中仍必须重复 X、Y 和 Z。即 Class>。至少菱形算子允许对右侧进行推理,这样就不会那么麻烦了。
【解决方案2】:

所以经过进一步研究,我在教科书Effective Java, by Joshua Block; Item 27: Favor generic methods中找到了答案。我一直在寻找的是在调用泛型构造函数时简化/减少类型参数的重复 - 即减少麻烦并且不重复已经给出的参数。

确实不可能为构造函数推断类型,但是有一种方法可以利用泛型方法来减少构造函数的重复次数和类型参数 - 通过为每个构造函数创建通用工厂方法并以这种方式推断类型参数.

这是解释整个情况的信息,以下是从教科书中引用的:

泛型方法的一个值得注意的特性是,您不需要像调用泛型构造函数时那样显式指定类型参数的值。编译器通过检查方法参数的类型来计算类型参数的值。在上面的程序中,编译器看到 union 的两个参数都是 Set 类型,所以它知道类型参数 E 必须是 String。这个过程称为类型推断。

正如第 1 项中所讨论的,您可以利用泛型方法调用提供的类型推断来简化创建参数化类型实例的过程。为了刷新您的记忆,在调用泛型构造函数时需要显式传递类型参数的值可能很烦人。类型参数冗余地出现在变量声明的左右两侧:

// Parameterized type instance creation with constructor`
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();

要消除这种冗余,请编写一个与您要使用的每个构造函数相对应的通用静态工厂方法。例如,这里是一个通用的静态工厂方法,对应于无参数的 HashMap 构造函数:

// Generic static factory method
public static <K,V> HashMap<K,V> newHashMap() {
    return new HashMap<K,V>();
}

使用这个通用的静态工厂方法,你可以用这个简洁的方法替换上面重复的声明:

// Parameterized type instance creation with static factory
Map<String, List<String>> anagrams = newHashMap();

如果语言在 在泛型类型上调用构造函数,就像在调用泛型方法时一样。有朝一日可能会,但从 1.6 版开始,它不会。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多