简体   繁体   中英

Final static variable initialized in static block using method that throws exception

Consider following part of code

private static class InnerClass
{
   private static final BufferedImage connectionImage; // line A
   private static final int width;
   // other not relevant fields
   static
   {
       try
       {
           connectionImage = ImageIo.read(...); // doeasn't really matter - any method that throws exception
       }
       catch(IOException e)
       {
           // handle
          connectionImage = null; // line B
       }
       if(connectionimage != null) // line C
       {
          width = connectionImage.getWidth();
       }
       else
       {
          width =0;
       }
   }
   // rest of the class definition
}

I this case I am getting "variable might already have been assigned" on line B, which can be true if I had more lines in try{} block and exception was caused after my variable has been initialized. When I remove word final from line A it compiles ok, but I am getting warnings later in static {} block when I am trying to assign imageWidth/height (also final static) using connectionImage.getWidth() (of course if its not null). The warning is "usage of non-final variable during initialization". If I decide to use final in line A and remove line B, I am getting "variable connectionImage might not have been initialized" on line C.

My question is: Is there a way to have static final variables initialized and usable in static {} block using functions that throws exception (or generally inside try/catch ) or I should handle other way? (constructor)

NOTE (if relevant): Yes, the name of this class is to tell you it is inner class. Also it is static because if it isn't I can't declare static fields inside.

I know how to write code which will do what I wan't, but I'd like to have this inner class because of my convenience and to separate some behaviors. I only wan't to know the static final, static block, try/catch situation. I couldn't find good exlpanation for this in google, I even Checked my old 'Thhinking in Java'...

Here is something similar Java - Can final variables be initialized in static initialization block? but author hadn't try to initialize variable in catch, also he is not using them in the static block after assignment so he is not getting "Usege of non-final..." warning later.

Basically, you should use a local variable:

BufferedImage localImage = null;
try
{
    localImage = ImageIo.read(...);
}
catch (IOException e)
{
    // No need to set a value, given that it's already going to be null.
    // You probably want to log though.
}
connectionImage = localImage;

Now you know for sure that your connectionImage variable will be assigned exactly once.

I would then use a conditional operator for width , which makes it clearer that there's exactly one assignment:

width = connectionImage != null ? connectionImage.getWidth() : 0;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM