That's because this code does not instantiate Comparator. As you said, that's not possible.
Instead, it is syntax sugar. It's short for:
// Yes, you can define a class inside a method.
class $AutoGeneratedName implements Comparator<Person> {
@Override public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}
Collections.sort(persons, new $AutoGeneratedName());
In other words, short for: Define a new class, which implements Comparator. Then, instantiate this class once right away. Resolve this entire expression as a reference to this newly created instance. This construct is called an anonymous inner class.
CAREFUL - this code is bad.
20 years ago, that code was mostly fine, except for one detail: using a - b in comparisons is dangerous for very large numbers, but presumably, given that this is about 'age', not going to be an issue. Still, bad form; return Integer.comparing(p1.getAge(), p2.getAge()) would be much better.
But since then, this is no longer needed. You can write the concept much shorter like so:
Collections.sort(persons, (a, b) -> Integer.compare(a.getAge(), b.getAge());
We can do even that much, much simpler, and more readably by using List#sort with Comparator.comparingInt.
persons.sort(Comparator.comparingInt(Person::getAge));
which does exactly what you think it does when you just read it like its english: It sorts the collection 'persons' by comparing a specific int - which int? The one you get when you invoke getAge() on the person method.
This last snippet is what you should be using instead.