Because Java byte-code is closer (more similar) to the source than assembly.
In particular, .class
files include metadata for classnames, method names, field & parameter types, etc…
All a Java (or .Net) decompiler needs to do is look at the instructions in each method body, and turn them into the appropriate syntactic constructs.
By contrast, native languages like C++ do not include any metadata at all, so the decompiler needs to reconstruct everything.