Java: accedere alle variabili locali da anon classe interna? (CodaConPriorita)
-
20-09-2019 - |
Domanda
Voglio usare un PriorityQueue
per fare una sorta topologico su un grafico. Per brevità, mi piacerebbe utilizzare una classe interna anonima per il comparatore. Tuttavia, ho bisogno di accedere al g
grafico al fine di determinare il grado in dei nodi che sto guardando. È possibile?
/**
* topological sort
* @param g must be a dag
*/
public static Queue<String> topoSort(DirectedGraph<String, DefaultEdge> g) {
Queue<String> result = new PriorityQueue<String>(g.vertexSet().size(),
new Comparator<String>() {
DirectedGraph<String, DefaultEdge> g;
@Override
public int compare(String arg0, String arg1) {
if (g.inDegreeOf(arg0) < g.inDegreeOf(arg1)) {
return -1;
}
if (g.inDegreeOf(arg0) > g.inDegreeOf(arg1)) {
return 1;
}
return 0;
}
});
result.addAll(g.vertexSet());
return result;
}
CORRETTO CODICE
/**
* topological sort
* @param g must be a dag
*/
public static Queue<String> topoSort(final DirectedGraph<String, DefaultEdge> g) {
Queue<String> result = new PriorityQueue<String>(g.vertexSet().size(),
new Comparator<String>() {
@Override
public int compare(String arg0, String arg1) {
if (g.inDegreeOf(arg0) < g.inDegreeOf(arg1)) {
return -1;
}
if (g.inDegreeOf(arg0) > g.inDegreeOf(arg1)) {
return 1;
}
return 0;
}
});
result.addAll(g.vertexSet());
return result;
}
Soluzione
Sì, lo rendono finale:
public static Queue<String> topoSort(final DirectedGraph<String, DefaultEdge> g) {
La parola finale sul finale di parola chiave :
anonimi Classi locali
La seconda situazione coinvolge finale variabili è in realtà incaricati dalla semantica del linguaggio. In tale situazione, il compilatore Java non ti consente di utilizzare un variabile a meno che non viene dichiarata finale. Questa situazione si verifica con chiusure, noto anche come classi locali anonime. classi locali possono solo riferimento locale variabili e parametri che sono dichiarato finale.
public void doSomething(int i, int j) { final int n = i + j; // must be declared final Comparator comp = new Comparator() { public int compare(Object left, Object right) { return n; // return copy of a local variable } }; }
La ragione di questa restrizione diventa evidente se far luce su come le classi locali sono implementati. Una classe locale anonimo può utilizzare locali variabili perché il compilatore dà automaticamente la classe di un campo di istanza privata di tenere una copia di ogni variabile locale la classe utilizza. Il compilatore aggiunge anche nascosto parametri di ogni costruttore inizializzare questi creati automaticamente campi privati. Così, una classe locale in realtà non l'accesso locale variabili, ma semplicemente il proprio privato copie di essi. L'unico modo questo può il lavoro è correttamente se il locale variabili sono dichiarate finale, in modo che sono garantiti di non cambiare. Con questa garanzia in atto, il classe locale è assicurato che la sua copie interne delle variabili corrispondere esattamente locale attuale variabili.
Altri suggerimenti
Se una variabile locale viene utilizzato in una classe interna, il compilatore genera un campo istanza per la classe interna e copia il valore variabili locali ad esso. Ora, se i cambiamenti delle variabili locali, allora il valore della variabile instancs saranno ancora avendo vecchio valore. Così, al fine di rendere il valore delle variabili locali stesso campo di istanza e non mutabile, si è fatto finale.
Cordiali saluti, con google collezioni si ha anche la possibilità di
Ordering.natural().onResultOf(
new Function<String, Integer>() {
public Integer apply(String arg) {
return g.inDegreeOf(arg);
}
});
Questo non significa necessariamente risparmiare un sacco di battitura, come si può vedere, a meno che non si possono trovare altri usi per quella funzione, ma lo fa si proteggere dagli insetti che molto spesso si insinuano nelle vostre by-mano implementazioni di confronto.