1、static关键字:
- 修饰属性:static 修饰的属性是全局变量,所有的对象可以共同访问公用(不属于对象属于类,随着类的加载而加载,优先于对象存在)
- 修饰方法:类方法,类名直接调用
- 用static修饰的成员不可以直接访问非static修饰的成员(非static修饰的成员需要new在堆区先创建出来才能访问,而static修饰的成员是在常量池可以直接访问到)
- 没有加static修饰的成员可以直接访问加static修饰的成员
2、final关键字:
用final修饰的类不能再被其他类继承(最终版)
方法不希望被重写
final 修饰的变量是基本类型:那么变量存储的数据值不能发生改变
final 修饰的变量是引用类型:那么变量存储的地址值不能发生改变,对象内部的可以改变
3、static final常量:
使用static final修饰的成为常量跟变量相对,常量必须赋初始值,常量是不变的量,不能再次更改
常量命名所有的字母全部大写
public static final double PI = 3.14
4、abstract抽象类和抽象方法
抽象类:
- 抽象类里面可以没有抽象方法
- 抽象类不能实例化对象
- 使用abstract修饰的类属于抽象类
抽象方法:
- 抽象方法没有方法体
- 抽象方法必须在抽象类里
- 抽象方法必须在子类中被实现,除非子类是抽象类(类也必须加abstract修饰)
5、重写:
- 子类重写的方法必须和父类或者接口里面的方法名完全一样
- 子类重写的方法必须和父类或者接口里面的参数的类型以及参数的个数和参数类型的顺序完全一致
- 子类重写的方法返回值类型比父类或接口里面被重写的方法返回值类型更加严格,至少一致
6、interface接口
接口是一种特殊的抽象类
特点:
- 接口是完全抽象的
- 接口是一套规范
- 接口里面定义的字段属性全是常量,默认都有public static final修饰
- 接口里面定义的方法全是抽象方法,默认都有public abstract修饰
- 一个子类可以实现多个接口,但只能继承一个父类
- 接口可以继承接口,接口不能继承类
- 接口是若干常量和抽象方法的集合
- 注意:接口中声明的成员变量默认都是 public static final 的,必须显示的初始化。因而在常量声明时可以省略这些修饰符。
- JDK7以前:接口中只能定义抽象方法
- JDK8:接口中可以定义有方法体的方法(默认default,静态 static)
- JDK9:接口中可以定义私有方法
- 私有方法分为两种:普通的私有方法,静态的私有方法
6.1、接口中只能定义抽象方法,这些方法默认为 public abstract 的,因而在声明方法时可以省略这些修饰符。试图在接口中定义实例变量、非抽象的实例方法及静态方法,都是非法的。例如:
public interface SataHdd{
//连接线的数量
public int connectLine; //编译出错,connectLine被看做静态常量,必须显式初始化
//写数据
protected void writeData(String data); //编译出错,必须是public类型
//读数据
public static String readData(){ //编译出错,接口中不能包含静态方法
return "数据"; //编译出错,接口中只能包含抽象方法,
}
}
6.2、接口中没有构造方法,不能被实例化
6.3、 一个接口不能实现implements另一个接口,但可以继承多个其他接口。接口的多继承特点弥补了类的单继承。例如:
//串行硬盘接口
public interface SataHdd extends A,B{
// 连接线的数量
public static final int CONNECT_LINE = 4;
// 写数据
public void writeData(String data);
// 读数据
public String readData();
}
interface A{
public void a();
}
interface B{
public void b();
}
为什么使用接口
大型项目开发中,可能需要从继承链的中间插入一个类,让它的子类具备某些功能而不影响它们的父类。例如 A -> B -> C -> D -> E,A 是祖先类,如果需要为C、D、E类添加某些通用的功能,最简单的方法是让C类再继承另外一个类。但是问题来了,Java 是一种单继承的语言,不能再让C继承另外一个父类了,只到移动到继承链的最顶端,让A再继承一个父类。这样一来,对C、D、E类的修改,影响到了整个继承链,不具备可插入性的设计。
接口是可插入性的保证。在一个继承链中的任何一个类都可以实现一个接口,这个接口会影响到此类的所有子类,但不会影响到此类的任何父类。此类将不得不实现这个接口所规定的方法,而子类可以从此类自动继承这些方法,这时候,这些子类具有了可插入性。
接口的使用
接口的使用与类的使用有些不同。在需要使用类的地方,会直接使用new关键字来构建一个类的实例,但接口不可以这样使用,因为接口不能直接使用 new 关键字来构建实例。
接口必须通过类来实现(implements)它的抽象方法,然后再实例化类。类实现接口的关键字为implements。
如果一个类不能实现该接口的所有抽象方法,那么这个类必须被定义为抽象类。
不允许创建接口的实例,但允许定义接口类型的引用变量,该变量指向了实现接口的类的实例。
一个类只能继承一个父类,但却可以实现多个接口。
实现接口的格式如下:
修饰符 class 类名 extends 父类 implements 多个接口 {
实现方法
}
请看下面的例子:
import static java.lang.System.*;
public class Demo{
public static void main(String[] args) {
SataHdd sh1=new SeagateHdd(); //初始化希捷硬盘
SataHdd sh2=new SamsungHdd(); //初始化三星硬盘
}
}
//串行硬盘接口
interface SataHdd{
//连接线的数量
public static final int CONNECT_LINE=4;
//写数据
public void writeData(String data);
//读数据
public String readData();
}
// 维修硬盘接口
interface fixHdd{
// 维修地址
String address = "北京市海淀区";
// 开始维修
boolean doFix();
}
//希捷硬盘
class SeagateHdd implements SataHdd, fixHdd{
//希捷硬盘读取数据
public String readData(){
return "数据";
}
//希捷硬盘写入数据
public void writeData(String data) {
out.println("写入成功");
}
// 维修希捷硬盘
public boolean doFix(){
return true;
}
}
//三星硬盘
class SamsungHdd implements SataHdd{
//三星硬盘读取数据
public String readData(){
return "数据";
}
//三星硬盘写入数据
public void writeData(String data){
out.println("写入成功");
}
}
//某劣质硬盘,不能写数据
abstract class XXHdd implements SataHdd{
//硬盘读取数据
public String readData() {
return "数据";
}
}