java初始化static final成员属性问题!!!

黄开军 发布于 2013/08/18 15:52
阅读 1K+
收藏 0

public class ImageResource {
 
 public static final Image background;

 static {
  try {
   background = ImageIO.read(ImageResource.class.getResource("I.png"));
  } catch (Exception e) {
   e.printStackTrace();
 }

这里为什么报background没有初始化的编译错误?

加载中
1
moyiguke
moyiguke

先解决问题。我个人习惯使用第一种方式。

你试一下这两种写法。 这个思路是使用一个辅助的方法提供image实例

public static final Image background = initial(); 
public static Image initial(){
Image tmp = null;
try {
ImageIO.read(new FileInputStream(""));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return tmp;
}



或者是 在类的构造函数里面初始化参数。(也推荐使用辅助方法)

public ImageResource (){

background = ImageIO.read(ImageResource.class.getResource("I.png"));

}

我先去翻翻资料,看看产生的原因。



0
戴威
戴威
因为 background没有初始化的编译,除非你在catch或者finally里做点什么。
戴威
戴威
回复 @黄开军 : 那就不要用final修饰变量
黄开军
可是我在catch里面给background赋值又报不能修改的错误,按道理try和catch只有一个会执行才对啊
0
typeorigin
typeorigin

如果

    ImageIO.read(ImageResource.class.getResource("I.png"));

失败了`background ` 还是同样为赋值

typeorigin
typeorigin
回复 @黄开军 : 你要么把final去掉,然后在catch中 处理下异常情况。final 只是保证引用不变,如果你是想保证背景图片不变的话,用final感觉用处不大
黄开军
可是ImageIO.read()就是有异常,怎么办?
0
悟方向
悟方向
在catch代码块中加个 background =null;就好了
0
铂金小虫
铂金小虫
因为你的静态初始块可能会抛异常,backgroud并不是一定能初始化成功的。所以要background=null;
0
乱世键客
乱世键客
你对final没有理解透彻,看看书就知道了。
0
old_big
old_big

以上人员都没有去实践,就高傲的指指点点,并且训话的口气说你。真实情况是:你的try中可能会抛出异常,所以有可能没有初始化,然后你在catch中赋值为null,又有多次赋值的嫌疑,违反了final的约定,编译器没有那么智能,知道try中赋值失败。

解决的办法?

public static final Image background;

	 static {
			background = getImage("I.png");
	 } 
	 private static Image getImage(String src) {
		 Image background = null;
		  try {
				background = ImageIO.read(TestS.class.getResource("I.png"));
			} catch (IOException e) {
				e.printStackTrace();
			}
		  return background;
	 }

铂金小虫
铂金小虫
看4L,不就是我说的吗。而且前面的人说的都对。final是不能多次赋值,但是lz的不是多次赋值的问题,而是可能抛异常导致初始化失败的问题。
戴威
戴威
这和在catch里直接写background=null有什么不同?
优雅先生
优雅先生
有道理!
0
王儒林
final修饰的属性不是要在声明时赋值吗,lz在巩固巩固java基础吧
moyiguke
moyiguke
回复 @王儒林 : 我也不清楚问题产生的具体原因,这和Java 虚拟机规范和赋值细节相关。在java puzzles 第38章,是这么描述的:在程序中,一个空final 域只有在它是明确未赋过值的地方才可以被赋值。 也就是说jvm 在编译的过程中无法确定这一点,它采取了保守措施,所以拒绝了这段代码的编译。
王儒林
回复 @moyiguke : 多谢了,我试了一下,是我原先理解的不对,还有你能告诉我lz的问题是出在哪了呢?
moyiguke
moyiguke
@王儒林 额。可以在其他地方赋值的。我找到这个问题的答案了(虽然不是很详细),java puzzles 第38 谜题。这本书不错,可以下载看看。
王儒林
回复 @moyiguke : 可以申明为空,可是有什么意义,final修饰的变量在声明之外是不能赋值的
moyiguke
moyiguke
这是不恰当的,final变量申明是可以申明空白的。
0
LucEsape
LucEsape
static final val 是不可修改的。
0
ArrayListt
ArrayListt

用final修饰过的变量,

你只能给他写一个=赋值。也就是只能赋值一次。

写多了也没用,他不给你执行的

ArrayListt
ArrayListt
回复 @moyiguke : 用最简单的话,描述一个问题。这么说也没有什么不对。如果他能清楚的知道,也不会发这个帖子了吧。
moyiguke
moyiguke
这是不恰当的。final修饰的变量只是引用不变而已。
返回顶部
顶部