I'm currently developing an Android app using Android Studio and I encountered an error that I can't understand. Here's an example of my code :
public class MyClass {
public void method1() throws MyException {
methodIO(); // Unhandled Exception: java.io.IOException
methodRun(); // OK
}
public void method2() throws Exception {
methodIO(); // OK
methodRun(); // OK
}
public void methodIO() throws IOException {}
public void methodRun() throws RuntimeException {}
}
class MyException extends Exception {
public MyException(){super();}
public MyException(String message, int errorCode) {
super(message);
}
}
I can't figure out why in method1(), I have the following error "Unhandled Exception: java.io.IOException" while method2() compiles fine. The issue doesn't appear with a method throwing a RuntimeException even if both classes are inheritd from Exception. Does someone know what's going on here ?
Ps : I'd like to avoid using a try/catch bloc or adding a new throws clause
MyException doesn't extend IOException, so the IOException thrown by methodIO isn't handled currently.
It works in method2 because Exception is a common superclass of IOException and MyException, so it specifies how both types of exception should be handled.
Add it to the throws clause of method1:
public void method1() throws MyException, IOException {
or catch in the method body:
public void method1() throws MyException {
try {
methodIO();
} catch (IOException e) {
// Handle appropriately.
}
}
method2() has a throws declaration for the base type Exception, of which IOException is a derived type; whereas method1() throws a MyException, which IOException does not derive from. Add IOException to the throws declaration of method1():
public void method1() throws MyException, IOException {
methodIO();
}
or you could always catch the IOException and throw a MyException instead:
public void method1() throws MyException {
try {
methodIO();
} catch (IOException e) {
throw new MyException();//construct MyException however; this is just an example
}
}
Related
I have created below User Defined Exception (MyException) class which extends Exception, Now I manually try to create a NullPointerException, But instead of throwing (MyException), it throws the same Generic(NullPointerException) Exception
public class Sample {
public static void main(String[] args) throws MyException {
String a = null;
callMethod(a);
}
public static void callMethod(String a) throws MyException {
a.toString();
}
}
public class MyException extends Exception {
public MyException(String exception)
{
super(exception);
}
}
Below is the Exception I'm getting
Exception in thread "main" java.lang.NullPointerException
at Sample.callMethod(Sample.java:9)
at Sample.main(Sample.java:5)
Process finished with exit code 1
The fact that you declare that a method throws an exception does not mean it will throw that exception when any other exception is thrown in the code.
In this case, a is null so the exception that's thrown is a NullPointerException. If you wanted to throw your custom exception you would have to check whether your value is null and throw your custom exception, like this
public static void callMethod(String a) throws MyException {
if (a == null) {
throw new MyException(e);
}
a.toString();
}
Declaring that a method throws MyException means that it may throw that exception.
It does not mean that all thrown exceptions automatically get wrapped in your MyException
Using throws MyException does mean that the method can throw an exception and u need to handle it, but it doesn't mean every exception u get inside the method will be thrown as MyException. If u want to throw every Exception u get as MyException you can do :
public static void main(String[] args) throws MyException {
try{
String a = null;
callMethod(a);
}catch(Exception e){
throw new MyException(...);
}
}
I don't think I understand the try-catch block and throws really.
public class TestException {
public static void main(String[] args) {
new TestException().tt();
}
public void tt() {
try {
throw new RuntimeException();
}catch (Exception e) {
throw e;
}
}
}
When in Eclipse, there is an error hint about 'Unhandled exception type xxx', and if you run this, you will get an
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type Exception
But in Idea, there's no errors. It runs and throws the exception correctly.
In my opnion, the 'e' was not declared as a RuntimeException(althrough it is an RuntimeException), so the tt() method must be declared with throws. But actually it's not. Why?
This should answer your question:
public class TestException {
public static void main(String[] args) {
new TestException().tt();
}
public void tt() {
try {
throw new RuntimeException();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
If you use throws, you tell those who use your function, "My function may throw exceptions. You have to handle that."
You should get difference of throws and throw in this sentence.
If you use try-catch, you handle that exception.
1) You should add throws keyword like below
public class TestException {
public static void main(String[] args) {
new TestException().tt();
}
public void tt() **throws Exception** {
try {
throw new RuntimeException();
}catch (Exception e) {
throw e;
}
}
}
2) Handle exception where you use function
public class TestException {
public static void main(String[] args) {
try{
new TestException().tt();
}catch(Exception e){
System.out.println("Error handled");
}
}
public void tt() throws Exception {
try {
throw new RuntimeException();
}catch (Exception e) {
throw e;
}
}
}
In general if you catch an exception you handle it. Like this
public class TestException {
public static void main(String[] args) {
new TestException().tt();
}
public void tt() {
try {
throw new RuntimeException();
}catch (Exception e) {
System.out.println("Error caught! ")
}
}
}
or
public class TestException {
public static void main(String[] args) {
try {
new TestException().tt();
}catch(Exception e){
System.out.println("Error caught! ")
}
}
public void tt() throws RuntimeException {
throw new RuntimeException();
}
}
You can also throw other's exception
public class TestException {
public static void main(String[] args) {
try{
new TestException().a();
}catch(Exception e){
System.out.println("Error handled");
}
}
public void a() throws Exception {
b();
}
public void b() throws Exception {
c();
}
public void c() throws Exception {
throw new RuntimeException();
}
}
I think that you want to look into 'Checked Exceptions' and 'Unchecked Exceptions'.
Only Checked Exceptions need to be declared in a methods signature, and RuntimeException is an unchecked exception (though you can declare it if you like - it just isn't necessary to compile).
https://docs.oracle.com/javase/7/docs/api/java/lang/Exception.html
The API for java Exception says:
"The class Exception and any subclasses that are not also subclasses of RuntimeException are checked exceptions. Checked exceptions need to be declared in a method or constructor's throws clause if they can be thrown by the execution of the method or constructor and propagate outside the method or constructor boundary"
https://docs.oracle.com/javase/7/docs/api/java/lang/RuntimeException.html
The API for java RuntimeException says:
"RuntimeException and its subclasses are unchecked exceptions. Unchecked exceptions do not need to be declared in a method or constructor's throws clause if they can be thrown by the execution of the method or constructor and propagate outside the method or constructor boundary."
In my opnion, the 'e' was not declared as a RuntimeException(althrough it is an RuntimeException), so the tt() method must be declared with throws. But actually it's not. Why?
Let's consider what we know:
When using rethrow syntax, the existing exception object (e) is rethrown.
e is an object of class Exception, or one of its subtypes.
RuntimeException is a subtype of exception, and is not compiled time checked, so it's possible the re-thrown object is a non compile time checked object.
The compiler cannot see a place where the code definitely, or even possibly throws a compile checked exception, and so it makes sense that it does not force those semantics.
For example, if you change your catch to an IOException, the compiler will not allow you to do that without a line in the try which could possibly lead to an IOException.
If you added such a line, then the compiler would recognize that the throw would rethrow a compile time checked exception, and make you catch it again, or mark the function with the appropriate throws clause.
As for eclipse, your code compiles OK in mine with my JDK.
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 know that we have to define methods with the following signatures to override the default serialization process:
private void writeObject(ObjectOutputStream os) {
}
private void readObject(ObjectInputStream is) {
}
Are there any restrictions on the type of exceptions which can be thrown by the above methods? I know that exceptions thrown by a method are not part of method signature but wanted to confirm.
Serializable defines the following exceptions:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
This is where the write method gets called:
try {
writeObjectMethod.invoke(obj, new Object[]{ out });
} catch (InvocationTargetException ex) {
Throwable th = ex.getTargetException();
if (th instanceof IOException) {
throw (IOException) th;
} else {
throwMiscException(th);
}
}
// ...
private static void throwMiscException(Throwable th) throws IOException {
if (th instanceof RuntimeException) {
throw (RuntimeException) th;
} else if (th instanceof Error) {
throw (Error) th;
} else {
IOException ex = new IOException("unexpected exception type");
ex.initCause(th);
throw ex;
}
}
As you can see you can throw any non-runtime exception and it will be wrapped in an IOException, though you should prefer IOExceptions due to shorter stack traces and more useful error messages.
I assume the read method gets called similarly, you might want to check it yourself though.
You can throw any RuntimeException in both Methods
In writeObject(ObjectOutputStream out) you can also throw IOException
In readObject(ObjectInputStream in) yu can also throw IOException and ClassNotFoundException
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.