Java推断了泛型类型

时间:2017-10-20 16:55:21

标签: java generics type-parameter inferred-type

我正在寻找推断捕获的泛型类型的类似概念,类似于以下方法片段,但是对于捕获泛型类型的类而言:

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

此代码段中的代码将捕获类型并将其分配给通用参数类型XYZ。这允许在代码体内使用泛型类型变量,并使该方法在使用中更加灵活。在此片段中,如果在未指定类型的情况下调用方法(即未参数化),则Java将推断类型,即someMethod(instaceOfImplementedObject)将起作用并且将推断类型。

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

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

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

然后我有其他类必须捕获相当多的泛型类型变量,其中一个是实现ObjectInterface<X, Y, Z>的对象。在这样的类中,我还需要处理在捕获的对象中定义的类型(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 */);
    }
}

有没有办法提取&#34;提取&#34;或者捕获这些类型,以便在工作示例中推断出它们而不是显式的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 */);
    }
}

即。编译器应该知道它实现ImplementedObject的类的声明中的ObjectInterface<Integer, Double, String>为X,Y和Z.

请注意,以上这些都是非常简化的,并且在实际代码中并不是唯一需要捕获的参数,因此这三个额外的参数会产生很大的差异;实现的对象也捕获泛型类型,

理想情况下,我想集体捕获扩展ObjectInterface<X, Y, Z>并推断XYZ的对象。有没有办法做到这一点?

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

我在措辞/解释这个问题上有些困难,所以如果有任何不确定性,请要求澄清:)

3 个答案:

答案 0 :(得分:1)

经过一些进一步的研究,我在教科书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开始,它没有。

答案 1 :(得分:1)

Map<String, List<String>> anagrams = new HashMap<>();

在Java 7以后也会这样做。 <>是钻石运营商。

答案 2 :(得分:0)

我之前没有得到这样的要求,但如果你在WishfullClass实现之前使用外卡(?)或使用抽象类,那么这个要求可能会实现。我将按照以下方式执行此操作。

public abstract class AbstractObjectInterface<X, Y, Z> implements ObjectInterface<X, Y, Z> {
 // What ever you want to do here. You can expose those type variables from here as well.
}

public class WishfullClass<X, Y, Z, N> extends AbstractObjectInterface<X, Y, Z> {
 // Use N type variable here. 
}

这不是要求。

<强>更新 否则,您可以按如下方式显式实现类的接口。

class WishfullClass<X, Y, Z, N> implements ObjectInterface<X, Y, Z> {
 // Use N type variable here. 
}