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

根据他们的说法,通用 &lt;Program&gt; 与返回类型无关,但在我的情况下,如果我对这个程序进行一些更改,如下所示,那么输出会有所不同。

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 调用,然后再考虑拆箱并调用替代方法。 您在这一行定义了一个新的泛型类型参数Programprivate static &lt;Program&gt; 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中的泛型如何适用于以下程序?的主要内容,如果未能解决你的问题,请参考以下文章

仅适用于数值类型的泛型类型约束

java中的泛型的使用与理解

Java数组中的泛型

Java中的泛型 (上) - 基本概念和原理

c++ 模板

Scala的泛型