2021-01-24

1.抽象类extends
接口 implements
(引入接口的意义是为了实现类似于“多继承"的效果)
接口相当于是一种约束,要求了实现该接口的类,必须重写所有的接口中的抽象方法.
接口是一个非常有用的语法机制,如果所有的代码都是一个人完成,此时接口的意义就不大了,如果这个代码需要很多人协同开发完成,此时接口就非常具有意义.
每个人需要负责一部分模块.
模块和模块之间往往需要一些相互调用.
模块A需要给模块B提供一些类/方法进行使用.
实现A模块的程序猿就可以和实现B模块的程序猿,约定一系列的interface .
此时调用者就按照interface中约定的接口来去编写调用的代码.实现者再提供一些类来完成 interface的实现.
一个类可以实现多组接口,表示不同的约束条件,每个接口里面又可以有多个抽象的方法.
实现多个接口的时候,接口之间使用,进行分割.
2.接口和接口之间是可以继承的(说是"继承",表述成"组合")
3.接口的概念:
关键字interface声明一个接口,接口不是类,而是一组对类的需求描述。接口使抽象的概念更进一步,接口就像是一个成产类的工厂模具,实现类都必须按照他的要求去编译,或者说接口是建立类的协议。
4.接口的特性
  1)接口不能new一个对象,他不是类
  2)接口的方法没有body,既不能有{};
  3)实现类使用关键字implements实现对应接口。实现类必须实现接口的所有方法。
  4)接口的所有修饰字只能为public,接口不能有实例但是去可以声明接口变量,只不过变量必须指向实现类。
  5)接口不能有实例域但是可以定义常量。
  6)接口可以有多个实现类,实现类也可以引用多个接口,但抽象类的子类只能继承一个父类。
5.实参是调用的时候写不是在主函数中写

public Frog(string name) {
super(name)}

调用父类的构造方法,此处的name 对于super()就是实参

异常
一、
1.
java.lang.ArithmeticException(除以0)
java. lang.ArrayIndexOutOfBoundsException(数组下标越界)
java.lang.NullPointerException(访问null对象)
2.异常是程序运行过程中出现的一种错误
编译期:
在编译过程中,如果编译通过,一定不存在编译错误.(比如拼写错误)
运行时:
在运行过程中,如果你现在没有错误,不代表后面就没错误;你自己的机器上没错误,不代表别人的机器没错误…
数学上可以证明: 没有办法证明一段程序是没有bug的.
3.
异常其实是帮助我们解决问题的一种很好的手段.
异常的种类有很多,分别代表不同的含义,一旦出现某个异常,此时这个异常的意义是明确的,明确的告诉我们出现异常的原因.
相比之下,C/C++中存在很多的"未定义行为"

二、防御式编程
1.防御式编程有两种具体的代码的体现形式:
(1)LBYL: Look Before You Leap
操作之前就做充分的检查,检查完上一步之后,再来做下一步的操作,如果上一步失败,就不继续执行了.
(2)EAFP: lt’s Easerto Ask Forciveness than Permission
事后获取原谅比事前获取可更简单,先斩后奏
2.LBYL风格的代码(伪代码来表示)
(伪代码(Pseudocode)是一种非正式的,类似于英语结构的,用于描述模块结构图的语言。这是和"真实的代码”相对,真实的代码,一般都是要求语法正确,能顺利编译执行的,伪代码不严格要求语法格式,也不要求编译运行,只是大概表述这一段逻辑。使用伪代码的目的是使被描述的算法可以容易地以任何一种编程语言(Pascal,C,Java等)实现。)这种风格,在C,C++,Go中非常常见

boolean ret = login();
if (!ret){
//登陆失败的处理
return;
}
ret = startMatch();
if (!ret) {
//处理匹配失败
return;
}
ret = enterRoom();
if (!ret) {
//处理进入房间失败
return;
}
ret = chooseHero();
if (!ret){
//处理选择英雄失败
return;
}

3.EAFP风格的代码(代码简单清楚,把正常的逻辑和错误的处理逻辑明确区分开了)

  try {
Login();
startMatch();
enterRoom();
chooseHero();
...........
} catch (xxxx){
//处理异常的代码
}

如果执行到某一步出错,就会抛出异常,━旦抛出异常,就会进入catch这样的代码中执行异常处理逻辑
4.异常的基本用法
主要涉及到这么几个关键字:
try是try…catch…finally块中用来引导第一部分的关键字,用于声明需要捕获指定语句块的异常

 try {
        语句块1
} catch (<? extends Throwable> e) {
        语句块2.1
} catch (<? extends Throwable> e) {
        语句块2.2
} catch (<? extends Throwable> e) {
        语句块2.3
...
} finally {
        语句块3
}
try{ 
有可能出现异常的语句 ; 
}[catch (异常类型 异常对象) { 
} ... ] 
[finally { 
异常的出口 
}]

catch可以出现0次、1次或多次,finally可以出现0次或1次,但是catch和finally不能同时不出现。

(1)try : try语句块中放置可能会抛出异常的代码.
(2)catch: catch语句块中放置用来处理异常的代码. try和catch往往要搭配使用.当try 中出现异常的时候,就会进入catch中执行.
当语句块1中抛出异常时,立即离开语句块1,之后会在所有catch中依次进行类名比对。如果抛出异常和catch声明的异常类名一致,或抛出异常是catch声明的异常的子类,则会进入该catch的语句块(成为异常的捕获),在catch的语句块中可以将异常输出到命令行或引导用户进行问题反馈。如果任何一个catch都不匹配,会向上层调用抛出这一异常
(3)throw:主动抛出一个异常对象.(Java的异常本质上就是一个一个的对象)
(4)throws:某个方法可能会抛出某些异常.
(5)finally:一般用于异常处理完毕后的收尾工作.
在语句块1、语句块2中,任何试图离开try…catch…finally块的语句都会导致语句块3被执行,如return throw break continue。在finally的语句块中可以进行内存回收等工作。需要注意的是,如果导致离开的不是语句造成的,而是断电、内存不足等计算机故障,finally语句块不会被执行。
Eg:

public class A {
    public static void main(String[] args) {
        int i = 10;
        try {
            System.out.println(i/0);
        }catch(ArithmeticException ame){
            ame.printStackTrace();
        }finally{
            System.out.println("byebye");
        }
    }
}

结果:java.lang.ArithmeticException: / by zero
at A.main(A.java:5)
byebye

Process finished with exit code 0
例一:不处理异常
如果代码中出现了异常,并且没有使用try catch,异常就会由JVM自己来处理,程序就会被直接终止,不会继续往下走

      int[] arr = {1, 2, 3}; 
System.out.println("before"); 
System.out.println(arr[100]); 
System.out.println("after"); 
结果:before

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 100

例二:使用try catch 后的程序执行过程
代码中可以使用try把可能抛出异常的代码给包裹起来,使用catch来处理这样的异常.

       int[] arr = {1, 2, 3}; 
try { 
          System.out.println("before"); 
          System.out.println(arr[100]); 
          System.out.println("after"); 
} catch (ArrayIndexOutOfBoundsException e) { 
          // 打印出现异常的调用栈 
         e.printStackTrace(); 
} 
System.out.println("after try catch"); 

结果:before
java.lang.ArrayIndexOutOfBoundsException: 100
at demo02.Test.main(Test.java:10)
after try catch
try catch 的执行顺序
1.先执行 try 中的代码(按顺序执行)
2.执行 try 代码的过程中,如果出现异常,就会进入到catch执行, try中剩下的代码就不再执行了.
3.当catch也执行完毕之后,就会继续执行后续的代码.程序没有异常终止.
此处的e类似于一个形参.当try 的代码抛出异常之后,e就对应着这个异常.通过e就可以获取到异常的一些具体信息(哪个代码中出现了异常.)

异常的种类是很多的,对应的问题的原因也是不一样的,对于异常逻辑的处理,也不能一概而论.
对于现在这里看到的"打印异常信息",这是一个简单粗暴的处理异常的方式.
如果是比较严重的异常(致命级别)
例如和钱相关的程序,此时出现的异常就是比较严重的问题,与其把钱算错,还不如不算,直接让程序就终止.
如果是没那么严重的异常(错误/警告级别):
尝试进行一些恢复性的手段.连接某个服务器的时候,连接失败.可能是因为网络抖动导致,代码中自动尝试重新连接即可.
还有一些异常,没那么重要(提示级别):
记录日志,给程序猿一些报警提示.
(和编译,和语法没有任何关系,常见的“错误分级”"体系.
最严重的 Fatal比较严重的Error不太严重的Warning没啥事的Info/Notice)
调用栈:方法之间是存在相互调用关系的, 这种调用关系我们可以用 “调用栈” 来描述. 在 JVM 中有一块内存空间称为 “虚拟机栈” 专门存储方法之间的调用关系.,当代码中出现异常的时候, 我们就可以使用e.printStackTrace(); 的方式查看出现异常代码的调用栈.

例三:catch 中的异常的类型需要和抛出的异常类型匹配,才能够正确的处理,否则执行不到catch 中的逻辑.
如果 try中抛出的异常的类型和catch中声明的类型不匹配,此时catch中的代码就不会被执行到.
使用try catch的时候,必须要非常明确的知道, try 中都会抛出哪些异常.

try {
System.out.println( "try中异常之前的代码");
int[] a= {1,23};
System.out.print1n(a[100]);
system.out.print1n("try中异常之后的代码");
}catch(NullPointerException e){
system.out.println( "catch 中的代码");
}
System.out. println( "hello");

例四:如果try 中可能抛出多种异常的话,也就需要多个catch语句来进行处理.
1个try可以对应N个catch
多个catch之间就好像多分支语句一样.

try {
System.out.println( "try中异常之前的代码");
int[] a = {123};
System.out.print1n(a[100]);
System.out.println("try中异常之后的代码");
catch (NullPointerException e){
System.out.printin("catch空指针异常");.
catch (ArrayIndexoutOfBoundsException e){
System.out.printin("catch下标越界异常");_
}

例五:可以使用一个catch语句来捕获多个异常.

try {
System.out.println( "try中异常之前的代码");
int[] a= {1,2, 33;
System.out.println(a[100]);
System.out.print1n(try中异常之后的代码");
}catch (Nul1PointerException | ArrayIndexOutOfBoundsException e){
System.out.println(" catch异常");
}

使用│就可以把多个异常的类型并列起来.相当于“逻辑或"抛出这若干个异常中的任何一个,都会触发catch

try {
System.out.println("try中异常之前的代码");
int[] a= {12, 3};
System.out. println(a[1ee]);
System.out.println("try中异常之后的代码");
}catch (Exception e) {
system.out.println( " catch异常");
}
System.out.println( "hello");

这是一个级别很高的父类.
空指针异常和数组下标越界异常,都是Exception的子类.
一般不太建议使用Exception .
杀伤力太大,强行就把所有的异常都使用同一个逻辑来处理了.
在进行catch 的类型匹配的时候,不一定要求类型就完全一模一样,如果抛出的异常是catch 的参数的异常的之类,也是可以的,这个操作,本质上还是一个"向上转型"
Exception e = new NullPointerException0;
try catch在使用的时候会涉及到代码的跳转.
使用finally放到 try catch的后面, finally中的逻辑是保证一定会执行到的.这个finally 里面一般用来放一些"收尾"/"善后”的工作.

例六:

try {
System.out.println( "try 中异常之前的代码");
int[] a= {123};
System.out. println(a[0]);
system.out.print1n("try中异常之后的代码");
}catch (Exception e){
system.out.println(" catch异常");
}finally {
//finally中的逻辑无论是前面的代码中是否触发异常,都会执行到.
System.out.print1n( "finally ");
}

例如文件操作:需要先打开文件,再使用.用完再关闭.文件关闭操作就可以放到finally中.
再例如:多线程代码中经常涉及加锁.加锁之后,要记得解锁.如果由于抛出异常导致没有执行到解锁操作可能就会出现死锁的问题.也就可以把解锁操作也放到finally 中.

例七:使用finally回收资源确实是一个靠谱的办法,但是代码写起来比较麻烦还可以使用Java1.7提供的try with resource机制来完成这个操作.
如果 try中没有抛出异常,并且执行到了return,此时close操作就执行不到了.
如果改成finally,即使 try / catch中有return,也能保证执行到close

//此时当 try catch代码块执行完毕之后,就会自动针对scanner进行关闭
try ( Scanner scanner = new Scanner(System.in)) {
//使用Scanner来进行若干操作
}catch (NullPointerException e){
System.out.printin("空指针异常");
Scanner scanner - null;
try {
scanner -new Scanner(System.in);
//使用scanner 进行若干操作
return ;
}catch (Nul1PointerException e){
System.out.println("空指针异常");
}
//进行善后工作,比如,关团scanner
scanner.close();

IDEA 能自动检查我们的代码风格, 并给出一些更好的建议.
如我们之前写的代码, 在 try 上有一个 “加深底色” , 这时 IDEA 针对我们的代码提出了一些更好的建议. 此时把光标放在 try 上悬停, 会给出原因. 按下 alt + enter, 会弹出一个改进方案的弹窗. 我们选择其中的Replace with 'try" with resources就会自动调整代码

例八:如果当前方法中没有合适的catch,异常就会沿着调用栈,向上传递.

try {
func1();
}catch(ArrayIndexoutOfBoundsException e){
system.out.println("异常");
}
}
public static void func1(){
func2();
}
public static void func2(){
int[ ] a- {12,3};
System.out.println(a[100]);
}

例九:如果异常往上传递的过程中,一直到了最上面之后也没有人来catch, 此时就回到了例一,相当于没有合适的代码来catch 异常,此时异常就会由JVM自己来处理.JVM的异常处理的行为就是打印异常调用栈,并且程序直接终止.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值