java实例和调用内部方法后对象为空

java Object null after instance and calling inside method

任何人都可以帮助我解决这个问题,我正在使用 SQLMap(ibatis) 与 java 合作。 我有 3 个 class,它们是 MainConfiguration、SQLMap、DBUtility。

  1. 主要配置(此 class 用于在 SQLMap class 中设置一个对象)

public class MainConfiguration
{
     public static String file = "configuration/db/SQLMapConfig.conf";

     public static void main(String[] args) throws Exception
     {
        new MainConfiguration().loadConfiguration();    
     }  

     public static void loadConfiguration()
     {
        SQLMap.setMapFile(file);
        List list = DBUtility.loadUsers();
     }
}
  1. SQL图(这个class是and对象的getter和setter

public final class SQLMap
{
    private static SqlMapClient sqlMap;

    public static void setMapFile(String sMapFile)
    {
        try
        {
            sqlMap = SqlMapClientBuilder.buildSqlMapClient(new FileReader(sMapFile));
        }
        catch (Exception e)
        {
            throw new RuntimeException("Error initializing SqlMapClient class", e);
        }
    }

    public static SqlMapClient getSqlMapInstance()
    {
        return sqlMap;
    }
}
  1. DBUtility(这个class是对象实例和从SQLMapclass获取对象的地方)

    public class DBUtility
    {
    // object utility
    protected static SqlMapClient sqlMap = SQLMap.getSqlMapInstance();
    
    //constructor
    public DBUtility() throws Exception
    {
    }
    
    public static List loadUsers()
    {
        //it's working
        logger.info("SQLMap Get Instance = " + SQLMap.getSqlMapInstance());
    
        //it's not working
        logger.info("SQLMap Get Instance = " + sqlMap);
    
        //code below will be error because of null sqlMap
        try
        {
            listUser = sqlMap.queryForList("getUsers");
        }
        catch (Exception sqle)
        {
            logger.error("Error on load all user", sqle);
        }
        return listUser;
    }
    }
    

记录员给我这个:

SQL地图获取实例=com.ibatis.sqlmap.engine.impl.SqlMapClientImpl@76707e36

SQL地图获取实例 = null

为什么第二个日志给我空值,即使我有实例对象?

您的字段 sqlMap 在加载 DBUtility class 时初始化,这显然发生在调用 SQLMap.setMapFile(file); 之前。因此,sqlMap 指向不同的东西:静态字段中的 null,以及在 loadUsers() 中调用 getter 时的实际实例。

问题是 DBUtility 查找 sqlMap 太早了。它必须等到 file 传递给 SQLMap。像这样更改代码以延迟 DbUtility.sqlMap:

的初始化
public static void loadConfiguration()
{
    SQLMap.setMapFile(file);
    DBUtility.initMapClient();  // notify DBUtility
    List list = DBUtility.loadUsers();
}

public class DBUtility
{
    protected static SqlMapClient sqlMap;  // do not initialize too early

    public static void initMapClient()
    {
        sqlMap = SQLMap.getSqlMapInstance();  // wait for SQLMap to be ready
    }

当然,如果DBUtility 中连sqlMap 字段都没有,那就更简单了。每次需要时只需调用 SQLMap.getSqlMapInstance() 即可。如果实例发生变化,这一点尤其重要:

listUser = SQLMap.getSqlMapInstance().queryForList("getUsers");

阅读 When are static variables are initialized? 以获取有关静态字段的更详细说明。