面向对象以及捕捉异常需要注意的问题

来源:互联网 发布:杨潇 知乎 编辑:程序博客网 时间:2024/05/18 01:16

一、面向对象

1.instanceof运算符

instanceof运算符的前一个操作数通常是一个引用类型的变量,后一个操作数通常是一个类,用于判断前面的对象是否是后面的类或者其子类。

当编译器编辑Java程序时,编译器无法检查引用变量的实际引用对象的类型,它只检查该变量的编译类型。对于强制转型要求如下(使用instanceof也是如此):

☆在编译阶段,要想编译通过,则(1)被转型变量的编译时的类型与目标类型相同(2)被转型变量编译时的类型是目标类型的父类(3)被转型变量编译时的类型是目标类型的子类。因此如果被转型变量编译时的类型与目标类型没有任何继承关系,则编译器会提示编译错误。

☆在运行阶段,被转型变量所引用的对象的实际类型必须是目标类型的实例或者目标类型的子类,否则运行时会出现ClassCastException异常。


△关于instanceof还有一点即null调用instanceof返回值是false。因此instanceof可以保证第一个操作数所引用的对象不是null。

2.构造器

构造器不能声明返回值类型也不能使用void声明构造器没有返回值。在创建新的对象时,new关键字负责申请内存空间,构造器负责初始化对象。某些时候,Java创建对象时是不需要用构造器的,反序列化的方式恢复Java对象和使用clone方式复制Java对象这两种方式 是不需要构造器创建Java对象的,实例可以看一下上一篇博客。

3.构造器递归会导致java.lang.StackOverfowError。为了产生递归调用(1)尽量不要在定义实例变量时指定实例变量的值是当前类的实例(2)尽量不要在初始化块中创建当前类的实例(3)不要在构造器中调用本构造器创建Java对象。

4.调用重载方法

(1)jvm在识别方法时,可以对方法中的实参进行向上转型以适应被调方法的需要,注意是向上转型,即int可以转到double,但是double不可以转向int。

(2)Java重载解析过程首先jvm会选取所有可获得匹配调用的方法或者构造器,然后会选取最精准的一个,根据精准匹配的原则,如果某个方法的形参要求参数范围越小,则这个方法越精确。


5.方法重写

(1)对于private修饰的方法只能在当前类中访问该方法,因此子类无法访问父类中private修饰的方法,因此如果在子类中定义了一个和在父类中private修饰的方法名字形参列表等完全一样的方法,依然不是重写,只是在子类中定义了一个新的方法而已。

(2)如果父类中定义了使用默认访问控制符的方法(即不使用访问修饰控制符),则只有父类和子类在同一个包中时,子类可以重写该方法,否则不可以重写该方法。

6.内部类可以直接访问外部类的private成员。

非静态内部类必须寄生在外部类的实例中,没有外部类的对象就不可能产生非静态内部类的对象,因此非静态内部类不可能有无参构造器。

非静态内部类不能拥有静态成员。静态内部类不能访问外部类的非静态成员。

二、异常

1.正常关闭物理资源

垃圾回收机制只负责堆内存中分配出来的内存,对于物理资源,垃圾回收机制是不管的。因此程序中打开的一些物理资源比如数据库的连接、磁盘文件打开等都必须显示的关闭。

为了正常关闭程序中的物理资源,应该使用finally块来保证回收。比较安全的资源关闭方式要做到(1)使用finally块来关闭物理资源,保证关闭操作总是会发生(2)为每个物理资源使用单独的try-catch块来关闭资源来保证关闭资源时引发的异常不会影响其他资源的关闭。

finally{if(oos!=null){try{oos.close();}catch(Exception e){e.printStackTrace();}}if(ois!=null){try{ois.close();}catch(Exception e){e.printStackTrace();}}}
2.finally块

(1)finally块代表的是总会被执行的代码块,即不论try块是正常结束还是非正常的退出,finally都会被执行,但是如果在try块中调用System.exit(0),finally就不会再执行了,因为System.exit(0)将停止当前线程和所有其他死亡的线程。

(2)当Java程序执行try、catch时遇到return语句,return语句会导致该方法立即结束,但是执行完return语句后并不会立即返回,而是去寻找程序中的finally块,如果没有finally块,则程序会停止并且返回相应的返回值,如果有finally块,则程序会执行finally块里面的代码,如果finally里面没有return语句,则程序执行完finally块后就会返回到try或catch中的return语句进行返回并结束程序,如果finally里面有return语句,则finally里面的return语句将会导致程序结束,不会再返回到try或者catch中的return中去。

public class tttttt {public static int test(){int count=5;try{return count=count+1;//finally里面没有return,则从这里返回,返回值是6.}finally{count=count+1;//return count;加上return返回值是7,从这里返回}}public static void main(String[] args){System.out.println(test());}}
(3)当程序执行try、catch块时遇到throw语句时,throw语句会导致方法立即结束,但是不会立即抛出异常,而是先去查找有没有finally块,如果没有finally则立马抛出异常,如果有则开始执行finally,执行完finally后再抛出异常,当然如果finally块中有return语句结束的话,则系统不会抛出异常。

3.catch

一个try可以对应多个catch。但是如果try被执行一次,则try后只有一个catch会被执行,不同的catch针对不同的异常类,try后跟随的多个catch块是有顺序的。许多异常类之间有父子关系,捕捉父类的异常的catch要在捕捉子类的异常的catch块之后,即一定要先捕捉小异常再捕捉大异常。

4.Checked隐藏属于运行时异常,运行时异常对应的try块必须可能抛出xxx异常或者其子类异常,否则编译器会报错。

Runtime异常无需显示的抛出,程序可以在任何有需要的地方使用try-catch进行捕获Runtime异常。