什么是内部类?
定义在一个类的内部的类
内部类的作用
-
内部类和外部类可以相互访问其成员--无条件地访问外围类的所有元素
-
通过内部类,可以实现多继承(解决单继承的缺陷)--实现多重继承
-
内部类可以对同一包中的其他类隐藏起来--实现隐藏
-
当我们想要定义一个回调函数却不想大量代码的时候可以选择匿名内部类来实现--通过匿名内部类来优化简单的接口实现
内部类与外部类的关系
1.对于非静态内部类,内部类的创建依赖外部类的实例对象,在没有外部类实力之前是无法创建内部类的
2.内部类是一个相对独立的实体,与外部不是继承关系
3.创建内部类的时刻并不依赖于外部类的创建
内部类的分类
静态内部类和非静态内部类。
非静态内部类又可以分为:成员内部类,方法内部类,匿名内部类。
静态内部类和非静态内部类的区别
静态内部类可以拥有静态成员变量,非静态内部类没有静态成员变量。
静态内部类不可以访问外部类的非静态变量,而非静态内部类可以访问外部类的非静态变量
无论是静态内部类还是非静态内部类都可以访问外部的静态变量
静态内部类的创建不依赖于外部类,而非静态内部类的创建依赖于外部类
public class ClassOuter {
private int noStaticInt = 5;
private static int STATIC_INT = 1;
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); //此时编辑器会报 不可访问外部类的非静态变量错
}
}
}
public class TestInnerClass {
public static void main(String[] args) {
//非静态内部类 创建方式1
ClassOuter.InnerClass innerClass = new ClassOuter().new InnerClass();
//非静态内部类 创建方式2
ClassOuter outer = new ClassOuter();
ClassOuter.InnerClass inner = outer.new InnerClass();
//静态内部类的创建方式
ClassOuter.StaticInnerClass staticInnerClass = new ClassOuter.StaticInnerClass();
}
}
分类:
成员内部类:
定义: 成员内部类定义在外部类的内部,相当于外部类的一个成员变量的位置,成员内部类可以使用任意的访问权限修饰符。
-
内部类在外部使用时,无法直接实例化,需要借助由外部信息才能完成实例化操作
-
内部类的访问权限修饰符任意,但是访问范围会受影响
-
内部类可以直接访问外部类的成员属性,如果有同名属性,默认会调用内部类的属性
-
可以通过 外部类.this.同名变量的形式访问外部类的同名属性
-
内部类编译后的储存命名格式是:外部类$内部类.class
-
内部类中包含外部类同名方法时,若在内部类中使用外部类同名方法格式:外部类.this.同名方法
方法内部类:
定义: 如果一个内部类只在一个方法中使用到了,那么我们可以将这个类定义在方法内部,这种内部类被称为方法内部类。其作用域仅限于该方法。
-
局部内部类不允许使用访问修饰权限符(public,private,protected)均不允许和static修饰符
-
局部内部类对外完全隐藏,除了创建这个类的方法可以访问它其他的地方是不允许访问的
匿名内部类:
定义: 没有类名的类,创建在只需要使用一次的类
-
匿名内部类是没有访问修饰符的
-
匿名内部类不能是抽象的,匿名内部类必须继承一个抽象类或者实现一个接口,二者不可兼得
-
匿名内部类中不能存在任何静态成员或方法
-
匿名内部类是没有构造方法的,因为它没有类名
-
匿名内部类为方法内部类时,方法内部类的所有限制同样对匿名内部类生效
静态内部类:
-
静态内部类中,可以直接访问外部类的静态成员。如果要访问外部类的非静态成员,需要用外部类对象的实例化
-
静态内部类对象实例时,可以不依赖外部类的实例
-
可以通过外部类.内部类.静态方法的形式调用静态内部类的静态成员
-
当内部类属性与外部类属性同名时,内部类默认调用的时内部类的成员变量
如果需要访问外部类的静态属性,可以通过外部类.属性名的方式获取
如果需要访问外部类的非静态属性,通过new 外部类().属性的方式获取