内部类
成员内部类
- 内部类就是在一个类的内部再定义一个类。内部类可以是静态的,也可以用public、default、protected和private 修饰,而外部类只能使用public 和default 修饰。
- 成员内部类的方法可以直接访问外部类的所有数据,包括私有的数据
- 定义了成员内部类后,必须使用外部类对象来创建内部类对象。即:内部类 对象名=外部类对象.new 内部类();
- 成员内部类class 文件格式为“外部类名$内部类名.class”。
- **外部类不能直接使用内部类的成员和方法。**可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法。
- 如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法。如果内部类要访问外部类的成员变量,可以使用this 关键字。
- 外部类的外部要声明完整,如外部类名.内部类名,外部类内部则不需要;
package com.test;
public class Test {
private int a = 100;
int b = 5;
public class Inner {
int b = 3;
public void test() {
System.out.println("访问外部类中的a:" + a);
System.out.println("访问外部类中的b:" + Test.this.b);
}
}
public static void main(String[] args) {
Test o = new Test();
//通过外部类对象创建内部类对象
Inner i = o.new Inner();
i.test();
}
}
输出:
访问外部类中的a:100
访问外部类中的b:5
匿名内部类
匿名内部类就是没有名字的内部类,多用于关注实现而不关注实现类的名称。匿名内部类是唯一的没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。
局部内部类
局部内部类是定义在一个方法或者一个作用域中的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。注意,局部内部类就像是方法中的一个局部变量一样,是不能有public、protected、private 以及static 修饰符的。
静态内部类
静态内部类也是定义在另一个类中的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这一点和类的静态成员属性有点类似,并且它不能使用外部类的非静态成员变量或者方法。
- 静态内部类不能直接访问外部类的非静态成员,但可以通过“new 外部类().成员”的方式访问。
- 如果外部类的静态成员与内部类的成员名称相同,可通“类名.静态名”访问外部类的静态成员;否则可通过成员名直接调用外部类的静态成员。
- 创建静态内部类中的对象时,不需要外部类的对象,可以直接创建,格式为:内部类名 对象名 = new 内部类名();
- 在其他类中创建内部类的对象时,不需要用外部类对象创建,格式为:外部类名.内部类名 对象名 = new 外部类名.内部类名();
package com.test;
public class Test {
private int a = 100;
static int b = 5;
public static class Inner {
int b = 3;
public void test() {
System.out.println("外部类的b:" + Test.b);
System.out.println("内部类的b:" + b);
System.out.println("外部类的非静态变量a:" + new Test().a);
}
}
public static void main(String[] args) {
Inner inner = new Inner();
inner.test();
}
}
输出:
外部类的b:5
内部类的b:3
外部类的非静态变量a:100
抽象类
抽象类要使用abstract 关键字声明,抽象类的使用原则:
- 抽象方法必须为public 或者protected,默认为public。
- 抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理。
- 抽象类必须有子类,使用extends 继承,一个子类只能继承一个抽象类
- 子类如果不是抽象类,则必须重写抽象类中的全部抽象方法。
- 抽象类不能使用final 关键字声明,因为抽象类必须有子类,而final 定义的类不能有子类。
抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现
package com.test;
public abstract class Action {//定义一个抽象行为类
//定义常量,表示不同的行为
public static final int EAT = 1;
public static final int SLEEP = 2;
public static final int WORK = 5;
//定义不同行为的抽象方法
public abstract void eat();
public abstract void sleep();
public abstract void work();
public void commond(int flags) {
switch (flags) {
case EAT:
this.eat();
break;
case SLEEP:
this.sleep();
break;
case WORK:
this.work();
break;
case EAT + SLEEP:
this.eat();
this.sleep();
break;
case SLEEP + WORK:
this.sleep();
this.work();
break;
default:
break;
}
}
}
package com.test;
public class Human extends Action {// 定义一个类Human继承类Action
// 实现抽象方法
public void eat() {
System.out.println("人吃饭");
}
public void sleep() {
System.out.println("人睡觉");
}
public void work() {
System.out.println("人工作");
}
}
package com.test;
public class Robot extends Action {// 定义一个类Robot继承类Action
// 实现抽象方法
public void eat() {
System.out.println("机器人充电");
}
public void sleep() {
System.out.println("机器人无需睡觉");
}
public void work() {
System.out.println("机器人工作");
}
}
package com.test;
public class Test {
public static void main(String[] args) {
show(new Robot());
show(new Human());
}
//子类向上转型的方式进行抽象类的实例化
public static void show(Action act) {
//相当于多态
act.commond(Action.EAT);
act.commond(Action.WORK);
act.commond(Action.SLEEP);
}
}
输出:
机器人充电
机器人工作
机器人无需睡觉
人吃饭
人工作
人睡觉