Жестко закодированные строки скомпилированы в таблицу строк JVM, которая содержит уникальные строки - то есть компилятор хранит только одну копию «Hi», поэтому вы сравниваете один и тот же объект , поэтому ==
работает.
Если вы на самом деле создаете новую строку, используя конструктор, например, новый String("Hi")
, вы получите другой объект.