2009-11-23 2 views
0

У меня есть метод, который содержит следующий код:Используя конечный объект в анонимных результатах внутреннего класса в нуле

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() вызываются из конструктора MyRepository. MyDao.someMethod() называется от MyRepository.doSomethingWithDao().

Однако MyDao().someMethod() возвращает null вместо Любая идея expectedDto

почему это?

Для уточнения, некоторые реальные рабочий код:

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()); 
    } 
} 

Это приводит к:

Error 
Dao :0 

дополнительная информация: В настоящее время я (должен) работать с Java 1.4. Моей средой разработки является Rational Application Developer 7.

Дополнение к данному (и принятому ответу). Для кода ниже я сделал метод 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()); 
} 

возвращения:

Error 
Dao :0 
Dao :8 
+0

Я предполагаю, что это опечатка - должно быть общедоступным MyDto somemethod() .. – Bozho

+0

Исправлено, спасибо. – dstibbe

+0

. Очень маленький код для продолжения - возможно, было скрыто то, что мы не можем видеть, так как не весь исходный код предоставлен - что, если вы уменьшите его до минималистского кода (который компилируется) и разместите его здесь? – Chii

ответ

4

Ошибка в Java 1.4, потому что поле, содержащее локальную переменную, еще не инициализируется при выполнении суперструктора для репозитория.

Он работает в Java 1.5 и более поздних версиях, потому что тогда поле инициализируется до вызова суперструктора.

В общем, это плохой стиль для вызова методов, которые могут быть переопределены в подклассах в конструкторе, потому что это приводит к таким проблемам.

+0

Я думаю, что вы что-то делаете, но я не могу следовать вашим объяснениям. О какой «локальной переменной» вы говорите? –

+0

А, я вижу. Спасибо. – dstibbe

+0

@Aaron Digulla Локальная переменная - testDao в main(), доступ к которой осуществляется в анонимном классе. Компилятор реализует это, добавляя параметр для переменной в конструктор и сохраняя его значение в поле анонимного класса, к которому затем обращаются. – starblue

0

Убедитесь, что вы на самом деле переопределить метод вы думаете, что вы делаете. Ваша IDE или @Override должны помочь.

+0

Я знаю, что это переопределено. Трассировка (Eclipse) показывает, что метод вызывается. Однако ожидается, что в тот момент он считается нулевым. – dstibbe

+0

В этом случае строка 'final MyDto expectedtDto = new MyDto();' не была вызвана (переменные 'final' могут быть назначены только один раз). Это означает, что код, который вы опубликовали, не отражает то, что на самом деле происходит. –

+0

Другим вариантом является наличие открытого/защищенного поля 'expectedtDto' в' MyDao' или 'MyRepository' –

0

Номер MyDto ребенок MyDao?
Ваше возвращение MyDto, когда метод указывает, что вы возвращаете MyDao.
Возможно, это часть проблемы.

Вторым решением может быть:
Поместите ожидаемое значение во внутреннем классе вместо метода.

Мартейн

+0

Извинения, это была опечатка. MyDto не является дочерью MyDAo. Я действительно применил это решение, однако я бы предпочел, чтобы код работал так, как я ожидал. – dstibbe

2

Согласно тому, что вы предоставили быстрый тест выходов [email protected] или аналогичные. Поэтому, я уверен, вы оставили некий важный код, который отвечает за скрытие имени переменной.

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

Ваш код работает для меня. Единственный способ увидеть, что expectedDto может быть нулевым внутри анонимного внутреннего класса, - это если вы ссылаетесь на него в другом потоке без надлежащей синхронизации.

0

Тестовый чехол, который вы описали, отлично подходит для меня.

Вы должны предоставить минимальный, но полный автономный тестовый чехол, который иллюстрирует проблему, чтобы получить справку.

+0

Теперь я добавил такой код. – dstibbe

+0

Ваш код производит «Дао: 8» для меня (java6 использовался во время тестирования) –

Смежные вопросы