java中的泛型如何适用于以下程序?
Posted
技术标签:
【中文标题】java中的泛型如何适用于以下程序?【英文标题】:How generics in java works for the following program? 【发布时间】:2017-10-08 19:15:53 【问题描述】:public class Program
private static <Program> void foo(Program x)
System.out.println(x+"-->1");
private static void foo(final int i)
System.out.println(i+"-->2");
public static void main(String[] args)
Integer i = 10;
foo(i);
输出是:
10-->1
我无法找到有关此主题的任何相关讨论。但是,另一个主题的答案让我有些困惑:- Return Type of Java Generic Methods
根据他们的说法,通用 <Program>
与返回类型无关,但在我的情况下,如果我对这个程序进行一些更改,如下所示,那么输出会有所不同。
public class Program
private static <Integer> void foo(Program x)
System.out.println(x+"-->1");
private static void foo(final int i)
System.out.println(i+"-->2");
public static void main(String[] args)
Integer i = 10;
foo(i);
输出:
10-->2
我使用的是JDK1.7
【问题讨论】:
在您的第二个示例中,只有foo()
的第二个版本具有与您在 main()
中调用的内容相匹配的签名。在第一个示例中,必须有一个优先规则匹配对通用函数的Integer
调用,然后再考虑拆箱并调用替代方法。
您在这一行定义了一个新的泛型类型参数Program
:private static <Program> void foo(Program x)
。该类型参数与您名为Program
的类无关。当您将类型参数的名称更改为Integer
时,参数Program x
突然具有您的实际类Program
的类型。教训:不要将你的类型参数命名为实际存在的类。
如果您的泛型参数名称遵循使用单个大写字母拼写的约定,您的代码将更容易遵循。无论如何,当您将它们命名为与具体类型相同的类型时,它会令人绝望地混淆,更不用说在范围内的类型了。将泛型参数名称与类型名称分开!
这是一个最近被问到的面试问题......无论如何你的回答都有意义。
【参考方案1】:
在您的第一个示例中,您实际上并没有指定Program
类型的参数,它是一个泛型。该类型参数与您名为Program
的类无关。通过输入这样的错字,您将得到相同的结果:
public class Program
private static <Programmmm> void foo(Programmmm x)
System.out.println(x+"-->1");
private static void foo(final int i)
System.out.println(i+"-->2");
public static void main(String[] args)
Integer i = 10;
foo(i);
但是,在您的第二个示例中,参数的字面意思是 Program
类型,因此当以 foo(10);
调用时它不匹配,并且您从第二种方法获得结果。
【讨论】:
【参考方案2】:在第一种情况下,Program
是用于方法的通用参数的名称。它可以是任何名称。重要的是方法参数是一个对象,所以当你用一个整数参数调用你的方法时,它使用接受对象的版本。
在第二种情况下,泛型参数命名为Integer
(不要这样做),但该方法采用的参数是程序。因此,通过使用 Integer 调用它,没有有效的 Object
或整数版本,因此它会将值拆箱。
就method overloading而言,它描述了解决重载的顺序。这将告诉您为什么第一个版本使用Object
方法而不是int
方法。
第二个问题是您将泛型参数命名为具体类型,这令人困惑。不这样做更容易看出。
private static <T> void foo(T x)
System.out.println(x+"-->1");
现在更清楚了,T
是一个参数化参数。在您的第二个版本中,
private static <T> void foo(Program x)
System.out.println(x+"-->1");
现在很清楚,您的论点必须是一个 Program 对象,而不仅仅是任何对象。
【讨论】:
如果您对讨论此问题的 JLS 的相关部分点赞 ^ ^ 也不要调用类型参数Program
,因为这是他主类的名字。当他将类型参数重命名为Integer
时,参数类型突然变为实际类Program
。以上是关于java中的泛型如何适用于以下程序?的主要内容,如果未能解决你的问题,请参考以下文章