Oii Felipe, tudo bem?
Seu código está bem estruturado! A lógica do loop com contador de tentativas e a verificação de login e senha juntos ficou bem resolvida.
Tem um ponto de atenção que vale você revisar: dentro de validarSenha(), você declarou as variáveis locais String senha="" e String login="". O problema é que esses nomes criam uma "sombra" sobre os atributos da classe (this.senha e this.login). Dentro do if, você até usou this.senha e this.login corretamente, então o código funciona. Mas a variável local senha e o atributo this.senha coexistem com o mesmo nome no mesmo escopo, o que pode gerar confusão na leitura e manutenção.
Uma convenção comum é usar nomes distintos para as variáveis locais do método, como senhaDigitada e loginDigitado:
String senhaDigitada = "";
String loginDigitado = "";
E aí no if fica mais legível:
if (senhaDigitada.equals(this.senha) && loginDigitado.equals(this.login)) {
Além disso, repara que quando o usuário erra na última tentativa (i = 1, ou seja, restantes = 0), o código não imprime "acesso negado!" porque o if(restantes>0) bloqueia essa mensagem. O usuário vai direto para "voce excedeu o limite de tentativas" sem saber que errou nessa última tentativa. Faz sentido para o que você quer que o código faça? Vale pensar se essa mensagem de negação deveria aparecer sempre que errar, ou só quando ainda tiver tentativas.
Qualquer dúvida, é só trazer aqui!
Conte com a Alura para evoluir seus estudos. Em caso de dúvidas, fico à disposição.
Bons estudos!
Sucesso ✨