Os objetos recriados com o mesmo nome são reescritos?

4 respostas Resolvido
java
Gabriel432135
while(j==0){ try{ j = (new Scanner(System.in).nextInt()); }catch(NumberFormatException | InputMismatchException erro){ System.out.println("erro: "+erro+"\nDigite um número válido"); } }

Cada vez que o loop é feito, ele cria um novo objeto? Se sim, como deletar o objeto antigo que não é mais usado? Eles são excluídos automaticamente? Se em um loop, for criado um objeto com um determinado nome, quando o loop reiniciar, o objeto é sobrescrito?

for(int i=0; i<10; i++){
Scanner scan = new Scanner(System.in);
}

ele rescreve o objeto?

4 Respostas

wldomiciano

Sim, a cada iteração do loop um novo objeto é criado.

Em Java vc não precisa se preocupar em destruir objetos que não são mais necessários já que o Garbage Collector faz esse trabalho por nós.

Contudo, há classes que alocam recursos quando instanciadas e que precisam liberados. Por exemplo, sempre que vc abre um arquivo, é importante fechá-lo.

O Scanner é uma dessas classes, para liberar seus recursos vc deve chamar o método close().

Tem algumas coisas que vc deve prestar atenção:

1. Vc tem um bom motivo para instanciar o Scanner dentro do loop? Porque vc pode instanciá-lo fora do loop e reaproveitar sempre a mesma instancia sem problema algum. Assim:

Scanner scan = new Scanner(System.in);
int j;

while(j == 0) {
  try {
    j = scan.nextInt();
  } catch(NumberFormatException | InputMismatchException erro) {
    System.out.printf("erro: %s\nDigite um número válido", erro); 
  }
}

scan.close();

2. Esse conceito de criar objetos com o mesmo nome não existe no Java. Pelo que vc está falando, acredito que vc está se referindo às variáveis.

Variáveis não são objetos, são regiões da memória que podem conter objetos. E objetos são instancias de uma classe.

Quando vc declara uma variável dentro de um loop, é como se ela fosse recriada a cada iteração, mas isso não é um problema e as vezes é até recomendável que vc faça isso.

Por exemplo, digamos que no exemplo acima a variável j fosse usada apenas dentro do bloco try, não haveria porque declará-la fora deste bloco e poderiamos seguramente fazer assim:

Scanner scan = new Scanner(System.in);

while(j == 0) {
  try {
    int j = scan.nextInt();
    System.out.println(j);
  } catch(NumberFormatException | InputMismatchException erro) {
    System.out.printf("erro: %s\nDigite um número válido", erro); 
  }
}

scan.close();

Quando instanciamos um objeto dentro de um loop, um novo objeto é criado a cada iteração. Esta prática, por si só, não é ruim, mas no exemplo que vc deu, criar varios Scanner é completamente desnecessario.

Eis um exemplo de uma situação em que criar objetos dentro do loop faz sentido:

import java.util.ArrayList;

class Pessoa {
  public final String nome;
  public final int idade;

  public Pessoa(final String nome, final int idade) {
    this.nome = nome;
    this.idade = idade;
  }

  @Override
  public String toString() {
    return String.format("{ nome: %s, idade: %d }", this.nome, this.idade);
  }
}

class Main {
  public static void main(String... args) {
    var pessoas = new ArrayList<Pessoa>();

    for(int i = 1; i <= 5; i++) {
      Pessoa p = new Pessoa("Pessoa " + i, 20 + i);
      pessoas.add(p);
    }

    pessoas.forEach(System.out::println);
  }
}
Gabriel432135
Eu coloquei o Scanner dentro do loop porque o método nextInt() só pedia para o usuário escrever uma vez. Se desse erro, ele ficava tentando de novo com o valor digitado antes, sem pedir de novo. Então, surgiu a dúvida. O único jeito foi criar um novo objeto a cada iteração. Você disse que não é ruim, mas tem alguma forma de pelo menos não precisar disso? Tem algum método melhor que o nextInt()? Dúvida de iniciante ksksksks E o que é esse Garbage Collector? Como ele funciona? E sobre a dúvida com criar novos objetos no loop, veja este trecho:
for(int i=0;i<10;i++){
Scanner gta = new Scanner(System.in);
}
se eu fizer isso: gta.metodo(); qual objeto eu me refiro? Se a cada loop, ele cria um novo objeto com esse mesmo nome
wldomiciano
Solucao aceita

Entendi o problema. Fiz uns testes e realmente ele passa direto.

Uma solução melhor seria usar o nextLine() em conjunto com o parseInt(), assim:

import java.util.Scanner;

class Main {
  public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    int j = 0;

    while (j == 0) {
      try {
        j = Integer.parseInt(scan.nextLine());
        System.out.println("> " + j);
      } catch (Exception erro) {
        System.out.printf("erro: %s\nDigite um número válido\n", erro);
      }
    }

    scan.close();
  }
}

Ou então, dentro do catch, chamar o next():

import java.util.Scanner;

class Main {
  public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    int j = 0;

    while (j == 0) {
      try {
        j = scan.nextInt();
        System.out.println("> " + j);
      } catch (Exception erro) {
        System.out.printf("erro: %s\n\"%s\" não é válido\n", erro, scan.next());
      }
    }

    scan.close();
  }
}

O garbage collector é a parte da JVM que busca por objetos que não são mais usados e os destrói. Objetos não usados são aqueles que não possuem mais referencias no seu código. Mas eu não sei como funciona tecnicamente.

1 for(int i = 0; i < 10; i++) {
2   Scanner gta = new Scanner(System.in);
3   gta.metodo();
4 }

A invocação na linha 3 é feita com base no objeto criado na linha 2.

Mas considere este outro exemplo:

Scanner gta;

for(int i = 0; i < 10; i++) {
  gta = new Scanner(System.in);
}

gta.metodo();

No caso acima, a invocação na ultima linha é feita no objeto criado na última iteração do loop, os Scanner criados nas primeiras 9 iterações são completamente perdidos.

Gabriel432135
Entendi kkkk. Então, quando eu chamo um objeto, ele se refere ao ultimo criado no loop kkk. É muito bom ter veteranos nisso ajudando a gente. Obrigado!.
Criado 1 de setembro de 2019
Ultima resposta 1 de set. de 2019
Respostas 4
Participantes 2