Reputation: 629
I am new bie to Java 8. I am trying to create a sample for Reference to an instance method of an arbitrary object of a particular type.
I have a person class with one field Name and trying to sort Array of Person objects on firstName field of person class.
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);
}
}
But I am facing compilation issue on below line.
Arrays.sort(personArr,Person::compareByFirstName);
1.The type Person does not define compareByFirstName(T, T) that is applicable here TestInstanceMethorRefArbObjSample.java /InstaceMethodArbitaryObjectProject/src/com/methodreference/instancemethodrefarbitary/client line 11 Java Problem 2.The type Person does not define compareByFirstName(T, T) that is applicable here TestInstanceMethorRefArbObjSample.java /InstaceMethodArbitaryObjectProject/src/com/methodreference/instancemethodrefarbitary/client line 11 Java Problem
I am just trying to pass the implementation of int compare(T o1, T o2); using compareByFirstname of Person class.
As soon as I am changing the method compareByFirstname of Person class to static everything is working fine.
Why I need to change the compareByFirstname to static method to make it work?
Upvotes: 1
Views: 711
Reputation: 8598
Some background
Arrays.sort
expects a Comparator
, which, when passing a method reference, must be a method that accepts two instances of the appropriate type.
There are two ways to create such a method:
Your compiler will make sure that the generated Comparator
instance calls the referenced method with the 2 instances it wants to compare.
Your compiler will make sure that the generated Comparator
instance calls the referenced method on the 1st instance with the 2nd instance as parameter.
Your specific case
Since your method takes two parameters, it must be static, as it otherwise needs a third instance to run. Either declare it static, or remove one parameter and implement the comparison between this and the parameter.
Upvotes: 3
Reputation: 39
You are using a method reference and since you have written it as Person::compareByFirstName
it is referencing a static method. If you wanted to reference an instance method instead you would need to first create an instance of the object, then you would reference the method with the instance, like so:
Person p = new Person("");
p::compareByFirstName
However this would not be what you want to do in your case as the compare method is not instance-specific.
You could change your comparison method to make it specific to the instance by comparing the object instance with another object
public int compareByFirstName(Person p2) {
return this.getFirstName().compareTo(p2.getFirstName());
}
In which case you would be able to use the method reference Person::compareByFirstName
as the comparison becomes arbitary.
Upvotes: 1