如何定义一个方法来接收两个类型为T的参数,以及在java中扩展T的S参数?

如何定义一个方法来接收两个类型为T的参数,以及在java中扩展T的S参数?,java,generics,generic-method,Java,Generics,Generic Method,在研究Java泛型时,我想知道是否可以声明一个接收两个参数的方法,第一个参数是泛型类型T,第二个参数是泛型类型s,它扩展了T或与T的类型相同。因此我开始对此进行实验,并编写了以下方法声明: public static <T, S extends T> void testMethod(T t, S s) { System.out.println("We are inside testMethod."); } 期望第二次调用导致编译时异常。但是程序编译并运行时没有错误。接下来,

在研究Java泛型时,我想知道是否可以声明一个接收两个参数的方法,第一个参数是泛型类型T,第二个参数是泛型类型s,它扩展了T或与T的类型相同。因此我开始对此进行实验,并编写了以下方法声明:

public static <T, S extends T> void testMethod(T t, S s)
{
    System.out.println("We are inside testMethod.");
}
期望第二次调用导致编译时异常。但是程序编译并运行时没有错误。接下来,我更改了方法testMethod声明,如下所示:

java.lang.Integer num1 = new java.lang.Integer(0);
java.lang.Integer num2 = new java.lang.Integer(1);

testMethod(num1, num2);
testMethod(num1, new Object());
public <T extends java.lang.Number, S extends T> void testMethod(T t, S s)
第一个调用没有错误,但第二个调用会导致编译时错误。似乎只要t和s都是java.lang.Number的子类型,不管s是否是t的子类型,都不会发生错误


我的问题:我们如何声明一个接收两个参数的方法,其中一个参数保证是另一个参数的子类型?

有两个问题:

就泛型而言,任何类型都是其自身的子类型。没有办法声明s扩展T,使s和T不能是同一类型。此外,即使有可能,在这里也不会有太大的影响,因为S的任何实例也可以作为t传递

类型推断尽最大努力使方法可编译。如果S与第一个参数的类型不兼容,编译器将推断最近的公共祖先为T。您可以通过在调用方法时显式指定T来避免此问题:

ThisClass.<Integer, Integer>testMethod(1, 2);    // compiles
ThisClass.<Integer, Integer>testMethod(1, 2.0);  // does not compile

事实是,最终,方法本身无法强制要求S是t类型的子类型,甚至与t类型兼容。我不认为有任何方法可以解决这个问题。

你写的东西是正确的,但推理的工作方式与你的想法不同。原因testMethodnum1,新对象;compiles是指编译器可以推断S和T都是对象。在第一个示例中,第二个调用不会生成编译时错误,因为类型推断决定使用调用方法。如果要使调用安全,请在调用泛型方法时指定类型:Test.testMethod…,这将生成编译时错误。但对象不会扩展Number@azro这就是为什么第二个示例的行为与OP预期的一样,生成编译时错误。@jacobm我希望T是对象的任意子类型,但我希望S被限制为T的子类型。您可以在执行时通过T.getClass.isAssignableFroms.getClass强制执行它。但除了显式泛型绑定之外,没有编译时强化。
ThisClass.<Integer, Integer>testMethod(1, 2);    // compiles
ThisClass.<Integer, Integer>testMethod(1, 2.0);  // does not compile