一、抽象
抽象可以修饰方法、类
A、修饰方法时:使用:abstract修饰且没有方法体的方法,称为抽象方法。
特点:
① 使用抽象abstract修饰,方法没有方法体,留给子类去实现,表示:仅仅有这一个行为功能,到底如何实现留给子类去做。
② 抽象方法修饰符不能是private和final以及static,为什么?保证,子类必须去覆盖父类的抽象方法,实现具体功能.
③ 抽象方法必须定义在抽象类或接口中。
一般的:习惯性把abstract写在方法修饰符最前面,一看就知道是抽象方法。
B、使用abstract关键字修饰的类。
特点:
① 不能创建实例即不能new一个抽象类。(因为功能不完整),也就是说抽象类不能被实例化
② 可以不包含抽象方法,若一旦包含,该类必须作为抽象类。
③ 若子类没有覆盖父类所有的抽象方法,那么子类也得作为抽象类(抽象派生类)。
④ 构造方法不能都定义成private的,否则不能有子类(创建子类对象前先调用父类构造方法)。
⑤ 抽象类不能使用final修饰,因为必须有子类,抽象方法才能得以实现。
⑥ 是不完整的类,需作为父类类,需要子类才能才能得以实现功能。
目的:abstract修饰类就是为了防止外界来创建该工具类对象.抽象是建立在继承的基础之上的,也就是说如果没有继承抽象就没有意义。开发中,父类(抽象类)只定义了方法体,并没有去实现方法的具体功能,留给子类去实现。
二、接口
1):其实就是一个程序,在Java中最小的程序单元就是类,理解接口就是一个特殊的类.也可以理解为接口是一种特殊的抽象类,但是抽象类中可以有抽象方法也可以没有,同样可以存在普通方法也可以不存在。但是在接口中的所有方法都必须全部都是抽象方法(也可以不定义方法).
2):接口可以定义很多抽象方法,用于规定实现该接口的类必须具有这些方法,要求某一些事物必须具有什么功能行为.
接口定义一种规范,规定某一类事物类必须具备某些功能,但它不管类如何具体实现这些功能。
格式:子类实现时:[修饰符] interface接口名extends父接口1,父接口2....
接口定义时:(注意:习惯在接口名前加上大写的I,以区分类和接口)
interface IWalkable {
void walk();
}
接口里的成员包括:全局静态常量、公共的抽象方法、公共静态内部类(包括内部类、内部接口、内部枚举)。
特点:
① 没有构造方法,不能实例化。
② 接口只能继承接口,不能继承类,且接口支持多继承。
③ 接口里的方法方法全是抽象的,默认修饰符是public abstract。
④ 接口里的字段全是全局静态常量,默认修饰符是public static final。
⑤ 接口里的内部类全是静态的,默认修饰符是public static。
在定义接口中的成员时:习惯不写接口里方法的修饰符。
类和接口之间的关系:
1:类和类之间是继承关系.单继承extends
2:接口和接口之间是继承关系.多继承extends
3:类和接口之间是实现关系.类 实现于 接口. implements.
接口和抽象类比较:
相同点:
1、都位于继承的顶端,用于被其他实现或继承。
2、都不能实例化。
3、都可以定义抽象方法,其子类都必须覆写这些抽象方法。
区别:
1、接口没有构造方法,抽象类有构造方法。
2、抽象类可包含普通方法和抽象方法,接口只能包含抽象方法;
3、一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口(接口弥补了Java的单继承)。
变量:接口里默认是public static final,抽象类是默认包权限。
方法:接口里默认是public abstract,抽象类默认是默认包访问权限。
内部类:接口里默认是public static,抽象类默认是默认包访问权限。
二者的选用:优先选用接口,尽量少用抽象类。若需要定义子类的行为,又要为子类提供共性功能时选用抽象类。
普通类,抽象类,接口之间的关系:
测试代码如下:
三、内部类:在类中定义另一个类.
A、为什么需要使用内部类:
1:该类只需要外部类访问,不运行外界其他类访问---->隐藏.
2:内部类是外部类的一个成员,但是该成员包含多个信息--->封装.
3:为什么使用匿名内部类,如果某一个类只需要用一次就报废,此时使用匿名内部类.
B、内部类的分类:
1):静态内部类,此时Inner属于Outer类,而不属于Outer的对象.
class Outer{
static class Inner{}
}
2:非静态内部类,此时Inner属于Outer类的对象,而不属于Outer类本身.
class Outer{
class Inner{}
}
3:局部内部类,在方法中定义的内部类.
class Outer{
public static void main(String[] args){
class Inner{}
}
}
4:匿名内部类,是一种特殊的局部内部类,没有名称的内部类,就只能使用一次.适合只使用一次的类,就没有必要定义成一个类.。
不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建匿名内部类的对象。
不能定义构造器,因为匿名内部类没有类名。
格式:
new父类构造器([实参列表])或 接口()
{
//实现接口中的抽象方法
}
注意:匿名内部类必须继承一个父类或者实现一个接口,但最多只能一个父类或实现一个接口。
C、局部内部类访问变量问题:
在局部内部类中(匿名内部类中),可以直接访问成员变量.但是不能直接访问局部变量.只能访问final修饰的局部变量。
为什么需要使用final?
变量不使用final修饰,当变量所在的方法被调用完毕,该方法的内存空间就被销毁,此时变量也就不存在了.但是方法销毁的时 候,对象可能还在,因为对象是有GC来负责回收,那也就是说,对象存在的时候,变量已经不存在了,但是在对象内部需要使用变量。 此时就出问题了.
解决方案:对局部变量使用final修饰,该变量变成常量,永驻内存.
匿名内部类演示:
四、枚举
定义:是一种特殊的类,存在的意义:表示数量固定有限的对象类型.一般的,用来表示事物的类型.
A、枚举特点:
① 枚举的直接父类java.lang.Enum,但是不能显示继承Enum。
② 枚举就相当于一个类,可以定义构造方法、成员变量、普通方法和抽象方法。
③ 默认私有的造方法,即使不写访问权限也是private。
④ 每个实例分别用一个全局常量表示,枚举类的对象是固定的,实例个数有限,不能使用new关键字。
⑤ 枚举实例必须位于枚举体中的最开始部分,枚举实例列表的后要有分号与其他成员相分隔。
⑥ 枚举实例后有花括号时,该实例是枚举类的匿名内部类对象(查看编译后的class文件)。
B、枚举的基本使用:
枚举常用的方法:
1):public static数组类型values():返回当前枚举类中所有的对象,所组成的一个数组.
Weekday[] arr = Weekday.values();//返回Weekday枚举类中所有的对象.
2):public static枚举类型valueOf(String s):把该字符串转换为对应的枚举对象.
Weekday day = Weekday.valueOf("MONDAY");
3:String name():返回当前枚举对象声明的对象名称.
4:int ordinal():返回当前枚举对象在定义的时候的序号(从0开始).
System.out.println(Weekday.FRIDAY.name());//获取对象名称:FRIDAY
System.out.println(Weekday.FRIDAY.ordinal());//获取对象序号:4
5:switch支持哪些数据类型:
最原始的类型: byte,short,char,int
从Java5开始:因为自动拆箱的问题:Byte,Short,Character,Integer.支持枚举类型:
从Java7开始:支持String类型.
反编译之后(反编译工具编译)