gpt4 book ai didi

java - 这是有效的Java吗?

转载 作者:IT老高 更新时间:2023-10-28 20:22:13 25 4
gpt4 key购买 nike

这是有效的 Java 吗?

import java.util.Arrays;
import java.util.List;

class TestWillThatCompile {

public static String f(List<String> list) {
System.out.println("strings");
return null;
}

public static Integer f(List<Integer> list) {
System.out.println("numbers");
return null;
}

public static void main(String[] args) {
f(Arrays.asList("asdf"));
f(Arrays.asList(123));
}

}
  • Eclipse 3.5 说是的
  • Eclipse 3.6 说 没有
  • Intellij 9 说 是的
  • Sun javac 1.6.0_20 说是的
  • GCJ 4.4.3 说
  • GWT 编译器说
  • 聚集在我的previous Stackoverflow question

我的java理论理解说!

知道the JLS 会很有趣正在谈论它。

最佳答案

这取决于您希望如何调用这些方法。如果您希望从其他 Java 源代码调用这些方法,则由于 Edwin's answer 中说明的原因,它被视为无效。 .这是 Java 语言的限制。

但是,并非所有类都需要从 Java 源代码生成(考虑使用 JVM 作为其运行时的所有语言:JRuby、Jython 等...)。 在字节码级别,JVM 可以消除这两种方法的歧义,因为字节码指令指定了它们所期望的返回类型。例如,这里有一个用 Jasmin 编写的类可以调用以下任一方法:

.class public CallAmbiguousMethod
.super java/lang/Object

.method public static main([Ljava/lang/String;)V
.limit stack 3
.limit locals 1

; Call the method that returns String
aconst_null
invokestatic TestWillThatCompile/f(Ljava/util/List;)Ljava/lang/String;

; Call the method that returns Integer
aconst_null
invokestatic TestWillThatCompile/f(Ljava/util/List;)Ljava/lang/Integer;

return

.end method

我使用以下命令将其编译为类文件:

java -jar jasmin.jar CallAmbiguousMethod.j

And call it using:

java CallAmbiguousMethod

Behold, the output is:

> java CallAmbiguousMethodstringsnumbers

Update

Simon posted an example program that calls these methods:

import java.util.Arrays;
import java.util.List;

class RealyCompilesAndRunsFine {

public static String f(List<String> list) {
return list.get(0);
}

public static Integer f(List<Integer> list) {
return list.get(0);
}

public static void main(String[] args) {
final String string = f(Arrays.asList("asdf"));
final Integer integer = f(Arrays.asList(123));
System.out.println(string);
System.out.println(integer);
}

}

这是生成的 Java 字节码:

>javap -c RealyCompilesAndRunsFineCompiled from "RealyCompilesAndRunsFine.java"class RealyCompilesAndRunsFine extends java.lang.Object{RealyCompilesAndRunsFine();  Code:   0:   aload_0   1:   invokespecial   #1; //Method java/lang/Object."":()V   4:   returnpublic static java.lang.String f(java.util.List);  Code:   0:   aload_0   1:   iconst_0   2:   invokeinterface #2,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;   7:   checkcast       #3; //class java/lang/String   10:  areturnpublic static java.lang.Integer f(java.util.List);  Code:   0:   aload_0   1:   iconst_0   2:   invokeinterface #2,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;   7:   checkcast       #4; //class java/lang/Integer   10:  areturnpublic static void main(java.lang.String[]);  Code:   0:   iconst_1   1:   anewarray       #3; //class java/lang/String   4:   dup   5:   iconst_0   6:   ldc     #5; //String asdf   8:   aastore   9:   invokestatic    #6; //Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;   12:  invokestatic    #7; //Method f:(Ljava/util/List;)Ljava/lang/String;   15:  astore_1   16:  iconst_1   17:  anewarray       #4; //class java/lang/Integer   20:  dup   21:  iconst_0   22:  bipush  123   24:  invokestatic    #8; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   27:  aastore   28:  invokestatic    #6; //Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;   31:  invokestatic    #9; //Method f:(Ljava/util/List;)Ljava/lang/Integer;   34:  astore_2   35:  getstatic       #10; //Field java/lang/System.out:Ljava/io/PrintStream;   38:  aload_1   39:  invokevirtual   #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V   42:  getstatic       #10; //Field java/lang/System.out:Ljava/io/PrintStream;   45:  aload_2   46:  invokevirtual   #12; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V   49:  return

事实证明,Sun 编译器正在生成消除方法歧义所需的字节码(参见最后一个方法中的说明 12 和 31)。

更新 #2

Java Language Specification表明这实际上可能是有效的 Java 源代码。在第 449 页(第 15.12 节方法调用表达式)我们看到:

It is possible that no method is the most specific, because there are two or more methods that are maximally specific. In this case:

  • If all the maximally specific methods have override-equivalent (§8.4.2) signatures, then:
    • If exactly one of the maximally specific methods is not declared abstract, it is the most specific method.
    • Otherwise, if all the maximally specific methods are declared abstract, and the signatures of all of the maximally specific methods have the same erasure (§4.6), then the most specific method is chosen arbitrarily among the subset of the maximally specific methods that have the most specific return type. However, the most specific method is considered to throw a checked exception if and only if that exception or its erasure is declared in the throws clauses of each of the maximally specific methods.
  • Otherwise, we say that the method invocation is ambiguous, and a compiletime error occurs.

除非我弄错了,否则这种行为应该只适用于声明为抽象的方法...

更新 #3

感谢 ILMTitan 的评论:

@Adam Paynter: Your bolded text does not matter, because it is only a case when two methods are override-equivalent, which Dan showed was not the case. Thus, the determining factor must be if the JLS takes generic types into account when determining most specific method. – ILMTitan

关于java - 这是有效的Java吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3110014/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com