2017-05-10 16 views
18
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); 
    } 

} 

,输出是:Java中的泛型如何适用于以下程序?

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

+0

在你的第二个例子中,只有第二个版本的'foo()'有一个签名,它可以匹配你在'main()'中调用的内容。在第一个例子中,在拆箱之前必须有一个优先规则匹配对通用函数的“Integer”调用,并调用替代方法。 –

+10

您正在此行上定义一个新的泛型类型参数'Program':'private static void foo(Program x){'。该类型参数与名为'Program'的类无关。当您将类型参数的名称更改为“整数”时,参数“程序x”突然有一种类型的实际类“程序”。课程:不要将您的类型参数命名为存在的实际类。 – marstran

+2

如果您的泛型参数名称遵循拼写为单个大写字母的约定,那么您的代码将更容易遵循。无论如何,当你将它们命名为具体类型时,它是毫无希望的混淆,更不用说它是一个范围。从您的类型名称中分离您的泛型参数名称! –

回答

14

在你的第一个例子中,你实际上没有指定类型为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);不匹配,你会得到从第二个结果方法。

13

在第一种情况,是Program用于该方法的一般参数的名称。它可以是任何名称。重要的是method参数是一个Object,所以当你用一个Integer参数调用你的方法时,它使用带Object的版本。

在第二种情况下,通用参数名为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"); 
} 

现在很清楚,你的论点是一个程序对象,而不是任何对象。

+0

如果您发现喜欢JLS的相关部分讨论此问题的奖励积分^^ –

+0

不要调用类型参数“程序”,因为它是他的主类的名称。当他将类型参数重命名为“整数”时,参数类型突然变为实际的类“程序”。 – marstran