• java含有静态代码块新建的时候报错java.lang.ExceptionInInitializerError


    问题描述

    最近在写一些单元测试用例,为了避免连接外界服务,所有选择mock了数据库Dao层,计划将数据库所需要的数据存在List中,在类加载的时候初始化List并且填充数据。代码如下:

     1 public class UserDaoMock extends UserDao {
     2     @Override
     3     public List<UserInfo> selectUserInfo() {
     4         return getUserInfo();
     5     }
     6 
     7     static {
     8         initUserInfo();
     9     }
    10 
    11     public static UserInfo getUserInfo() {
    12         return userInfos;
    13     }
    14 
    15     
    16     private static List<UserInfo> userInfos = new ArrayList<UserInfo>();
    17     private static void initUserInfo() {
    18         UserInfo userInfo1 = new UserInfo();
    19         userInfo1.setId(1L);
    20         userInfo1.setPin("user1");
    21         userInfo1.setUserId(1L);
    22         userInfo1.setDataBillingType(1);
    23         userInfo1.setErp("operator1");
    24         userInfo1.setCreatedTime("2019-01-01");
    25         userInfo1.setModifiedTime("2019-05-01");
    26         userInfo1.setYn(1);
    27         userInfos.add(userInfo1);
    28 
    29         UserInfo userInfo2 = new UserInfo();
    30         userInfo2.setId(2L);
    31         userInfo2.setPin("user2");
    32         userInfo2.setUserId(2L);
    33         userInfo2.setDataBillingType(1);
    34         userInfo2.setErp("operator2");
    35         userInfo2.setCreatedTime("2019-01-01");
    36         userInfo2.setModifiedTime("2019-05-01");
    37         userInfo2.setYn(1);
    38         userInfos.add(userInfo2);
    39 
    40         UserInfo userInfo3 = new UserInfo();
    41         userInfo3.setId(3L);
    42         userInfo3.setPin("user3");
    43         userInfo3.setUserId(3L);
    44         userInfo3.setDataBillingType(1);
    45         userInfo3.setErp("operator1");
    46         userInfo3.setCreatedTime("2019-01-01");
    47         userInfo3.setModifiedTime("2019-05-01");
    48         userInfo3.setYn(1);
    49         userInfos.add(userInfo3);
    50     }
    51 }

    结果在new对象的时候:

    1 UserDao userDao = new UserDaoMock();

    一直报错:

    java.lang.ExceptionInInitializerError
            at com.jd.ads.afa_index.indexes.task.TestUserServiceTask.setUp(TestUserServiceTask.java:37)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
            at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
            at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
            at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
            at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
            at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
            at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
            at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
            at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
            at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
            at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
            at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
            at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
            at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
            at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
            at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
            at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
            at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
            at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
            at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:119)

    起初以为是init方法出错了,尝试了多种方式,才发下原来是类加载时,当执行到static{}语句块时开始调用userInfos,但userInfos这个list由于是在后面而还未定义和初始化,所以导致了错误。还是因为基础知识不扎实啊!!!

    问题解决

    将static对象提到最前面,即解决了此问题,简直愚昧的我啊:

     1 public class UserDaoMock extends UserDao {
     2     private static List<UserInfo> userInfos = new ArrayList<UserInfo>();
     3 
     4     @Override
     5     public List<UserInfo> selectUserInfo() {
     6         return getUserInfo();
     7     }
     8 
     9     static {
    10         initUserInfo();
    11     }
    12 
    13     public static UserInfo getUserInfo() {
    14         return userInfos;
    15     }
    16 
    17     private static void initUserInfo() {
    18         UserInfo userInfo1 = new UserInfo();
    19         userInfo1.setId(1L);
    20         userInfo1.setPin("user1");
    21         userInfo1.setUserId(1L);
    22         userInfo1.setDataBillingType(1);
    23         userInfo1.setErp("operator1");
    24         userInfo1.setCreatedTime("2019-01-01");
    25         userInfo1.setModifiedTime("2019-05-01");
    26         userInfo1.setYn(1);
    27         userInfos.add(userInfo1);
    28 
    29         UserInfo userInfo2 = new UserInfo();
    30         userInfo2.setId(2L);
    31         userInfo2.setPin("user2");
    32         userInfo2.setUserId(2L);
    33         userInfo2.setDataBillingType(1);
    34         userInfo2.setErp("operator2");
    35         userInfo2.setCreatedTime("2019-01-01");
    36         userInfo2.setModifiedTime("2019-05-01");
    37         userInfo2.setYn(1);
    38         userInfos.add(userInfo2);
    39 
    40         UserInfo userInfo3 = new UserInfo();
    41         userInfo3.setId(3L);
    42         userInfo3.setPin("user3");
    43         userInfo3.setUserId(3L);
    44         userInfo3.setDataBillingType(1);
    45         userInfo3.setErp("operator1");
    46         userInfo3.setCreatedTime("2019-01-01");
    47         userInfo3.setModifiedTime("2019-05-01");
    48         userInfo3.setYn(1);
    49         userInfos.add(userInfo3);
    50     }
    51 }

    注:

    类加载时不会为实例变量赋值,对象创建时不会为静态变量赋值。我们调用静态方法时,此类就开始加载,加载的时候不会为实例变量赋值,但是会按顺序给静态变量赋值。

    类加载特性 :
          *在虚拟机的生命周期中一个类只被加载一次。
          *类加载的原则:延迟加载,能少加载就少加载,因为虚拟机的空间是有限的。
          *类加载的时机:
          1)第一次创建对象要加载类.
          2)调用静态方法时要加载类,访问静态属性时会加载类。
          3)加载子类时必定会先加载父类。
          4)创建对象引用不加载类.
          5) 子类调用父类的静态方法时
              (1)当子类没有覆盖父类的静态方法时,只加载父类,不加载子类
              (2)当子类有覆盖父类的静态方法时,既加载父类,又加载子类
          6)访问静态常量,如果编译器可以计算出常量的值,则不会加载类,例如:public static final int a =123;否则会加载类,例如:public static final int a = math.PI。

    转载请注明:https://www.cnblogs.com/fnlingnzb-learner/p/10615516.html

  • 相关阅读:
    [导入]简单而强力的JS退弹代码(强制 弹出)
    [导入]在上传的图片上写字
    [导入]无法创建WEB项目文件路径与URL不符 处理方法
    [导入]ASCII码表完整版
    [导入]访QQ/MSN淡出窗口例子二则
    [导入]生成图片缩略图
    [导入]javascript调用webservice例子
    在字典的三级菜单中添加内容
    服务列表中找不到mysql
    CentOS 7安装后的配置
  • 原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/10615516.html
Copyright © 2020-2023  润新知