web-dev-qa-db-fra.com

la variable locale est accessible dans la classe interne (Java)

J'ai eu deux erreurs après avoir compilé mon code.

Les erreurs sont:

1.

  local variable input is accessed within inner class; 
  needs to be declared final
     String name = input.getText();

2.

  local variable c_age is accessed within inner class; 
  needs to be declared final
     Object child_age = c_age.getSelectedItem();

Voici mon code:

import javax.swing.*;
import Java.awt.event.*;

public class GUI
{
    public static void main(String[] args)
    {
        JFrame frame = new JFrame("Try GUI");
        JLabel l1 = new JLabel("Please Enter Your Child's Name");
        JTextField input = new JTextField("",10);

        JLabel l2 = new JLabel("Choose Your Child's Age");
        String[] age = {"Age","1","2","3","4","5","6"};
        JComboBox c_age = new JComboBox(age);

        JButton button = new JButton("Search");

        JTextArea result = new JTextArea();
        JScrollPane extend_area = new JScrollPane(result);

        button.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                String name = input.getText();
                Object child_age = c_age.getSelectedItem();
            }
        });

        JPanel panel = new JPanel();
        panel.add(l1);
        panel.add(input);
        panel.add(l2);
        panel.add(c_age);
        panel.add(button);
        panel.add(extend_area);
        frame.add(panel);
        frame.setSize(350,350);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

}

Comment puis-je résoudre cette erreur?

18
Roubie

Vous devez déclarer

JTextField input = new JTextField("",10);

et

JComboBox c_age = new JComboBox(age);

comme ça:

final JTextField input = new JTextField("",10);

final JComboBox c_age = new JComboBox(age);

Cela signifie que input et c_age ne peut pas changer:

Toute variable locale, utilisée mais non déclarée dans une classe interne doit être définitivement affectée avant le corps de la classe interne.

Explication tirée de la Java, Section - 8.1.3 Classes internes et instances de clôture

16
edwardsmatt

Si vous déclarez les variables en tant que final, cela résoudra vos erreurs, mais selon moi, ce n'est pas la bonne solution au problème. Un problème similaire a été discuté ici, vous pouvez jeter un œil ici pour plus de compréhension.

Pour résoudre votre problème, vous pouvez définir des méthodes en les utilisant, vous pouvez obtenir une meilleure solution. Pour obtenir un indice, vous pouvez lire Comment accéder à la variable locale non finale à l'intérieur d'une classe interne anonyme

5

Toute variable que vous utilisez dans la méthode actionPerformed de votre classe interne devra être déclarée finale. Essayez ce qui suit:

import javax.swing.*;
import Java.awt.event.*;

    public class GUI
    {
        public static void main(String[] args)
        {
            JFrame frame = new JFrame("Try GUI");
            JLabel l1 = new JLabel("Please Enter Your Child's Name");
            final JTextField input = new JTextField("",10);

            JLabel l2 = new JLabel("Choose Your Child's Age");
            String[] age = {"Age","1","2","3","4","5","6"};
            final JComboBox c_age = new JComboBox(age);

            JButton button = new JButton("Search");

            JTextArea result = new JTextArea();
            JScrollPane extend_area = new JScrollPane(result);

            button.addActionListener(new ActionListener()
            {
                    public void actionPerformed(ActionEvent ae)
                    {
                        String name = input.getText();
                        Object child_age = c_age.getSelectedItem();


                    }
            });

            JPanel panel = new JPanel();
            panel.add(l1);
            panel.add(input);
            panel.add(l2);
            panel.add(c_age);
            panel.add(button);
            panel.add(extend_area);
            frame.add(panel);
            frame.setSize(350,350);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        }

    }
2
Sean Kleinjung

Comme l'ajout de final enlève beaucoup de flexibilité, je voudrais suggérer ce qui suit: créer une méthode d'accesseur, ce qui est encouragé de toute façon. Mais cela est surtout utile lorsque vous traitez des objets, alors que dans votre cas, tout est statique. Par conséquent, cette réponse peut ne pas s'appliquer à votre situation spécifique, mais comme la recherche de votre message d'erreur sur Google renvoie cette question comme résultat supérieur, je pense qu'une alternative qui est applicable dans la plupart des cas (l'utilisation d'objets est plus courante que de tout faire à partir d'une méthode statique) devrait également être présent ici.

public class MyClass extends MySuperClass {
    private MyPropertyClass aProperty;

    public MyClass() {
        new JButton().setActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // aProperty.aMethod(); -- Bang! That should be final, the compiler says.
                getMyProperty().aMethod(); // -- Everything okay, works fine, no compiler complaints.
            }
        });
    }

    public getMyProperty() {
        return aProperty;
    }
}
1
11684

L'entrée nommée JTextField a été déclarée à l'intérieur de la méthode principale. Vous devriez probablement faire quelque chose comme ça:

  public class GUI{

      //declare all your components here e.g.

      JTextField input;

      public static void main(String args[]){
              new GUI();
      }

      public GUI(){
          //instantiate components here
          input = new JTextField();
          //and so on.
      }

  }

De cette façon, la référence à l'entrée dans la classe interne ne posera aucun problème.

0
Vincent Ramdhanie

Vous devez déclarer final les deux variables auxquelles vous accédez: input et c_age.

Si vous ne voulez pas faire cela, vous pouvez soit créer une nouvelle classe appropriée (pas une classe ad-hoc) et les passer en tant que paramètres dans le constructeur, ou (je l'ai fait lorsque je travaillais avec des GUI en Java) créer un classe d'écoute qui prend des objets dans son constructeur et les rend disponibles localement, puis instancie cela de manière ad hoc.

0
slezica

La variable d'entrée et la variable c_age disparaissent une fois l'exécution de la méthode terminée. Vous ne serez pas autorisé à utiliser ces variables à l'intérieur des classes internes locales, sauf si elles sont finales.

0
Ammu

Je viens de créer un var temporaire dans la classe principale, par exemple 'tempString', puis il peut être défini sur le var qui cause le problème. Alors:

tempString = myString

de cette façon, je peux appeler tempString sans aucun problème. Consultez mon exemple ci-dessous:

// Create my temp var here
private String tempUrl;

// my function here
public void updatePage(String url)
{
    // Can use 'url' here because it's not within inner class
    if(!url.equals(""))
    {
        // Set 'tempUrl' to 'url' so I can use it without problem
        tempUrl = url;

        // My inner class that used to cause the problem
        backgroundUpdate = new Thread(new Runnable()
        {
            // From here on I use 'tempUrl' to solve the problem
            public void run()
            {
                // Do something with 'tempUrl' here (where 'url' used to be used)
            }
        });

        backgroundUpdate.start();
    }
}
0
Luke Alderton