Java 为什么我传递给Arrays.sort的方法引用需要是静态的?
我是Java 8的新手。我试图创建一个示例,用于引用特定类型的任意对象的实例方法 我有一个只有一个字段名的person类,并试图对person类的firstName字段上的person对象数组进行排序Java 为什么我传递给Arrays.sort的方法引用需要是静态的?,java,methods,java-8,Java,Methods,Java 8,我是Java 8的新手。我试图创建一个示例,用于引用特定类型的任意对象的实例方法 我有一个只有一个字段名的person类,并试图对person类的firstName字段上的person对象数组进行排序 public class Person{ String firstName; public Person(String firstName) { super(); this.firstName = firstName; } pu
public class Person{
String firstName;
public Person(String firstName) {
super();
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public int compareByFirstName(Person p1, Person p2) {
return p1.getFirstName().compareTo(p2.getFirstName());
}
}
public class TestInstanceMethorRefArbObjSample {
public static void main(String[] args) {
TestInstanceMethorRefArbObjSample obj=new TestInstanceMethorRefArbObjSample();
obj.personSorting();
}
private void personSorting() {
Person[] personArr= {new Person("Jinesh"),new Person("Sejal"),new Person("Ashish")};
Arrays.sort(personArr,Person::compareByFirstName);
}
}
但我在下面一行面临着编译问题
Arrays.sort(personArr,Person::compareByFirstName);
1.类型Person未定义适用的compareByFirstNameT,T
这里是testInstanceMethodoreBobjSample.java/InstaceMethoderBitaryObjectProject/src/com/methodreference/InstanceMethoderBitary/client行
11 Java问题
2.类型Person未定义适用的compareByFirstNameT,T
这里是testInstanceMethodoreBobjSample.java/InstaceMethoderBitaryObjectProject/src/com/methodreference/InstanceMethoderBitary/client行
11 Java问题
我只是想通过int compareto1,t2的实现;使用Person类的compareByFirstname
只要我将Person类的compareByFirstname方法更改为static,一切都正常工作
为什么我需要将compareByFirstname更改为静态方法以使其工作?您使用的是一个方法引用,并且由于您将其编写为Person::compareByFirstname,因此它引用的是一个静态方法。如果要引用实例方法,则需要首先创建对象的实例,然后使用实例引用方法,如下所示:
Person p = new Person("");
p::compareByFirstName
但是,在您的案例中,这不是您想要做的,因为compare方法不是特定于实例的
通过将对象实例与另一个对象进行比较,可以更改比较方法,使其特定于实例
public int compareByFirstName(Person p2) {
return this.getFirstName().compareTo(p2.getFirstName());
}
在这种情况下,当比较变得任意时,您可以使用方法引用Person::compareByFirstName。您使用的是方法引用,并且由于您将其作为Person::compareByFirstName编写,因此它引用的是静态方法。如果要引用实例方法,则需要首先创建对象的实例,然后使用实例引用方法,如下所示:
Person p = new Person("");
p::compareByFirstName
但是,在您的案例中,这不是您想要做的,因为compare方法不是特定于实例的
通过将对象实例与另一个对象进行比较,可以更改比较方法,使其特定于实例
public int compareByFirstName(Person p2) {
return this.getFirstName().compareTo(p2.getFirstName());
}
在这种情况下,当比较变得任意时,您可以使用方法reference Person::compareByFirstName。一些背景知识
Arrays.sort需要一个比较器,在传递方法引用时,该比较器必须是一个接受两个适当类型实例的方法
创建这种方法有两种方法:
在任何接受两个适当类型参数的类中创建静态方法。这基本上就是你所做的。这样的方法不需要在特定的类中声明,您还可以使用其他一些类来提供这样的帮助器方法。
编译器将确保生成的Comparator实例调用引用的方法,并使用它想要比较的2个实例
在该类型的特定类中创建一个实例方法,该方法接受一个适当类型的参数。
编译器将确保生成的比较器实例调用第一个实例上的引用方法,并将第二个实例作为参数
你的具体情况
因为您的方法需要两个参数,所以它必须是静态的,否则它需要第三个实例来运行。要么将其声明为静态,要么删除一个参数并实现此参数与参数之间的比较。一些背景信息
Arrays.sort需要一个比较器,在传递方法引用时,该比较器必须是一个接受两个适当类型实例的方法
创建这种方法有两种方法:
在任何接受两个适当类型参数的类中创建静态方法。这基本上就是你所做的。这样的方法不需要在特定的类中声明,您还可以使用其他一些类来提供这样的帮助器方法。
编译器将确保生成的Comparator实例调用引用的方法,并使用它想要比较的2个实例
在该类型的特定类中创建一个实例方法,该方法接受一个适当类型的参数。
编译器将确保生成的比较器实例调用第一个实例上的引用方法,并将第二个实例作为参数
你的具体情况
因为您的方法需要两个参数,所以它必须是静态的,否则它需要第三个实例来运行。要么将其声明为静态,要么删除一个参数并实现此参数与参数之间的比较。因为没有静态,您的方法是一个实例方法,您将
s需要3个Person对象来调用它:接收方,即this、p1和p2。一个比较器是一个需要2个人的函数,而不是3个人。删除p1参数,并将其与p2进行比较,它将按预期工作。compareByFirstName不是静态的。方法定义需要一个比较器实例作为其第二个参数。@JBNiZet谢谢您的解释。我这边的一个问题是,为什么下面的代码作为String[]stringArray={Barbara,James,Mary,John,Patricia,Robert,Michael,Linda}工作;Arrays.sortstringArray,String::CompareTIgnoreCase;我看不出compareToIgoreCase被定义为静态方法。好吧,请再次阅读我的评论。compareToIgnoreCase不像方法那样接受2个参数。需要一个。因此,它将这个字符串与另一个字符串进行比较。因此,它可以作为比较器使用,因为它是一个包含两个字符串的函数:接收方字符串和作为参数传递的字符串。因为没有static,您的方法是一个实例方法,因此您需要3个Person对象来调用它:接收方,即this、p1和p2。一个比较器是一个需要2个人的函数,而不是3个人。删除p1参数,并将其与p2进行比较,它将按预期工作。compareByFirstName不是静态的。方法定义需要一个比较器实例作为其第二个参数。@JBNiZet谢谢您的解释。我这边的一个问题是,为什么下面的代码作为String[]stringArray={Barbara,James,Mary,John,Patricia,Robert,Michael,Linda}工作;Arrays.sortstringArray,String::CompareTIgnoreCase;我看不出compareToIgoreCase被定义为静态方法。好吧,请再次阅读我的评论。compareToIgnoreCase不像方法那样接受2个参数。需要一个。因此,它将这个字符串与另一个字符串进行比较。因此,它作为比较器是可以接受的,因为它是一个包含两个字符串的函数:接收方字符串和作为参数传递的字符串。而且,由于您将其编写为Person::compareByFirstName,它引用的是一个静态方法否,construct ClassName::method并不仅仅保留给静态方法。如果我们有一些FunctionInterface,它包含像handleSomeClass sc、Foo f、Bar b这样的方法,那么我们可以提供ClassName::nonStaticMethod作为它的实现。这类似于使用lambda SomeClass sc,Foo f,Bar b->sc.nonStaticMethodf,b;实现它;。因此,第一个参数将被视为调用非静态方法的实例。由于您已将其编写为Person::compareByFirstName,它引用的是一个静态方法否,因此construct ClassName::method不仅保留给静态方法。如果我们有一些FunctionInterface,它包含像handleSomeClass sc、Foo f、Bar b这样的方法,那么我们可以提供ClassName::nonStaticMethod作为它的实现。这类似于使用lambda SomeClass sc,Foo f,Bar b->sc.nonStaticMethodf,b;实现它;。因此,第一个参数将被视为调用非静态方法的实例。@感谢JBNizet和MaxVollmer的详细解释。为了完整起见:它也可以是一个包含两个参数的非静态方法,引用来自一个实例,与personInstance::CompareByFirstName类似,但首选的方法是使用Comparator.comparingPerson::getFirstName,它完全不需要额外的比较方法。@感谢JBNizet和MaxVollmer的详细解释。为了完整性:它也可以是一个包含两个参数的非静态方法,使用从实例获取的引用,如personInstance::CompareByFirstName,但首选方法是使用Comparator.comparingPerson::getFirstName,这样就完全不需要额外的比较方法。