Java:带有子类的try-catch块问题

时间:2017-06-12 12:59:38

标签: java eclipse nullpointerexception try-catch

我正在使用Java(Eclipse Neon)开发Web服务代码,我有两个用于数据分配操作的模型类,如下所示。

编辑器强迫我从类'ChatHistoryModel'的构造函数中删除try catch块,并带有消息: Unreachable catch block for JSONException。从不会从try语句中抛出此异常  体

如果我删除try-catch块,当数据分配操作无法分配数据(nil值)时,将导致代码崩溃。阻止if变量is_group_chat thorws 空指针异常

如何处理这种情况。

class TestHistoryModel extends TestModel {
    private Boolean is_read, is_group_chat;

    public TestHistoryModel(JSONObject jsonObject){

        super(jsonObject);
        try {

             // value assignment operations

          if (is_group_chat){  // Null pointer exception line

          }

        } catch (JSONException e) {   // Error line
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}



class TestModel {



    public TestModel(JSONObject jsonObject){

        try {

            // value assignment operations

        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

以下是类的catch块的错误快照 - TestHistoryModel

enter image description here

3 个答案:

答案 0 :(得分:2)

  1. 您正在获取"无法访问的捕获块"消息,因为JSONException是一个已检查的异常,并且您的try块中没有任何内容被声明为能够抛出该JSONException。因此,此异常将永远不会被抛入您的try块中,并且catch块从未使用过。
  2. 由于try catch块是不必要的,并且无法修复原始问题,您只需将其删除即可。

    1. 您正在获取NullPointerException,因为您正在使用null的Boolean对象,而Java将尝试将其自动装入一个小布尔值。
    2. 使其成为NullPointerException安全更改

      if (is_group_chat)
      

      if (Boolean.TRUE.equals(is_group_chat))
      

      如果is_group_chat仍然为null,则方法Boolean.TRUE.equals将返回false。

      你的try catch块可以删除,实际上是解决这个问题的错误方法。

      另一种解决方案是将is_group_chat更改为小boolean。但请记住,这些将使用false作为默认值进行初始化。

答案 1 :(得分:2)

1 JSONException

JSONException是一个检查异常。这意味着如果从未在try语句中抛出它,则无法捕获它。您可以根据需要将其删除。请阅读JLS Chapiter以获取更多信息。

2 NullPointerException

Boolean一样访问if(is_group_chat)实例相当于if(is_group_chat.booleanValue()),因为它为空,您得到NullPointerException

  1. 在检查实例之前检查实例是否为空
  2. 使用自动装箱课程的boolean insteand
  3. 请参阅OH GOD SPIDERS answer以查看替代条件

答案 2 :(得分:2)

在Java中,有两种类型的例外:已选中未选中。在Exception未选中时,已检查的例外情况从RuntimeException延伸。如果某个方法抛出了检查异常,那么该方法必须具有签名throws {SomeCheckedException},除非它在方法体中处理此异常。这样我们就说:要特别小心,这种方法可能会失败

以下是如何处理已检查的例外

的示例
public List<String> getFileLines(Path filePath) throws IOException {
    // this line is throwin checked exception "IOException" therefore, 
    // we need to rethrow this exception since it is not handled by try-catch
    // from this moment, exception handling will be left on "getFileLines" caller
    return readAllLines(filePath, StandardCharsets.UTF_8); 
}

public List<String> getFileLinesOrNull(Path filePath) {
    try {
        // here IOException is caught, so we don't have to rethrow this exception
        return readAllLines(filePath, StandardCharsets.UTF_8);
    } catch (IOException e) {
        return null; // return null if file reading failed...
    }
}

使用方法:

public void getFileLinesTest() {
    try {
        // we are forced to write try-catch since method signature contains "throws IOException"
        List<String> lines = getFileLines(somePath); 
    catch (IOException e) {
        System.out.println("Some error occurred");
    } 
}

public void getFileLinesOrNullTest() {
     List<String> lines = getFileLinesOrNull(somePath); 
     if (lines == null) {
         System.out.println("Something went wrong...");
     }
}

如果我们正在处理已检查的异常,但没有引发此异常的行,则代码将无法编译。编译器知道方法是否在签名中“抛出...”,因此编译器可以轻松识别这样的错误(因此我们称之为编译时异常这样的例外):

public List<String> getFileLines() {
    try {
        return Collections.emptyList();
    } catch (IOException e) {  // COMPILATION ERROR! 
        // handling checked exception, but Collections.emptyList(); does not throw IOException 
        // method signature of the Collections.emptyList() is following: 
        // public static List<E> emptyList(); 
        // as you can see there is no "throws IOException"
        return null;
    }
} 

以上示例,因为JSONExceptionException延伸,因此已检查异常,而在您的代码中,有没有在try块中抛出此类异常的行。

但是,TestHistoryModel构造函数正在抛出NullPointerException 未选中,因为它从RuntimeException延伸。这些异常在方法签名中没有“抛出”,因此编译器不会强制我们通过try-catch块处理这样的异常。这是一个例子:

public int getLength(String s) {
    if (s == null) {
        // NullPointerException extends from RuntimeException = we are not  forced to write 
        // add "throws NullPointerException " in getLength signature
        throw new NullPointerException();
    }
    return s.length();
}

处理运行时例外可选

public void getLengthTest() {
   int length = getLength(null); // will throw NullPointerException

   try {
       length = getLength(null);
   } catch(NullPointerException e) {
       System.out.println("null argument");
   }
}

注意,我们不必在if (s == null)方法中编写getLength,因为s.length()如果参数为NullPointerException,则会自动抛出null 我们正试图在null上调用方法。正是这种情况发生在你的构造函数中,因为这行if (is_group_chat)。字段is_group_chat具有Boolean类型。 Boolean 引用类型与{strong>基本类型 boolean不同。默认情况下,未初始化的“引用类型”变量为null。因此if (is_group_chat) if (null)正在投掷NullPointerException