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

java - 为什么JAVA可以通过 “类::实例方法” 的方式获取到方法的引用?

龙佐
2024-04-12

对于JAVA的方法引用“类::实例方法”的方式的疑惑

/*1. 被引用方法的参数,需要与抽象方法的第2个到最后1个参数保持一致    ps: 实例方法的第1个参数其实是隐含的this        如果这个this (实例对象) 的类型与抽象方法的第一个参数类型一致,就可以用类名引用实例方法*/ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "a", "b", "c");// 将集合中的字母转为大写list.stream()        // 数据流中的数据类型为 String,所以可以引用 String 类中的实例方法        .map(String::toUpperCase)        .forEach(System.out::println);

请问按照注释中的理解,是否是正确的呢?

共有3个答案

杭柏
2024-04-12

当你在Java代码中调用方法时,编译器会将这些方法调用转换为Java字节码中的不同指令,以实现相应的功能。以下是这些指令的简要介绍:

invokedynamic
作用:在运行时动态选择要调用的方法。
用途:主要用于实现动态语言和动态生成的代码,以及在Java中与其他语言集成。
示例:在Java 7中引入,允许在运行时动态地绑定到目标方法。

invokevirtual
作用:调用对象的实例方法。
用途:用于调用普通的实例方法。
示例:常用于调用对象的方法,方法的选择在编译期间就确定。

invokeinterface
作用:调用接口中的方法。
用途:专门用于接口方法的调用。
示例:通常用于调用接口中定义的方法,灵活性相对于invokevirtual更高。

invokestatic
作用:调用类的静态方法。
用途:用于调用类的静态方法,无需实例化对象。
示例:常用于调用工具类的静态方法,或者在没有实例对象的情况下执行某些操作。

invokespecial
作用:调用特殊方法,如私有方法、构造方法和超类方法。
用途:用于调用私有方法、构造方法、超类方法等。
示例:常用于调用构造方法初始化对象,或者调用类中的私有方法。

这些指令在Java字节码中扮演着不同的角色,用于实现方法调用的不同场景。了解它们可以帮助你更好地理解Java程序的执行过程,以及在需要时进行优化或调试。

以上是AI介绍,Lambda表达式就是利用第一个指令完成的,没记错的话这个指令一直到14/15版本还在更新,你可以简单理解为有些方法调用是编译期就确定的,这就是一般理解的方法解析,但是使用invokedynamic指令可以做到在运行期动态绑定

丌官招
2024-04-12

可以用String.toUpperCase不是因为toUpperCase是String的方法,而是因为参数是String,你这里也可以调用Integer::valueOf,只要参数一样就可以,这其实是一个Function实现的简单写法,比如我想把一个字符串集合转成整形的

1.匿名实现

List<String> list = new ArrayList<>();List<Integer> integers = list.stream().map(new Function<String, Integer>() {            @Override            public Integer apply(String string) {                return Integer.valueOf(string);            }        }).collect(Collectors.toList());

2.等价于lambda

List<String> list = new ArrayList<>();List<Integer> integers = list.stream().map(a->Integer.valueOf(a)).collect(Collectors.toList());

3.等价于方法引用

List<String> list = new ArrayList<>();List<Integer> integers = list.stream().map(Integer::valueOf).collect(Collectors.toList());

常见的还有list.sort方法传Comparator,那个是两个参数,也可以简写。

一般写到lambda就行了,但是Idea会提示你转成方法引用,你一点就变成双冒号了。

====更新====
你说的我不敢确定,gpt说是传了隐式,是不是this我不太清楚;

我当初在stackoverflow提问过comparator方法引用为什么传一个参数就行了,但是compare要两个参数,他们也提到了一个是invoker,一个是参数
方法引用提问

邢炯
2024-04-12

这个是 Method Reference Expression。

此时,如果它是类成员函数,调用的第一个参数就是调用函数的对象,后续参数是调用成员函数的参数。

基本跟你注释里写的差不多。

If the form is ReferenceType :: [TypeArguments] Identifier, the body of the invocation method similarly has the effect of a method invocation expression for a compile-time declaration which is the compile-time declaration of the method reference expression. Run-time evaluation of the method invocation expression is as specified in §15.12.4.3, §15.12.4.4, and §15.12.4.5, where:

  • The invocation mode is derived from the compile-time declaration as specified in §15.12.3.
  • If the compile-time declaration is an instance method, then the target reference is the first formal parameter of the invocation method. Otherwise, there is no target reference.
  • If the compile-time declaration is an instance method, then the arguments to the method invocation expression (if any) are the second and subsequent formal parameters of the invocation method. Otherwise, the arguments to the method invocation expression are the formal parameters of the invocation method.
 类似资料:
  • 问题内容: 我有一个使用XML和反射将 s 返回到另一个类的类。 通常,这些对象是外部对象的子字段,但有时我想即时生成它。我已经尝试过类似的方法,但无济于事。我相信这是因为Java不允许你访问进行反射的方法。 如果提供的方法失败,则失败。我可以通过制作方法来解决它,或者制作另一个类来派生它。 长话短说,我只是想知道是否存在一种通过反射访问方法的方法。 问题答案: 你可以使用反射调用私有方法。修改已

  • 本文向大家介绍python 通过类中一个方法获取另一个方法变量的实例,包括了python 通过类中一个方法获取另一个方法变量的实例的使用技巧和注意事项,需要的朋友参考一下 1、在进行接口自动化测试过程中,经常出现接口数据的互相调用,如一些操作需要调用登陆之后返回的session或者token,下面同个简单的方法进行讲解 运行之后,打印的结果为 以上这篇python 通过类中一个方法获取另一个方法变

  • 本文向大家介绍Java方法签名的获取实例代码,包括了Java方法签名的获取实例代码的使用技巧和注意事项,需要的朋友参考一下 本文研究的主要是Java方法签名的获取,下面是具体实现实例。 实例代码: 总结 以上就是本文关于Java方法签名的获取实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

  • 问题内容: 有没有一种更友好的方法来获取FontMetrics实例,而不是 由于以下示例,我讨厌这种方式: 如果要在游戏中创建菜单,并且希望所有菜单项都位于屏幕中央,则需要字体度量。但是,大多数菜单项都是可单击的。因此,我创建了一个数组,所有矩形都适合这些项目,因此当按下鼠标时,我可以简单地使用 但是要创建矩形,我还需要FontMetrics作为其坐标。因此,这意味着我必须在菜单的绘制方法中构造所

  • 问题内容: 请解释一下 与功能界面兼容。 方法已在功能接口中实现。 正在工作 请单独解释所有要点。 问题答案: __ is的 等效 lambda表达式 这是 特定类型的任意对象的实例方法的 命名 引用 的功能之一。 __ 考虑以下示例, 输出值 请注意,这对于call even 方法不是静态的有效。 当你调用该方法的功能界面,你仍然有两个参数,其是与并为有效的lambda表达式可以有参数,所以你的

  • 问题内容: 我仍在学习Java中的方法,并且想知道您可能如何使用实例方法。我在想这样的事情: 但是,我不确定这实际上是实例方法还是其他类型的方法。有人可以帮我吗? 问题答案: 如果不是静态方法,则为实例方法。这是一个或另一个。是的,您的方法, 是实例方法的示例。 关于 并想知道您到底如何使用实例方法 您将创建类的实例,对象,然后在该实例上调用实例方法。即 可以这样使用: