Est-il possible de passer des paramètres ou d'accéder à des paramètres externes à une classe anonyme? Par exemple:
int myVariable = 1;
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// How would one access myVariable here?
}
});
Existe-t-il un moyen permettant à l'auditeur d'accéder à myVariable ou de recevoir myVariable sans créer l'auditeur en tant que classe nommée?
Techniquement, non, car les classes anonymes ne peuvent pas avoir de constructeur.
Cependant, les classes peuvent référencer des variables à partir de portées. Pour une classe anonyme, il peut s'agir de variables d'instance de la ou des classes contenant ou de variables locales marquées comme finales.
edit: Comme Peter l’a souligné, vous pouvez également passer des paramètres au constructeur de la superclasse de la classe anonyme.
Oui, en ajoutant une méthode d'initialisation qui retourne 'this' et en appelant immédiatement cette méthode:
int myVariable = 1;
myButton.addActionListener(new ActionListener() {
private int anonVar;
public void actionPerformed(ActionEvent e) {
// How would one access myVariable here?
// It's now here:
System.out.println("Initialized with value: " + anonVar);
}
private ActionListener init(int var){
anonVar = var;
return this;
}
}.init(myVariable) );
Aucune déclaration "finale" nécessaire.
oui. vous pouvez capturer variable, visible pour la classe interne. la seule limitation est qu'il doit être final
Comme ça:
final int myVariable = 1;
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Now you can access it alright.
}
});
Cela fera la magie
int myVariable = 1;
myButton.addActionListener(new ActionListener() {
int myVariable;
public void actionPerformed(ActionEvent e) {
// myVariable ...
}
public ActionListener setParams(int myVariable) {
this.myVariable = myVariable;
return this;
}
}.setParams(myVariable));
Comme indiqué à l'adresse http://www.coderanch.com/t/567294/Java/java/declare-constructor-anonymous-class , vous pouvez ajouter un initialiseur d'instance. C'est un bloc qui n'a pas de nom et qui est exécuté en premier (comme un constructeur).
On dirait qu'ils sont aussi discutés à Pourquoi Java Initialisateurs d'instance? et Comment un initialiseur d'instance est-il différent d'un constructeur? discute des différences entre constructeurs.
Ma solution consiste à utiliser une méthode qui renvoie la classe anonyme implémentée. Des arguments normaux peuvent être transmis à la méthode et sont disponibles dans la classe anonyme.
Par exemple: (à partir de code GWT permettant de gérer un changement de zone de texte):
/* Regular method. Returns the required interface/abstract/class
Arguments are defined as final */
private ChangeHandler newNameChangeHandler(final String axisId, final Logger logger) {
// Return a new anonymous class
return new ChangeHandler() {
public void onChange(ChangeEvent event) {
// Access method scope variables
logger.fine(axisId)
}
};
}
Pour cet exemple, la nouvelle méthode de classe anonyme serait référencée avec:
textBox.addChangeHandler(newNameChangeHandler(myAxisName, myLogger))
OU , en utilisant les exigences du PO:
private ActionListener newActionListener(final int aVariable) {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Your variable is: " + aVariable);
}
};
}
...
int myVariable = 1;
newActionListener(myVariable);
D'autres personnes ont déjà répondu que les classes anonymes ne peuvent accéder qu'aux variables finales. Mais ils laissent ouverte la question de savoir comment garder la variable initiale non finale. Adam Mlodzinski a donné une solution mais elle est plutôt boursouflée. Il existe une solution beaucoup plus simple au problème:
Si vous ne voulez pas que myVariable
soit final, vous devez l'envelopper dans une nouvelle portée où ce n'est pas grave, si c'est final.
int myVariable = 1;
{
final int anonVar = myVariable;
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// How would one access myVariable here?
// Use anonVar instead of myVariable
}
});
}
Adam Mlodzinski ne fait pas autre chose dans sa réponse, mais avec beaucoup plus de code.
Vous pouvez utiliser plain lambdas ("les expressions lambda peuvent capturer des variables")
int myVariable = 1;
ActionListener al = ae->System.out.println(myVariable);
myButton.addActionListener( al );
ou même une fonction
Function<Integer,ActionListener> printInt =
intvar -> ae -> System.out.println(intvar);
int myVariable = 1;
myButton.addActionListener( printInt.apply(myVariable) );
Utiliser Function est un excellent moyen de refactoriser les décorateurs et les adaptateurs, voir ici
Je viens tout juste de commencer à apprendre sur les lambdas, alors si vous remarquez une erreur, n'hésitez pas à écrire un commentaire.
Un moyen simple de mettre de la valeur dans une variable externe (qui n’appartient pas à la classe anonymus) est la suivante:
De la même manière, si vous voulez obtenir la valeur d’une variable externe, vous pouvez créer une méthode qui retourne ce que vous voulez!
public class Example{
private TypeParameter parameter;
private void setMethod(TypeParameter parameter){
this.parameter = parameter;
}
//...
//into the anonymus class
new AnonymusClass(){
final TypeParameter parameterFinal = something;
//you can call setMethod(TypeParameter parameter) here and pass the
//parameterFinal
setMethod(parameterFinal);
//now the variable out the class anonymus has the value of
//of parameterFinal
});
}