开发者

Using final object in anonymous inner class results in null

开发者 https://www.devze.com 2022-12-12 11:28 出处:网络
I have a method that contains the following code: public void myMethod(){ final MyDto expectedtDto = new MyDto();

I have a method that contains the following code:

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() is called from the constructor of MyRepository. MyDao.someMethod() is called from MyRepository.doSomethingWithDao().

However, the MyDao().someMethod() returns null instead of the expectedDto

Any idea why this is?

For clarification, some real working code:

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

This results in :

开发者_开发技巧Error 
Dao :0

Some additional information: I currently (have to) work with java 1.4. My development environment is Rational Application Developer 7.

Addendum, to the given (and accepted answer). For the below code I've made the createDao() method public :

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

Returns:

Error
Dao :0
Dao :8


It fails in Java 1.4 because the field containing the local variable is not yet initialized when the super constructor for Repository is executed.

It works in Java 1.5 and later, because then the field is initialized before the super constructor is called.

In general it is bad style to call methods which may be overridden in subclasses in a constructor, because it leads to this kind of problems.


According to what you provided a quick test outputs MyDto@190d11 or similar. So I bet you left out some important code which is responsible for some variable name hiding.

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


Make sure you actually override the method you think you do. Your IDE or @Override should help.


Is MyDto a child of MyDao?
Your return a MyDto when the method indicates you return a MyDao.
Maybe that is a piece of the problem.

A second solution could be:
Put the expectedtDto in the inner-class instead of the method.

Martijn


Your code works for me. The only way I could see that expectedDto could be null within the anonymous inner class is if you're referencing it on another thread without proper synchronization.


The test-case you described works fine for me.

You should provide minimal but complete standalone test-case that illustrates the problem to get help.

0

精彩评论

暂无评论...
验证码 换一张
取 消