@Wouter Coekaerts's answer is the simplest way to do this.
However!
The problem with any solution that uses reflection under the hood is that reflective operations are significantly more expensive than their non-reflective (compiled code) equivalents. Typically 1 to 2 orders of magnitude more expensive.
In your case, the comparator is going to be called O(NlogN)
times each time you sort the object list. If your application is going to be sorting large lists ... or small lists lots of times ... the overheads of using a reflective comparator could make a big difference to your application's overall performance.
If performance turns out to be an issue (and profiling tells you that the reflective comparator is at fault), the alternatives are:
Write the comparators by hand. This is the simplest and most performant solution, whether or not you think it is elegant.
Use run-time source code generation to generate comparator classes and then compile and load them.
Use run-time bytecode generation to generate comparator classes and load them.
These could be combined with a lookup / caching mechanism that stores the comparators in a hash table using a key that combines the class and the field name. (A cache is essential if you use the code generation approach. But you still need to consider whether any given generated comparator will be used often enough to justify the large once-off overhead of generating/compiling/loading a class.)