java常见问题
- finally和return执行流程
代码:
public class TryCatchFinally {
// 测试try catch finally 流程
public void demo01(){
try{
System.out.println("try.............");
Integer.parseInt("java");
return;
}catch(Exception e){
System.out.println("catch...........");
e.printStackTrace();
}finally{
System.out.println("finally.........");
}
}
public static void main(String[] args) {
TryCatchFinally tryCatchFinally = new TryCatchFinally();
tryCatchFinally.demo01();
}
}
- try {}里有一个return 语句,那么紧跟在这个try 后的finally {}里的代码会不会被执行,
什么时候被执行
a. 不会执行
b. 会执行,在return 前执行
c. 会执行,在return 后执行
d. 会执行,可能在return 前执行,也可能在return 后执行
解析:try catch一般用于捕获异常
finally里边的代码无论是否发生异常,都会正常执行,一般用来释放资源,关闭资源(I/O流的关闭 和数据库资源的关闭)
没有抛异常的情况下,finally{}里的代码会在return之前被执行,用来释放资源
但是一旦出现异常,直接抛出异常 并执行finally{}中的语句,不会return;
扩展:数据库的connection为什么要关闭
代码
public class FinallyConn {
// 为什么conn一定要在finally关闭
public void demo01(){
Date date=new Date();
Connection conn=null;
try{
// 此处已经获取connection对象
conn = JDBCUtil.getConnection();
System.out.println("数据库连接对象为:" + conn);
System.out.println("---已经获取conn将执行CRUD操作---");
}catch(Exception e){
throw new RuntimeException(e);
}finally{
// 为什么一定要关闭
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
FinallyConn tryCatchFinally = new FinallyConn();
tryCatchFinally.demo01();
}
}
思考:在main函数最后出栈后,所有方法引用的对象资源被释放掉后,connection真的有必要关闭吗?
date和conn存放的不是对象本身,而是对象的引用,对用本身存储在堆中,当demo01()方法出栈后,对象引用即会被释放掉,从而connection对象和connection对象称为垃圾。
Object类中的方法 finalize()方法——当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法,子类重写finalize()方法,以配置系统资源或者执行其他清除。
connection对象比较特殊,一旦被创建,与数据库创建了连接,默认是open状态,所以即使没有引用指向该对象,但是它属于open状态,所以不会被垃圾回收。
所以connection对象资源必须被关闭。
eg:
mysql中 show processlist —展示当前连接数据库的进程
注意:在main方法中,程序执行完毕,整个java虚拟机都会被退出。整个运行期间申请的资源都会被关闭。所以该环境下,即使不释放connection,也会在程序运行结束释放数据库连接
但是如果在web项目中进行测试,web服务器不关闭,整个项目没有关闭,如果web服务器重启,资源才可能全部关闭。结合实际项目,有些应用服务器刚开始的运行速度还不错,但到后来越来越慢!(可能由于流和connection没有关闭)。
- OverLoad注意事项
- 能与public void methodA(){ }形成重载的有
a. private void methodA(){ }
b. private int methodA(){ return 1;}
c. public void methodA(int a){ }
d. public void methodA() throws Exception{ }
方法重载 :方法名称相同,不同的参数类型或参数数量
java虚拟机要判断调用哪个方法,是根据传入参数决定的,而根据返回结果return是做不到的 因为只有执行完毕后才会有返回结果,同时d的形式也无法区分调用哪个方法
/*
* Overload:相同的方法名,不同的参数类型或者参数数量.
* */
public class MethodOverload {
private void methodA() {
}
// private int methodA() {
// return 1;
// }
// public void methodA() throws Exception {
// }
public void methodA(int a) {
}
// public void methodA(int[] a) {
// System.out.println(a);
// }
//
public void methodA(int... a) {
System.out.println(a);
}
public static void main(String[] args) {
MethodOverload load = new MethodOverload();
// load.methodA(new int[] { 1, 2, 3 });
load.methodA(1,2,3);
}
}
注意public void methodA(int… a) 和public void methodA(int[] a) 本质 上都是传入参数为数组。
可变参数的本质就是以数组的形式传入(传可变参数比较书写简单,不需要new 数组对象)
扩展 override-重写
-五大注意事项
重写父类的方法
* 1: 方法名称、参数列表必须与被重写方法的相同(与父类一致)
* 2: 返回类型必须与被重写方法的返回类型相同(与父类一致)
* 3: 重写方法不能比被重写方法限制有更严格的访问级别 (比父类更高的访问级别)
* 4: 不能重写被标识为final的方法(比如Math类 就是final类型的 为准确的方法,不允许重写,如果你定义的类不希望被重写,可以定义为final 类型的 —方法、类都可以设置为final)
* 5: 重写方法不能抛出新的异常或者比被重写方法声明的检查异常更广的检查异常。但是可以抛出更少,更有限或者不抛出异常
class SuperClass {
protected void show1() throws SQLException {
}
}
public class SonClass extends SuperClass {
@Override
public void show1() throws SQLException {//此处重写的方法不能抛出比父类方法范围更大的异常,
//比如Exception,否则 在父类的引用可以指向子类的对象SuperClass superClass = new SonClass(); superClass.show1()在捕获异常时无法捕获比父类范围更大的异常,所以会有矛盾
super.show1();
}
}
class ExceptionDemo {
// 父类的引用可以指向子类的对象
private SuperClass superClass = new SonClass();
public void show1() {
try {
superClass.show1();
} catch (SQLException e) {
throw new RuntimeException();
}
}
}