All Comments
TopTalkedBooks posted at August 19, 2017

They should be considered only as pure functions and even then giving up polymorphism can lead to software components that cannot be easily changed and interchanged.

Static factory methods are useful and should be considered instead of constructors. You can learn more about that from Effective Java .

Otherwise static methods are unnatural in an object-oriented environment and they can considerably hinder testability.
Kotlin (a JVM language that aims to be a better Java) for example does not have static methods and variables for this reason, instead it has class objects. Instances of a class delegate to a shared, singleton object and the caller can invoke methods of that class object on any instance of the class as if they were static methods.

TopTalkedBooks posted at August 19, 2017

A few months ago I had to do the same thing and start with Java again professionally after not using it for the past 15 or so years (They knew this, I was honest and told them upfront that I had prior C/C++/C# etc but no rel java outside of minecraft mods from the hmod/early bukket days); thankfully I know so many other programming languages that I was able to dive in and just fill in the gaps as needed. If you are in the same boat do this and you should be ready to use it after a weekend of study like I did:

First get the O'Reilly Pocket Guide to Java (whatever version your using, yes the Java version matters!) http://shop.oreilly.com/product/9780596514198.do and read it front to back. Its a small book so it wont take more than a few hours at most on the first read. Your going t read it multiple times over the next few weeks, but read it once first.

Now Get the "Java For Dummies" books and read them. Not trolling, not kidding. Read the smaller one - Java For Dummies 6th Edition. - first - it will take you about 4-5 hours if you paid attention the pocket guide as it will simply reinforce what you already know in many places - then read the bigger one, the "Java All in One Dummies Book". It will take you the rest of the weekend, and the first half will effectively be the the pocket guide and the first dummies book again so it will go fast.

Smaller one: http://www.dummies.com/store/product/Java-For-Dummies-6th-Edition.productCd-1118407806.html

Larger one: https://toptalkedbooks.com/amzn/1118408039

THEN read "Effective Java" - https://toptalkedbooks.com/amzn/0321356683 as you can get the time.

Go back to the pocket guide as needed over the week as you use the language. Do your planning, machine set up, and all the BS they ask you to do for HR in the first week and use your lunch breaks to read and learn. Then use what you learn on the job.

This is of course assuming you know C++, C#, JavaScript, or some other compatible language. You should also be a student of SOLID and have read Clean Code and Clean Coder.. if not buy them and read them as well.

TopTalkedBooks posted at August 19, 2017

> Is there a true singular source to learn Java?

Unfortunately, no. There are 1000s of places to learn Java. The right choice is dependent on your skill level and what you want to build (e.g. web apps, mobile apps, desktop sevices, etc.).

If you need some recommendations, start with The Java Tutorials .

If you need a comprehensive overview of the language, you can use Java: The Complete Reference 9th Edition .

TopTalkedBooks posted at August 19, 2017
I am passionate about writing good code, and I'll try to offer some practical advice. As others said, the first step is understanding the importance of writing clean code and taking pride in your craft. By doing this, you are already ahead of most other programmers who don't really care. Now, how do you improve?

1) Read books.

With 4-5 years of experience, you already have a good intuition for "good" and "bad" code. Still, it doesn't hurt to learn more about it. There are a lot of good books on this subject.

The first is "Clean Code", by Robert C. Martin. It's the first book I read on this subject, and I learned a lot. Note that the book uses Java in the examples, but I think the ideas would apply to most other languages.

Its author, Uncle Bob ( http://en.wikipedia.org/wiki/Robert_Cecil_Martin ) has long been a proponent of writing clean, beautiful code. He recently did an interview for Xebia: http://blog.xebia.fr/2011/05/25/interview-avec-robert-martin... (French blog, but the interview is in English). In it, he advises:

"Well there are a number of books that talk about writing code well. Kent Beck wrote a book called “Implementation Patterns” very recently. It’s an excellent book all about software craftsmanship. The pragmatic programmers wrote a wonderful book in 2000 called “The pragmatic programmer”, again a wonderful book. Chad Fowler wrote a book call the “Passionate Programmer”. Again the book is about doing everything well. I wrote a book recently called “Clean Code” which is very specific about particular things you can do with your code to do it well. So there is a tremendous number of resources that are available for people who are interested in doing software craftsmanship well."

Out of those, disregard "The passionate Programmer". It's an okay book, but its focus is on building a good programmer career, not on code.

"Implementation Patterns" by Kent Beck is a great book with a lot of best practices when writing * Java * code. Less useful if you use another language.

"The pragmatic programmer" is a good book on software craftsmanship. I'm personally half-way through. There is a lot of good advice in it, but I often find myself thinking it's "common-sense". Maybe because I've already been exposed to most of the ideas by reading blogs? Still, it's a great book, with a lot of best practices. It's main focus is not code, though, so you might want to start with other books if your focus is on writing good code.

To these books, I'd add "Code Complete (2nd Edition)" (language-agnostic) and "Effective Java 2nd Edition" if you use Java.

Summary:

If you use Java, read:

  - Clean Code - http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
  - Effective Java 2nd Edition - http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683
  - Implementation Patterns - http://www.amazon.com/Implementation-Patterns-Kent-Beck/dp/0321413091
  - Code Complete / Pragmatic Programmer
If you use another language, read:

  - Clean Code - http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
  - Code Complete - http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670
  - Pragmatic Programmer - http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X
Other people might chime in with suggestions for other languages?

2) Practice.

Implement what you learned in the books. Keep improving.

3) Read other people's code.

Read good open source code. Not all code is good code. Ask around for OSS projects with good code in your language.

If you use Java, start with:

  - Google Guava - http://code.google.com/p/guava-libraries/
  - Google Guice - http://code.google.com/p/google-guice/
  - Spring Framework - http://www.springsource.org/
4) Practice.

5) Practice.

TopTalkedBooks posted at August 19, 2017
Yes. I believe such a book exists (or should at least) for every language as well.

Effective Java — http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp...

POODR (Ruby) — http://www.poodr.com/

Javascript the good parts — http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockfor...

There is of course also the gang of 4 language agnostic classic on design patterns http://www.amazon.com/Design-Patterns-Elements-Reusable-Obje...

TopTalkedBooks posted at August 19, 2017
Not true. You'll get, for instance, people who read Effective Java [1], by Joshua Bloch (who is, IMHO, THE man when it comes to java), and remembered the PECS mnemonics. PECS stands for producer-extends, consumer-super.

So, to cite the textbook example, say you are implementing a Stack<E>. It will probably have the methods:

  public void push(E element);
  public E pop();
and, for convenience:

  public void pushAll(Iterable<? extends E> elements);
  public void popAll(Collection<? super E> destination);
The pushAll has "? extends" because the elements Iterable will "produce" elements for the stack. The popAll has super because the destination Collection will "consume" elements from the stack. It is not that hard, is it? Let's note that guard-of-terra is talking about proficiency, not mere familiarity. I believe reading "Effective Java" is a nice way to get closer to the proficient level.

Let it be noted that this whole mess exists because generics in Java were implemented with type erasure so their introduction wouldn't break legacy code. I personally think this was a bad idea, but it does show that when a language is evolving, there are a bunch of constraints the designers must be aware of.

[1] http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp...

TopTalkedBooks posted at August 20, 2017

Well, Josh Bloch said himself in Effective Java 2d:

Prefer interfaces over abstract classes

Some main points:

  • Existing classes can be easily retrofitted to implement a new interface. All you have to do is add the required methods if they don’t yet exist and add an implements clause to the class declaration.

  • Interfaces are ideal for defining mixins. Loosely speaking, a mixin is a type that a class can implement in addition to its “primary type” to declare that it provides some optional behavior. For example, Comparable is a mixin interface that allows a class to declare that its instances are ordered with respect to other mutually comparable objects.

  • Interfaces allow the construction of nonhierarchical type frameworks. Type hierarchies are great for organizing some things, but other things don’t fall neatly into a rigid hierarchy.

  • Interfaces enable safe, powerful functionality enhancements via the wrap- per class idiom. If you use abstract classes to define types, you leave the programmer who wants to add functionality with no alternative but to use inheritance.

Moreover, you can combine the virtues of interfaces and abstract classes by providing an abstract skeletal implementation class to go with each nontrivial interface that you export.

On the other hand, interfaces are very hard to evolve. If you add a method to an interface it'll break all of it's implementations.

PS.: Buy the book. It's a lot more detailed.

TopTalkedBooks posted at August 20, 2017

we use primitives because they are fast.. here is answer from Why do people still use primitive types in Java? post for quick reference

In Joshua Bloch's Effective Java, Item 5: "Avoid creating unnecessary objects", he posts the following code example:

public static void main(String[] args) {
    Long sum = 0L; // uses Long, not long
    for(long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

and it takes 43 seconds to run. Taking the Long into the primitive brings it down to 6.8 seconds... if that's any indication why we use primitives.

The lack of native value equality is also a concern (.equals() is fairly verbose compared to ==)

for biziclop:

class biziclop {

    public static void main(String[] args) {
        System.out.println(new Integer(5) == new Integer(5));
        System.out.println(new Integer(500) == new Integer(500));

        System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
        System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
    }
}

Results in:

C:\Documents and Settings\glow\My Documents>java biziclop
false
false
true
false
TopTalkedBooks posted at August 20, 2017

The term utility function was used by Joshua Bloch in the book Effective Java to describe the methods on classes such as Arrays, Objects and Math.

The approach predates Java, and is defined by Wikipedia - Utility Class as a set of methods that perform common, often reused functions. I would go on to also point out that the functions tend to require no Object level state, that is they tend to be global functions. And that is why, in Java they tend to become implemented as static methods on a container class. As that way there is no need to instantiate the class first, and it implies through convention that the method should not have any side effects. Of course counter examples of this probably exist, but not to my knowledge within the Java Core libraries.

TopTalkedBooks posted at August 20, 2017

Assert will throw a runtime error (AssertionError) if its condition is false. Asserts give you a streamlined way of documenting, checking, and enforcing correctness criteria for your code. The benefits are a language-level hook for defining and manipulating these correctness conditions. To the extent that you wish to enable or disable them (there are arguments about whether or not this is a good idea) you can do so from the JVM command-line. Some commenters below note that assertions are disabled by default unless running in debug mode; my practice is to add "-ea" (enable assertions) in my wrapper scripts at all times. Even in performance sensitive code, for me the tradeoff weighs in favor of the security/correctness confidence I get from assertions. Assertions at Oracle and API Description for AssertionError

Note the distinction between expected or unexpected failures (exceptions), which may be outside your control, and assertion failures -- assertion failures document programmer assumptions, and indicate an incorrect program rather than an unexpected external condition or expected exceptional condition. If an assertion failure occurs, the interpretation is that the programmer has misunderstood or incorrectly expressed the program, rather than other sources of error or failure.

In practice, I use it to document obvious or non-obvious assumptions I make and invariants which I want to enforce as I produce (particularly private/internal) code, making it clear to myself and others why these assumptions are made, where they are made, and whether or not they are validated. Much better than comments to the same effect. This is a (small) step toward Design by Contract.

Effective Java item #38 "Check Parameters for Validity" (Google Books, Amazon.com) provides a useful presentation of the distinction between parameter checking and appropriate use of assertions.

Related on SO: (Enabling assertions in netbeans), (Assertions vs. Exceptions), (Near duplicate, asking for examples), (Badly named, but very similar content)

TopTalkedBooks posted at August 20, 2017

clone() was designed with several mistakes (see this question), so it's best to avoid it.

From Effective Java 2nd Edition, Item 11: Override clone judiciously

Given all of the problems associated with Cloneable, it’s safe to say that other interfaces should not extend it, and that classes designed for inheritance (Item 17) should not implement it. Because of its many shortcomings, some expert programmers simply choose never to override the clone method and never to invoke it except, perhaps, to copy arrays. If you design a class for inheritance, be aware that if you choose not to provide a well-behaved protected clone method, it will be impossible for subclasses to implement Cloneable.

This book also describes the many advantages copy constructors have over Cloneable/clone.

  • They don't rely on a risk-prone extralinguistic object creation mechanism
  • They don't demand unenforceable adherence to thinly documented conventions
  • They don't conflict with the proper use of final fields
  • They don't throw unnecessary checked exceptions
  • They don't require casts.

All standard collections have copy constructors. Use them.

List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);
TopTalkedBooks posted at August 20, 2017

As far as I can tell there is nothing special here, is just classical constructor chaining and polymorphism applied to virtual method invocations.

When you instantiate your anonymous class, it will automatically invoke its default constructor (which is automatically given by the compiler), before its default constructor succeeds it must first invoke its parent class default constructor, which in turn will invoke the init() method, which, since it has been overridden by your anonymous class, polymorphically, ends up calling the init method in the child class, which initializes the model to your SubModel instance.

Joshua Bloch has a few interesting arguments against this pattern in his famous book Effective Java, in the section "Item 17: Design and document for inheritance or else prohibit" he wrote:

“There are a few more restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods, directly or indirectly. If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will get invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected. To make this concrete, here's a class that violates this rule:”

He then proceeds to give an example which you would do well to study:

“Here's a subclass that overrides the overrideMe, method which is erroneously invoked by Super's sole constructor:”

public class Super {
    // Broken - constructor invokes an overridable method
    public Super() {
        overrideMe();
    }

    public void overrideMe() {
    }
}

public final class Sub extends Super {
    private final Date date; // Blank final, set by constructor

    Sub() {
        date = new Date();
    }

    // Overriding method invoked by superclass constructor
    @Override public void overrideMe() {
        System.out.println(date);
    }

    public static void main(String[] args) {
        Sub sub = new Sub();
        sub.overrideMe();
    }
}

“You might expect this program to print out the date twice, but it prints out null the first time, because the overrideMe method is invoked by the Super constructor before the Sub constructor has a chance to initialize the date field. Note that this program observes a final field in two different states! Note also that if overrideMe had invoked any method on date, the invocation would have thrown a NullPointerException when the Super constructor invoked overrideMe. The only reason this program doesn't throw a NullPointerException as it stands is that the println method has special provisions for dealing with a null argument.”

So, as you can see, and as Joshua Bloch explained so well, the risks lurk in the shadows: in the possibilities of what you can do in the overridden method, where you have license to touch instance variables that the constructor chain has not yet had a chance to initialize. The point is that you should not be allowed to touch the object state until it has been fully initialized by the constructor chain.

You might say that in your particular case that does not happen, since you are not illegally altering state and your overridden method is protected, not public, but the problem is that any person touching this code needs a very clear understanding of all these things happening under the hood, happening in places other than your current code. During maintenance it is easy to make a serious mistake, particularly when you or some other developer, comes back here to make changes, possibly months or even years after this was originally defined, and having lost context of all these dangers somebody introduces a bug that will be really hard to find and fix.

TopTalkedBooks posted at August 20, 2017

The use of try/catch blocks in normal program flow incurs a performance hit. It's better to use the if/then statements in the first example.

https://softwareengineering.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why

This is mentioned in Effective Java. Exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow.

TopTalkedBooks posted at August 20, 2017

If you throw exceptions that are too low-level catch them few calls above, and pack as more general and meaningful exception with user friendly message what went wrong, and throw them once again to highest possible level, where you stop your app and view them somehow (e.g. on label) to user.

from Effective Java (item 61):

It is disconcerting when a method throws an exception that has no apparent connection to the task that it performs. This often happens when a method propagates an exception thrown by a lower-level abstraction. Not only is this disconcerting, but it pollutes the API of the higher layer with implementation details. If the implementation of the higher layer changes in a subsequent release, the exceptions that it throws will change too, potentially breaking existing client programs.

To avoid this problem, higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction. This idiom is known as exception translation:

// Exception Translation
try {
   // Use lower-level abstraction to do our bidding
   ...
} catch(LowerLevelException e) {
   throw new HigherLevelException(...);
}

While exception translation is superior to mindless propagation of exceptions from lower layers, it should not be overused. Where possible, the best way to deal with exceptions from lower layers is to avoid them, by ensuring that lower-level methods succeed. Sometimes you can do this by checking the validity of the higher-level method’s parameters before passing them on to lower layers.

If it is impossible to prevent exceptions from lower layers, the next best thing is to have the higher layer silently work around these exceptions, insulating the caller of the higher-level method from lower-level problems. Under these circumstances, it may be appropriate to log the exception using some appropriate logging facility such as java.util.logging. This allows an administrator to investigate the problem, while insulating the client code and the end user from it.

In summary, if it isn’t feasible to prevent or to handle exceptions from lower layers, use exception translation, unless the lower-level method happens to guarantee that all of its exceptions are appropriate to the higher level. Chaining provides the best of both worlds: it allows you to throw an appropriate higher-level exception, while capturing the underlying cause for failure analysis (Item 63).

TopTalkedBooks posted at August 20, 2017

In recent years, inheritance is often treated like code-smell, because it can lead to different problems: https://dzone.com/articles/is-inheritance-dead

If we talk in pure performance term, an empty array takes about 8 bytes in RAM (4 bytes store length and 4 bytes a reference, but it is a little platform-dependent: How much space array occupies). So, even if you have a thousand of such objects, one array field will take approximately 1_000 * 8 bytes ~ 8 KBytes in RAM.

As you probably know, nowadays phones usually contain > 1 GByte of RAM. However, don't forget that your app usually can take from 60 to 192 MBytes of RAM (Detect application heap size in Android).

In any case, it is more than enough not to count every little field that you are adding to your class.

However, going back to my first statement, I suggest you to think about solving the problem using composition instead of inheritance, as it is suggested in Effective Java

Update
About performance, I would suggest you to read this topic: The performance impact of using instanceof in Java Are you sure that you need such type of premature optimization? Or is it more a theoretical question than practical?

TopTalkedBooks posted at August 20, 2017

1. What you should be more concerned with here, is not efficiency, but scope. Generally, you should strive to keep your variables as locally scoped as possible. This means, if you only need x within the loop, you should define it within the loop.

You get a number of benefits with keeping your variables as locally scoped as possible:

  • Your code will be much more readable to someone else
  • You won't accidentally assign to, or use the value of a variable you defined further up in your code that is still in scope, thus minimizing errors in your program
  • Most importantly, the garbage collector will free up any memory used by the variable as soon as it goes out of scope, keeping your program's performance high, and memory usage low.

You can read up more on variable scope and best practices from Josh Bloch's excellent book, "Effective Java" (scope is discussed in items 13 and 45). You might also want to read item 55, which discusses why it is important to optimize judiciously.

2. For the second part of your question, see The Skeet's answer here.

Here's an example:

public static void main(String[] args) {
    for(int i=0; i<getSize(); i++) {
        System.out.println("i: " + i);
    }
}

private static int getSize() {
    int size = new Random().nextInt(10);
    System.out.println("size: " + size);
    return size;
}

This outputs:

size: 2
i: 0
size: 4
i: 1
size: 4
i: 2
size: 8
i: 3
size: 0

Notice how getSize() is called for every iteration of the loop. In your example, calling .length won't make a huge difference, as the JIT runtime will know how to optimize this call. But imagine getSize() was a more complex operation, like counting the number of rows in a database table. Your code will be super slow as every iteration of the loop will call getSize(), resulting in a database roundtrip.

This is when you would be better off evaluating the value before hand. You can do this and still retain minimal scope for size, like this:

public static void main(String[] args) {
    for(int size = getSize(), i=0; i<size; i++) {
        System.out.println("i: " + i);
    }
}


private static int getSize() {
    int size = new Random().nextInt(10);
    System.out.println("size: " + size);
    return size;
}

size: 5
i: 0
i: 1
i: 2
i: 3
i: 4

Notice how getSize() is only called once, and also, the size variable is only available inside the loop and goes out of scope as soon as the loop completes.

TopTalkedBooks posted at August 20, 2017

It's extremely bad practice to let equals() or hashCode() throw exceptions (I'd encourage you to read Effective Java for the details).

Also, your methods are unnecessarily complex. Ever since Java 7, this is pretty much the canonical way of writing these methods:

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }else if (o instanceof MyClass) {
        // some will argue that the line above should have a
        // .getClass() check instead of an instanceof check.
        // those people also need to read Effective Java :-)
        MyClass that = (MyClass) o;
        return Objects.equals(this.classA, that.classA)
            && Objects.equals(this.classB, that.classB)
    } else {
        return false;
    } 
}

@Override
public int hashCode() {
    return Objects.hash(classA, classB);
}
TopTalkedBooks posted at August 20, 2017

You should probably use String.hashCode().

If you really want to implement hashCode yourself:

Do not be tempted to exclude significant parts of an object from the hash code computation to improve performance -- Joshua Bloch, Effective Java

Using only the first five characters is a bad idea. Think about hierarchical names, such as URLs: they will all have the same hash code (because they all start with "http://", which means that they are stored under the same bucket in a hash map, exhibiting terrible performance.

Here's a war story paraphrased on the String hashCode from "Effective Java":

The String hash function implemented in all releases prior to 1.2 examined at most sixteen characters, evenly spaced throughout the string, starting with the first character. For large collections of hierarchical names, such as URLs, this hash function displayed terrible behavior.

TopTalkedBooks posted at August 20, 2017

The best approach is Long.valueOf(str) as it relies on Long.valueOf(long) which uses an internal cache making it more efficient since it will reuse if needed the cached instances of Long going from -128 to 127 included.

Returns a Long instance representing the specified long value. If a new Long instance is not required, this method should generally be used in preference to the constructor Long(long), as this method is likely to yield significantly better space and time performance by caching frequently requested values. Note that unlike the corresponding method in the Integer class, this method is not required to cache values within a particular range.

Generally speaking, it is a good practice to use the static factory method valueOf(str) of a wrapper class like Integer, Boolean, Long, ... since most of them reuse instances whenever it is possible making them potentially more efficient in term of memory footprint than the corresponding parse methods or constructors.


Excerpt from Effective Java Item 1 written by Joshua Bloch:

You can often avoid creating unnecessary objects by using static factory methods (Item 1) in preference to constructors on immutable classes that provide both. For example, the static factory method Boolean.valueOf(String) is almost always preferable to the constructor Boolean(String). The constructor creates a new object each time it’s called, while the static factory method is never required to do so and won’t in practice.

TopTalkedBooks posted at March 18, 2018

The book Effective Java gives two more reasons for "memory leaks":

  • Once you put object reference in Cache and forget that it's there. The reference remains in cache long before becoming irrelevant. Solution is to represent cache as a WeakHashMap
  • in an API where clients register callbacks and don't re-register them explicitly. Solution is to store only weak references to them.
TopTalkedBooks posted at March 18, 2018

I would say both NumberFormatException and MyBusinessException are useful but in different cases.

They usually appear at different levels of class hierarchy: for example NumberFormatException is a lower-level exception and you might not want to expose it at a higher level (e.g. user interface) if the user of it has no power to recover from it. In this case it is more elegant to just throw MyBusinessException and display an informative message that explains for example that something in a previous step was badly supplied or some internal processing error occurred and he/she needs to restart the process.

On the other hand, if your function is used at an intermediate-level (e.g. API) and the developer has the means to recover from the exceptional behavior, NumberFormatException is more useful, as it can be dealt with programmatically and the flow of the application might continue with minimal interruption (e.g. supply a default valid number). Alternatively, this can indicate a flaw/bug in the code that should be fixed.

For details about how to follow best practice in using exceptions, read Item 61 - Throw exceptions appropriate to the abstraction from Effective Java by Joshua Bloch.

Top Books
We collected top books from hacker news, stack overflow, Reddit, which are recommended by amazing people.