Porque a interpretação desses codepoints (\u000A, por exemplo) é feita antes do código ser compilado. É como se você estivesse colocando a quebra de linha no teu código, e não na String. Depois do parser substituir esse código por espaço, teu código vai ficar assim:
class Teste {
public static void main(String[] args) {
System.out.println("Oi
Estou aqui!");
}
}
E esse código não é valido.
Quer ver como isso é verdade? testa isso aqui:
public class FalsoEhVerdadeiro {
public static void main(String[] args) {
if ( false == true ) { // \u000a\u007d\u007b
System.out.println("Falso eh verdadeiro!");
}
}
}
Se você olhar na tabela Unicode, o codepoint \u000a significa a quebra de linha, o \u007d significa fechamento de chaves, e o \u007b a abertura de chaves. O código que chega pro compilador é esse aqui:
public class FalsoEhVerdadeiro {
public static void main(String[] args) {
if ( false == true ) {
} {
System.out.println("Falso eh verdadeiro!");
}
}
}
E o resultado é o print, pois ele está fora do if.
Porque não usar \n?