I don't know Java books, but I would like to react to this part anyway:
Most Java programmers seem to basically not believe in many of the ways I have learned to write good software (e.g. be precise and concise, carefully encapsulate state, make small reusable modular parts which are usually pure functions, REPL-driven development, etc. etc.) or they apply them in ways that seem unfortunate to me.
There are much more bad programmers than good programmers, so any language that is sufficiently widely used is necessarily a language mostly used by bad programmers. (Also, if the programming language is Turing-complete, it also means that you can reinvent any historical bad programming practices in that language.) On the other hand, there are often genuine mistakes in the language design, or in the standard libraries. So here is my opinion on which is which in Java:
precise and concise -- sorry, no can do. Using proper formatting, merely declaring a read-only integer property of a class will cost you five lines not including whitespace (1 line declaration, 1 line assignment in constructor, 3 lines read accessor). (EDIT: Removed an obsolete info.)
carefully encapsulate state -- that's what the "private" and "public" keywords are for. I don't quite understand what could be the problem here (other than bad programmers not using these keywords; or the verbosity).
make small reusable modular parts which are usually pure functions -- this is not how Java is typically used, but it can be done. It has the garbage collector. It has immutable types; and for the mutable ones, you could create an immutable wrapper class (yes, a lot of writing again). So you can write a module that gets immutable values as inputs, returns them as outputs, which is more or less what you want. The only problem is that "immutability" is not recognized by the language; you only know that a class is immutable by reading the documentation or looking at the source code; you cannot have the compiler check it for you.
REPL-driven development -- it could be technically possible to make an interactive functional shell, and maybe someone already did it. But that's definitely not how Java is typically used. A slightly more traditional solution, although not exactly what you want, would be to use the Groovy language for the interactive shell. (Groovy is more or less a "scripting Java". Very similar to Java, with minor differences; can directly call functions from the Java program it is included in.) The traditional solution is to do unit testing with JUnit.
As a beginner, avoid Java EE like hell. That is the really ugly part. Stay with Java SE until the Stockholm syndrome kicks in and you develop feelings for Java, or until you decide you do not want to go this way.
Feel free to give me a short example in other programming language or pseudocode, and I will try to write it in Java in a functional-ish style.
I might try Groovy for the REPL stuff -- I was trying Clojure before, but I ran into problems getting it to get the dependencies and stuff all into the REPL (I work on a big project that uses Gradle as a build system, and Clojure doesn't usually use Gradle.)
carefully encapsulate state -- that's what the "private" and "public" keywords are for. I don't quite understand what could be the problem here (other than bad programmers not using these keywords; or the verbosity).
One pattern I have in mind here: if I have some algorithm I have...
If it's worth saying, but not worth its own post (even in Discussion), then it goes here.
Previous Open Thread
Next Open Thread
Notes for future OT posters:
1. Please add the 'open_thread' tag.
2. Check if there is an active Open Thread before posting a new one. (Immediately before; refresh the list-of-threads page before posting.)
3. Open Threads should be posted in Discussion, and not Main.
4. Open Threads should start on Monday, and end on Sunday.