Java compiler (javac) translates your code in Java to byte code which is executed by the JVM.
It also does some optimizations for you. You can check the generated byte code using javap utility with -c parameter
Concatenation with final String
c==a is true because c is final
Here is the byte code for this snippet (last comparison only):
public static void main(java.lang.String[]);
  Code:
   0:   ldc     #2; //String Hello
   2:   astore_2
   3:   getstatic       #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   6:   aload_2
   7:   ldc     #2; //String Hello
   9:   if_acmpne       16
   12:  iconst_1
   13:  goto    17
   16:  iconst_0
   17:  invokevirtual   #4; //Method java/io/PrintStream.println:(Z)V
   20:  return
}
As you see the java compiler has merged the "Hel" with "lo" and just comparing two string leterals "Hello". Java interns string literals by default - that's why it returns true
Concatenation with non-final String
If you are concatenating the string literal with non-final String variable, the byte code will be different:
public static void main(java.lang.String[]);
  Code:
   0:   ldc     #2; //String lo
   2:   astore_1
   3:   ldc     #3; //String Hello
   5:   astore_2
   6:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   9:   aload_2
   10:  new     #5; //class java/lang/StringBuilder
   13:  dup
   14:  invokespecial   #6; //Method java/lang/StringBuilder."<init>":()V
   17:  ldc     #7; //String Hel
   19:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   22:  aload_1
   23:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   26:  invokevirtual   #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   29:  if_acmpne       36
   32:  iconst_1
   33:  goto    37
   36:  iconst_0
   37:  invokevirtual   #10; //Method java/io/PrintStream.println:(Z)V
   40:  return
}
Here we are comparing the result of java/lang/StringBuilder.toString:()Ljava/lang/String; method which obviously returns another object - it is equal to "Hello" by value but not by reference
You can find more details on comparing strings in this stackoverflow question