Toolkit.getDefaultToolkit().getImage(Panel.class.getResource())在Java11中返回空指针

事先声明:本人刚开始学Java,如果有什么说的不对的地方敬请指正。

一、问题

1、环境:win10,java11 & java8
2、跟着教程学习java,在使用Toolkit.getDefaultToolkit().getImage(Panel.class.getResource())导入图片的时候,老师可以正常运行,我的代码运行时却报空指针。
Toolkit.getDefaultToolkit().getImage(Panel.class.getResource())在Java11中返回空指针_第1张图片
bomb1.gif,bomb2.gif,bomb3.gif放在out/production/chapter16下,与com平级。getResource()中资源名是带/的。类名是MyPanel,不是Panel,下面的代码中写的是Panel,老师就是这么写的。
Toolkit.getDefaultToolkit().getImage(Panel.class.getResource())在Java11中返回空指针_第2张图片
Toolkit.getDefaultToolkit().getImage(Panel.class.getResource())在Java11中返回空指针_第3张图片

image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb1.gif"));

二、原因

老师用的是java8,我用的是java11(切成java8就能正常运行)。从java9开始,定位资源的方式发生了变化。getResource()只会在调用该方法的module内定位资源。这是由于getResource()受getResourceAsStream​()中规则的约束,这在之前的版本里是没有的。

三、解决办法

从找到的资料来看,似乎需要具体指定.class.getResource(),也就是说写成Panel.class.getResource()(老师的写法)或Class.class.getResource()(上面链接中stackoverflow上提问者的写法)是不行的,这里的应该就是官方文件里说的named module,相对应地,Panel和Class这种不是由用户定义的就是unnamed module。所以我在这里把代码写成:

image1 = Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb1.gif"));

四、其他

1、在改成MyPanel的前提下,把bomb1.gif,bomb2.gif,bomb3.gif放到out\production\chapter16\com\shouie\tankgame3目录下,并把getResource()中资源名的/去掉,即getResource("/bomb1.gif")改成getResource(“bomb1.gif”)。这种做法在java8和java11中都是可以的。因为带/的是绝对路径,表示getResource()从当前路径(所在包的上级目录)开始搜索;不带的是相对路径,就是把包所在路径的.用/代替。(参考资料1,参考资料2)
2、java.lang.ClassLoader负责加载类,每一个class都有一个指向定义它的classloader的引用(参考资料)

你可能感兴趣的:(Java,java)