Java养成计划----学习打卡第六天
内容导航
Java入门到精通(打卡第六天)
学习内容
面向对象的习题总结
内容巩固,Java异常处理机制
内容管理
面向对象的习题总结
我们前面已经分享了很多Java的面向对象知识,了解了很多知识点诸如UML,Java类,特殊类包,封装,继承extends(单),多态(抽象类,上转型,abstract,重写,final,常量标准定义),接口interface(多继承),API,this,构造方法;super;static(静态环境),特殊类(容器类,String类—包装类)·········这么多知识点,你看看有哪个不理解赶紧去看看(⊙﹏⊙)
所以我们有必要联系巩固一下,我做的是《Java基础测试题(面向对象)》,这个题目只要不过时都是可以的,好了,我接下来会分享试题中考察的内容,看看xdm是否也不familiar with呢?
- 如过代码中有package(这是声明包的,封装哟)语句,则就应该放在第一行;但是import就不一定了(毕竟我们可以多次导入,都放一行岂不是作死);定义的public接口,接口名和文件名要相同额(接口就是一种特殊的抽象类,类就要求类名与文件名相同;就算多个,做主的那个也必须相同)
- 方法覆盖(重写)要求参数列表一致,(没说返回值要相同哦,xdm不要掉坑里了)访问呢?只可以升高或相同不可以降低这要怎么记住不至于弄错 emmm…拿个多态举例子吧,原本的是动物类我们在所有地方都可以访问,🐕也是动物啊,那如果缩小了,那我在那个地方岂不是不可见到🐕,但你发现牌子上写着“这里可以看到所有动物”,这岂不是打脸,;那如何理解这个可以升高呢,就是我们知道子类可以扩展,在继承父类的方法属性基础上还可以增加新方法,那访问权限扩大不也是它的新增的功能嘛,覆盖方法不能是private;这个就是因为private是类外不可见,这咋继承,引用都不可以,**抛出的异常不能更多 **异常机制里的
- 其实我们只要记住子类可以在父类基础上扩展就OK了
- 关于访问权限protected,它是包内友好且包外子类可见;
- 关于继承,子类可以继承父类所有非私有的方法和属性,不是全部都是可以继承额,私有的private只是类内可见
- 构造方法方法名要与类名相同
- 为实现重载,采用不同的参数列表,(方法名相同),重载之和方法名与参数列表有要求,和返回值类型没有关系
- super在构造函数第一行,先调用的是父类;所以子类一定会通过super调用父类的构造方法,隐式的也是通过super,子类可以继承普通方法,但子类是无法继承构造方法的,它只是会调用父类的构造方法(要明白继承的表现就理解了)
- 类方法可以用this调用本类的方法嘛? 这是错的,静态环境中只能有静态变量和方法,不能使用this和super关键字,this这个,那个岂不是乱套了
- 带参数的方法先定义再调用,方法返回值类型任意,参数数据类型任意,个数任意
- 再强调一遍,重载之和方法名和参数列表有关(返回值类型等不作为依据)因为在引用的时候只关注这两个,所以你void,int都可以重载
- 构造方法是没有返回值类型的,一旦有了void之类就变成了普通方法,这时程序执行还是按默认,null;
- 多层继承,super只能指代直接父类
- 上转型于变量对于直接与否没有要求,A an = new B();这里的B可以是子类,也可以是子类的子类,和super不同额
- 看继承时一定要仔细观察权限,private不能继承,会报错
- java中,this就是指当前对象,引用当前对象的关键字就是this了
- 自增运算符,在前面就是先自增再运算,后就是先运算再自增,但增的是变量,不是表达式的值
- 重写方法的返回类型(abstract)可以相同,也可以是子类
public Animal getInstance(){//这是父类的方法
return new Animal();
}
public Animal getInstance(){//方法名相同,参数列表相同,默认返回值类型相同,可以修改为子类
//return super.getInstance;
return new Dog();
}
在非静态的环境中,我们就直接使用this指代对象调用本类的变量方法
异常机制
看到这个次词语,你也许还不明白是什么意思,我们先来举一个例子:
小张每天开车就要开车去上班,耗时半个小时,这是正常情况;但是异常情况迟早会发生,万一今天堵车了怎么办,今天出车祸了怎么办;这就是异常情况
我们先上一段代码,简单一点,就输出了两个数相除的结果
package java_study;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入一个数:");
int num1 = in.nextInt();
System.out.println("请输入二个数:");
int num2 = in.nextInt();
int result = num1/num2;
System.out.println("商 is "+ result);
}
}
这就是一个简单的输出商的结果,但是我们如果把第二个数变成0会怎么样?我们知道在数学中这是不成立的
请输入一个数:
10
请输入二个数:
0
Exception in thread “main” java.lang.ArithmeticException: / by zero
at java_study.Main.main(Main.java:14)
这是我输入数字之后系统给的反馈,像这里就有一个exception / by zero ;这里的异常我们在编译时是检测不出来的,并且在程序运行过程中一旦有一个异常,接下来的代码都不可以执行,那在Java里就有专门处理解决这些问题,称为异常机制。
Java里面处理异常机制的主要就是先掌握五个关键字:try, catch, finally, throws, throw
try ----catch语句块,try是不能单独使用的,要结合catch一起
try是尝试,试图,就是将可能出现问题的代码先执行一下,如果正确就执行什么操作,错误执行什么操作
将可能出现问题的代码放在try语句块里面
try{
int result = num1/num2;
}
实践出真知,这里我就先只这样写,然后程序报错了
Syntax error: insert “finally” to complete the tryStatement;但这只是实践的结果,其实我们搭配使用的是catch配合使用
就是说try不能单独使用,要结合finally使用,就像上面所说的完成try的陈述;这里我们就是将可能出现异常的程序块包裹起来抛给我们的程序,没有异常就正常执行,有异常我们将异常给封装好抛给程序,然后我们就紧接着使用catch来抓取这个异常,我们定义一个异常对象来与之比较,如果是那个异常,那就执行catch里面的语句;
package java_study;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入一个数:");
int num1 = in.nextInt();
System.out.println("请输入二个数:");
int num2 = in.nextInt();
int result = 0;
try{
result = num1/num2;
}catch(ArithmeticException e){//定义异常类对象,不得不说,有很多情况
e.printStackTrace();//打印错误信息
}
System.out.println("商 is "+ result);
}
}
这里我们就定义了一个算数异常对象 e,如果try里面的代码真的有算数异常,那我们就要执行catch里的语句,那我们捕捉成功要怎么做呢,我们一般将错误信息打印出来,就是e.printStackTrace();
我们执行上面的操作得到的结果是
请输入一个数:
10
请输入二个数:
0
java.lang.ArithmeticException: / by zero
商is 0
at java_study.Main.main(Main.java:16)
和上面有上面不同发现了嘛,对,后面的代码执行了,因为我们的result为0,所以输出了商为0;
try里面的语句可以有很多条,其实我们这可以把整个放在里面执行,总之,这样之后不影响异常之后的语句的执行
当异常类型不匹配时,程序不会处理异常,程序还是会崩溃,后面的代码不能执行,上面我们也发现了,这个异常类是真的多啊。。。我怎么知道是哪个异常啊。。。别单行,我们还可以二次捕获,我们直接弄个异常类Exception,它是所有异常类的父类,我们直接catch它试试效果
try{
result = num1/num2;
}catch(Exception e){/
e.printStackTrace();//打印错误信息
}
这样之后我们还是处理了异常,这下就简单了,我们直接按照Exception匹配就好了,还有一点我们说过可以二次捕获;
try{
result = num1/num2;
}catch(ArithmeticException e){/
e.printStackTrace();//打印错误信息
}catch(Exception e){
e.printStackTrace();//打印错误信息
}
这种操作也是被允许的额
finally 它要和catch, try一起使用
finally的意思是最终最后的意思,意味着不管程序有没有异常在执行到finally时都会执行代码块里的内容,这里我们将它放在catch块的后面;
try {
result = num1/num2;//可能出现问题的代码
}catch(Exception e) {
e.printStackTrace();
}finally {
System.out.println("hello,Echo!");
}
System.out.println("商is "+ result);
执行结果是
请输入一个数:
10
请输入二个数:
4
hello,Echo!
商is 2请输入一个数:
10
请输入二个数:
0
java.lang.ArithmeticException: / by zero
hello,Echo!
at java_study.Main.main(Main.java:16)
商is 0
很容易就可以看出来finally就是强制执行语句,但是注意执行顺序不是在最后面,而是在try,catch块的后面
面试常问:如果try语句块里有return,还会执行finally里面的语句吗?
刚刚我们说过finally是强制执行语句,会执行的!!!,这里我就实践了一下,就在try里面加了一句return
请输入一个数:
10
请输入二个数:
4
hello,Echo!
看到了吧,还是执行了,只是我们的商是0没有执行了,所以这个冷知识一定要记住
回答对了,面试再问:finally语句是在return之前还是之后执行?
你觉得呢,当然是之前啊,如果是之后那不就卡bug了,return强制结束方法,效果是杠杠的,其实这里finally被执行是靠的识别:当没有return时,就正常执行就好了,当发现return时,程序给finally说:快动起来,方法要结束了,然后就先把finally执行了,然后就去执行return
回答又对了,那再来:我就不想执行finally,怎么做?
这里我们刚刚说过这个finally是一种强制的语句,都能摆脱return的查杀,那就一种方法,我直接断电,终止虚拟机,我们知道程序运行,JVM起了大作用,我们把JVM终止了,程序都瘫痪了,finally,return之流都就没用了,但是整个也都瘫痪了。就其实和异常没什么区别了,就只会执行终止之前的语句,后面的都不执行,finally也逃不掉
System.exit(1);//模拟终止虚拟机,关掉系统
throws
throws意为抛出,就是如果你的程序执行时可能出现异常,但是你又不想处理,那就用throws将其抛出,然后让调用者来处理这个异常,我们就在可能出现异常的方法前加上throws Exception
public static void divid() throws Exception{
System.out.println("请输入一个数:");
int num1 = in.nextInt();
System.out.println("请输入二个数:");
int num2 = in.nextInt();
int result = 0;
result = num1/num2;
System.out.println("商is "+ result);
}
//然后让调用它的函数来处理这个异常
比如main函数调用,但main函数还是不想处理然后抛出了呢,那就只能JVM处理了,怎么处理呢,中断程序
throw
自定义异常,就是我们自己定义,当出错时就往外面抛,但是我们在方法中使用了throw,那我们就必须在方法前加throws Exception,毕竟抛出了,不处理;
if(num2 == 0)
{
throw new Exception("除数为0是非法的");//在方法的前面加上throws Exception
}
我们常用的就是 try catch finally处理大礼包,throws 和throw都是不处理,甩锅还是少做为好,但是有的时候throws用的也挺多
再强调一下静态环境额,不然会出现这样的语句,还有就是不要忘记给无参的方法加括号了
Exception in thread “main” java.lang.Error: Unresolved compilation problem:
Cannot make a static reference to the non-static method DFS(int, int, int[], int) from the type LuoguTest
但是我们可以这样子访问本类的其他方法
- 我们创建一个本类的对象,然后通过这个对象调用非静态的方法
我觉得对于静态还有必要再说两句,因为我发现我之前的表达不够清晰
静态的深入理解
我们之前说过static修饰的方法叫做静态方法或者类方法,可以直接通过类来调用,非静态方法也叫做实例方法,可能因为不同的对象调用的方法不同。
所以说static变量,方法是属于类的,随着类的加载而加载,储存在静态内存单元中,是不需要实例化的,就是类存在的时候它就存在了
而非静态方法又叫实例方法,它是属于对象的,当我们没有创建对象的时候,这些方法都处于尘封状态,而在类的静态环境中去访问(类在它就在)非静态的方法,但是我们又并没有创建对象的时候,这些方法就是不存在的,既然不存在,我们如何访问?
而我们所说的访问就是本类中在不创建对象的情况下去调用方法,这个一般就是在简单的,需求少的题目,比如简单的算法题,只需要定义一个类时我们按照C的习惯的操作。
而非静态可以使用静态,因为静态一直都存在,和类同在
所以我们只会在一种情况下定义static方法,就是在没有成员变量,属性的时候;比如我们的驱动类,我们写的一些简单的算法题就可以只创建一个驱动类来执行就好了,这个类没有具体意义;
说了这么多,就是说,static属于类,实例方法属于实例(对象),我们要使用实例方法,当然就要有实例了呀,但是类没有意义,创建的对象的意义就不大了,这时我们想要的是访问而不是调用。那自然就不能用非静态的变量和方法了。