一、内部类介绍
在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类
为什么需要内部类?
- 内部类继承自某个类或实现某个接口,内部类方法可以访问该类定义所在作用域中的数据,包括被 private 修饰的私有数据,这为外部类的访问提供了窗口
- 内部类可以实现 java 单继承的缺陷
- 我们想要定义一个回调函数,且只在一个地方使用,我们可以选择使用匿名内部类来实现,没必要再定义一个类
二、内部类分类
成员内部类
代码:
public class Circle {
private double radius = 0;
static int count =1;
public Circle(double radius) {
this.radius = radius;
getDrawInstance().drawSahpe(); //必须先创建成员内部类的对象,再进行访问
}
private Draw getDrawInstance() {
return new Draw();
}
class Draw { //内部类
public void drawSahpe() {
System.out.println(radius); //外部类的private成员
System.out.println(count); //外部类的静态成员
}
}
public static void main(String[] args) {
Circle circle = new Circle(2);
//第一种创建内部类对象方式
Circle.Draw draw = circle.new Draw(); //必须通过外部对象来创建
//第二种创建内部类方式
Circle.Draw draw1 = circle.getDrawInstance();
}
}
成员内部类是最普通的内部类,它的定义为位于另一个类的内部
- 成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
- 当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员
- 如果要访问外部类的同名成员,需要这样形式进行访问:外部类.this.成员变量/成员方法
- 在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问
- 外部类.内部类 XXX = 外部类实例.new 内部类();
- 外部类.内部类 XXX = new 外部类.内部类(); 和正常new对象差不多,只不过前面需要加上外部类
- 成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象
局部内部类
代码:
public class Animal {
private int i = 1;
public void test() {
final int a = 2; //范问局部变量必须final
class PartClass {
public void print() {
System.out.println("局部内部类");
i++;
System.out.println("i的值:" + i);
System.out.println("a的值:" + a);
}
}
PartClass p = new PartClass();
p.print();
}
public static void main(String[] args) {
Animal animal = new Animal();
animal.test();
System.out.println(animal.i);
}
}
运行结果:
局部内部类
i的值:2
a的值:2
2
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内
- 局部内类不允许使用访问权限修饰符 public private protected 均不允许
- 局部内部类对外完全隐藏,除了创建这个类的方法可以访问它其他的地方是不允许访问的
- 局部内部类可以引用方法的局部变量,但是该变量必须是final类型,并且不能修改该变量
静态内部类
代码:
public class ClassOuter {
private int noStaticInt = 1;
private static int STATIC_INT = 2;
public void fun() {
System.out.println("外部类方法");
}
public class InnerClass {
//static int num = 1; 此时编辑器会报错 非静态内部类则不能有静态成员
public void fun(){
//非静态内部类的非静态成员可以访问外部类的非静态变量。
System.out.println("静态变量 " + STATIC_INT);
System.out.println("非静态变量 " + noStaticInt);
}
}
public static class StaticInnerClass {
static int NUM = 1;//静态内部类可以有静态成员
public void fun(){
System.out.println(STATIC_INT);
//System.out.println(noStaticInt); 此时编辑器会报 不可访问外部类的非静态变量错
}
}
}
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static
- 静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似
- 静态内部类可以有静态成员,而非静态内部类则不能有静态成员
- 静态内部类可以访问外部类的静态变量,而不可访问外部类的非静态变量
匿名内部类
代码:
public class Button {
private int i = 1;
public void click(final int params){
final int a = 2;
//匿名内部类,实现的是ActionListener接口
new ActionListener(){
public void onAction(){
System.out.println("click action..." + params);
i++;
System.out.println("i的值:" + i);
//a++;
System.out.println("a的值:" + a);
}
}.onAction();
}
//匿名内部类必须继承或实现一个已有的接口
public interface ActionListener{
public void onAction();
}
public static void main(String[] args) {
Button button=new Button();
button.click(1);
}
}
匿名内部类就是没有名字的内部类,一般这个用的比较多,比如创建线程
- 匿名内部类是唯一一种没有构造器的类
- 匿名内部类必须继承一个抽象类或者实现一个接口
- 匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调
- 匿名内部类是没有访问修饰符的
- 匿名内部类可以使用final类型的局部变量,不能修改该变量
- 匿名内部类中不能存在任何静态成员或方法