简体   繁体   English

Java 推断的泛型类型

[英]Java inferred generic types

I'm looking for a similar concept of inferring captured generic types, similar to the following method snippet, however instead for a class that captures generic types:我正在寻找类似的推断捕获的泛型类型的概念,类似于以下方法片段,但用于捕获泛型类型的类:

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

The code in this snippet will capture types and assign them to the generic parameter types X , Y and Z .此片段中的代码将捕获类型并将它们分配给通用参数类型XYZ This allows the use of the generic type variables inside the body of the code and makes the method more flexible in use.这允许在代码主体内使用泛型类型变量,并使方法在使用中更加灵活。 In this snippet, if the method is called without specifying the types (ie not parameterized), then Java will infer the types, that is someMethod(instaceOfImplementedObject) will work and the types will be inferred.在此代码段中,如果在未指定类型的情况下调用方法(即未参数化),则 Java 将推断类型,即someMethod(instaceOfImplementedObject)将起作用并推断类型。

My problem is, I have the following (simplified) structure for an object interface and objects that implement the interface:我的问题是,对于对象接口和实现该接口的对象,我有以下(简化的)结构:

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

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

Then I have other classes that have to capture quite a few generic type variables, of which one of them is an object that implements ObjectInterface<X, Y, Z> .然后我有其他类必须捕获相当多的泛型类型变量,其中一个是实现ObjectInterface<X, Y, Z> Within such a class, I also need to have a handle on the types ( X , Y , Z ) that is defined in the object that was captured.在这样的类中,我还需要处理在捕获的对象中定义的类型( XYZ )。

The following (not ideal, and very simplified) code works:以下(不理想,非常简化)代码有效:

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

However, this is very cumbersome for the person trying to use/initiate this class, even in this simplified version, for example:但是,即使在这个简化版本中,这对于尝试使用/启动此类的人来说也是非常麻烦的,例如:

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 */);
    }
}

Is there a way to "extract" or capture these types so that they are inferred instead of explicit as it is for ClassWorks in the working example?有没有办法“提取”或捕获这些类型,以便推断它们而不是像工作示例中的ClassWorks那样显式地推断它们? Possibly something similar to the following (Note this does not work):可能类似于以下内容(注意这不起作用):

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.
}

Edit: So an implemented example of WishfullClass would be:编辑:所以 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 */);
    }
}

ie. IE。 The compiler should know that ImplementedObject from the declaration of the class that it implements ObjectInterface<Integer, Double, String> as X, Y and Z.编译器应该从将ObjectInterface<Integer, Double, String>为 X、Y 和 Z 的类的声明中知道已ImplementedObject

Please note, these above are very simplified and in the real code are not the only parameters that need capturing, so those three extra parameters make quite a big difference;请注意,上面这些是非常简化的,在实际代码中并不是唯一需要捕获的参数,所以这三个额外的参数有很大的不同; also the implemented object also captures generic types,实现的对象也捕获泛型类型,

So ideally I would like to just collectively capture the object that extend the ObjectInterface<X, Y, Z> and have X , Y and Z inferred.因此,理想情况下,我只想共同捕获扩展ObjectInterface<X, Y, Z>并推断出XYZ Is there a way to do this?有没有办法做到这一点?

Ie The snippet of someMethod shows how you can infer X, Y and Z for the scope of a method.即 someMethod 的片段显示了如何为方法的范围推断 X、Y 和 Z。 My question refers to, is there a way to infer X, Y and Z for the entire scope of the class by only capturing a type that extends ObjectInterface .我的问题是,是否有一种方法可以通过仅捕获扩展ObjectInterface的类型来推断类的整个范围的 X、Y 和 Z。

I had some trouble wording/explaining this question, so if there is any uncertainty, please ask for clarification :)我在措辞/解释这个问题时遇到了一些麻烦,所以如果有任何不确定性,请要求澄清:)

So after some further research, I found the answer in the textbook Effective Java, by Joshua Block; Item 27: Favor generic methods所以经过一些进一步的研究,我在Effective Java, by Joshua Block; Item 27: Favor generic methods的教科书Effective Java, by Joshua Block; Item 27: Favor generic methods找到了答案Effective Java, by Joshua Block; Item 27: Favor generic methods Effective Java, by Joshua Block; Item 27: Favor generic methods . Effective Java, by Joshua Block; Item 27: Favor generic methods What I was looking for was to simplify/reduce the reiteration of type parameters when invoking the generic constructor - ie make it less cumbersome and not repeating parameters that are already given.我正在寻找的是在调用泛型构造函数时简化/减少类型参数的重复 - 即使其不那么麻烦并且不重复已经给出的参数。

It is indeed impossible to infer types for a constructor, however there is a way to exploit generic methods to reduce the reiteration and type parameters for constructors - by making generic factory methods for each constructor and infer the type parameters in this way instead.确实不可能推断构造函数的类型,但是有一种方法可以利用泛型方法来减少构造函数的重复和类型参数 - 通过为每个构造函数创建泛型工厂方法并以这种方式推断类型参数。

This is the information that explains this entire situation, the following is quoted out of the textbook:这是解释整个情况的信息,以下是从教科书中引用的:

One noteworthy feature of generic methods is that you needn't specify the value of the type parameter explicitly as you must when invoking generic constructors.泛型方法的一个值得注意的特性是您不需要像调用泛型构造函数时那样显式指定类型参数的值。 The compiler figures out the value of the type parameters by examining the types of the method arguments.编译器通过检查方法参数的类型来计算类型参数的值。 In the case of the program above, the compiler sees that both arguments to union are of type Set , so it knows that the type parameter E must be String.在上面的程序中,编译器看到 union 的两个参数都是 Set 类型,因此它知道类型参数 E 必须是 String。 This process is called type inference.这个过程称为类型推断。

As discussed in Item 1, you can exploit the type inference provided by generic method invocation to ease the process of creating parameterized type instances.如第 1 项所述,您可以利用泛型方法调用提供的类型推断来简化创建参数化类型实例的过程。 To refresh your memory, the need to pass the values of type parameters explicitly when invoking generic constructors can be annoying.为了刷新您的记忆,在调用泛型构造函数时需要显式传递类型参数的值可能很烦人。 The type parameters appear redundantly on the left- and right-hand sides of variable declarations:类型参数冗余出现在变量声明的左侧和右侧:

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

To eliminate this redundancy, write a generic static factory method corresponding to each constructor that you want to use.要消除这种冗余,请编写与您要使用的每个构造函数相对应的通用静态工厂方法。 For example, here is a generic static factory method corresponding to the parameterless HashMap constructor:例如,这里有一个对应于无参数 HashMap 构造函数的通用静态工厂方法:

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

With this generic static factory method, you can replace the repetitious declaration above with this concise one:使用这个通用静态工厂方法,您可以用这个简洁的声明替换上面的重复声明:

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

It would be nice if the language did the same kind of type inference when invoking constructors on generic types as it does when invoking generic methods.如果该语言在调用泛型类型的构造函数时执行与调用泛型方法时相同类型的类型推断,那就太好了。 Someday it might, but as of release 1.6, it does not.有一天它可能会,但从 1.6 版开始,它不会。

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

Would do the same in Java 7 onwards.在 Java 7 以后也会做同样的事情。 <> is diamond operator. <>是菱形运算符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM