PreparedStatement (é claro que isso depende muito da qualidade do driver JDBC para o banco que você está usando) normalmente faz o que é necessário para que você não tenha problemas com os parâmetros que você passou.
"SELECT USUARIO FROM TABELA_USUARIOS WHERE NOME_USUARIO = ? AND SENHA_USUARIO = ?" -> isto não deve ter problemas com SQL Injection, a menos que o driver seja muito mal-feito (por exemplo, se o driver simplesmente concatena as strings sem se preocupar em duplicar as aspas simples, se elas existirem).
"SELECT USUARIO FROM TABELA_USUARIOS WHERE NOME_USUARIO = ‘’ + nomeUsuario + “’ AND SENHA_USUARIO = ‘’” + senhaUsuario + “’” -> não importa se for ou não um PreparedStatement, isso vai dar problemas de SQL Injection com certeza.
"SELECT USUARIO FROM TABELA_USUARIOS WHERE NOME_USUARIO = ‘’ + duplicaAspasETrataCaracteresEspeciais (nomeUsuario) + “’ AND SENHA_USUARIO = ‘’” + duplicaAspasETrataCaracteresEspeciais (senhaUsuario) + “’” -> não deve dar problemas de SQL Injection sendo ou não um PreparedStatement, mas você tem de escrever e testar muito bem esse método duplicaAspasETrataCaracteresEspeciais para evitar problemas.
É a string que você monta que é sujeita a problemas; não exatamente usar ou não PreparedStatement. Usar PreparedStatement é o método mais seguro porque evita problemas do tipo "puxa, esqueci de chamar a duplicaAspasETrataCaracteresEspeciais" e coisas desse tipo.