0

据我所知,在 Java 的编译期间,只记录类/方法签名。实际的实现在 JVM 中一直绑定到运行时。

让我们假设有一个名为MyClass. 在 Java 1.6 版中:

public class NativeClass {
    public String getVersion() { return "1.6"; }
}

在 Java 1.7 版中:

public class NativeClass {
    public String getVersion() { return "1.7"; }
    public String somethingMore() { return "more"; }
}

我们的 IDE 和编译器是 1.7。程序编译完成后,当我们在 JRE 1.6 和 1.7 中运行它时,我们会得到不同的返回值NativeClass.getVersion();。这是众所周知的。

但是如果我们NativeClass.somethingMore()在 JRE 1.6 上运行会发生什么?

如果可能,请在真实的 Java 源代码中给出一个示例,其中某些类/方法仅存在于较新的版本中。

4

3 回答 3

2

但是如果我们在 JRE 1.6 上运行 NativeClass.somethingMore() 会发生什么?

ANoSuchMethodError将被抛出。

如果应用程序尝试调用类的指定方法(静态或实例),并且该类不再具有该方法的定义,则抛出该异常。


如果一个类不存在怎么办?没有NoSuchClassError

请参阅NoClassDefFoundError& ClassNotFoundException

但不要问我 a) 为什么有两个。b)为什么使用一个而不是另一个/有什么区别,或者 c)为什么方法也有NoSuchMethodException.

似乎它们都应该是一个Error而不是一个Exception

于 2013-06-11T02:20:37.317 回答
1

就他所说的而言,安德鲁汤姆森是正确的。这是一个更丰富的答案:

第一点是,如果您使用 Java 1.7 SDK(或 IDE)编译代码,并尝试在 Java 1.6(或更早版本)上运行它,您可能会遇到“幻数”错误。基本上,除非“目标版本”设置为旧版本,否则编译器将发出旧 JVM 无法理解的字节码文件。

一旦你过去了:

  • 尝试调用不存在的方法将导致NoSuchMethodError.

  • 尝试(以任何方式)使用不存在的类将导致ClassDefNotFoundError.

当 JVM 尝试解决类之间的依赖关系时,会检测并抛出错误。(这在 JLS 中称为“链接”。它发生在类“初始化”之前的某个时间,但 JVM 可以自由地实现加载和链接延迟,因此它可能不会在应用程序启动时立即发生。

这两个都是致命的错误。它们使 JVM 处于应用程序不太可能恢复的状态,因为应用程序的一组不确定的基本类不可用。

这些是“二进制兼容性错误”的示例。其他示例包括缺少字段、签名错误的方法、访问修饰符的一些更改、继承层次结构的更改等。(有一个完整的 JLS 章节处理二进制兼容性规则;即,在不破坏兼容性的情况下,您可以和不能在类中更改什么。)

这真的都是常识。如果您尝试调用不存在的方法或使用不存在的类,则以致命错误退出是唯一安全的做法。“一次编写,随处运行”存在实际限制。


如果您想要一个简单的示例,请尝试运行String.isEmpty()在 Java 1.5 或更早版本的 JVM 上使用的应用程序。(或早期版本的 Android 手机...)


你不会得到一个ClassNotFoundException. 仅当您尝试使用Class.forName(...).

于 2013-06-11T03:13:59.010 回答
0

此代码适用于最新的 MySQL JDBC 驱动程序 - mysql-connector-5.1.22

Connection conn = DriverManager.getConnection"jdbc:mysql://localhost:3306/test", "root", "root");
conn.getSchema();

但如果我使用旧版本,例如 mysql-connector-5.1.20 我会得到

Exception in thread "main" java.lang.AbstractMethodError: com.mysql.jdbc.JDBC4Connection.getSchema()Ljava/lang/String;
    at main.MySQL.main(MySQL.java:21)

因为Connection.getSchema从 1.7 开始。

如果缺少具体类,例如。Integer.compare(int, int) 从 1.7 开始你会得到java.lang.NoSuchMethodError

如果缺少 JRE 类,例如 java.util.Scanner 从 1.5 开始,我使用 JRE 1.4,我会得到java.lang.NoClassDefFoundError

于 2013-06-11T02:31:55.800 回答