7.1 抽象类
抽象类的声明格式:
【其他修饰符】abstractclass抽象类名{
}
抽象方法的声明格式:
【其他修饰符】abstract返回值类型抽象方法名(【形参列表】); //没有方法体
抽象类的特点:
(1)抽象类不能直接new对象,只能创建它子类的对象。
(2)包含抽象方法的类必须是抽象类,但是抽象类可以没有抽象方法。
(3)抽象类就是用来被继承的,子类继承抽象类时必须重写/实现抽象类的所有抽象方法,否则子类也必须是抽象类。
(4)抽象类也可以声明普通的属性、自己的构造器等其他成员。
问:普通的非抽象类和抽象类的区别?
抽象类不能直接new对象,可能包含抽象方法,其余都一样。
问:为什么要声明抽象类呢?
(1)在声明某个父类时,它的某个方法无法给出适用于所有子类的具体的统一的实现,那么这个方法可以声明为抽象方法,包含抽象方法的类,就声明为抽象类。
(2)在声明某个父类时,不希望别人创建该父类的对象,而是希望创建它更加具体的子类对象时,把这样的父类声明为抽象类。
abstractclassShape{
}
classCircleextendsShape{
publicdoublearea(){
}
}
classRectangleextendsShape{
publicdoublearea(){
}
}
abstractclassShape{
publicabstractdoublearea(); //推荐下面的写法
}
classCircleextendsShape{
publicdoublearea(){
//....
}
}
classRectangleextendsShape{
publicdoublearea(){
//....
}
}
Shapes=newCircle();
Doublea=s.area(); //语法层面上,便于多态引用
逻辑层面上:
类的定义:一类具有相同特性的事物的抽象描述。
Shape类代表形状这个事物,所有的形状按照理论来说都是可以求面积。求面积是所有形状的共同特征,在Shape类中就应该体现该特征。
7.2 接口
接口的声明格式:
【修饰符】interface接口名{
}
接口的成员声明:
(1)公共的静态的常量:publicstaticfinal数据类型常量名=常量值; //其中public static final可以省略,也建议省略
(2)公共的抽象方法:publicabstract返回值类型方法名(【形参列表】); //其中public abstract可以省略,也建议省略
(3)公共的静态方法:publicstatic返回值类型方法名(【形参列表】){方法体}//其中public 可以省略,也建议省略
(4)公共的默认方法:publicdefault返回值类型方法名(【形参列表】){方法体}//其中public 可以省略,也建议省略
(5)私有的方法:private ...,JDK1.9之后引入的。(了解)
接口的成员的使用:
(1)公共的静态的常量:
A:非实现类中:接口名.常量名
B:实现类中:
①没有重名问题,即不冲突:直接通过“常量名”就可以使用
②有重名问题,即有冲突:接口名.常量名
(2)公共的抽象方法:
A:实现类:必须重写,除非该实现类是抽象类
B:非实现类中:必须创建实现类的对象才能调用,最终执行的是实现类重写的方法体
(3)公共的静态方法:
无论是在实现类中还是非实现类中,都是“接口名.静态方法(【实参列表】)
注意一下:父类中的静态方法可以被子类继承,但是父接口中的静态方法不会被实现类继承。
(4)公共的默认方法:
A:实现类:
①没有冲突问题:实现类可以选择重写,也可以选择不重写。重写时在实现类中不用加default。
②有冲突问题:
a:父类与父接口冲突:默认遵循亲爹优先原则。当然也可以选择重写。如果要选择保留某个父接口的默认方法实现,可以通过“父接口名.super.默认方法名(【实参列表】)
b:多个父接口的默认方法冲突:必须重写。可以完全重写,也可以保留某个父接口的默认方法实现,可以通过“父接口名.super.默认方法名(【实参列表】)
B:在非实现类中:
必须创建实现类的对象才能调用,如果该实现类没有重写,那么仍然执行接口中的默认方法方法体,如果该实现类重写了,就执行重写的代码。
实现类实现接口的语法格式:
【修饰符】class实现类【extends父类名】implements父接口们{
}
接口的特点:
(1)接口也不允许直接new对象,这一点和抽象类一样。
(2)接口的成员有限制,只能上面列出的那些成员,没有构造器等其他成员。
(3)类与类之间只允许单继承,但是接口与接口之间允许多继承。
【修饰符】class子类extends父类{
}
【修饰符】interface子接口extends父接口们{
}
(4)类与接口之间是多实现关系。
【修饰符】class实现类【extends父类名】implements父接口们{
}
(5)接口就是用来被实现的,实现类在实现接口时,必须实现接口所有的抽象方法,否则实现类也得是抽象类。
为什么要使用接口?(后续在接触更多的接口之后再慢慢体会)
高内聚低耦合。
面向接口编程。
希望通过接口类型,统一管理一组不相关的类的对象,这些类不一定属于同一个事物的类别,但是它们具体相同的“方法”。
interfaceFlyable{
voidfly();
}
classBirdextendsAnimalimplementsFlyable{
@Override
publicvoidfly(){
//...
}
}
classPlaneimplementsFlyable{
@Override
publicvoidfly(){
//...
}
}
classKiteimplementsFlyable{
@Override
publicvoidfly(){
//...
}
}
Flyable[] all=newFlyable[3];
all[0] =newBird();
all[1] =newPlane();
all[2] =newKite();
for(inti=0; i<all.length; i++){
all[i].fly();
}
7.3 内部类
见word文档
7.4 枚举类
1、枚举类的特点:
(1)枚举类是一种特殊的类,特殊在:它的对象是固定的有限的几个,提前创建好的几个对象。
换句话说,它和普通类的不同,就在于获取它的对象的方式不同。
普通类:需要它的对象,就直接new。
枚举类:需要它的对象,只能通过 “枚举类.常量对象”的方式获取
(2)构造器一定是私有化
(3)枚举类中必须提前创建好该类的几个常量对象,使用public static final的形式表示
//JDK1.5之前
【修饰符】class枚举类{
public staticfinal枚举类名常量对象名1=new构造器名(【实参列表】);
public staticfinal枚举类名常量对象名2=new构造器名(【实参列表】);
//....
private构造器名(){
}
private构造器名(【形参列表】){
}
}
//JDK1.5之后,现在推荐的写法
【修饰符】enum枚举类{
常量对象名1(【实参列表】),常量对象名2(【实参列表】),...; //如果常量对象使用无参构造创建的,那么()可以省略
//如果枚举类中除了常量对象列表,没有其他的成员声明了,那么常量对象列表最后的;可以省略
//如果后面还有其他成员,那么;不能省略
//普通成员变量声明列表
【修饰符】数据类型成员变量名; //建议加final修饰,但是不是强制
private构造器名(){//构造器的权限修饰符只能是private,private可以省略
}
private构造器名(【形参列表】){//构造器的权限修饰符只能是private,private可以省略
//...
}
//其他成员列表
}
(4)枚举类没有子类(因为构造器私有化,子类无法调用,所以无法声明子类)
(5)枚举类不能手动指定直接父类,它的直接父类默认只能是java.lang.Enum类
(6)枚举类可以实现接口,可以统一实现接口的抽象方法,也可以让枚举的每一个常量对象单独实现接口的抽象方法
2、枚举类的方法
(1)String name():返回常量对象的对象名
(2)int ordinal():返回常量对象的序列号,从0开始的下标值
(3)String toString():Enum类重写了Object类的toString方法,默认返回的是常量对象的对象名,当然我们自己的枚举类还可以继续重写。
(4)static 枚举类[] values():返回枚举类的所有常量对象构成的数组
(5)static 枚举类 valueOf(String name):根据指定的常量对象名返回常量对象
3、switch从JDK1.5之后,开始支持枚举类型(enum)
7.5 包装类
1、包装类的类型
byte<->Byte
short<->Short
int<->Integer
long<->Long
float<->Float
double<->Double
char<->Character
boolean<->Boolean
2、基本数据类型与包装类之间的转换:JDK1.5之后都是支持自动装箱与自动拆箱,但是只支持对应类型之间的装箱与拆箱
3、包装类的特点
(1)包装类对象不可变
(2)部分包装类对象可能共享
Byte,Short,Integer,Long:-128~127
Character:0-127
Boolean:true,false
Float,Double:没有
(3)计算的规则
如果运算符两边都是引用数据类型(包装类),运算符是==和!=,比较的是地址值,要求两边的类型必须一致,否则就编译报错。
如果运算符两边都是引用数据类型(包装类),运算符是>等其他类型,那么会先自动拆箱再计算。
如果运算符两边一边是引用数据类型(包装类),另一边时基本数据类型,那么无论什么运算符都是先自动拆箱再计算。
4、一些API方法
技巧:(1)能记住多少先记多少,记住了使用更快(2)记不住的知道去哪里查,例如:笔记、API文档,百度等
(1)和字符串之间的转换问题
从基本数据类型->字符串类型: 基本数据类型+"" 或 String.valueOf(基本数据类型)
从字符串类型->基本数据类型: 包装类.parseXxx(字符串) 例如:Integer.parseInt(字符串) Double.parseDouble(字符串)
字符串.charAt(下标)
(2)获取某个类型的最大最小值
包装类.MAX_VALUE
包装类.MIN_VALUE
(3)转大小写
Character.toUpperCase(字符)转大写
Character.toLowerCase(字符)转小写