在Java 8中,"特定类型的任意对象"是什么意思?

Rom*_*nov 16 java java-8 method-reference

在Java 8中有"方法参考"功能.其中一种是"引用特定类型的任意对象的实例方法"

http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html#type

有人可以解释"特定类型的任意对象"在这种情况下的含义吗?

小智 19

Oracle Doc链接的示例是:

String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
Run Code Online (Sandbox Code Playgroud)

lambda相当于

 String::compareToIgnoreCase
Run Code Online (Sandbox Code Playgroud)

将会

(String a, String b) -> a.compareToIgnoreCase(b)
Run Code Online (Sandbox Code Playgroud)

Arrays.sort()方法正在寻找比较器作为其第二个参数(在此示例中).传递String::compareToIgnoreCase创建一个比较器a.compareToIgnoreCase(b)作为比较方法的主体.然后你问好了什么ab.比较方法的第一个参数变为a第二个参数b.这些是String类型(特定类型)的任意对象.

不明白?

  • 确保您知道比较器是什么以及如何实现它.
  • 了解功能界面是什么以及它如何影响Java中的lambdas.
  • 比较器是一个功能接口,这就是为什么该方法引用变得比较对象内的比较方法的正文中.
  • 阅读下面源代码,了解页面底部的另一个示例.

阅读更多信息来源:http: //moandjiezana.com/blog/2014/understanding-method-references/


小智 13

它是某种类型的实例方法的引用.在示例的情况下,compareToIgnoreCase是一种方法String.程序知道它可以在一个实例上调用此方法String,因此它可以获取该类型的引用和任何对象,并保证该方法存在.

我会将它与Method类进行比较,因为它们引用了一个方法,并且可以在某种类型的任意实例上调用.

例如,它可以使用两个String对象并调用compareToIgnoreCase一个对象,并使用另一个作为参数来匹配方法签名.这允许它根据数组类型的任何方法获取数组并对其进行排序,而不是要求比较器实例执行此操作.

以下是未点击问题链接的任何人的示例:

String[] stringArray = { "Barbara", "James", "Mary", "John",
"Patricia", "Robert", "Michael", "Linda", "George" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
Run Code Online (Sandbox Code Playgroud)


小智 6

请参阅下面的代码示例,它解释了https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html中描述的“对特定类型的任意对象的实例方法的引用”类别

import java.util.Arrays;

class Person{
    String name;

    //constructor
    public Person(String name){
        this.name = name;
    }

    //instance method 1
    public int personInstanceMethod1(Person person){
        return this.name.compareTo(person.name);
    }

    //instance method 2
    public int personInstanceMethod2(Person person1, Person person2){
        return person1.name.compareTo(person2.name);
    }
}

class Test {
    public static void main (String[] args) throws Exception{
        Person[] personArray = {new Person("A"), new Person("B")};
    
        // Scenario 1 : Getting compiled successfully
        Arrays.sort(personArray, Person::personInstanceMethod1);
    
        // Scenario 2 : Compile failure
        Arrays.sort(personArray, Person::personInstanceMethod2);
    
        // Scenario 3 : Getting compiled successfully. 
        Person personInstance = new Person("C");
        Arrays.sort(personArray, personInstance::personInstanceMethod2);

        // Scenario 4 : Getting compiled successfully. As the same way as "Scenario 1"
        String[] stringArray = { "Barbara", "James", "Mary", "John",
                                "Patricia", "Robert", "Michael", "Linda" };
        Arrays.sort(stringArray, String::compareToIgnoreCase);
    }

}
Run Code Online (Sandbox Code Playgroud)

场景 1 和场景 4 描述了https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html中描述的“对特定类型的任意对象的实例方法的引用”类别

如果方法参数采用与元素的实例 Type 相同的实例 Type 中的变量,则可以使用 Type.( Person::personInstanceMethod1)调用该实例方法

将“ ”类personInstanceMethod1中的“”实例方法PersoncompareToIgnoreCase“”类中的“”实例方法进行比较Stringhttps://docs.oracle.com/javase/8/docs/api/java/lang/String.html#compareToIgnoreCase-java.lang .String- ) 以查看相似性。两者都采用具有相同类型的单个参数。

比较场景 1 和场景 2,看看有什么不同。


小智 6

我认为在这种情况下,由于在文档中使用未定义的术语,理解这个概念变得更加困难。

请记住,方法引用作为 lambda 的一种类型,实现了函数式接口,并且只要可以在程序中引用它,就可以使用与接口签名匹配的任何方法。

四种方法引用中,分别代表访问(引用)该方法所需的不同方式。这三个方法的语法非常简单:如果它是静态方法,则在 :: 运算符之前使用类名;如果它是对象中的实例方法,则通常使用该对象的引用变量,或者如果它是构造函数使用 ClassName::new。

第四种是您要调用的方法,该方法是传递给函数的参数的实例方法。使用 lambda 就没有问题,因为您可以引用参数变量,如下所示:

(String someString) -> someString.toLowerCase();
Run Code Online (Sandbox Code Playgroud)

但是,由于方法引用中没有显式参数变量,因此使用的语法是:

String::toLowerCase;
Run Code Online (Sandbox Code Playgroud)

编译器采用“特定类型”(String)来引用“任意对象”(参数中传递的对象)中包含的函数方法(toLowerCase)。使用术语“任意对象”是因为每次执行方法引用时,参数中传递的实际对象可能不同。