Domanda

Il seguente metodo non funziona perché il blocco interno dichiara una variabile con lo stesso nome di uno nel blocco esterno. Apparentemente le variabili appartengono al metodo o alla classe in cui sono dichiarate, non al blocco in cui sono dichiarate, quindi non posso scrivere un breve blocco temporaneo per il debug che capiti di spingere una variabile nello scope esterno in ombra solo per un momento:

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

Quasi tutte le lingue con ambito di blocco che abbia mai usato lo supportano, inclusi piccoli linguaggi banali per i quali ho scritto interpreti e compilatori a scuola. Perl può farlo, così come Scheme, e persino C. Anche PL / SQL lo supporta!

Qual è la logica di questa decisione di progettazione per Java?

Modifica: come qualcuno ha sottolineato, Java ha l'ambito del blocco. Qual è il nome del concetto che sto chiedendo? Vorrei poter ricordare di più da quelle lezioni di progettazione del linguaggio. :)

È stato utile?

Soluzione

Credo che la logica sia che il più delle volte, ciò non è intenzionale, è un difetto di programmazione o di logica.

in un esempio banale come il tuo, è ovvio, ma in un grande blocco di codice, la dichiarazione accidentale di una variabile potrebbe non essere ovvia.

ETA: potrebbe anche essere correlato alla gestione delle eccezioni in Java. ho pensato che parte di questa domanda fosse discussa in una domanda relativa al motivo per cui le variabili dichiarate in una sezione try non erano disponibili negli ambiti catch / finally.

Altri suggerimenti

Beh, a rigor di termini, Java ha dichiarazioni di variabili con ambito di blocco; quindi questo è un errore:

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

Perché 'i' non esiste al di fuori del blocco for.

Il problema è che Java non consente di creare una variabile con lo stesso nome di un'altra variabile dichiarata in un blocco esterno dello stesso metodo. Come altri hanno già detto, presumibilmente è stato fatto per prevenire bug difficili da identificare.

Perché non è raro che gli scrittori lo facciano intenzionalmente e poi rovinino tutto dimenticando che ora ci sono due variabili con lo stesso nome. Cambiano il nome della variabile interna, ma lasciano il codice che utilizza la variabile, che ora utilizza involontariamente la variabile precedentemente ombreggiata. Ciò si traduce in un programma che si compila ancora, ma viene eseguito correttamente.

Allo stesso modo, non è raro ombreggiare accidentalmente le variabili e cambiare il comportamento del programma. L'ombreggiamento inconsapevole di una variabile esistente può cambiare il programma con la stessa facilità con cui si fa ombra a una variabile come ho detto sopra.

Ci sono così pochi vantaggi nel permettere questo oscuramento che lo hanno escluso come troppo pericoloso. Seriamente, chiama semplicemente la tua nuova variabile qualcos'altro e il problema scompare.

Immagina che porti a bug difficili da individuare. È simile in C #.

Pascal non supporta questo, poiché è necessario dichiarare le variabili sopra il corpo della funzione.

Il presupposto alla base di questa domanda è sbagliato.

Java ha un ambito a livello di blocco. Ma ha anche una gerarchia di ambito, motivo per cui è possibile fare riferimento a i all'interno del ciclo for , ma non j al di fuori del ciclo for .

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

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

Non posso per la vita di me capire perché vorresti che lo scoping si comportasse diversamente. Sarebbe impossibile determinare a quale i stavi riferendo all'interno del ciclo for, e scommetterei che le probabilità sono del 99,999% delle volte che vorresti fare riferimento a i all'interno del metodo.

un altro motivo: se questo tipo di dichiarazione delle variabili fosse consentita, le persone vorrebbero (bisogno?) un modo per accedere alle variabili di blocco esterne. potrebbe essere qualcosa come "esterno" la parola chiave verrebbe aggiunta:

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;
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top