2009-11-23 3 views
0

J'ai une méthode qui contient le code suivant:L'utilisation objet final dans les résultats de classe internes anonymes null

public void myMethod(){ 
    final MyDto expectedtDto = new MyDto(); 

    MyRepository reposWithMock = new MyRepository(){ 
     protected MyDao createDao(){ 

      return new MyDao() { 
       public MyDto someMethod(){ 
        return expectedtDto; 
       } 
      }; 

     } 
    }; 

    reposWithMock.doSomethingWithDao(); 
} 

MyRepository.createDao() est appelé à partir du constructeur de MyRepository. MyDao.someMethod() est appelée à partir de MyRepository.doSomethingWithDao().

Cependant, les rendements MyDao().someMethod()null au lieu de expectedDto

Toute idée pourquoi est-ce?

Pour plus de précisions, un code de travail réel:

package nl.tests; 

public class TestAnon { 
    static class MyDao { 
    private int value; 

    public MyDao(int value) { 
     this.value = value; 
    } 

    public int getValue() { 
     return value; 
    } 
    } 

    static class Repository { 
    private MyDao dao; 

    public Repository() { 
     dao = createDao(); 
    } 

    protected MyDao createDao(){ 
     return new MyDao(4); 
    } 

    public MyDao getDao(){ 
     return dao; 
    } 
    } 

    public static void main(String[] args) { 
    final MyDao testDao = new MyDao(8); 

    Repository repos = new Repository() { 
     protected MyDao createDao() { 
      if (testDao == null) { 
       System.out.println("Error "); 
       return new MyDao(0); 
      } 
      return testDao; 
     } 
    }; 

    System.out.println("Dao :" + repos.getDao().getValue()); 
    } 
} 

Il en résulte en:

Error 
Dao :0 

Quelques informations supplémentaires: Je actuellement (dois) travailler avec Java 1.4. Mon environnement de développement est Rational Application Developer 7.

Addendum, à la réponse donnée (et acceptée). Pour le code ci-dessous, je l'ai fait la méthode publique createDao():

public static void main(final String[] args) {   
    final MyDao testDao = new MyDao(8);  


    Repository repos = new Repository() { 
     public MyDao createDao() { 

      if (testDao == null) { 
       System.out.println("Error "); 
       return new MyDao(0); 
      } 
      return testDao; 
     } 
    }; 

    System.out.println("Dao :" + repos.getDao().getValue()); 
    System.out.println("Dao :" + repos.createDao().getValue()); 
} 

Retours:

Error 
Dao :0 
Dao :8 
+0

Je suppose que c'est une faute de frappe - devrait être public MyDto somemethod() .. – Bozho

+0

Correction, merci. – dstibbe

+0

theres très peu de code pour continuer - il pourrait potentiellement avoir été ombrage que nous ne pouvons pas voir puisque tout le code source n'est pas fourni - et si vous le réduisiez au code minimaliste (qui compile) et le publiez ici? – Chii

Répondre

4

Echec de Java 1.4 car le champ contenant la variable locale n'est pas encore initialisé lorsque le super-constructeur de Repository est exécuté.

Cela fonctionne dans Java 1.5 et versions ultérieures car le champ est initialisé avant l'appel du super-constructeur.

En général, il est de mauvais style d'appeler des méthodes qui peuvent être surchargées dans les sous-classes d'un constructeur, car cela conduit à ce genre de problèmes.

+0

Je pense que vous êtes à la hauteur de quelque chose mais je ne peux pas suivre votre explication. De quelle "variable locale" parlez-vous? –

+0

Ah, je vois. Je vous remercie. – dstibbe

+0

@Aaron Digulla La variable locale est testDao dans main(), accessible dans la classe anonyme. Le compilateur implémente ceci en ajoutant un paramètre pour la variable au constructeur et en stockant sa valeur dans un champ de la classe anonyme, auquel on accède alors. – starblue

0

Assurez-vous de passer outre en fait la méthode que vous pensez que vous faites. Votre IDE ou @Override devrait vous aider.

+0

Je sais que c'est annulé. Le tracé (Eclipse) me montre la méthode appelée. Cependant attenduDto est considéré comme nul à ce moment. – dstibbe

+0

Dans ce cas, la ligne 'final MyDto expectedtDto = new MyDto();' n'a pas été appelée (les variables 'final' ne peuvent être affectées qu'une seule fois). Cela signifie que le code que vous avez posté ne reflète pas ce qui se passe réellement. –

+0

Une autre option est qu'il existe un champ public/protected 'expectedtDto' dans' MyDao' ou 'MyRepository' –

0

Est-ce que MyDto est un enfant de MyDao?
Vous renvoyez un MyDto lorsque la méthode indique que vous renvoyez un MyDao.
Peut-être que c'est une partie du problème.

Une deuxième solution pourrait être:
Placez le expectedtDto dans la classe interne au lieu de la méthode.

Martijn

+0

Excuses, c'était une faute de frappe. MyDto n'est pas un enfant de MyDAo. J'ai effectivement appliqué cette solution, mais je préférerais que le code fonctionne comme je l'attendais. – dstibbe

2

D'après ce que vous avez fait une sortie de test rapide [email protected] ou similaires. Donc je parie que vous avez omis un code important qui est responsable de la dissimulation d'un nom de variable.

Test.java

public class Test { 
    public static void main(String args[]) { 
    new Test().myMethod(); 
    } 
    public void myMethod() { 
    final MyDto expectedtDto = new MyDto(); 

    MyRepository reposWithMock = new MyRepository() { 
     @Override 
     protected MyDao createDao() { 
     return new MyDao() { 
      @Override 
      public MyDto someMethod(){ 
      return expectedtDto; 
      } 
     }; 
     } 
    }; 
    reposWithMock.doSomethingWithDao(); 
    } 
} 

MyDto.java

public class MyDto {} 

MyRepository.java

public abstract class MyRepository { 
    protected abstract MyDao createDao(); 
    public void doSomethingWithDao() { 
    System.out.println(createDao().someMethod()); 
    } 
} 

MyDao.java

public abstract class MyDao { 
    public abstract MyDto someMethod(); 
} 
0

Votre code fonctionne pour moi. La seule façon dont je pourrais voir que expectedDto pourrait être nul dans la classe interne anonyme est si vous faites référence sur un autre thread sans synchronisation appropriée.

0

Le test-case que vous avez décrit fonctionne bien pour moi.

Vous devez fournir un cas d'essai autonome minimal mais complet qui illustre le problème pour obtenir de l'aide.

+0

J'ai maintenant ajouté un tel code. – dstibbe

+0

Votre code produit 'Dao: 8' pour moi (java6 a été utilisé lors des tests) –

Questions connexes