When the compiler creates String's, it puts them into a literal pool. This is managed by Java. If, at compile time, a String is already in the pool Java reuses that copy of the String instead of creating another one containing the same data. (Since String's are immutable, a given String will always contain the same data during its lifetime.)
The expression "Ja" + "va" is evaluated at compile time to "Java" which is already in the literal pool. Therefore, the same String in the pool is used for both the expressions "Java" and "Ja" + "va". The address of that literal pool String is what is being compared in the expression str1 == "Ja" + "va".
On the other hand the three String's str1, str2, str3 in your second example create three String's in the literal pool. One contains "Java", the second contains "Ja", and the third contains "va". At runtime (not compile time) the expression str2 + str3 creates a fourth String variable containing "Java". Even though str1 and the new (temporary) String contain "Java" as their data, the addresses of these two String's are different. So str1 == [the new String containing "Java"] is false.