So I know to declare and initialize a global variable one would have to do something like this for example:
public static int Variable = 2;
But I want to know if there is a way to initialize a global BufferedImage variable with an image from a file. I can't use the above code, since I also need to include a try/catch statement.
Anyone have any solutions to my problem?
I think that you want to use a static bloc.
public static BufferedImage image = null ;
static
{
try {
image = javax.imageio.ImageIO.read(new File("Image path")) ; // Or whatever reader you use.
}
catch (IOException ex)
{
Logger.getLogger(Prototyper.class.getName()).log(Level.SEVERE, null, ex);
}
}
Btw, as mentioned in the first comment below, this is REALLY bad practice. Usually you want to use a Read static method, and you read the image where you need it, not by default.
Related
So I have the following bit of code:
public static Image getImage(String filepath, Class cl) {
try {
return ImageIO.read(cl.getResource(filepath));
}
catch (IOException e) {
e.printStackTrace();
}
return null; // Will never execute
}
It's a basic try-catch block. If I am unable to read the image and return it, I immediately go into my catch block. However, because my return is within the scope of the try block and not the entire function, my compiler issues an error when I try to compile and run because it sees that it's possible that I never hit a return statement. Therefore, I've added the return null; line to suppress this warning, but I'd rather have a neater way of doing this without putting code that will never run. I've tried adding
#SuppressWarnings("all")
To my code, but it still gives me an error. Any ideas? I feel like there should be a way to tell the compiler to ignore errors like this.
Also, if it is of any use, I am using IntelliJ as my IDE.
I would suggest what #LuCio eagerly in the comments tried to say. Just don't catch the Exception and pass it upwards:
public static Image getImage(String filePath, Class<?> clazz) throws IOException {
return ImageIO.read(clazz.getResource(filePath));
}
That way you have created an easy helper method. If you would return null, you'd have to document that in JavaDoc and every caller will have to use a not-null assertion logic to then throw an error if it is null.
A try catch block does the same. So instead of passing null upwards you just propagate the exception upwards. You somewhere said that you want to assign the Image to a static field, so you can do that easily like this:
static {
try {
MY_IMAGE = getImage("somepath", MyClass.class);
} catch(IOException e){
throw new IOError(e); // will kill the Vm with an error
}
}
But maybe somewhere you have another action. Than to just kill the VM. Maybe use a default image:
final Image image;
try {
image = getImage("somepath", MyClass.class);
} catch(IOException e){
e.printStacktrace();
image = new SomeDefaultImage();
}
// do something with image
Which all in all is the way to go. You can't have a helper method to decide what to do when it fails. That should always be done by the calling code.
Ok so, I believe I was confusing the purpose of the catch block. Thank you to #Ben and #Zephyr and everybody else for your help. I will be amending my code to:
public static Image getImage(String filepath, Class cl) {
try {
return ImageIO.read(cl.getResource("hello"));
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
throw new IOError(e);
}
}
Edit: After some more discussions, and looking through other options other people have posted, I have updated my code above, which satisfies the compiler. Note that replacing the line
throw new IOError(e)
with
System.exit(0);
does not fix the error because, as far as I know, the compiler cannot tell at compile time whether the program would end. It would've been helpful to have a way of suppressing the warning, since we know that at runtime the program will always (or practically always) end, but alas #SuppressWarnings is of no use.
static void goOut(String in) {
//instance variables
String fileCopy = currentLine + in;
try {
FileWriter writer = new FileWriter(output,true);
writer.write(line1 + System.getProperty("line.separator", "\r\n"));
writer.write(fileCopy + System.getProperty("line.separator", "\r\n"));
} catch(IOException ex) {
ex.printStackTrace();
}
}
Edited code to the correct standard as pointed out by other users.
of course because thats what you r telling it to do. every time is called it writes both x and the number. a quick fix: you can keep a flag if it is the first run set it flag = true. and check within ur method, sth like this:
public class YourClass{
private boolean didRun = false;
static void goOut(String in) {
...... init ur file and writer
if(!didRun)
writer.write(Y);
writer.write(in);
writer.close();
didRun = true;
}
}
I dont know the rest of the code but i think thats what u need
I believe you want to separate the jobs the "goOut" is responsible for.
You should make "goOut" only write the numbers (in your example).
The writing of the y's (in your example) should not be apart of the method and called once, at the start of writing to the file.
Also, #Jon Skeet is right about the multiple FileWriters. Use one, since its the same file.
Agree, sounds like a disaster.
When you use multiple writers to access the file, I would expect to get unpredictable results.
I dont think there is any guarantee that FileWriter1 would complete the task before FileWriter2.
In addition, the method is not synchronized.
At first I was going to make the question solely about the Image class, but I wanted to make it as broadly applicable as possible.
Basically, here's the scenario. I'm making a file for GUI constants, and in this file I'd like to have final variables for each of the Images I'm using. So my fields are declared like this UP_ARROW is:
public static final Image UP_ARROW;
Then I try to load them when the ImageIO API, like so:
static {
UP_ARROW = ImageIO.read(new File("img/upArrow.png"));
}
Unfortunately, this isn't valid, compilable code, because it explicitly throws IOException, which I have to deal with. So I modify it and surround it with a try/catch:
static {
try {
UP_ARROW = ImageIO.read(new File("img/upArrow.png"));
}
catch(IOException ioe) {
//TODO
}
}
Now I get a different compiler error. This time it says there's a possibility that the field may not have been initialized. Okay, that makes sense. Thank you for pointing that out to me, compiler. That seems like an easy fix:
static {
try {
UP_ARROW = ImageIO.read(new File("img/upArrow.png"));
}
catch(IOException ioe) {
UP_ARROW = null;
}
}
Now, no matter what, the UP_ARROW must be populated with either my image or null. I'm prepared to declare victory and move on. But now I get another, unexpected compiler error:
... Foiled again, compiler!
Hence the question: is there any way to get around this, such that I can dynamically load final fields at runtime? Or do I declare defeat and simply make the Images non-final?
Also, an explanation as to why the compiler won't allow this would be helpful as well. As I understand it, based on the code above, the UP_ARROW object could not have been assigned before reaching the catch{} block, because that's what must have thrown the exception. So if the try{} executes successfully, only one assignment takes place. If it does not execute successfully, still only one assignment take place. How is that not valid?
The following should do it:
static {
Image up_arrow = null;
try {
up_arrow = ImageIO.read(new File("img/upArrow.png"));
}
catch(IOException ioe) {
// log the error?
}
UP_ARROW = up_arrow;
}
It might make sense to enclose the final assignment in a finally block .
NPE's answer is good, but I think this one is (based off his and) better:
public enum Arrows {
UP ("img/upArrow.png"),
DOWN ("img/downArrow.png"),
LEFT ("img/leftArrow.png"),
RIGHT ("img/rightArrow.png");
public final Image myImage;
private Arrows(String fileName) {
Image tempImage;
try {
tempImage = ImageIO.read(new File(fileName));
} catch (IOException e) {
tempImage = null;
}
myImage = tempImage;
}
}
This solves your problem and gives you all the advantages of an enum over static final variables.
I am trying to write an imageloading function for my program, however it is doing something strange.
public void loadImage(BufferedImage img, String filepath) {
try {
img = ImageIO.read(new File(filepath));
}
catch (IOException e) {
}
}
And I am calling it like so:
BufferedImage background = null;
loadImage(background, path);
I see in debugging that img loads properly, but background remains null the whole time and causes a NullPointerException.
When I change to a direct reference to background like background = ImageIO.read(new File(filepath)); then it works just fine.
What's even more strange is that System.out.println(img == background) prints true.
What am I doing wrong?
This is because Java passes arguments by value, not reference. As far as Java is concerned, img from loadImage has nothing to do with background. All you did was pass over the address to whatever background refers to, not the reference background itself. background basically told the parameter img, "Hey, point at whatever I'm pointing at."
When you go
img = ImageIO.read(new File(filepath));
You've just set img to refer to some new object, but background will still refer to whatever it was referring to before.
Instead, you should return the BufferedImage and set background to the return value, so something like
public BufferedImage loadImage(String filepath) {
try {
return ImageIO.read(new File(filepath));
}
catch (IOException e) {
}
return null;
}
background = loadImage(path);
This previous question has a little more info on the Pass-by-Value vs Pass-by-Reference issue in Java. Personally, the idea of the value of references being passed took me a while to get it through my head until I read this article.
Hope this helps.
As for your second note that img == background returns true, I'm not sure where you are checking this, but if you check it before img = ImageIO..., that will return true, because img and background both refer to null, since they are uninitialized.
==, when dealing with two Objects, will return true if and only if they both refer to the same object in memory, not if they are the same exact reference.
I keep running into slight variations of a problem in Java and it's starting to get to me, and I can't really think of a proper way to get around it.
I have an object property that is final, but dynamic. That is, I want the value to be constant once assigned, but the value can be different each runtime. So I declare the class level variable at the beginning of the class - say private final FILE_NAME;. Then, in the constructor, I assign it a value - say FILE_NAME = buildFileName();
The problem begins when I have code in the buildFileName() method that throws an exception. So I try something like this in the constructor:
try{
FILE_NAME = buildFileName();
}
catch(Exception e){
...
System.exit(1);
}
Now I have an error - "The blank final field FILE_NAME may not have been initialized." This is where I start to get slightly annoyed at Java's strict compiler. I know that this won't be a problem because if it gets to the catch the program will exit... But the compiler doesn't know that and so doesn't allow this code. If I try to add a dummy assignment to the catch, I get - "The final field FILE_NAME may already have been assigned." I clearly can't assign a default value before the try-catch because I can only assign to it once.
Any ideas...?
How about
String tempName = null;
try{
tempName = buildFileName();
}
catch(Exception e){
...
System.exit(1);
}
FILE_NAME = tempName;
Either
try {
FILE_NAME = buildFileName();
} catch (Exception e){
...
System.exit(1);
throw new Error();
}
Or some prefer:
private static final String FILE_NAME = fileName();
private static String fileName() {
try {
return buildFileName();
} catch (Exception e){
...
System.exit(1);
throw new Error();
}
}
But calling System.exit in a static initialiser is probably a bad idea. It's going to mess your unit tests up.
On second thought, I think I just came up with a solution! - use an intermediate variable.
String fileName = null;
try{
fileName = buildFileName();
}
catch(Exception e){
...
System.exit(1);
}
FILE_NAME = fileName;
Don't know why it took me so long to think of this...
I would personally just throw an Error -- if your error flow is properly designed, the System.exit() should be redundant. Your program presumably doesn't plough on into the wilderness if an Error is thrown...?
Along the same lines as the OP's issue, I had to be able to find a way to assign values to final fields to be read in from a .properties file on the filesystem, so the values couldn't be known by my app until that happened. Using a generalized method call to assign the value after reading the content of the .properties file into a Properties object on app startup was a Hail Mary pass that thankfully worked out. It also limits the no. of times the file has to be read to once per the app's getting loaded into the memory simply by the code checking to see if the Properties object is or is not currently null. But of course, once assigned, the final field's value cannot be altered except by altering its "final" status via manuipulating the field's modifying definition at runtime (as discussed in some other places here on SO, such as https://stackoverflow.com/a/3301720/1216686 - sneaky, but I love it!). Code example, with typical runtime error checking such as for NPEs omitted for brevity:
import java.util.Properties;
public class MyConstants {
private static Properties props; // declared, not initialized,
// so it can still be set to
// an object reference.
public static String MY_STRING = getProperty("prop1name", "defaultval1");
public static int MY_INT = Integer.parseInt(getProperty("prop2name", "1"));
// more fields...
private static String getProperty(String name, String dflt) {
if ( props == null ) {
readProperties();
}
return props.getProperty(name, dflt);
}
private static void readProperties() {
props = new Properties(); // Use your fave way to read
// props from the file system; a permutation
// of Properties.load(...) worked for me.
}
// Testing...
public static void main(String[] args) {
System.out.println(MY_STRING);
System.out.println(MY_INT);
}
}
This lets you externalize properties to be read into the app and still mark the fields used to hold their values as "final". It also allows you to guarantee a returned value for the final field value since getProperty() in the Properties class allows the method's calling code to pass in a default value to use in case the property's key-value pair wasn't found in the external .properties file.