抽象类
特点:
1.方法只有声明没有实现时,该方法就是抽象类,需要用 abstract 修饰
2.抽象类不可以被实例化,因为调用抽象方法没意义
3.抽象类必须有其子类覆盖所用的抽象方法后,该子类才可以实例化,否则这个子类还是抽象类
1.抽象类中有构造函数么?
有,虽然抽象类不能用 new 创建对象,不需要初始化,但是可以用于给子类进行初始化。
2.抽象类可以不定义抽象方法么?
可以,但很少见,目的就是//不让该类创建对象。
通常这种类中的方法有方法体,但是没有内容。
例:void show()
{}
3.抽象关键字不可以和那些关键字共存?
private 不行,因为 private 修饰的内容不能被子类覆盖
static 不行,
final 不行,因为 final 修饰的内容不能被子类覆盖
4.抽象类和一般类的异同
相同:
均用来描述事物,在内部定义成员。
不同点:
1.一般类不能定义抽象方法
抽象类可以定义抽象及非抽象方法。
2.一般类可以被实例化
抽象类不可以被实例化
抽象类演示:
abstract class Damo { abstract void show(); //抽象的函数 } class DemoA extends Dame { void show() //如果子类继承抽象类狗没有覆写抽象方法,该子类仍然为抽象类 { System.out.println("Hello DemoA"); } } class DemoB extends Demo { void show() { System.out.println("Hello DemoB"); } }
抽象类的应用
雇员示例:
需求:公司程序员有姓名,工号,薪水,工作内容。
项目经理有。。。等,还有奖金。
分析:
想找出涉及的对象
程序员:
属性:姓名,工号,薪水
行为:工作
经理:
属性:姓名,工号,薪水,奖金
行为:工作
程序员与经理不存在直接继承关系,但是程序员与经理具有共性内容。
将程序员与经理进行抽取,建立体系
abstract class Employee //定义雇员 { private String name; //定义成员变量 private String id; private int payment; Employee(String name,String id,int payment)//定义成员构造函数 { this.name = name ; this.id = id ; this.payment = payment ; } public abstract void work(); //定义抽象方法 } //描述程序员 class Programmer extends Employee //令程序员继承雇员 { Programmer(String name,String id,int payment) //定义程序员的构造方法 { super(name,id,payment); } void work() //此行覆盖父类中的抽象方法 { System.out.println("code..."); //定义程序员的特有方法 } } //描述项目经理 class Manager extends Employee //令项目经理继承雇员 { private int bonus; //定义成员变量 Manager(String name,String id,int payment,int bonus) //定义项目经理的构造函数 { super(name,id,payment); //继承父类构造函数 this.bonus = bonus ; } void work() //覆盖父类抽象方法 { System.out.println("manage..."); //定义项目经理特有方法 } }
当一个抽象内中的方法均为抽象时,可以将该抽象类用另一种形式定义和表示,就是接口 interface
此时,定义接口的关键字是 interface 而非 class
对于接口中的成员,均有固定的修饰符
1.全局常量 public static final (这些修饰符是固定的,即使没有写,程序也会自动添加。)
2.抽象方法 public abstract (这些修饰符是固定的,即使没有写,程序也会自动添加。)
由此可以看出,接口中成员都是公共权限。
interface InterfaceDemo { public static final int num = 4 ; abstract void show1(); abstract void show2(); }
类与类之间是继承关系,接口与接口之间是继承关系(而且可以多继承),类与接口之间是实现关系此时关键字用 implements 。
接口不可以被实例化,只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实现化。
class DemoA implements InterfacceDemo // implements A,B就是多实现 { void show1() { //具体的实际的方法略 } void show2() { //具体的实际的方法略 } }
实现的好处是可以实现 多实现,一个类可以实现多个接口。
一个类在继承一个类的时候,还可以实现多个接口,接口的出现避免了单继承的局限性。
class Test extends C implements A,B
一个接口使用实例
笔记本电脑通过usb接口扩展u盘
interface USB //暴露接口规则 { public void open(); public void close(); public void work(); } class Upan implements USB //定义一个符合usb规则的upan { public void open() { System.out.println("upan open"); //定义具体的实现方法 } public void close() { System.out.println("upan close"); } public void work() { System.out.println("upan work"); } } class Laptop { public static void main(String[] args) { useUSB(new Upan()); //创建一个upan,并通过定义的使用方法使用 } public static void useUSB(USB u) //定义一个使用usb的方法 { u.open(); u.close(); u.work(); } }
运行结果:U盘正常运行
内部类的特点:
1.内部类可以直接访问外部类的成员。
2.外部类药访问内部类必须建立内部类的对象。
静态类中的成员,函数均为静态的。
内部类在局部位置在上只能访问局部中被final修饰的局部变量。
interface Demo { void show(); } class Outsider { private int num = 3 ; void method()//如无此行,内部类直接写在外部类中时,可用 Outsider.Intersider in2 = new Outsider().new Intersider(); //直接访问内部类中的内容,记格式。 { final int a = 4 ; //在内部类中访问局部变量时,必须在变量前加final class Intersider { int num = 5 ; void show() { System.out.println("num="+num); System.out.println("num="+Outsider.this.num); //此时输出的是外部的num = 3. 仅内部类与外部类出现重名变量的时候才这样使用。 System.out.println("a="+a); //要访问a这局部变量,必须在变量前加 final } } Intersider in1 = new Intersider(); in1.show(); System.out.println(); } //以下为演示匿名内部类 public void method0() { new Demo() //此时Demo是抽象类,不能直接创建对象,但此时已经在其中具体了其抽象方法的具体实现,所以这步实际上是创建了一个Demo的子类的对象 { //这种方法是创建了一个子类,所以可以在其中添加子类特有的方法,例如 show2() public void show() //public 必须加上(重要) { System.out.println("匿名内部类01"); } }.show(); //.show()很重要,和普通一样,表示使用。 Demo in = new Demo() //这种方法创建的子类,自动向上转型成为了Demo类,所以不可以添加子类特有的方法,仅可以复写Demo中已有的方法。 { public void show() //public 必须加上(重要) { System.out.println("匿名内部类02"); } }; // ; 很重要 in.show(); } } class Neibulei { public static void main(String[] args) { Outsider Out = new Outsider(); Out.method(); new Outsider().method(); //此方法为用匿名类 new Outsider().method0(); } }
异常类
注意:如果让一个类成为异常类,必须继承异常体系,因为只有成为异常类才能被关键字 throws throw
异常的分类:
1:编译时被检测异常,主要是Exception 和 其子类(除 RuntimeException)
这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式
这种问题都可以针对性的处理。
2:编译时不检测异常(运行时异常):就是RuntimeException 及 其子类。
这种问题发生,无法让功能继续,大多是因为调用者的原因导致
这种问题一般不处理,直接编译通过,在运行时,让调用哪个最调用时的程序强制停止,让调用者对代码进行修正
异常处理的捕捉形式:
这是可以对异常进行针对性处理的方式。
具体格式:
try { //需要被检测异常的代码 } catch(异常类 变量)//该变量用于接收发生的异常对象 { //处理异常的代码。 } finally //通常用于关闭(释放)资源 { //一定会被执行的代码。 }
异常处理原则
1:函数内部如果抛出需要检测的异常,那么函数上必须要添加声明,或者必须在函数内用try catch捕捉,否则编译失败。
2:功能内容可以解决,用catch
解决不了,用throws告诉调用者,由调用者解决。
3:一个功能如果抛出 多个异常,那么调试时,必须有对应多个catch进行针对性的处理。
抛出几个,就catch几个。
异常应用演示
class Fushuindex extends RuntimeException //继承的Exception时,需要throws Fushuindex (添加捕捉自定义声明) { Fushuindex(String a) { super(a); //直接调用父类的方法 } } class Demo { public int method(int [] arr , int index) //继承的Exception时,需要throws Fushuindex (添加捕捉自定义声明) { if(arr==null) throw new NullPointerException("数组的角标不能为空"); if(index >=arr.length) //判断问题 throw new ArrayIndexOutOfBoundsException("数组角标越界了: "+index); //自定义异常返回信息 else if(index < 0) throw new Fushuindex("数组角标不能小于0: "); else return arr[index]; } } class ExceptionDemo { public static void main(String[] args) //继承的Exception时,需要throws Fushuindex (添加捕捉自定义声明) { int [] a = new int [3]; Demo d = new Demo(); int num1 = d.method(a,1); System.out.println("Hello World!"+num1); //以下演示异常捕捉 //多catch 时,父类catch必须放在最下面 try { int num2 = d.method(a,-30); System.out.println("num2 = "+num2); } catch (Fushuindex x) { System.out.println("负数角标异常"); System.out.println(x.toString()); //异常信息 } catch (Exception e) {} System.out.println("over"); } }