Java推断的泛型类型 [英] Java inferred generic types

查看:163
本文介绍了Java推断的泛型类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  public  static void someMethod(ObjectInterface< X,Y,Z> object){
//使用推断泛型类型参数X,Y和Z的代码...
}

这段代码中的代码将捕获类型并将它们分配给通用参数类型 X Y Z 。这允许在代码体内使用泛型类型变量,并使该方法在使用中更加灵活。在这个片段中,如果调用方法时没有指定类型(即没有参数化),那么Java将推断出类型,即 someMethod(instaceOfImplementedObject)将会工作,类型将被推断出来。



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

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

类实现对象实现ObjectInterface< SomeType1,SomeType2,SomeType3> {
// ...
}

然后我有其他的类必须捕获相当多的泛型类型变量,其中一个是实现 ObjectInterface< X,Y,Z> 的对象。在这样的类中,我还需要处理类型( X Y ,<$ c $



下面的(不理想的,也是非常简化的)代码工作:



  public class ClassWorks< X,Y,Z,N extends ObjectInterface< X,Y,Z>> {
//代码体使用X,Y,Z和N ...
}

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

  public class实现Object实现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>>示例= new ClassWorks< Integer,Double,String,ImplementedObject>(/ *可能的参数* /);


$ / code>

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

pre $ pulic class WishfullClass< N extends ObjectInterface< N X,Y,Z>> {
//类型N被捕获; X,Y和Z没有明确捕获。
//代码使用类型N,以及X,Y和Z
//其中X,Y和Z以某种方式从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>(/ *可能的参数* /);
}
}

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



请注意,上述内容非常简单,并且在真实代码中不是唯一需要捕获的参数,所以这三个额外的参数有很大的不同;所实现的对象也捕获泛型类型,所以理想情况下,我想集体捕获扩展 ObjectInterface 并且具有 X Y 并且 Z 推断。有没有办法做到这一点?

I.e。 someMethod的片段展示了如何推断方法范围的X,Y和Z.我的问题指的是,是否有一种方法可以通过捕获一个扩展 ObjectInterface 的类型来推断整个类的X,Y和Z。 / p>

我在解释这个问题时遇到了一些麻烦,所以如果有任何不确定性,请询问澄清:)

Effective Java中找到了答案。第27项:赞成通用方法。我在寻找的是在调用泛型构造函数时简化/减少类型参数的重复 - 也就是说,减少繁琐,并且不会重复已经给出的参数。



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



这是解释整个情况的信息,下面引用了教科书:


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

正如在第1条中所讨论的那样,您可以利用通用方法调用提供的类型推断来简化创建参数化类型实例的过程。为了刷新你的记忆,当调用泛型构造函数时需要显式传递类型参数的值可能会很烦人。类型参数在变量声明的左侧和右侧冗余: //使用构造函数创建参数化类型实例
Map< String,List< String>> anagrams = new HashMap< String,List< String>>();




为了消除冗余,编写一个通用的静态工厂方法你想要使用的构造函数。例如,下面是对应于无参数HashMap构造函数的泛型静态工厂方法:



  / /通用静态工厂方法
public static< K,V>的HashMap< K,V> newHashMap(){
返回新的HashMap< K,V>();

$ / code>




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



  //使用静态创建参数化类型实例工厂
地图< String,List< String>> anagrams = newHashMap();




如果语言做了相同类型的推理当
调用泛型类型的构造函数时,就像调用泛型方法时一样。有一天它可能,但是从1.6版开始,它不会。



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. 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 (i.e. not parameterized), then Java will infer the types, that is someMethod(instaceOfImplementedObject) will work and the types will be inferred.

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

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? 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:

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. The compiler should know that ImplementedObject from the declaration of the class that it implements ObjectInterface<Integer, Double, String> as X, Y and Z.

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. Is there a way to do this?

I.e. The snippet of someMethod shows how you can infer X, Y and Z for the scope of a method. 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.

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. What I was looking for was to simplify/reduce the reiteration of type parameters when invoking the generic constructor - i.e. 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. 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. 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:

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

这篇关于Java推断的泛型类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆