V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Wuuuu
V2EX  ›  Java

请老司机指点一下,为神马这个代码在 JDK1.8 下能运行, JDK11 下就报 NullPointerException 额

  •  
  •   Wuuuu · 2019-11-13 16:57:39 +08:00 · 3745 次点击
    这是一个创建于 1835 天前的主题,其中的信息可能已经有所发展或是发生改变。

    刚刚在看黑马 Spring P14 这里,然后按照视频中做的这个 Demo,在 JDK1.8 下面可以正常运行,JDK11 下直接就报错

    Exception in thread "main" java.lang.NullPointerException
    	at com.itheima.service.impl.AccountServiceImpl.saveAccount(AccountServiceImpl.java:20)
    	at com.itheima.ui.Client.main(Client.java:16)
    
    Process finished with exit code 1
    

    一直以为 JDK 都是向后兼容的,不知道有木有老司机指点一下这个是什么原因额……

    Debug 的时候也只是看到AccountServiceImpl里面通过BeanFactory.getBean("accountDao");创建的 accountDao 值是 Null,但是完全不知道为什么这个没能创建出来,是 null……

    运行的就是 ui 下面的 Client 里面的 main 方法,在 IDEA 里直接右键 run 的……

    JDK 一开始用的是 adoptopenjdk 最新的 11.0.5+10,报错,一开始怀疑是 JDK 问题,改成了 amazon-corretto-11.0.3.7.1-1-windows-x64. 还是不行,最后用了 amazon-corretto-8.232.09.1-windows-x64 这个 JDK 成功的……

    代码也传到 github 上了。

    第 1 条附言  ·  2019-11-13 19:55:55 +08:00

    感谢 @sagaxu @lxk11153 @tt0411 三位的回复,因为我不知道 Properties 的结果是无序,导致一开始没有检查到静态代码块那部分创建实例的地方…… 新的知识点Get√

    看了下网络上解决的方案都是创建一个继承Properties的类覆写其中的方法,之后我也会试着写一下,并且尝试读一下Spring源码。

    当然也知道了 原来JDK向后兼容性没有想象的辣么美好……

    sagaxu
        1
    sagaxu  
       2019-11-13 17:24:15 +08:00 via Android   ❤️ 1
    BeanFactory 的 static initializer 还没执行完,就调用 getBean 方法,返回 null 才符合预期吧,Java 8 能执行才是意料之外。
    optional
        2
    optional  
       2019-11-13 17:47:17 +08:00
    jdk 的向后兼容最近做的不太好,,我见过好几个应用>11 不能用了
    lxk11153
        3
    lxk11153  
       2019-11-13 17:55:55 +08:00   ❤️ 1
    我没 debug,我也同 #1 觉得奇怪呢
    1. bean.properties 中先 accountService 后 accountDao
    2. 执行 Client main 方法
    3. 引用到 BeanFactory,执行它的 static init
    4. 先 newInstance accountService,accountService 内部 BeanFactory.getBean("accountDao"),但此时 Map<String,Object> beans 里面没有"accountDao"呀,所以返回 null
    Wuuuu
        4
    Wuuuu  
    OP
       2019-11-13 18:03:07 +08:00
    @lxk11153 @sagaxu 谢谢两位额,因为我之前一直没在意静态代码块这里的问题……但是还是不确定怎么才能保证 accoutDao 优先于 accountService 被创建实例额。刚刚我用了一个蠢办法,把 配置文件里面的 dao 和 service 颠倒了一下,也不行……囧
    x537196
        5
    x537196  
       2019-11-13 18:23:07 +08:00
    你放代码出来
    sagaxu
        6
    sagaxu  
       2019-11-13 18:35:46 +08:00 via Android   ❤️ 1
    @Wuuuu 因为你用的是 Properties,它是无序的
    sagaxu
        7
    sagaxu  
       2019-11-13 18:45:42 +08:00 via Android   ❤️ 1
    Java 8 下面可用,可能是因为 JDK 8 的 Properties 内部实现,恰好满足了你的加载顺序,纯属巧合。

    像 Go 比较愤青,干脆保证无序容器的遍历的随机的,让你不能错误依赖某个具体实现
    x537196
        8
    x537196  
       2019-11-13 18:48:32 +08:00
    @Wuuuu 在 BeanFactory 的静态块中,加一下日志,看看 beans 中的对象是什么状态,什么阶段初始化完成
    realpg
        9
    realpg  
       2019-11-13 19:10:29 +08:00
    一直以为 JDK 都是向后兼容的

    何来自信……

    JDK 6 7 8 内牛满面
    tt0411
        10
    tt0411  
       2019-11-13 19:13:08 +08:00   ❤️ 1
    我觉得 6 楼是对的, 你这个代码能不能跑和 Properties 内部实现有关; BeanFactory 不应该这么实现的, 去看 Spring 源码吧.
    tt0411
        11
    tt0411  
       2019-11-13 19:26:27 +08:00   ❤️ 1
    看了下 JDK 8 的 Properties 是个 HashTable, 数据放在父类内部数据结构中; 而 JDK 11 的 Properties 虽然依旧继承自 HashTable, 但仅仅实际读写在自己的一个 ConcurrentHashMap.
    NoKey
        12
    NoKey  
       2019-11-13 22:31:18 +08:00
    标记一下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1167 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:06 · PVG 07:06 · LAX 15:06 · JFK 18:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.