第07章高级类特性——v512工作室 编辑:玄玉
接口 | 嵌套类 | 我的博客 | v512工作室 | |
抽象类 | 枚举类型 | 给我发邮件 | 中科院新科海学校 |
抽象类abstract
概述:抽象类主要是通过继承,然后再由其子类发挥作用的。抽象方法必须使用关键字abstract修饰
Java方法被定义时可以只给出方法头,而不必给出方法体(即方法实现的细节),这样的方法被称为抽象方法
Java语言规定,子类必须实现父类中的所有抽象方法,否则该子类也要声明为抽象类
特性:抽象类不能实例化。但可以由子类继承抽象类,然后生成子类的对象,进而使用抽象类
包含抽象方法的类必须声明为抽象类。但抽象类中可以不包含抽象方法
子类可以不全部实现抽象父类中的抽象方法,但此时子类也只能声明为抽象类
父类不是抽象类的时候,也可以在子类中可以添加抽象方法,但此时子类也要声明为抽象类
只要类中存在抽象方法,那么该类就一定要声明为抽象类。抽象类中也可以声明static属性和方法
作用:代码重用:子类可以重用父类当中的方法的代码
规划:父类中都已经规划好了子类应该具有的行为。子类必须要具有这些行为,即对抽象的方法加以实现
多态性:类Person继承了Animal抽象类,那么Animal a=new Person()可以编译通过
接口interface
接口:是抽象方法和常量值的定义的集合。从本质上讲,接口是一种特殊的抽象类
特性:接口可以继承其它的接口,并添加新的属性和抽象方法。接口间支持多重继承
和继承关系类似,Java类可以实现接口,且接口和实现类之间也存在多态性
实现接口用implements。接口可以被多重实现。即一个类只能extends一个类,但一个类可同时implements多个类
一旦一个类实现了接口,那么就需要重写这个接口当中所有的抽象方法。在重写之外也可以增加自己的一些方法
接口中不可以定义具体的方法,它里面所有的方法都是抽象方法,所包含的属性值也都是常量值
接口中定义属性必须是public static final的,定义方法必须是public abstract的。这些修饰符可以部分或全部省略
通过接口可以实现不相关类的相同行为,即提炼出不相关类间的共性,而不需要考虑这些类之间的层次关系
多态性:类Person实现了Runner接口,那么Runner r=new Person()可以编译通过,而r调用的方法也自然是重写以后的方法
举例:public static final int id=1;等价于int id=1; //因为即使不加这些修饰符,但由于是在接口中
public abstract void start();等价于void start(); //那么系统也会自动地加上这些修饰符的
嵌套类Nested Class
概念:Java语言支持类的嵌套定义,即允许将一个类定义在其它类的内部,其中内层的类被称为嵌套类
分类:静态嵌套类(Static Nested Class):使用static修饰的嵌套类
内部类(Inner Class):非static的嵌套类
内部类:普通内部类:在Java类中、方法或语句块的外部定义的非static类
局部内部类:也称局部类(Local Class),定义在方法或语句块中的类
匿名内部类:也称匿名类(Anonymous Class),定义在方法或语句块中,该类没有名字,只能在其所在之处使用一次
特性:内部类可以声明为抽象类,因此可以被其他的内部类继承
内部类可以声明为private或protected的,也可以声明为final的
内部类也会被独立编译出来一个class文件,文件名为<外部类名>$<内部类名>.class的形式。如A$B.class
内部类与其所在的外层类之间存在着逻辑上的依赖关系。内部类的对象不能单独存在,它必须依赖一个外层类的对象
内部类中可以直接访问其外层类的属性或方法,即使这些属性和方法是private型。相当于自家兄弟,当然可以使用了
内部类中只有非private型属性或方法才能被外层类的对象使用
使用内部类:①:先生成外部类的实例,再调用外部类中能够生成该内部类实例的方法
教程中本章的40:05——42:39段有详细讲解
class A { private int s;public class B{public voidmb(){s=100;System.out.println("在内部类B中s="+s);}}
public void ma(){ B i=new B();i.mb(); }}//再通过生成的内部类的实例i调用内部类的方法
public class TestInner{public static void main(String args[]){
A o=new A(); o.ma();}}//先生成外部类A的实例o,再调用ma()方法,通过ma()生成内部类的实例
②:在外部使用其它类中的内部类时,应指明其完整层次,并显式建立对象间的依赖关系
其实我们还可以直接生成内部类的对象
class A{ private int s;public class B{public voidmb(){ System.out.println(s); }}}
public class TestInner2{public static void main(String args[]){
A a=new A(); //通过外部类的实例a调用内部类的构造方法new B()
A.B b=a.new B(); //创建一个依赖于a而存在的b
b.mb(); }} //A.B的意思是要生成的是A类中的内部类B的实例
③:内部类中出现变量命名冲突时,可以使用内部类对象的特殊属性<外层类名>.this来访问其所以来外层类对象的成员
class A{ private int s=111;public class B {private int s=222; public void mb(int s) {
System.out.println(s); //局部变量s(因为传进来的参数里的s离这个s最近)
System.out.println(this.s); //内部类对象属性s
System.out.println(A.this.s); }}} //外层类对象属性s
枚举类型Enum
概述:Java SE5.0开始,Java语言引入了一种新的引用数据结构——枚举
特性:Java语言中枚举类型均自动继承了java.lang.Enum类(该类继承了Object类)
枚举类型使用一组常量来表示特定的数据集合,该集合中数据的数目确定,通常较少。且这些数据能取预先定义的值
枚举类型编译后也会生成一个class文件,编译方式与普通类文件一样。但注意它里面的最后一条数据的后面没有分号
由于之前我们定义常量时用final,然后还要定义数值类型等等,比较麻烦,所以枚举类型能够更好的帮助我们定义一些常量
实例:public enum Week{ MON,TUE,WED,THU,FRI,SAT,SUN }//枚举类型中定义的都是常量,而常量要用大写字母
①:public class TestEnum{public static void main(String[] args){TestEnum te = new TestEnum();
te.work(Week.SUN);System.out.println(Week.SAT.ordinal());} //输出常量SAT在Week内部是用哪个整数来代表的,得到结果5
public void work(Week day){
if(day.equals(Week.SAT)){System.out.println("购物!");
}else if(day.equals(Week.SUN)){System.out.println("祈祷!");
}else{ System.out.println("工作!"); }}}
②:public class ListEnum{public static void main(String[] args){
Week[] days = Week.values();for(Week d:days){ System.out.println(d);}}}