Java中的异常与错误都继承自Throwable,Exception又分为运行时异常(RuntimeException)和编译时异常。

    运行时异常是程序的逻辑不够严谨或者特定条件下程序出现了错误,例如做除法运算时除数为0,运行时异常Java是不要求一定去try,catch进行捕获的。我们调试代码要减少的就是运行时异常,随着代码的调试运行时异常被捕获,程序的健壮性也就得到了提升。

    编译时异常例如文件未找到异常,IO异常,SQLException等,这些是可以预知的异常(checked Exception),不像运行时异常是unchecked Exception。我们的代码中进行文件读取,IO操作时就必须对这些异常进行捕获并做相应的处理。

     异常捕获后最起码的操作是记录日志,做到有据可查。必要时要抛出异常,让上层调用的代码知道这里已经出现了异常。

     方法中抛出新的异常用的是throw,方法声明抛出异常用的是throws,这也是要注意的。throw之后的代码都是不会执行的,会直接到catch或者finally中。

     子类方法抛出的异常只能比父类方法抛出的异常少或相等,子类方法抛出的也只能是父类方法抛出的异常或者其子类,而不能是其的父类。

     错误(Error)是指JVM的底层出现了错误,是程序所不能控制的,例如StackOverFlowError,OutOfMemoryError。

 

     抛出异常时要带上原异常的信息,可以如下定义自己的异常:

public class DaoException extends RuntimeException //继承RuntimeException的都是运行时异常
{

    ...
    public DaoException(String message, Throwable cause) {
        super(message, cause);
   }
    
}

     抛出异常时的代码,这里抛出的是运行时异常,引用该方法的地方不要求强制处理:

public static void updateObject(String sql, String[] params) throws DaoRuntimeException {
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
   conn = DBConnectionManager.getConnection();   
   pstmt = conn.prepareStatement(sql);

   for (int i = 0; params != null && i < params.length; i++) {
    pstmt.setString(i + 1, params[i]);
   }
   rs = pstmt.executeUpdate();

  } catch (Exception e) {
   logger.info("Execute sql : " + sql + " fail!!!");
   throw new DaoRuntimeException(e.getMessage(),e);
  } finally {
   DBConnectionManager.free(conn, pstmt, rs);
  }
 }

    文件加载常见的代码如下:

    InputStream is = new FileInputStream("src/test.properties");

    这样的写法是文件一旦换了路径还要修改,还有打包成运行程序时,是没有src目录的,这时也可以用下面的方法来加载文件:

    InputStream is = FileLoadTest.class.getClassLoader.getResourceAsStream(test.properties);

    这时只要test.properties在classpath下面即可,和具体的路径无关。

 

    new一个对象时,初始化的顺序是:静态变量和静态代码块,成员变量,构造方法。

public class Tests {
    
    private static Tests t = new Tests();
    private static String s = "d";
    public Tests(){
        s = "abc";
    }
    
    public static void main(String [ ] args) {
        System.out.println(s);        
    }
    
}

    上面的代码输出的结果是d,注意初始化的顺序就可以得到正确的结果了。

     

     同步方法锁住的是类本身的class,由于class只会有一个,也就是说一个同步方法锁住了class的话,该类中的其他同步方法就只能等待了。相比较如果使用同步代码块,不同方法可以锁不同的对象,冲突的机会要小一些。