I wrote this code as a solution on another Question:
record Person( String name , int age ) { }
List < Person > persons =
List.of(
new Person( "Alice" , 52 ) ,
new Person( "Bob" , 23 ) ,
new Person( "Carol" , 39 )
);
List < Person > sorted =
persons
.stream()
.sorted( Comparator.comparing( Person :: age ) )
.toList();
This code runs successfully on Java 17.
persons.toString() = [Person[name=Alice, age=52], Person[name=Bob, age=23], Person[name=Carol, age=39]]
sorted.toString() = [Person[name=Bob, age=23], Person[name=Carol, age=39], Person[name=Alice, age=52]]
Upon further thought, I am surprised this code works. I pass a method reference for the accessor method (“getter”) on the record to Comparator.comparing
call.
Comparator.comparing( Person :: age )
… but age
member field, and the return type of this method, are both int
primitive, not an object.
This leaves me puzzled as to why this works, because I would think the comparator requires objects, not primitives.
Is there some auto-boxing at play here? If so, exactly where? What triggers the compiler or runtime to perform auto-boxing in this code?
I am hoping for a narrow and precise answer rather than same hand-waving. The hand-waving was already done when I authored the code! So, now, I am not asking out of practicality, as clearly the code is intuitive and the code works. The language-lawyer
tag is indeed appropriate here, as I am asking about the “intricacies of formal or authoritative specifications of programming languages”.