I have question about #SneakyThrows can be used to sneakily throw checked exceptions without actually declaring this in your method's throws clause.
public class Demo {
public static void main(String[] args) {
}
private void throwE() throws ClassNotFoundException {
}
#SneakyThrows
private void t() {
throwE();
}
}
Here is generate by lombok.
public class Demo {
public Demo() {
}
public static void main(String[] args) throws IOException {
}
private void throwE() throws ClassNotFoundException {
}
private void t() {
try {
this.throwE();
} catch (Throwable var2) {
throw var2;
}
}
}
Why the code generate by lombok can fakes out the compiler without declaring throws clause.
See #SneakyThrows, it uses Lombok.sneakyThrow(t) and not var2:
public void run() {
try {
throw new Throwable();
} catch (Throwable t) {
throw Lombok.sneakyThrow(t);
}
}
The answer is that Lombok cheats the compiler - but what you've shown is a decompiled version of the compiled byte code - and the JVM running the byte code does not distinguish between checked and unchecked exceptions: it does not care.
If you take a look at Lombok.sneakyThrow() source code, you'll see that it eventually does two things:
A null check
A cast
Both are removed as part of the compilation, which is why your decompiled code simply rethrows the exception.
Related
I want to throw an exception (any type) in Java, but the restriction is that i can't add " throws Exception " to my main method. So i tried this:
import java.io.IOException;
class Util
{
#SuppressWarnings("unchecked")
private static <T extends Throwable> void throwException(Throwable exception, Object dummy) throws T
{
throw (T) exception;
}
public static void throwException(Throwable exception)
{
Util.<RuntimeException>throwException(exception, null);
}
}
public class Test
{
public static void met() {
Util.throwException(new IOException("This is an exception!"));
}
public static void main(String[] args)
{
System.out.println("->main");
try {
Test.met();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
This code works, but when i am trying to catch an "IOException", for examle, in try-catch block, it doesnt compile. The compiler tells me that IOException is never thrown. It works only for exceptions that extend RuntimeException. Is there a way to solve this?
Added:
import java.io.IOException;
class Util
{
#SuppressWarnings("unchecked")
private static <T extends Throwable> void throwException(Throwable exception, Object dummy) throws T
{
throw (T) exception;
}
public static void throwException(Throwable exception)
{
Util.<RuntimeException>throwException(exception, null);
}
}
public class Test
{
public static void met() { // this method's signature can't be changed
Util.throwException(new IOException("This is an exception!"));
}
public static void main(String[] args)
{
System.out.println("->main");
try {
Test.met();
} catch (IOException e) { // can't be changed and it does not compile right now
System.out.println(e.getMessage());
}
}
}
The simple answer: you can't.
The more complex answer: you can't, and you really shouldn't look to do this. The main reason being, if your code can catch exceptions that it's not advertised to, then that leads to inconsistency and bugs.
Above all, that code block isn't meant to catch anything other than an IOException; that is, the code is only meant to recover on something going haywire with IO. If I were to try and catch anything else, then that would imply that the code knows how to recover from that scenario, which is very much not the case.
As an aside, any children of IOException will be caught by that block, so you don't have to worry about catching FileNotFoundExecption, since that will handle it.
This is awful coding, and I feel dirty just writing it...
Instead of catch-ing the IOException directly, you can check that the caught Exception is an IOException.
public class Test
{
public static void main(String[] args)
{
System.out.println("->main");
try {
Test.met();
} catch (Exception e) {
if (e instanceof IOException) {
System.out.println(e.getMessage());
}
}
}
}
I would expect the following code to raise a compile-time error on throw t;, because main is not declared to throw Throwable, but it compiles successfully (in Java 1.7.0_45), and produces the output you would expect it to if that compile-time error was fixed.
public class Test {
public static void main(String[] args) {
try {
throw new NullPointerException();
} catch(Throwable t) {
System.out.println("Caught "+t);
throw t;
}
}
}
It also compiles if Throwable is changed to Exception.
This does not compile, as expected:
public class Test {
public static void main(String[] args) {
try {
throw new NullPointerException();
} catch(Throwable t) {
Throwable t2 = t;
System.out.println("Caught "+t2);
throw t2;
}
}
}
This compiles:
public class Test {
public static void main(String[] args) {
try {
throwsRuntimeException();
} catch(Throwable t) {
System.out.println("Caught "+t);
throw t;
}
}
public static void throwsRuntimeException() {
throw new NullPointerException();
}
}
This does not:
public class Test {
public static void main(String[] args) {
try {
throwsCheckedException();
} catch(Throwable t) {
System.out.println("Caught "+t);
throw t;
}
}
public static void throwsCheckedException() {
throw new java.io.IOException();
}
}
This compiles as well:
public class Test {
public static void main(String[] args) throws java.io.IOException {
try {
throwsIOException();
} catch(Throwable t) {
System.out.println("Caught "+t);
throw t;
}
}
public static void throwsIOException() throws java.io.IOException {
throw new java.io.IOException();
}
}
A more complex example - the checked exception is caught by an outer catch block, instead of being declared to be thrown. This compiles:
public class Test {
public static void main(String[] args) {
try {
try {
throwsIOException();
} catch(Throwable t) {
System.out.println("Caught "+t);
throw t;
}
} catch(java.io.IOException e) {
System.out.println("Caught IOException (outer block)");
}
}
public static void throwsIOException() throws java.io.IOException {
throw new java.io.IOException();
}
}
So there seems to be a special case to allow rethrowing exceptions when the compiler can determine that the caught exception is always legal to re-throw. Is this correct? Where is this specified in the JLS? Are there any other obscure corner-cases like this?
This is covered by JLS 11.2.2 (emphasis mine):
A throw statement whose thrown expression is a final or effectively final exception parameter of a catch clause C can throw an exception class E iff:
E is an exception class that the try block of the try statement which declares C can throw; and
E is assignment compatible with any of C's catchable exception classes; and
(...)
In other words, E, the type referenced in the doc, is the type that can be thrown, not the type of the catch clause parameter that catches it (the catchable exception class). It just has to be assignment compatible to the catch clause parameter, but the parameter's type is not used in analysis.
This is why the go out of their way to say a final or effectively final exception parameter--if t in your example were reassigned, the analysis would go out the window.
Because the compiler is smart enough to know that a checked exception can not be thrown from the try block, and the caught Throwable is thus not a checked exception that must be declared.
Note that this is true since Java 7, if I'm not mistaken.
When you catch Throwable or Exception and the variable is effectively final you can rethrow the same variable and the compiler will know which checked exceptions you could have thrown in the try {} catch block.
public class XGetProgramGuideDirectTestControllerCmdImpl extends ControllerCommandImpl implements XGetProgramGuideDirectTestControllerCmd {
public final String CLASSNAME = this.getClass().getName();
public void performExecute() throws ECException { /* code is here*/ }
private void callUSInterface() throws ECException { /* code is here*/ }
private void callDEInterface() throws ECException { /* code is here*/ }
private void callUKInterface() throws ECException { /* code is here*/ }
public void setRequestProperties(TypedProperty req) throws ECException { /* code is here*/ }
private void displayResponse(StringBuffer testResult) { /* code is here*/ }
public static void main(String[] args) {
XGetProgramGuideDirectTestControllerCmdImpl PGDirTestController = new XGetProgramGuideDirectTestControllerCmdImpl();
PGDirTestController.performExecute();
}
}
I'm simply trying to run this application as a java application in Eclipse-RAD using public static void main(String[] args) but it is giving me an error of:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type ECException
on:
PGDirTestController.performExecute();
Please go easy on me, I'm pretty new to Java still.
Since you declared:
public void performExecute() throws ECException
Then you are forced to deal with ECException.
So when you call it, you should surround it with try-catch or declare the method in which you call it to throw the exception:
public static void main(String[] args) {
XGetProgramGuideDirectTestControllerCmdImpl PGDirTestController = new
XGetProgramGuideDirectTestControllerCmdImpl();
try {
PGDirTestController.performExecute();
} catch(ECException e) {
e.printStackTrace();
//Handle the exception!
}
}
OR
public static void main(String[] args) throws ECException {
XGetProgramGuideDirectTestControllerCmdImpl PGDirTestController = new
XGetProgramGuideDirectTestControllerCmdImpl();
PGDirTestController.performExecute();
}
First, variables should start with lowercase as per Java convention, otherwise it's confusing:
XGetProgramGuideDirectTestControllerCmdImpl pGDirTestController = new XGetProgramGuideDirectTestControllerCmdImpl();
About your question, Unhandled exception type means this method throws an exception that's not a RuntimeException and you're not handling it. In Java, you must explicitly catch all exceptions that are not children of RuntimeException.
try {
pGDirTestController.performExecute();
} catch (final ECException e) {
// Do whatever you need to do if this exception is thrown
}
The catch part will be executed whenever an ECException is thrown. You should add code here to handle what to do if this exception is thrown. I strongly advise you against leaving this catch empty, because if the exception is thrown, you'll never know.
I strongly suggest you get a Java book/tutorial if you will be working with Java. This is very basic stuff, so you better understand this very well. Good luck.
Do we not need exception specification for the main method in a Java program. For example, the following code works exactly the same without specifying "throws Xcept" for the main method.
class Xcept extends Exception {
public Xcept(){
}
public Xcept(String msg){
super(msg);
}
}
public class MyException {
public void f() throws Xcept {
System.out.println("Exception from f()");
throw new Xcept("Simple Exception");
}
public static void main(String[] args) throws Xcept {
MyException sed = new MyException();
try {
sed.f();
} catch(Xcept e) {
e.printStackTrace();
}
finally {
System.out.println("Reached here");
}
}
}
I read that java enforces this, but I don't get a compile time error if I exclude this specification for the main method.
That's because Xcept will never be thrown out of your main method, as you actually catch it there... The sed.f() call may result in an Xcept being thrown, but it's caught and handled.
I have a test that expects a particular exception, for example:
#Test(expected=MyException.class)
public void testMyMethod(){
myMethod();
}
The myMethod() method actually throws a subclass of MyException, lets call it MySubclassException.
Is there anyway to define my test using the #Test annotation to accept subclasses of MyException as well as the class itself?
I know that I could simply write the test checking logic myself without using expected by catching the exception and setting a flag, but I was wondering whether or not JUnit already supported matching exception subclasses.
This is already handled for you by the framework
Let's take a small example (very bad code):
import static org.junit.Assert.*;
import org.junit.Test;
public class TestExpect {
#Test(expected=MyException.class)
public void test() throws MyException {
new Foo().foo();
}
}
With 2 exception classes MyException and MyExtendedException inheriting from the previous one and a simple Foo class like this one:
public class Foo {
public void foo() throws MyException{
throw new MyExtendedException();
}
}
Launching the test using the Eclipse runner prints a green bar because the test raises one instance of Myexception (is a relationship in POO)
If you prefer to read source code this is an exxcerpt from the Junit source code (ExpectException.java):
#Override
public void evaluate() throws Exception {
boolean complete = false;
try {
fNext.evaluate();
complete = true;
} catch (AssumptionViolatedException e) {
throw e;
} catch (Throwable e) {
if (!fExpected.isAssignableFrom(e.getClass())) {
String message= "Unexpected exception, expected<"
+ fExpected.getName() + "> but was<"
+ e.getClass().getName() + ">";
throw new Exception(message, e);
}
}
if (complete)
throw new AssertionError("Expected exception: "
+ fExpected.getName());
}
The test will pass if MyException or MySubclassException is thrown by myMethod(). I tested the concept with this code:
public class ExceptionTest {
private static class ExceptionA extends Exception {
}
private static class ExceptionB extends ExceptionA {
}
#Test(expected=ExceptionA.class)
public void test() throws Exception {
throw new ExceptionB();
}
}
BDD Style Solution with Catch Exception
#Test
public void testMyMethod() {
when(foo).myMethod();
then(caughtException()).isInstanceOf(MyException.class);
}
Dependencies
com.googlecode.catch-exception:catch-exception:1.2.0