final关键字
- 采用final修饰的类不能被继承
- 采用final修饰的方法不能被覆盖
- 采用final修饰的变量不能被修改(只能赋一次值)
- final修饰的变量必须显示初始化
- final修饰的引用只能指向一个对象,该引用不能再次赋值,但被指向的对象可以修改
- 构造方法不能被final修饰
抽象类
- 采用abstract关键字定义的类就是抽象类,采用abstract关键字定义的方法就是抽象方法。
- 抽象方法只能出现在抽象类中
- 抽象类被子类继承后,抽象方法必须被重写。如果子类中不重写该抽象方法,则必须将此类再次声明为抽象类
- 抽象类不能被实例化
- 抽象类不能被final修饰
- 抽象方法不能被final修饰,是需要被子类实现的
抽象类中可以包含一些方法的实现,可以将一些公共代码放进抽象类中,也可以定义抽象方法,这样子类必须实现该方法。
接口
接口可以看作是抽象类的特殊情况,在接口中只能定义抽象的方法和常量,接口是完全抽象的。
- 接口采用interface声明
- 接口中的方法默认都是 public abstract 的,不能修改
- 接口中的变量默认都是 public static final 类型的,不能修改,必须显示的初始化
- 接口不能被实例化,接口中没有构造方法的概念
- 接口之间可以继承,但是接口之间不能实现
- 接口中的方法只能通过类来实现,通过implements关键字
- 如果一个类实现了接口,那么该接口中的所有方法必须被实现
- 类可以实现多个接口
声明方法,默认public abstract
interface StudentManager{
// 正确,等同于 public abstract void addStudent(int id,String name);
void addStudent(int id,String name);
//正确,加public修饰符的写法较多
public void delStudent(int id);
//编译错误,接口需要让其他类实现
private String findStudent(int id);
}
声明变量,需要显示初始化
interface StudentManager{
//正确,默认加入public static final
String YES="True";
//正确,开发中一般按照如下方式进行声明
public static final String NO="False";
//错误,必须显示赋值
int ON;
//错误,不能采用private声明
private static final int OFF=-1;
}
接口之间可以继承,但接口之间不能实现
interface inter1{
public void method1();
public void method2();
}
//接口可以继承
interface inter2 extends inter1{
public void method3();
}
//错误,接口不能实现接口,只能被类实现
interface inter3 implements inter2{
public void method4();
}
接口中方法必须全部实现
class InterImpl implements inter1{
@Override
public void method1() {
System.out.println("method1执行了!");
}
@Override
public void method2() {
System.out.println("method2执行了");
}
}
或者再次声明为抽象方法
abstract class InterImpl implements inter1{
@Override
public void method1() {
System.out.println("method1执行了!");
}
public abstract void method2();
}
类可以实现多个接口
实现多个接口,采用逗号隔开
class InterImpl implements inter1,inter2{
@Override
public void method1() {
System.out.println("method1 running");
}
@Override
public void method2() {
System.out.println("method2 running");
}
@Override
public void method3() {
System.out.println("method3 running");
}
}
接口的应用
接口描述了类需要做的事情,类要遵循接口的定义来做事,使用接口的好处有:
- 解决了Java单继承的问题
- 实现了可接插性(重要)
接口在开发中的应用,类似于多态在开发中的作用。
多态:面向抽象编程,而不是面向具体编程。降低程序的耦合度,提高程序的扩展力。
接口和抽象类的区别
- 抽象类是半抽象的,接口是完全抽象的
- 抽象类中有构造方法,接口中没有构造方法
- 接口和接口之间支持多继承,类和类之间只能单继承
- 一个类可以同时实现多个接口,一个抽象类只能继承一个类
- 接口描述了方法的特征,没有给出实现,解决了Java的单继承问题,实现了可接插性
- 抽象类给出了部分实现,抽象类是不能实例化的,抽象类的存在主要是可以把公共的代码移植到抽象类中
- 面向接口编程,而不要面向具体编程
- 优先选择接口,因为继承抽象类后,此类将无法再继承,会丧失此类的灵活性。
类之间的关系
- 泛化关系,类和类之间的继承关系及接口与接口之间的继承关系
- 实现关系,类对接口的实现
- 关联关系,类与类之间的连接,一个类可以知道另一个类的属性和方法,在Java语言中使用成员变量体现
- 聚合关系,是关联关系的一种,是整体和部分的关系,聚合关系的类处于不平等的层次上,一个代表整体,一个代表部分,在Java语言中使用实例变量体现
- 合成关系,比聚合关系强的关联关系,在Java语言中使用实例变量体现
- 依赖关系,在Java语言中体现为返回值,参数,局部变量和静态方法调用
访问控制权限
Java访问级别修饰符主要包括:private,protected和public,可以限定其他类对该类、属性和方法的使用权限。
修饰符 | 类的内部 | 同一个包下 | 子类 | 任何地方 |
---|---|---|---|---|
private | Y | N | N | N |
default | Y | Y | N | N |
protected | Y | Y | Y | N |
public | Y | Y | Y | Y |
内部类
在一个类的内部定义的类称为内部类
主要分为:
- 实例内部类
- 静态内部类
- 局部内部类
实例内部类
- 创建实例内部类,外部类的实例必须已经创建
- 实例内部类会持有外部类的引用
- 实力内部类不能定义static成员,只能定义实例成员
public class InnerClassTest01 {
private int a;
private int b;
InnerClassTest01(int a,int b){
this.a=a;
this.b=b;
}
//内部类可以用private和protected修饰
private class Inner1{
int i1=0;
int i2=a;
int i3=b;
}
public static void main(String[] args) {
InnerClassTest01.Inner1 inner1=new InnerClassTest01(1,2).new Inner1();
}
}
静态内部类
- 静态内部类不会持有外部的类的引用,创建时可以不用创建外部类
- 静态内部类可以访问外部的静态变量,如果访问外部类的成员变量必须通过外部类的实例访问
public class InnerClassTest01 {
static int a=1;
int b=2;
static class Inner2{
//在静态内部类可以定义实例变量
int i1=10;
//可以定义静态变量
static int i2=100;
//可以直接使用外部类的静态变量
static int i3=a;
//不能直接引用外部类的实例变量
//int i4=b;
//采用外部类的引用可以取得成员变量的值
int i4=new InnerClassTest01().b;
}
public static void main(String[] args) {
InnerClassTest01.Inner2 inner2=new InnerClassTest01.Inner2();
System.out.println(inner2.i1);
}
}
局部内部类
局部内部类是在方法中定义的,它只能在当前方法中使用。和局部变量的作用一样,局部内部类和实力内部类一致,不能包含静态成员。
public class InnerClassTest01 {
private int a=10;
//局部变量,在内部类中使用必须采用final修饰
public void method1(final int tmp){
class Inner3{
int i1=10;
//可以访问外部类的成员变量
int i2=a;
int i3=tmp;
}
//使用内部类
Inner3 inner3=new Inner3();
System.out.println(inner3.i3);
}
public static void main(String[] args) {
InnerClassTest01 Inner3=new InnerClassTest01();
Inner3.method1(100);
}
}
匿名内部类
是一种特殊的内部类,该类没有名字
- 没有使用内部类
public class InnerClassTest01 {
public static void main(String[] args) {
MyInterface myInterface=new MyInterfaceIpml();
myInterface.add();
}
}
interface MyInterface{
public void add();
}
class MyInterfaceIpml implements MyInterface{
@Override
public void add() {
System.out.println("add操作已执行!");
}
}
- 使用了内部类
public class InnerClassTest01 {
public static void main(String[] args) {
InnerClassTest01 Inner4=new InnerClassTest01();
Inner4.method1(new MyInterface(){
public void add() {
System.out.println("add操作已执行!");
}
});
}
private void method1(MyInterface myInterface){
myInterface.add();
}
}
interface MyInterface{
public void add();
}