The book is accurate. You’re mixing “supporting operators” with “operator overloading”. Java does support a number of operators, such as + for addition and string concatenation. It does not support operator overloading, though, as it is traditionally defined. To put it another way, when someone says “language X supports operator overloading”, it implicitly mean what you call “user defined operator overloading”. That you can customize operators to have different meanings on different classes.
For example, if class Z is a regular class (not a number or string), and you have two instances z1 and z2, you cannot define what z1 + z2 is.
It's a bit confusing because Java chose to support the + operator in a way that was similar to what was done in C++ with operator overloading. But that doesn't mean it's actually overloading in Java - just that it was similar to something else in C++.
In my understanding, operator overloading means an operator can be used on more than one function, that is why I thought "+" is overloaded here. Something is not legit in programming doesn't necessarily mean the language throws the technique away.
But anyway, if you say the meaning of "user defined" is implicitly included, I trust you.
99 little bugs in the code, 99 little bugs in the code.
Take one down, patch it around, 117 little bugs in the code.
The token itself is a different operator based on the context in which it occurs (and has a different name, ex unary plus operator vs concatenation operator). The compiler knows what the context is, and generates different instructions based on that information.
We can see evidence of what's going on when we examine the instructions generated by the compiler.
When we compile and run javap -c on the class file we can identify that these are, in fact, two completely different instructions with similar human readable syntax: