代码之家  ›  专栏  ›  技术社区  ›  Smiley

Java推断泛型类型

  •  2
  • Smiley  · 技术社区  · 7 年前

    我正在寻找一个类似的概念来推断捕获的泛型类型,类似于下面的方法片段,然而,对于一个捕获泛型类型的类:

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

    X Y Z . 这允许在代码体中使用泛型类型变量,并使该方法在使用中更加灵活。在这个代码段中,如果调用方法时没有指定类型(即未参数化),那么Java将推断类型,即 someMethod(instaceOfImplementedObject) 将起作用,并将推断类型。

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

    public interface ObjectInterface<X, Y, Z> {
        //...
    }
    
    class ImplementedObject implements ObjectInterface<SomeType1, SomeType2, SomeType3> {
        //...
    }
    

    然后我还有其他类,它们必须捕获相当多的泛型类型变量,其中一个是实现的对象 ObjectInterface<X, Y, Z> 十、 , , Z )这是在捕获的对象中定义的。

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

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

    编译器应该知道 ImplementedObject ObjectInterface<Integer, Double, String> 如X、Y和Z。

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

    理想情况下,我只想集体捕捉扩展 ObjectInterface<十、 Y,Z> 而且有 十、 Y 推断。有办法做到这一点吗?

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

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

    2 回复  |  直到 7 年前
        1
  •  2
  •   Sachith Dickwella    7 年前
    Map<String, List<String>> anagrams = new HashMap<>();
    

    在Java 7以后的版本中也会这样做。 <> 是菱形运算符。

        2
  •  1
  •   Community CDub    4 年前

    因此,经过进一步研究,我在教科书中找到了答案 Effective Java, by Joshua Block; Item 27: Favor generic methods

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

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

    // 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版开始,它就不会了。