10天-02-面向对象(异常-处理语句其他格式)
一、异常-处理语句的3种格式
第一种:
try{
}catch(){
}
第二种:
try{
}catch(){
}finally{
}
第三种:
try{
}finally{
}
² 记住一点:catch用于处理异常,如果没有catch就代表异常没有被处理过,如果该异常是检测异常,那么必须声明。
10天-03-面向对象(异常-覆盖时的异常特点)
二、异常在子父类覆盖中的体现:
1) 子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
2) 如果父类的方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
3) 如果父类或者接口的子集中没有抛出异常,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须要进行try处理,决不能抛。
10天-04-面向对象(异常-练习)
有一个圆形和长方形,度可以获取面积。对于面积如果出现非法的数值,视为是面积获取出现问题。问题通过异常来描述。
现在对这个程序进行基本设计。
class NoValueExceptionextends RuntimeException{
private Stringmessage;
private int value;
public NoValueException(String message) {
super(message);
}
public NoValueException(String message,int value) {
this(message+String.valueOf(value));
}
public NoValueException(String message,int value1,int value2) {
this(message+"("+String.valueOf(value1)+","+String.valueOf(value2)+")");
}
}
interface Shap{
void getArea();
}
class Rec implements Shap{
private int len,wid;
public Rec(int len,int wid)/*throwsNoValueException*/ {
if(len<=0 || wid<=0){
if(len<=0&&wid<=0){
throw new NoValueException("数值非法坐标:",len,wid);
}else if(len<=0){
throw new NoValueException("非法数值X坐标:",len);
}else{
throw new NoValueException("非法数值Y坐标:",wid);
}
}
this.len = len;
this.wid = wid;
}
public void getArea() {
System.out.println(len*wid);
}
}
class Circle implements Shap{
private int radius;
public static final double PI = 3.14;
public Circle(int radius) {
if(radius<=0){
throw new NoValueException("非法半径:",radius);
}
this.radius = radius;
}
public void getArea() {
System.out.println(radius*radius*PI);
}
}
public class ShapDemo {
public static void main(String[] args) {
// Rec r = new Rec(-2, -1);
// r.getArea();//不需要用try/catch
// System.out.println("over!");
Circle c = new Circle(-3);
c.getArea();
}
}
² 总结:在该视频的学习过程中,我觉得,异常信息不光只是打印出固定的提示信息,还应该更具体地报出出现异常时的值(或相关数值)。既然有了想法,就在控制台上经过了一番调试,我将继承RuntimeException异常的子类NoValueException的构造方法进行了重构,得到了理想的结果。在封装异常信息时我本想先将message= message+String.ValueOf(value);再super(message);可是,居然报错,原因,super(message);必须位于构造方法中的首行。我苦恼了一阵,终于想到了原来还可以这样:super(message+String.ValueOf(value));这么简洁的赋值,既把固定信息和值封装成了一条信息,又让super(…)位于了首行。虽然花费了一些时间思考,来满足自己的设计思路,但终究是值得的。看来无论做什么,勤学多练,举一反三,是很有必要的,小小的灵光,可能会获得意外的收获。光看视频不练习,编程的动手能力是会在一定程度上受到制约的,今后应该注意,不能太急于求成。
10天-05-面向对象(异常-总结)
三、异常总结补充:
一、异常的好处:
1. 将问题进行封装;
2. 将正常流程代码和问题处理代码相分离,方便于阅读。
二、异常的处理原则:
1. 处理方式有两种:try和throws;
2. 调用到抛出异常的功能时,抛出几个,就处理几个;
一个try对应多个catch。
3. 多个catch,父类的catch放到最下面。
4. catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace输出语句,
也不要写printStackTrace输出语句。
当捕捉到异常时,本功能处理不了,可以继续在catch中抛出。
try{
throw new AException();
}catch(AExceptione){
Throw e;
}
如果该异处理不了,但并不属于该功能出现的异常,可以将异常转换后,再抛出和该功能相关的异常。
或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,当调用者知道,并处理,也可以将捕获异常处理后,转换为新的异常。
try{
throw new AException();
}catch(AExceptione){
//对AException处理
throw new BException();
}
比如,汇款的例子。
三、异常的注意事项:
在子父类覆盖时:
1) 子类抛出的异常必须是父类的异常的子类或者子集。
2) 如果父类或者接口没有抛出异常时,子类覆盖出现异常,只能try不能抛。
3) 代码1演示:
class NoValueExceptionextends RuntimeException{
publicNoValueException(String message) {
super(message);
}
}
interface Shap1{
void getArea()throwsNoValueException;//接口方法上可以抛异常,第一次见。
}
class Rec1implements Shap1{
private int radius;
private static final double PI = 3.14;
public Rec1(int radius) {
this.radius = radius;
}
public void getArea1(){
if(radius<=0){
throw new NoValueException(“半径小于或等于零”);
}
System.out.println(radius*radius*PI);
}
}
代码2演示:
public void getArea1(){
try{
if(radius<=0){
throw new NoValueException("半径为零了");
}
System.out.println(radius*radius*PI);
}catch(NoValueException e){
// throw e;//<1>:<2>出注释1处
e.printStackTrace();//<2>:<1>处注释(2)不注释,也能在控制台上显示//异常信息。
}
System.out.println("over!");<3>
}
}
结果:
(1)注释上面<2>处代码,<1>不注释,此函数在主函数中运行时,当radius<=0时,显示结果只有异常信息,<3>处的代码未执行到。
(2)注释上面<1>处代码,<2>不注释,此函数在主函数中运行时,当radius<=0时,显示结果:异常信息输出换行后,还会显示:over!。
第二种结果分析:发生异常时,抛出了RuntimeException类或其子类异常,捕获异常后,程序不能终止,继续执行了try/catch语句后边的语句,这种情况以后应该注意。
总结:在进行异常处理时,应该正确规范书写形式(代码不要乱摆放),要不然会出现不可预计的后果。
10天-06-面向对象(练习四)
我对上一节的代码还是存有一些疑惑,但通过本节视频的试题讲解,对异常的认识进一步加深了,其次我还截取了几个我认为值得再多看一看的改错题,改错题如下:
(1)
public class Demo {
public static void func()/*throwsException*/{
try{
thrownew Exception();
}finally{
System.out.println("B");
}
}
public static void main(String[] args) {
try{
func();
System.out.println("A");
}catch(Exception e){
System.out.println("C");
}
System.out.println("D");
}
}
//编译失败:
//如果注释部分去掉,放上声明的异常,就对了,结果是:B C D
(3)
interface A{
}
class B implements A{
public String func(){
return"func";
}
}
public class Demo_2 implements A {
public static void main(String[] args) {
A a = new B();
System.out.println(a.func());
}
}
编译失败:因为A接口中未定义func方法。
(6)写出程序结果:
class Super{
int i = 0;
public Super(String a){
System.out.println("A");
i = 1;
}
public Super(){
System.out.println("B");
i+=2;
}
}
public class Demo_3 extends Super{
public Demo_3(String a){
//super();//默认会隐式地在子函数的构造函数的首行加一个父类无参构造方法引用。
System.out.println("C");
i = 5;
}
public static void main(String[] args) {
int i = 4;
Super d = new Demo_3("A");
System.out.println(d.i);
}
}
结果:
D
C
5
(14)
class Super1{
int i =0;
public Super1(String name){
i = 1;
}
}
class Demo1 extends Super1{
public Demo1(String name){
i = 2;
}
public static void main(String[] args) {
Demo1 d = new Demo1("yes");
System.out.println(d.i);
}
}
//编译会报错,原因:父类没有空参数的构造方法。
//或者子类应该通过super语句指定要调用的父类中的构造函数。
(13)
public class ExceptionExciseDemo_13 {
public static void func(){
try {
showExc();//<1>把抛出的异常封装到方法中,外部不知道,我只在函数上做个声明,
//这个声明叫做这个方法有可能出问题,也有可能不出问题,后面可以写语句。
//throw newException();//<2>这句直接抛出异常,由catch处理,try语句块后边的语句就不能执行,会编译报错。
System.out.println("A");
} catch (Exception e) {
System.out.println("B");
}
}
public static void showExc()throws Exception{
throw new Exception();
}
public static void main(String[] args) {
try{
func();
}catch(Exception e){
System.out.println("C");
}
System.out.println("D");
}
}
//编译能通过,原因,把抛出的异常封装成函数。但是如果不封装成函数,编译就不能通过,//看16题。
(16)
public class ExceptionExciseDemo_1 {
public static void func(){
try {
throw new Exception();
System.out.println("A");
} catch (Exception e) {
System.out.println("B");
}
}
public static void main(String[] args) {
try{
func();
}catch(Exception e){
System.out.println("C");
}
System.out.println("D");
}
}
//编译失败,因为打印"A"的输出语句执行不到。
² 记住:throw单独存在,下面不要定义语句,因为执行不到。
(17) public class ExceptionExciseDemo_17 {
public void func(){
//位置1
new Inner();
}
class Inner{}
public static void main(String[] args) {
ExceptionExciseDemo_17 d = new ExceptionExciseDemo_17();
//位置2
//new Inner();//不可以,因为主函数是静态的,如果访问Inner需要被static修饰。
}
}
//A.在位置1写 newInner();//OK
//B.在位置2写 newInner();//No
//C.在位置2写 new d.Inner();//错误:格式错误。 new //ExceptionExciseDemo_17().new Inner();
//D.在位置2写 new ExceptionExciseDemo_17.Inner;//错误,因为Inner不是静态//的。
(17)
interface Test1{
void func();
}
public class ExceptionExciseDemo_19 {
public static void main(String[] args) {
//补充代码(匿名内部类)
new ExceptionExciseDemo_19().show(
new Test1(){
publicvoid func() {
}
});
//注意,不可以像以下这样写,因为主函数是static的。
/*
show(
new Test1(){
public void func() {
}
});
*/
}
public void show(Test1 t){
t.func();
}
}
(20)
public class Test20 {
public static String output ="";
public static void foo(int i){
try{
if(i==1){
throw new Exception();
}
output += "1";
}catch(Exception e){
output +="2";
return;//如果此句注释掉,foo(1);的结果将是134234.
}finally{
output +="3";
}
output +="4";
}
public static void main(String[] args) {
foo(0);
System.out.println(output);
foo(1);
System.out.println(output);
}
}
结果:
134
13423
总结:本节的练习,好多一针见血,以后再回过来多看一看,一定还会有不小的收获。