As for the more general parts of this discussion, OK I’ll play:
I’m retired now, and mostly only program for my own purposes. I use java. I first worked as a professional software developer in 1978, so I think I can say I have a very long perspective. I moved from mainframes to PC/workstation to the web over that time.
I would suggest that java is what C++ should have been, as an OO language suitable for commercial development, and being comfortable for the old base of C programmers out there. C++ was heavily constrained by Stroustrup’s goal that existing K&R C code would go through the C++ compiler and work. He retained a bunch of old baggage that java made a clean break from, such as the pointer and the way it masqueraded as array notation in C, the lack of a boolean primitive type which led to its sloppy way doing conditional tests, the indeterminacy of the sizes of primitive types, and other things. Not to mention retaining the old “struct” semantics grafted onto class definitions, and having to say “virtual” to get actual polymorphism.
What I like about java, not necessarily OO features:
Garbage collection - I would say that 95% of the bugs I had to chase for years in C code were from memory corruption or leaks. In large commercial projects involving many people, programmers managing their own memory allocations led inevitably to these. You could run something like purify, and discover an embarassing number of bad memory references in standard runtime libraries you were using. When you first start coding java, it makes your scalp crawl to do something like:
x.someMethod(new Thing());
but you get used to it, and eventually you realize how much effort you were putting in in C based code to manage memory allocation.
Java has a very good, usable thread implementation. MUCH easier to write threads in java than any lightweight process / thread model I ever used in C / C++.
It doesn’t have C++'s fragile multiple inheritance lattice, forcing you into a lot of investigation as to WHICH method implementation you are going to wind up with. Java doesn’t support multiple inheritance for a good reason - the concept of interfaces takes care of almost all of the places you would want it anyway. The interface concept is very useful.
The way inner classes work in java seems mondo screwed up when you first encounter it, but it’s actually useful. You can sub-encapsulate a lot of logic which needs to have access to the members of an instance of the defining object. If it was simply a scoping mechanism, it wouldn’t work nearly as well for a large number of the places where you use it.