一.学习内容
1.接口
2.抽象类
3.final关键字
4.代码块
二.具体记录
1.接口
定义:就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来
1.语法
interface 接口名{
//属性
//方法
}
class 类名 implements 接口{
自己属性;
自己方法;
必须实现的接口的抽象方法
}
2.在JDK7.0前
接口里的所有方法都没有方法体,即都是抽象方法(在接口中,抽象方法,可以省略abstract关键字)
3.JDK8.0后
接口类可以有静态方法(加static),默认方法(要加default关键字),也就是说接口中可以有方法的具体实现
4.接口使用细节
1.接口不能被实例化
2.接口中所有的方法时public方法,接口中抽象方法,可以不用abstract修饰
3.一个普通类实现接口,就必须将该接口的所有方法都实现(快捷键alt+enter)
4.抽象类实现接口,可以不用实现接口的方法
5.一个类同时可以实现多个接口
6.接口中的属性,只能是final的,而且是public static final 修饰符
比如:public static final int a=1;(必须初始化)
7.接口中属性的访问形式:接口名.属性名
8.一个接口不能继承其他的类,但是可以继承多个别的接口
9.接口的修饰符只能是public和默认,这点和类的修饰符是一样的
5.实现接口和继承类的比较
1.继承:
当子类继承了父类,就自动拥有父类的功能
如果子类需要扩展功能,可以通过实现接口的方式扩展
可以理解为,实现接口是对java单继承机制的一种补充
2.接口和继承解决的问题不同
继承的价值主要在于:解决代码的复用性和可维护性
接口的价值在于:设计好各种规范(方法),让其他类去实现这些方法
3.接口比继承更灵活
继承是满足is-a的关系,而接口只需要满足like-a的关系
4.接口在一定程度上实现代码解耦(即 接口规范性+动态绑定机制)
6.接口的多态特性
1.多态参数:在前面的usb接口案例中,即可接受手机对象,又可以接收相机对象
就体现了接口多态(接口引用可以指向实现了接口的类的对象)
2.接口多态传递现象:接口A继承接口B,而tea类实现A接口,
那么就相当于tea类实现B接口
2.抽象类
1.定义:
当父类的某些方法,需要声明,但是又不确定如何实现时,就可以将其声明为抽象方法,这个类就是抽象类
public abstract void eat();
1.所谓抽象方法就是没有实现的方法,即没有方法体
2.当一个类中存在抽象方法时,需要将该类声明为abstract类
3.一般来说,抽象类会被继承,由其子类来实现抽象方法
2.抽象类介绍
1.用abstract关键字修饰的类就是抽象类:访问修饰符 abstract 类名{ }
2.用abstract修饰的方法就是抽象方法:访问修饰符 abstract 返回类型 方法名(参数列表);
3.细节
1.抽象类不能被实例化
2.抽象类不一定要包含abstract方法,并且还可以有实现的方法
3.一旦类包含了abstract方法,则这个类必须声明为抽象类
4.abstrsct只能修饰类和方法,不能修饰属性和其他的
5.抽象类可以有任意成员(因为抽象类还是类),比如:非抽象方法,构造器,静态属性等
6.抽象方法不能有主体{ },即不能实现
7.如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非他自己也声明为抽象类
abstract class E { public abstract void hi(); }
class G extends E{
//覆盖
public void hi() { }//这里相当于G子类实现了父类E的抽象方法,所谓实现方法,就是有方法体
}
8.抽象方法不能用private,final,static来修饰,因为这些关键字都是和重写违背的
(抽象方法要被子类重写或实现的)
3.final关键字
1. 使用情况:
1.当不希望类被继承时,可用他修饰
2.当不希望父类的某个方法被子类覆盖/重写时,可用
3.当不希望类的某个属性的值被修改,可使用(此时也称为局部常量)
4.当不希望某个局部变量被修改
2.注意事项和细节
1.final修饰的属性又叫常量,一般用XX_XX来命名
2.final修饰的属性在定义时,必须赋初值,并且以后不能修改,赋值可以在如下位置之一:
定义时:如public final double TAX_RATE=0.08
在构造器中; 在代码块中;
3.如果final修饰的属性时静态的,则初始化的位置只能是:
定义时; 在静态代码块,不能在构造器中赋值
4.final类不能继承,但是可以实例化对象
5.如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承
6.一般来说如果一个类已经是final类了,就没有必要再将方法修饰成final方法了
7.final不能修饰构造方法(即构造器)
8.final和static往往搭配使用,效率更高,不会导致类的加载,底层编译器做了优化处理
9.包装类(Integer,Double,Float,Boolean等都是final),String也是final类
4.代码块
1.定义:
又称为初始化块,属于类中的成员(即是类的一部分),类似于方法,将逻辑语句封装在方法体中,通过{ }包围起来。但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类的显示调用,而是加载类时,或创建对象时隐式调用
2. 基本语法:
【修饰符】{代码};
1.修饰符可不写,要写的话,也只能写static
2.代码块分为两类,使用static修饰符的叫静态代码块,没用static的叫普通代码块
3.逻辑语句可以为任何逻辑语句(输入,输出,方法调用,循环,判断等)
4. ;可以写也可以省略
3.代码块的好处
1.相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作
2.如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性
(当我们不管调用哪个构造器,创造对象,都会先调用代码块的内容)
4.注意事项和细节
1.static代码块,作用就是对类进调用态属性,静态方法)
2.普通的代码块,在创建对象实例时,会被隐式调用。被创建一次,就会调用一次。如果只是使用类的静态成员时,普通代码块并不会执行。
3.可以这样简单理解,普通代码块是构造器的补充,若构造器被调用,则普通代码块也执行
4.创建一个对象时,在一个类 调用顺序是:(类加载肯定是在创建对象之前的)
1.调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样, 如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)
private static int n1 =getN1();//静态属性初始化
2.调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样, 如果有多个,则按照定义顺序调用)
3.调用构造器
5.构造器 的最前面其实隐含了(前面讲过) super()和 调用普通代码块,静态相关的代码块,属性初始化,在类加载时,就执行完毕,因此是优先于构造器和普通代码块执行的
class A{
public A(){//构造器
//隐藏执行
1.super()
2.调用普通代码块
system.out.printIn("ok");
}
}
5.调用顺序
创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
先完成类的加载,再创建对象
1.父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
2.子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
3.父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
4.父类的构造方法
5.子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
6.子类的构造方法
6.注意:
静态代码块(也是个静态方法)只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员