内部类

参考于:https://www.jianshu.com/p/0d0bd9046039

https://www.kuangstudy.com/

定义

内部类就是在一个类的内部在定义一个类

作用

  • 内部类方法可以访问该类定义所在的作用域的数据,包括私有的数据
  • 内部类可以对同一个包中的其他类隐藏起来,一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
  • 可以实现多重继承
  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷

分类

内部类分为四种:

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类

成员内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Outer { 
private int id;
public void out(){
System.out.println("这是外部类方法");
}
class Inner{
public void in(){
System.out.println("这是内部类方法");
}
}
}

public class Test{
public static void main(String[] args) {
//实例化成员内部类分两步
//1、实例化外部类
Outer outObject = new Outer();
//2、通过外部类调用内部类
Outer.Inner inObject = outObject.new Inner();
//测试,调用内部类中的方法
inObject.in();//打印:这是内部类方法
}
}

静态内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Outer { 
private int id;
public void out(){
System.out.println("这是外部类方法");
}
private static class Inner{
public void in(){
System.out.println("这是静态内部类方法");
}
}
}

public class Test{
public static void main(String[] args) {
//实例化静态内部类
//静态内部类能够直接被外部类给实例化,不需要使用外部类对象
Outer.Inner inner = new Outer.Inner();
}
}

注意:

  • 静态类不能访问非静态属性,包括自己类的非静态属性

提醒:

  • static修饰成员变量:整个类的实例共享静态变量
  • static修饰方法:静态方法,只能够访问用static修饰的属性或方法,而非静态方法可以访问static修饰的方法或属性
  • 被static修饰了的成员变量和方法能直接被类名调用。
  • static不能修饰局部变量,切记,不要搞混淆了,static平常就用来修饰成员变量和方法。

局部内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Outer { 
private int id;
public void out(){
System.out.println("这是外部类方法");
}
public void method(){
class Inner{
public void in(){
System.out.println("这是局部内部类");
}
}

Inner In = new Inner();
In.in();
}
}

注意

  • 如果要访问局部变量,那么该局部变量要用final修饰
  • 原因:如果不用final修饰,当局部内部类被实例化后,方法弹栈,局部变量随之跟着消失,这个时候局部内部类对象在想去调用该局部变量,就会报错,因为该局部变量已经没了,当局部变量用final修饰后,就会将其加入常量池中,即使方法弹栈了,该局部变量还在常量池中呆着,局部内部类也就还能够调用

匿名内部类

匿名对象:如果一个对象只要使用一次,那么我们只需要new Object().method(),而不需要给这个实例保存到该类型变量中去。

匿名内部类:我也只需要用一次,那我就不需要在类中先定义一个内部类,而是等待需要用的时候,我就在临时实现这个内部类,因为用次数少,可能就这一次,那么这样写内部类,更方便。工作中可能遇到的最多

  1. 匿名内部类需要依托于其他类或者接口来创建

    • 如果依托的是类,那么创建出来的匿名内部类就默认是这个类的子类

    • 如果依托的是接口,那么创建出来的匿名内部类就默认是这个接口的实现类。

  2. 匿名内部类的声明必须是在使用new关键字的时候

    • 匿名内部类的声明及创建对象必须一气呵成,并且之后能反复使用,因为没有名字。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test { 
public static void main(String[] args) {
//如果我们需要使用接口中的方法,我们只需要走一步,就是使用匿名内部类,直接将其 类的对象创建出来。
new Test1(){
public void method(){
System.out.println("实现了Test1接口的方法");
}
}.method();
}
}

interface Test1{
public void method();
}