0

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.

  • 3
    *"Code that will never run"* - well what if your code does indeed throw an `IOException` for some reason? Why are you so sure you will never ever be in the situation where the given filepath is simply... wrong? – Ben Jul 04 '18 at 06:17
  • 2
    Also: This is the "neat" way of doing it. Add a Javadoc comment explaining: *"@return the loaded image or null if the filepath did not point to an existing file"* – Ben Jul 04 '18 at 06:18
  • @user2864740 I think the error is only there if the last line `return null` is commented out (which is what they want to do as this line in their eyes never is going to be executed anyhow) – Ben Jul 04 '18 at 06:19
  • I am not sure. When the exception is thrown, does the compilation stop after the catch block? Or am I confusing that with putting fail("message") in my catch block? – stackUnderflow Jul 04 '18 at 06:19
  • @Ben Ah, good catch :} – user2864740 Jul 04 '18 at 06:19
  • This doesn't make any sense. There is nothing wrong here; your code would compile just fine and simply return `null` if an exception was thrown. Why would you think this would never execute? You caught the exception, so Java will print the stacktrace and then continue as if nothing went wrong... – Zephyr Jul 04 '18 at 06:19
  • 1
    @stackUnderflow the execution does not simply stop on the catch... a catch block is explicitely there so your application **does not stop** but has time to actually handle the issue. – Ben Jul 04 '18 at 06:20
  • Oh ok I see. So in that case, how would I make it so that the execution **does** stop if an exception is thrown? – stackUnderflow Jul 04 '18 at 06:21
  • Just add `thow e;` to your `catch` block. That will print the exception and then throw it back out to your main method, causing the method to fail. You will need to change your method a bit, though, to declare that it may throw an exception. Lots of questions here.... – Zephyr Jul 04 '18 at 06:21
  • The catch block "catches" the exception, and then continues to execute the remaining code. You could of course, just throw the exception upwards so you will always return an Image, or throw an exception – Lino Jul 04 '18 at 06:22
  • If you wouldn't catch the exception but throw it then there would be no need for an additional `return` at the end. – LuCio Jul 04 '18 at 06:22
  • If you want the program to terminate, don't catch the exception. The whole point of catching an exception is saying "I can handle this." – Silvio Mayolo Jul 04 '18 at 06:22
  • Errors cannot be suppressed. Warnings should only be suppressed if you fully understand what the compiler is telling you, and can reason that it is safe, *and there is no way to rewrite the code to avoid it*. These messages from the compiler are there to help you, and should not be casually ignored. – Andy Turner Jul 04 '18 at 06:38

2 Answers2

0

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.

Lino
  • 19,604
  • 6
  • 47
  • 65
  • Though the intent is clear, there are two syntax errors in the first code sample. It should be: `return ImageIO.read(clazz.getResource(filePath));` – LuCio Jul 04 '18 at 06:52
-1

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.

  • This will not work either. You need to declare that your `getImage()` method might throw an `Exception`. So `public static Image getImage(String filepath, Class cl) throws IOException {`. However, this just means you'll need another `try/catch` block in your code where you call `getImage()` – Zephyr Jul 04 '18 at 06:25
  • 3
    If you catch and throw the exception without any additional handling, you do not need to catch it at all. This would give: `public static Image getImage(String filepath, Class cl) throws IOException { return ImageIO.read(cl.getResource(filepath)); }` – LuCio Jul 04 '18 at 06:26
  • When a method throws an exception, it is basically saying "Something went wrong and I don't know what to do; YOU handle it!" So the code that calls the method now has to deal with the problem. Eventually, you need to handle the Exception in your code... – Zephyr Jul 04 '18 at 06:26
  • @LuCio That is not true. Whatever method is calling the `getImage()` method would then have to catch the exception. – Zephyr Jul 04 '18 at 06:27
  • @Zephyr You're absolutely right. This is really annoying. – stackUnderflow Jul 04 '18 at 06:27
  • There is no gravity in Java. If something is thrown, it does not come down; it has to be caught by someone, somewhere :) – Zephyr Jul 04 '18 at 06:28
  • Especially because I am assigning a static field to the value that is returned by the method – stackUnderflow Jul 04 '18 at 06:28
  • If at some point I have to catch the exception, what should I do with it? – stackUnderflow Jul 04 '18 at 06:29
  • @stackUnderflow Just leave the `return null;` line for now. Then in your calling code, you can check if something went wrong by using a simple `if` statement: `if (getImage("file.png") == null) { //Something went wrong }` – Zephyr Jul 04 '18 at 06:29
  • Is there a way to just have the compilation stop and crash if the exception is thrown? That sounds like bad design, but if the image doesn't load, then I can't exactly play a game without images. – stackUnderflow Jul 04 '18 at 06:30
  • Sort of like fail("Message") with JUnit tests – stackUnderflow Jul 04 '18 at 06:30
  • Well, sure, if the Exception is thrown, you could add your own error message to the `catch` block and then run `System.exit(0);` to end the program. Usually, you would want to display an error to the user and possibly ask them to provide the location of the file, though. – Zephyr Jul 04 '18 at 06:31
  • @Zephyr not sure if returning null is better than to throw an exception. – Lino Jul 04 '18 at 06:31
  • 2
    @Zephyr Yes - but in the above case too - only the exception declaration in the method signature is missing. It gives an compile time error. It should be: `public static Image getImage(String filepath, Class cl) throws IOException {...}`. So my suggestion is shorter but changes nothing. – LuCio Jul 04 '18 at 06:31
  • @Zephyr OK I will do just that. Although I might want to pass a different parameter than 0 since it is not exiting normally. Thank you very much for your help – stackUnderflow Jul 04 '18 at 06:33
  • 1
    @Zephyr I would say it is less confusing since nobody has to wonder for what purpose the catch was defined. It has no additional value. – LuCio Jul 04 '18 at 06:33
  • Ummm... It still didn't work. My code looks like this: public static Image getImage(String filepath, Class cl) { try { return ImageIO.read(cl.getResource(filepath)); } catch (IOException e) { System.out.println(e.getMessage()); e.printStackTrace(); System.exit(-1); } } And I still get missing return statement warning – stackUnderflow Jul 04 '18 at 06:37
  • I assume that is because the Java compiler does not recognize the `System.exit()` method as a full stop to the application. Add the `return null;` to your `catch` block or just outside of it. – Zephyr Jul 04 '18 at 06:40
  • Great explanation to that is found here: https://stackoverflow.com/questions/11487184/why-is-return-needed-even-after-system-exit0 - Basically, Java sees `System.exit()` as just another method call; it does not know or check what it does ... – Zephyr Jul 04 '18 at 06:41