1、异常
Throwsable--异常的顶级父类
---Error--系统异常,我们解决不了,比如:栈溢出异常
---Exception--可以通过编程解决的异常
--编译时异常--比如:括号写错了,压根就不通过编译
--运行时异常--RunTimeException--比如:输入不匹配异常/算术异常
2、异常的处理方案:
1).捕获处理
格式: try{
可能会出现异常的代码
}catch(Exception e){//我们预测到可能会发生的异常类型
解决方案
}
TIPS:catch捕获处理异常是可以嵌套的
一般用Exception首尾,担心会有未想到的其他异常,所以做通用解决方案,也可以只写一个Exception,那么其他异常均不作特殊处理,统一处理。
2).向上抛出 throws
格式:在方法声明的两个括号之间,加 “throws 异常类型1,异常类型2,...”,多个异常类型用逗号隔开
注意:不能把问题抛给main(),因为没有人解决了,所以要在main()调用之前解决
比如案例中:method3()会抛出异常,所以先用f()调用method3捕获处理异常
再由main()调用f()执行method3()的功能
f()的作用:f()用来捕获处理method3()的异常
练习:异常测试
package cn.tedu.exception;
import java.util.InputMismatchException;
import java.util.Scanner;
/*本类用作测试异常的入门案例*/
public class ExceptionDemo {
public static void main(String[] args) {
//method1();//调用method1方法--人为暴露异常--简单看看异常长什么样
method2();//调用method2方法--异常解决方案1--捕获处理--自己解决
// method3();//调用method3--异常解决方案2--向上抛出--交给调用
f();//为了写一个标准的写法,在main()调用之前解决异常
}
private static void f() {
try{
method3();
}catch (Exception e){
System.out.println("请输入正确的数据!");
}
}
/*如果一个方法抛出了异常,那么谁调用这个方法,谁就需要处理这个异常
* 这里的处理也有两种方案:捕获解决和继续向上抛出
* 但是注意:我们一般会在main()调用之前解决异常
* 而不是把问题抛给main()方法,因为没人解决了,详见本类f()调用method3()*/
//6.创建method3(),异常解决方案2
/*异常抛出的格式:在小括号与大括号之间写:throws 异常类型1,异常类型2,...
*若有多个异常,使用逗号隔开*/
private static void method3()
throws InputMismatchException,ArithmeticException,Exception {
//7.1复写刚刚的代码
System.out.println("请输入你要计算的一个整数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请输入你要计算的第二个整数");
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
}
/*异常捕获处理的格式:
* try{
* 可能会抛出异常的代码
* }catch(异常类型 异常的名字){
* 捕获到了异常,进行处理的解决方案
* }
* */
//创建方法用来捕获处理异常--自己处理
private static void method2() {
//5.按照捕获处理的语法提供异常解决方案1
/*4.try中放着的是可能会出现异常的代码
* 5.如果发生异常,就会被捕获,执行之前catch中提供的解决方案*/
try{
//5.2复写刚刚的代码
System.out.println("请输入你要计算的一个整数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请输入你要计算的第二个整数");
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
}//catch(InputMismatchException e){//注意:异常类型要导包import class
// System.out.println("请输入规定的整数类型!");
// }catch(ArithmeticException e){
// System.out.println("除数不能为0,请重新输入");
// }
catch(Exception e){//可以直接使用Exception异常类型进行捕获处理,因为它包含--RunTimeException、ClassCastException、ClassNotFoundException
System.out.println("您输入的不对!请重新输入!");
}
/*6.try-catch可以嵌套,若有多种异常类型需要特殊处理的话
*7.这就是多态最为经典的一种用法,我们并不关心子类的具体类型
* 而是将所有子类统一当作父类类型来处理,提供通用的解决方案*/
}
private static void method1() {
//.提示并接收用户输入的第一个数
System.out.println("请输入你要计算的一个整数:");
int a = new Scanner(System.in).nextInt();
//2.提示并接受用户输入的第二个整数
System.out.println("请输入你要计算的第二个整数");
int b = new Scanner(System.in).nextInt();
//3.直接打印这两个数除法的结果
System.out.println(a/b);
//输入3和3.2,报错:InputMismatchException--输入不匹配异常
//输入17和0,报错:ArithmeticException--算术异常,除数不能为零是数学规定
/*1.不要害怕BUG,真正的勇士敢于直面自己写的BUG
* 2.学会看报错的信息提示,确定自己的错误方向
* 3.学会看报错的行号信息,确认自己报错的位置,哪里不对点哪里
* 注意:源码不会错,要看的是自己写的代码*/
}
}
2.抽象类
abstract 关键字
分为:
1).修饰类--被abstact修饰的类是抽象类
2).修饰方法--被abstract修饰的方法是抽象方法(指的是对普通方法的修饰)
格式:
注意:没有方法体
1》有抽象方法的类一定是抽象类,但是抽象类可以没有抽象方法
2》抽象类中既可以都是普通方法,也可以都是抽象方法,还可以混着来
3》抽象类不可以实例化(创建自己的对象),但是抽象类有构造方法,为了子类创建对象时调用
4》如果一个类继承了抽象类,那么:
方案一:继续抽象,作为抽象子类
方案二:实现抽象父类中的(所有!!!)抽象方法
5》创建时如果想使用父类,那么可以创建多态父类对象进行测试
练习:抽象类测试的入门案例
package cn.tedu.oop;
/*本类用于抽象类测试的入门案例*/
public class AbstractDemo {
public static void main(String[] args) {
/*4.抽象类不可以实例化(创建对象)!!!*/
//5.1测试抽象父类是否可以创建对象
//Animal a = new Animal();//不可以
//5.2创建多态对象进行测试
Animal a = new Pig();
a.eat();//调用抽象父类普通方法--可以
a.fly();//调用抽象父类抽象方法--可以
}
}
//1.创建父类Animal
/*2.被abstract修饰的类是抽象类
* 若一类中包含抽象方法,那这个类必须被声明成抽象类*/
//4.2添加抽象方法后,此类必须也变成抽象类
abstract class Animal{
//3.创建普通方法--功能
public void eat(){
System.out.println("吃啥都行~");
}
public void play(){
System.out.println("玩啥都行!!");
}
//4.1创建抽象方法
/*1.被abstract修饰的方法是抽象方法,且抽象方法没有方法体*/
public abstract void fly();
public abstract void fly2();
}
//2.创建子类Pig,继承父类Animal
/*3.当一个子类继承了抽象父类以后,有两种解决方案:
* 方案一:变成抽象类,“子类也不实现,继续抽象”
* 方案二:实现抽象父类中的所有抽象方法,“父债子偿”*/
//4.3子类需要处理。继续抽象/实现父类所有抽象方法
//abstract class Pig extends Animal{//方案一:子类也变成抽象类
class Pig extends Animal{//方案二:implement method()
@Override//注解,标识这是一个重写的方法
public void fly() {
System.out.println("父债子偿");
}
@Override
public void fly2() {
System.out.println("抽象父类中的所有抽象方法都需要子类来实现");
}
}
练习:抽象类中建立成员变量、final常量和普通方法
package cn.tedu.oop;
/*本类用于抽象类中的成员测试*/
public class AbstractDemo3 {
}
//1.创建抽象父类Fruit
abstract class Fruit{
/*1.抽象类中可以定义成员变量吗--可以*/
int sum = 100;
/* 2.抽象类可以定义成员常量吗--可以*/
final String name = "xiao huang ren";
/*3.抽象类中可以定义普通方法吗?--可以
* 抽象类中可以都是普通方法吗?--也可以
* 4.如果一个类中都是普通方法,那为什么它还要修饰成抽象类呢?
* 答:因为抽象类不可以实例化,所以如果不想让外界创建本类的对象
* 就可以把普通类声明成抽象类*/
public void clean(){
System.out.println("水果还是要洗洗再吃~~~");
}
/*5.抽象类中可以定义抽象方法吗?--可以
* 6.若类中添加了抽象方法,那么这个类必须被声明成抽象类*/
public abstract void grow();
public abstract void breath();
}
//2.创建子类Banana,继承父类Fruit
class Banana extends Fruit{//使用方案二:implement method()创建父类中抽象方法的具体方法
@Override
public void grow() {
System.out.println("一串香蕉老沉了~~");
}
@Override
public void breath() {
System.out.println("香蕉不用洗");
}
}
3.接口
1.概念:接口( Interface )在Java中也是一种抽象类型,接口中的内容是抽象形成的需要实现的功能,接口更像是一种规则和一套标准.
2.接口的关键字是interface
3.我们通过implements建立接口与接口实现类的关系InterImpl implements Inter{ }
4.接口可以看作是一种特殊的抽象类,因为他里面全是抽象方法
5.实现子类如果与父类接口建立了实现关系,有两种方案:
方案一:继续抽象--》抽象子类
方案二:不再抽象-->实现父类接口中所有的抽象方法
6.接口没有构造方法,实现子类可以创建对象的原因是调用了Object顶级父类的无参构造
TIPS:问题:子类在创建对象时,默认会调用父类的无参构造
那么如果接口的实现类在没有明确指定父类时,使用的是哪个构造方法呢?
答案:默认继承顶级父类Object,所以实现类的构造方法中super();调用的是Object类的无参构造
7.接口中没有普通成员变量,有的只是静态常量,所以当你定义int age =10;时默认添加public static final int age =10;
练习-1:创建接口
创建包: cn.tedu.inter
创建接口:Inter.java
package cn.tedu.inter;
/*本接口用于创建测试
* 1.我们通过interface关键字来定义接口*/
public interface Inter {
/*2.接口中可以定义普通方法吗?--不可以*/
//public void play(){}
/*3.接口中可以有抽象方法吗?--可以,接口中的方法都是抽象方法*/
public abstract void paly();
public abstract void eat();
}
练习-2:创建接口实现类
创建包: cn.tedu.inter
创建接口实现类:InterImpl.java
package cn.tedu.inter;
/*本类作为Inter接口的实现类
* 1.实现类如果想要和接口建立实现关系,就通过implements来实现
* 2.接口实现类 与接口建立关系以后,有两种解决方案:
* 方案一:添加abstract ,变成抽象子类,不实现任何抽象方法
* 方案二:implement methods,继续作为普通子类,实现父类接口的所有的抽象方法*/
//abstract public class InterImpl implements Inter {方案一:添加abstract
public class InterImpl implements Inter {//方案二:implement methods
@Override
public void paly() {
System.out.println("划龙舟!");
}
@Override
public void eat() {
System.out.println("吃粽子~");
}
}
练习-3:创建接口测试类
创建包: cn.tedu.inter
创建接口测试类:InterTests.java
package cn.tedu.inter;
/*本类用于测试接口的实现*/
public class InterTests {
//创建程序的抽象入口函数main()方法
public static void main(String[] args) {
//测试创建接口对象
/*接口可以创建对象吗?--不可以*/
//Inter i =new Inter();
//创建多态对象进行测试
Inter i = new InterImpl();//接口Inter是父类,InterImpl是子类
i.eat();
i.paly();
//创建子类对象进行测试
InterImpl i2 = new InterImpl();
i2.eat();
i2.paly();
}
}
3.1接口的用法
练习:测试接口中能使用什么?
接口中只能有静态常量和抽象方法,不能有成员变量、构造方法、普通方法。
package cn.tedu.inter2;
/*本类用于进一步测试接口的使用、构造方法*/
public class TestUserInter {
public static void main(String[] args) {
//创建多态对象进行测试
Inter2 i = new Inter2Impl();
//接口中的变量实际上都是静态的,因为可以通过类名直接调用
System.out.println(Inter2.age);
//接口中的变量都是常量,因为不可以被重新赋值
//Inter2.age = 30;
}
}
//1.创建接口
interface Inter2{
/*1.接口中有构造方法吗?--没有,且不可以创建*/
//public Inter2(){}
/*2.接口中可以有成员变量吗?--没有
* 实际上是一个静态常量,实际的写法public static final int age = 10;
* 在接口中可以省略不写,接口中都是静态常量 */
//接口中的变量实际上都是常量,因为必须初始化(赋值)
int age = 10;
/*3.接口里可以有抽象方法吗?--可以!全是
* 方法定义可以简写,默认自动拼接public abstract*/
public abstract void eat();
void eat2();
}
//2.创建接口实现类
/*如果一个类没有明确指定父类,那么它的父类就是Object顶级父类,默认存在此现象*/
//class Inter2Impl extends Object implements Inter2 {
class Inter2Impl implements Inter2 {
//3.创建子类的构造方法
public Inter2Impl(){
super();//表示调用的是父类Object的无参构造
System.out.println("我是实现类Inter2Impl的构造方法~");
}
//如果普通子类实现了接口,需要实现接口中的所有抽象方法
@Override
public void eat() {
}
@Override
public void eat2() {
}
}
总结:
1.接口里是没有构造方法的,在创建实现类的对象时默认的super(),是调用的默认Object的无参构造
2.接口里没有成员变量,都是常量。所以,你定义一个变量没有写修饰符时,默认会加上:public static final
3.接口里的方法,默认就都是抽象的,如果你不写明是abstract的,那会自动补齐。例如:public abstract void save
3.2 面向抽象编程
package cn.tedu.design;
/*本类设计老师类,要求:面向抽象编程--后天向上抽取形成的结果*/
public class DesignTeacher1 {
public static void main(String[] args) {
//创建子类对象进行测试
CGBTeacher ct = new CGBTeacher();
ct.ready();
ct.teach();
ACTeacher at = new ACTeacher();
at.ready();
at.teach();
SCDTeacher st = new SCDTeacher();
}
}
//三个老师类都有共性内容,所以创建一个父类老师,让他们三个继承,就都可以使用了
abstract class Teacher{
int id;
String name;
public abstract void ready();//由于后面三个老师讲课内容会改变,需要重写
public abstract void teach();//改变成抽象类、抽象方法
}
//1.创建培优老师类--冗余
class CGBTeacher extends Teacher{//implement methods
@Override
public void ready() {
System.out.println("正在备课...电商项目");
}
@Override
public void teach() {
System.out.println("正在讲课...电商项目");
}
}
class ACTeacher extends Teacher{
@Override
public void ready() {
System.out.println("正在备课...加强模块");
}
@Override
public void teach() {
System.out.println("正在讲课...加强模块");
}
}
class SCDTeacher extends Teacher{
@Override
public void ready() {
System.out.println("正在备课...hadoop");
}
@Override
public void teach() {
System.out.println("正在讲课...hadoop");
}
}
3.3面向接口编程
package cn.tedu.design;
//刚刚的Teacher1案例:面向抽象编程--后天向上抽取形成的结果
/*本类用于设计老师类,要求:面向接口编程--先天设计的结果*/
public class DesignTeacher2 {
}
//1.创建接口,设计形成父级接口--接口体现的是预先定义好的规则
interface Teacher2{
void ready();
void teach();
}
//2.创建接口实现类
class CGBTeacher2 implements Teacher2{
@Override
public void ready() {
System.out.println(1);
}
@Override
public void teach() {
System.out.println(2);
}
}
3.4接口的多继承多实现
package cn.tedu.inter;
/*本类测试接口相关的复杂关系*/
public class InterDemo {
public static void main(String[] args) {
//多态对象
Inter3 i3 = new Inter3Impl();
i3.add();
//创建实现类对象进行测试--最常用
Inter3Impl inter3 =new Inter3Impl();
}
}
/*1.定义接口关键字:interface,
接口不是类,可以看作是一个内部全是抽象方法的特殊抽象类*/
interface Inter1{
/*2.接口中有成员变量吗?没有!会默认拼接public static final,静态常量*/
int age = 10;
/*3.接口中的方法都是抽象方法,默认拼接public abstract,所以可以简写*/
void update();//更新
void find();//查询
}
interface Inter2{
/*4.接口没有构造方法,不可以实例化(创建对象)*/
void delete();//删除
void add();//新增
}
/*接口与接口是继承关系,且一个接口可以继承多个接口*/
interface Inter3 extends Inter1,Inter2{ }//实现多个接口
/*类与接口是实现(implements)的关系,且一个类可以实现多个接口*/
class Inter3Impl implements Inter3{//实现一个接口
@Override
public void update() {
System.out.println("更新");
}
@Override
public void find() {
System.out.println("发现");
}
@Override
public void delete() {
System.out.println("删除");
}
@Override
public void add() {
System.out.println("新增");
}
}
3.5总结
1. 类与类的关系
继承关系,只支持单继承
比如,A是子类 B是父类,A具备B所有的功能(除了父类的私有资源和构造方法)
子类如果要修改原有功能,需要重写(方法名+参数列表与父类一致 ,子类权限修饰符>=父类修饰符)
2. 类和接口的关系
实现关系.可以单实现,也可以多实现
class A implements B,C{};或者class D implements B,C{ }-->class A implements D{}
其中A是实现类,B和C是接口,A拥有BC接口的所有功能,只是需要进行方法的重写,否则A就是抽象类
3. 接口与接口的关系
是继承关系,可以单继承,也可以多继承
interface A extends B,C{}
其中ABC都是接口,A是子接口,具有BC接口的所有功能(抽象方法)
class X implements A{}
X实现类需要重写ABC接口的所有方法,否则就是抽象类
class A extends B implements C,D{}
其中A是实现类,也是B的子类,同时拥有CD接口的所有功能
这时A需要重写CD接口里的所有抽象方法
4. 抽象类与接口的区别
1)抽象类是一个特殊的类,特殊在,抽象类中可以包含没有方法体的方法(抽象方法)
抽象类里成员变量、成员常量、构造方法、普通方法、抽象方法都可以有
抽象方法只能声明,不能实现,抽象类是向上抽取形成的结果,接口则是预先设计的结果
抽象类可以有构造方法–用来给子类创建对象,接口中没有构造方法
抽象类和接口都不能实例化(创建对象)
2)接口可以理解成一个特殊的抽象类,特殊在,接口里除了被static或者default修饰普通方法有方法体,其他的都是抽象方法,没有其他普通方法
接口里只能有静态常量和抽象方法
接口会为方法自动拼接public abstract,还会为变量自动拼接public final static
接口可继承接口,并可多继承接口,但类只能单继承