By design:
Some people will say incorrectly that
objects are passed "by reference." In
programming language design, the term
pass by reference properly means that
when an argument is passed to a
function, the invoked function gets a
reference to the original value, not a
copy of its value. If the function
modifies its parameter, the value in
the calling code will be changed
because the argument and parameter use
the same slot in memory.... The Java
programming language does not pass
objects by reference; it passes object
references by value. Because two
copies of the same reference refer to
the same actual object, changes made
through one reference variable are
visible through the other. There is
exactly one parameter passing mode --
pass by value -- and that helps keep
things simple.
-- James Gosling, et al., The Java Programming Language, 4th Edition
As for deeper reasons, here's my take: it's the combination of two facts:
- The last line of the Gosling citation: "...that helps keep things simple..."
- Unlike C++, Java is garbage collected with all objects allocated on the heap.
I can't help it if you don't like the first one. You'll have to tell James Gosling and Bill Joy and all the other folks who designed Java that they made a critical error. Good luck with that. Java is far more widely used than C++ today by several measures. The marketplace, however imperfect, has not penalized Java for what you perceive as an oversight.
Pass by value in C++ places burdens on both the developer (e.g. requirement of assignment and copy constructors) and the compiler writer (e.g. differentiating between stack and heap variables, all permutations of pass by value and reference with const and non-const).
The second one might have more of a technical explanation besides the designers' taste. I'm not an expert in the design and implementation of garbage collected systems, but perhaps that influenced their choice for a technical reason that I don't know.