Pergunta

O método a seguir não funciona porque o bloco interno declara uma variável com o mesmo nome como um no bloco externo. Aparentemente variáveis ??pertencem ao método ou classe em que elas são declaradas, e não ao bloco em que elas são declaradas, por isso, portanto, não pode escrever um bloqueio temporário pouco curto para depurar o que acontece para empurrar uma variável no escopo externo para dentro sombra apenas por um momento:

void methodName() {
  int i = 7;
  for (int j = 0; j < 10; j++) {
    int i = j * 2;
  }
}

Quase todas as linguagens de escopo de bloco que já usei apoiou esta, incluindo as línguas pouco triviais que eu escrevi interpretes e compiladores para a escola. Perl pode fazer isso, como pode Scheme, e até mesmo C. Mesmo PL / SQL suporta isso!

Qual é a razão para esta decisão de design para Java?

Edit: como alguém apontou, Java tem bloco de escopo. Qual é o nome para o conceito que eu estou perguntando sobre? Eu gostaria de poder lembrar mais a partir dessas classes de linguagem de design. :)

Foi útil?

Solução

Eu acredito que a lógica é que na maioria das vezes, isso não é intencional, é uma programação ou lógica falha.

em um exemplo tão trivial como a sua, é óbvio, mas em um grande bloco de código, acidentalmente redeclaring uma variável pode não ser óbvio.

ETA: ele pode também estar relacionado com a manipulação de exceção em java. eu pensei que parte desta questão foi discutida em uma questão relacionada com a razão pela qual as variáveis ??declaradas em uma seção tentativa não estavam disponíveis no catch / finally escopos.

Outras dicas

Bem, estritamente falando, Java faz tem declarações de variáveis ??com escopo de bloco; por isso este é um erro:

void methodName() {
  for (int j = 0; j < 10; j++) {
    int i = j * 2;
  }
  System.out.println(i); // error
}

Porque 'i' não existe fora do para o bloco.

O problema é que Java não permite que você para criar uma variável com o mesmo nome de outra variável que foi declarada em um bloco externo do mesmo método. Como outras pessoas disseram, supostamente isso foi feito para evitar erros que são difíceis de identificar.

Porque não é incomum para os escritores de fazer isso intencionalmente e, em seguida, aperte-o totalmente até esquecendo que existem agora duas variáveis ??com o mesmo nome. Eles mudar o nome da variável interna, mas o código de licença que usa a variável, que agora usa unintentially a variável anteriormente sombreada. Isto resulta em um programa que ainda compila, mas executa buggily.

Da mesma forma, não é incomum para acidentalmente sombra variáveis ??e mudar o comportamento do programa. Inconscientemente sombreamento uma variável existente pode alterar o programa tão facilmente como unshadowing uma variável como eu mencionei acima.

Não é tão pouco benefício para permitir que este sombreamento que descartou essa possibilidade como muito perigosa. Sério, basta ligar para a sua nova variável outra coisa e o problema desaparece.

Isso leva a erros que são difíceis de detectar, eu acho. É semelhante no C #.

Pascal não suporta este, pois você tem que declarar variáveis ??acima do corpo da função.

O pressuposto subjacente a esta pergunta está errada.

Java não têm escopo em nível de bloco. Mas também tem uma hierarquia de escopo, que é por isso que você pode fazer referência i dentro do ciclo for, mas não j fora do loop for.

public void methodName() {
  int i = 7;
  for (int j = 0; j < 10; j++) {
    i = j * 2;
  }

  //this would cause a compilation error!
  j++;
}

Não consigo para a vida de me descobrir por que você iria querer escopo a se comportar de outra maneira. Seria impossível determinar qual i você estava referindo-se dentro do loop for, e eu aposto que as chances são de 99,999% do tempo que você quer para se referir ao i dentro do método.

outra razão: se esse tipo de declaração da variável foram autorizados, as pessoas gostariam (necessidade?) Uma maneira de acessar variáveis ??bloco externo. pode ser algo como palavra-chave "exterior" seria acrescentado:

void methodName() {
    int i = 7;
    for (int j = 0; j < 10; j++) {
        int i = outer.i * 2;
        if(i > 10) {
            int i = outer.outer.i * 2 + outer.i;
        }
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top