内部类
概念
在一个类中书写另一个类
分类
同级类(严格意义上来讲只是一种书写形式不是内部类)
成员内部类(全局内部类)
局部内部类(包含匿名内部类)
①同级类
在当前类同级下继续书写其他类,书写语法与普通类相同,但修饰符只能使用默认
在使用时与普通类一致,只是访问范围只有本包下,将相当于少创建了一个文件‘
//员工类
public abstract class Employee {
public String name;// 姓名
public int birthdayMonth;// 生日月份
public double salary;// 薪资
public abstract void getSalary(int month);
}
// 同级类的形式
class sale extends Employee {
public double saleMoney;// 销售额
public double rate;// 提成率
@Override
public void getSalary(int month) {
salary+=saleMoney*rate;
if(birthdayMonth==month){
salary+=100;
}
System.out.println("销售员"+name+month+"月份的工资为:"+salary);
}
}
②成员内部类(全局内部类)
书写在类体中的类
修饰符 class 类名称 {
修饰符 class 类名称 {
//...
}
//...
}
1
2
3
4
5
6
public class A {
int aa;
// 成员内部类
// 在一个类中书写另一个类
public class B {
// 内部类可以随意访问外部类(包含其他外部类)
public void b() {
// 直接访问当前外部类
A a = new A();
// 可以直接访问其他外部类
A1 a1 = new A1();
int b=A.this.a;//内部类可以直接使用外部类的属性
//由于就近原则当出现属性与外部类相同时,使用语法
//外部类.this.属性名进行指定
}
}
public void a() {
B b = new B();
b.b();
}
}
class A1 {
// 内部类的调用
public static void main(String[] args) {
// 1、间接调用
// 其他外部类不能直接访问但是书写内部类的外部类可以访问
// 在外部类声明方法创建内部类对象调用方法
// 在其他类中创建外部类调用内部类方法
A a = new A();
a.a();// 实际调用内部类b方法
// 2、直接调用
//直接在其他外部类创建内部类对象
//语法:外部类.内部类 标识符 =new 外部类().new 内部类();
A.B b=new A().new B();
//可以将内部类当做变量,如果想获取一个类的成员变量那么必须先创建这个类的对象
//之后因为是一个类 如果想使用必须创建对象
b.b();//直接使用B对象调用b方法
}
}
成员内部类总结:
1、书写在类体中的类
2、只能由当前类的外部类直接访问
3、可以直接访问外部类(其他外部类)
4、使用同名外部类变量时注意语法 外部类.this.属性名
5、其他外部类访问方式 间接方式(创建外部类通过外部类方法使用内部类) 直接方式(通过外部类直接创建内部类对象)
③局部内部类
如果类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。
修饰符 class 外部类名称 {
修饰符 返回值类型 外部类方法名称(参数列表) {
class 局部内部类名称 {
//...
}
}
}
1
2
3
4
5
6
7
public class B {
int b = 1;
// 局部内部类
// 在方法体中定义的类
public void b() {
int b = 2;
// 由于方法中变量在方法执行结束后会释放
// 并且只能由当前方法调用,所以修饰符不能使用public
class C {
int c = 3;
public void c() {
System.out.println(c);
System.out.println(b);// 可以直接使用方法中的变量
System.out.println(B.this.b);// 通过固定语法访问同名全局变量
// 当局部内部类使用方法中的变量时,一般使用final修饰
// 由于其数据存储空间不同,在执行时可能导致错误
// 1. new 出来的对象在堆内存当中。
// 2. 局部变量是跟着方法走的,在栈内存当中。
// 3. 方法运行结束后,立刻出栈,局部变量就会立刻消失。
// 4. 但是new出来的对象在堆当中持续存在,直到垃圾回收消失。
}
}
C c = new C();
c.c();
}
public void b1() {
// 其他方法不能调用局部内部类,只能通过间接调用
}
public static void main(String[] args) {
B b = new B();
b.b();
}
}
局部内部类总结:
1、书写在方法体中的类
2、只能由当前方法直接访问
3、可以直接访问外部类(其他外部类)
4、使用同名方法所在类变量时注意语法 外部类.this.属性名(对于方法中同名属性不能直接调用建议改名)
5、其他外部类(方法)访问方式 间接方式(通过访问方法的形式进行调用)
6、局部内部类使用方法中变量的值实际过程是创建空间将值复制过来进行使用,要求变量理论不变的原因,是因为回收时机不同,可能导致程序错误(局部内部类不建议使用方法中的属性进行属性的赋值)
修饰内部类的权限
public > protected > (default) > private
定义一个类的时候,权限修饰符规则:
外部类:public / (default)
成员内部类:都可以写,public > protected > (default) > private
局部内部类:什么都不能写,但不是default
匿名内部类
属于局部内部类,书写在方法中但创建类无需类名与class关键字,只需要书写方法体{}
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次。
那么这种情况下就可以省略调该类的定义,而改为使用【匿名内部类】。
匿名内部类用于创建子类或者实现类
接口(父类) 对象名 = new 类名或者接口名称() {
//覆盖重写所有抽象方法
};
1
2
3
public interface C {
void a();
void b();
void c();
}
class Test{
public static void main(String[] args) {
//匿名内部类就是省略类的声明与命名只书写类体{}
//一般用于只使用一次的子类或实现类
C c=new C(){
@Override
public void a() {
System.out.println("a");
}
@Override
public void b() {
System.out.println("b");
}
@Override
public void c() {
System.out.println("c");
}
};
//会直接使用匿名内部类创建一个唯一对象
//这个对象只有一个,因为没有类
//相当于使用类体临时创建了一个类并用其创建对象
c.a();
}
}