当前位置: 首页 > 知识库问答 >
问题:

Java字节码和没有这样的方法错误

柳俊健
2023-03-14

我们可能看到了错误:

既然这是正确的,为什么字节码记下了被调用方法的返回类型,并在用该方法的返回类型更新库时引发错误。

共有1个答案

田英卓
2023-03-14

Java字节码是强类型和验证的,这意味着调用者的代码必须与被调用的方法返回的内容兼容。因此,即使调用方的方法引用不包含预期的返回类型,代码仍然包含隐式假设,例如,尝试对结果执行long算术,表明该方法预期返回long,而不是objectvoid

使用指示预期返回类型的方法引用可以简化验证,并使整个过程更加高效。您可以使用预期的方法签名来验证方法代码的正确性,而无需执行实际的链接。当方法调用指令最终链接时,不需要验证可执行代码,只需要匹配签名即可。

这就是为什么Java字节码是这样设计的,即使Java源代码不能定义不同的返回类型,至少在早期版本中是这样的。从Java ;5开始,规则不再那么严格了。

interface StringFunction<R> {
    R apply(String input);
}

现在考虑以下实现类:

class Length implements StringFunction<Integer> {
    public Integer apply(String input) {
        return input.length();
    }
}

不仅允许声明更具体的返回类型,而且Java语言实际上也需要声明,因为根据泛型类型系统,它从stringfunction 继承了一个抽象方法integer apply(String)

在字节码级别上,它将具有实际实现方法整数apply(String)以及桥接方法对象apply(String input)正式履行字节码级别上接口的约定并委托给实际实现方法。

class Base {
    Object getValue() {
        return null;
    }
}
class Sub extends Base {
    @Override String getValue() {
        return "now a string";
    }
}

因此,可以生成具有多个具有相同参数类型但不同返回类型的方法的类,尽管不是通过重载。

可以选择处理这些情况,例如,定义方法只通过参数类型来区分,它们的返回类型必须相同或更具体,以与协变返回类型兼容,但这意味着JVM在构建类的方法表时必须急切地解析所有返回类型,以验证类型是否真的更具体。但是,它仍然需要对返回类型进行编码,以便在调用方和被调用方之间建立适当的契约。

 类似资料:
  • 我试图使用jackson来序列化和反序列化一个POJO。从POJO到JSON可以很好地工作,但是反过来就不行了。 我有一个POJO 并运行和测试我运行的包calendar.model 引发异常 我已经尽我所能让JSON到POJO工作,但它不会。如果我从JSON映射到map类型,它确实有效。 感谢您的帮助 这是我的依赖项中杰克逊的 grep 看起来除了jackson2,没有其他版本的jackson了

  • 问题内容: 我正在尝试使用杰克逊对POJO进行序列化和反序列化。从POJO到JSON可以完美地工作,而从另一个方向去则不行。 我有一个POJO 并运行和测试我运行了calendar.model包; 引发异常 我已经尽力将JSON转换为POJO了,但是没有。如果我从JSON映射到Map类型,它确实可以工作。 谢谢您的帮助 编辑 这是我依赖中的杰克逊的grep 看起来除了jackson2之外,没有其他

  • 问题内容: 我在Jenkins管道中使用JSON函数并获取。我正在使用Jenkins 2.85。 任何想法如何解决这个问题? 问题答案: 使用管道实用程序步骤插件可以使用该功能。 没有此插件,您将无法使用此功能。 有关更多信息,请检查:步骤

  • 问题内容: 我正在尝试设置 Jenkins 从属服务器,以构建使用名为“ Freddy”的Swift窗格的Swift项目。 问题是构建因错误而失败: 错误:没有这样的模块“ Freddy” 这是我的Podfile: CocoaPods版本0.39.0 Xcode 7.2.1( 直接从Xcode构建时没有问题 ) PS。在我将其替换为AFNetworking之前,Alamofire吊舱也发生了同样的

  • 问题内容: 我试图让我的应用程序使用保存布尔值来更改屏幕的方向时保存一些数据。 我已经设置了许多断点,并且在变量视图中得到了布尔值的错误 我不知道为什么要在启动活动时用false值声明它,如果按下按钮将其更改为true。谁能帮我吗? 问题答案: 检查您的Android Studio中的构建变体是否具有 可调试 为真 proguard 被禁用或已被注释掉。

  • 我在我的API中使用条带连接,我想更新和处理现有的paymentIntent。使用NodeJS条带包创建paymentIntent成功 这将成功返回一个paymentIntent对象,该对象具有id('pi_yyy')、客户端密码('pi_yyy_secret_zzz')、状态('requires_payment_method')和更多字段。 但是,当使用返回的支付意图id进一步更新支付意图或使用