java基础复习 - 8 - 抽象类、接口、内部类
抽象类
基本介绍
- 用abstract关键字修饰一个类时,这个类就叫抽象类 访问修饰符 abstract 类名{}
- 用abstract关键字修饰一个方法时,这个方法就是抽象方法 访问修饰符 abstract 返回类型 方法名(参数列表);
注意 - 抽象类不能被实例化
- 抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract方法
- 一旦类包含了abstract方法,则这个类必须声明为abstract
- abstract只能修饰类和方法,不能修饰属性和其它
- 抽象类可以有任意成员
- 抽象方法不能有主体
- 如果一个类继承了抽象类,则必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类
练习 - abstract final class A{}能编译通过吗? 错误final类不能被继承
- abstract public static void test2(); 能编译通过吗? 错误 static关键字和方法重写无关
- abstract private void test3();能编译通过吗?错误 私有的方法不能重写
接口
- 接口不能被实例化
- 接口中所有的方法都是public方法,接口中抽象方法可以不用abstract修饰
- 一个普通类实现接口,就必须将该接口的所有方法都实现
- 抽象类实现接口可以不用实现接口的方法
- 一个类同时可以实现多个接口
- 接口中的属性,只能是final的而且是public static final修饰符
- 接口中属性的访问形式:接口名.属性名
- 一个接口不能继承其它的类,但是可以继承多个别的接口 interface A extends B,C{}
- 接口的修饰符只能是public和默认,这点和类的修饰符是一样的
interface A{ int a = 23; } class B implements A{ } main中: B b = new B(); System.out.println(b.a); // 23 System.out.println(A.a); // 23 System.out.println(B.a); // 23
interface A{ int x = 0; // 看到接口的属性就等价于 public static final int x = 0; } class B{ int x = 1; // 普通属性 } class C extends B implement A{ public void pX(){ System.out.println(x);// 错误,原因不明确x是谁 System.out.println(A.x + " " + super.x); } public static void main(String[] args){ new C().px(); } }
内部类
一个类的内部又完整的嵌套了一个类结构。被嵌套的类成为内部类。
类的五大成员:属性、方法、构造器、代码块、内部类
- 定义在外部类局部位置上(比如方法内):
- 局部内部类(有类名)
- 匿名内部类(没有类名)
- 定义在外部类的成员位置上:
- 成员内部类(没用static修饰)
- 静态内部类(使用static修饰)
局部内部类
局部内部类是指定义在外部类的局部位置,比如方法中,有类名
- 可以直接访问外部类的所有成员包括私有的
- 不能添加访问修饰符,因为他的位置是一个局部变量。局部变量不能使用修饰符的。但是可以用final修饰,因为局部变量也可以使用final 不能被继承
- 作用域:仅仅在定义它的方法或代码块中
- 局部内部类 --- 访问 --- 外部类成员[访问方式:直接访问]
- 外部类 --- 访问 --- 局部内部类的成员 访问方式:创建对象,再访问
- 外部其它类 --- 不能访问 --- 局部内部类(因为局部内部类地位是一个局部变量)
- 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问 System.out.println(外部类名.this.n2)
public class LocalInnerClass { public static void main(String[] args) { Outer02 outer02 = new Outer02(); outer02.m1(); /* Outer02 初始化 inner初始化 n1 = 100 Outer02 m2 n2 = 800 n2 = 100 */ } } class Outer02 { public Outer02 () { System.out.println("Outer02 初始化"); } private int n1 = 100; private int n2 = 100; private void m2() { System.out.println("Outer02 m2"); } public void m1() { final class Inner02 { private int n2 = 800; public Inner02() { System.out.println("inner初始化"); } public void f1() { System.out.println("n1 = " + n1); m2(); System.out.println("n2 = " + n2); System.out.println("n2 = " + Outer02.this.n2); } } class Inner03 { } class Inner04 extends Inner03 { } Inner02 inner02 = new Inner02(); inner02.f1(); } }
匿名内部类
匿名内部类定义在外部类的局部位置,比如方法中,并且没有类名,匿名内部类既是一个类的定义,同时他本身也是一个对象
- 可以创建出来调用 Person person = new Person(){}; person.xx,也可以直接调用new Person().xx
- 属性重名时和局部内部类一样
成员内部类
成员内部类是定义在外部类的成员位置,且没有static修饰。
- 可以直接访问外部类的所有成员,包含私有的
- 可以添加任意的访问修饰符,因为他的地位就是一个成员
- 作用域和外部类的其它成员一样,为整个类体
- 成员内部类 --- 访问 --- 外部类(比如属性)[访问方式:直接访问]
- 外部类 --- 访问 --- 成员内部类 访问方式:创建对象再访问
- 外部其它类 -- 访问 --- 成员内部类
public class MemberInnerClass01 { public static void main(String[] args) { Outer08 outer08 = new Outer08(); outer08.t1(); // 外部其它类,使用成员内部类的三种方式 Outer08.Inner08 inner08 = outer08.new Inner08(); // 第二种方式 在外部类中编写一个方法,返回内部类的实例 Outer08.Inner08 inner081 = outer08.getInner08Instance(); // 第三种方式 Outer08.Inner08 inner082 = new Outer08().new Inner08(); } } class Outer08 { private int n1 = 10; public String name = "张三"; class Inner08 { public void say() { System.out.println("n1 = " + n1 + "name = " + name); } } public void t1() { // 使用成员内部类 Inner08 inner08 = new Inner08(); inner08.say(); } public Inner08 getInner08Instance() { return new Inner08(); } }
- 如果外部类和内部类的属性名重名,默认遵循就近原则,如果内部类要访问外部类的属性(外部类名.this.属性名)Outer08.this.name
静态内部类
静态内部类是定义在外部类的成员位置,并且有static修饰
- 可以直接访问外部类所有的静态成员,包含私有的,但不能直接访问非静态成员
- 可以添加任意的修饰符,因为它的地位就是一个成员
- 作用域:同其他的类成员,为整个类体
- 静态内部类--- 访问 --- 外部类(比如:静态属性)[访问方式:直接访问所有静态成员]
- 外部类 --- 访问 --- 静态内部类 访问方式:创建对象再访问
- 其他外部类创建静态内部类Outer10.Inner10 inner10 = new Outer10.Inner10();
- 如果外部类和静态内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问