概述

1.基本定义
  • 可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
  • 内部类一般包括四种:成员内部类、局部内部类、匿名内部类和静态内部类
2.内部类特点
  • 内部类是一种编译时的语法,编译后生成的两个类是独立的两个类。
  • 内部类可以访问外部类的任何成员,但外部类不能直接访问内部类的成员。
  • 内部类可为静态,可以用public、protected、private修饰,而外部类只能使用public和缺省的包访问权限。
  • 用内部类定义在外部类中不可访问的属性。这样就在外部类中实现了比外部类的private还要小的访问权限。
四种内部类
1.成员内部类
  • 成员内部类是最普通的内部类,它的定义为位于另一个类的内部
  • 作为类的一个方法存在,地位与成员方法相同
//外部类:不可用private修饰,public和缺省都可以
//公有的外部类只能定义一个,而且名字必须与文件名一致
public class OuterClassA {
    //成员属性和成员方法
    private String outterstr;
    private int num = 10;

    public void setOutterstr(String outterstr) {
        this.outterstr = outterstr;
    }

    public String getOutterstr() {
        return outterstr;
    }

    //不能直接访问内部类的成员
    //先创建内部类的对象,再访问内部类的成员
    public void outerFun(){
        //setInnerStr("abc");
        InnerClassA innerClassA = new InnerClassA();
        innerClassA.setInnerStr("abc");

        //System.out.println(InnerClassA.this.num);
    }

    //成员内部类(地位与成员方法一致)
    //不会再出外部类的地方使用
    public class InnerClassA {
        //成员属性和方法
        private String innerStr;
        private int num = 20;

        public void setInnerStr(String innerStr) {
            this.innerStr = innerStr;
        }

        public String getInnerStr() {
            return innerStr;
        }

        public void innerFun(){
            //成员内部类中,可以访问外部类的所有成员
            setOutterstr("abc");
            System.out.println(num);//内部类定义的num属性
            System.out.println(this.num);//内部类定义的num属性
            System.out.println(OuterClassA.this.num);//外部类定义的num属性
        }
    }
}
  • 创建成员内部类的对象,先创建外部类的对象,通过外部类加点号的方法创建内部类对象
OuterClassA outerClassA = new OuterClassA();
InnerClassA innerClassA = outerClassA.new InnerClassA();

OuterClass.InnerClass  inner  = new OuterClass().new  InnerClass ();
2.局部内部类
  • 局部内部类是定义在一个方法或者一个作用域里面的类
  • 地位同局部变量
  • 局部内部类不能加修饰符public、protected和private,其范围为定义它的代码块。
  • 可以访问外包方法之外外部类之内的所有成员。还可以访问所在外包方法中的参数。
  • 局部内部类只能访问局部中被final修饰的局部变量。
  • 局部内部类不能声明为接口
public class OuterClassb {
    //成员属性和成员方法
    private String outterstr;
    private int num = 10;

    public void setOutterstr(String outterstr) {
        this.outterstr = outterstr;
    }

    public String getOutterstr() {
        return outterstr;
    }

    public void outerFun(){
        //局部常量,在局部内部类中不允许改变值(final可以省略)
        int num = 0;
        //局部内部类,限定在方法内部(地位同局部变量)
        class InnerClassB{
            //成员属性和方法
            String innerStr;

            public void setInnerStr(String innerStr) {
                this.innerStr = innerStr;
            }

            public String getInnerStr() {
                return innerStr;
            }

            public void innerFun(){
                //局部内部类中可以直接访问外部类的所有成员属性和方法
                outterstr = "abc";
                setOutterstr("abc");
            }
        }

        //创建局部内部类的对象
        InnerClassB innerClassB = new OuterClassA().new InnerClassB();
    }
}
  • 要想使用局部内部类时,需要生成外部类对象,通过外部类对象调用外包方法,在方法中才能调用局部内部类。
3.匿名内部类
  • 匿名类是不能有名字的类,它们不能被引用,只能在创建时用 new 语句来声明它们。
  • 匿名类没有类名,它必须继承一个类或是实现一个接口。不能有显示的extends和implements子句。
  • 匿名类不能有构造函数并且只能一次性的创建其对象
  • 匿名类可以在方法体中,也可以在参数列表中。
public static void staticFun(Itext iTest){
    iTest.test();
}

staticFun(new Itext() {
    //内部类定义范围
    @Override
    public void test() {
        System.out.println("参数中使用匿名内部类");
    }
});
  • 匿名内部类必须实现它的抽象父类或者接口里的所有抽象方法
public interface Itext {
    void test();
}

public class OuterClassC {
    private String outterstr;
    private int num = 10;

    public void setOutterstr(String outterstr) {
        this.outterstr = outterstr;
    }

    public String getOutterstr() {
        return outterstr;
    }

    public void outerFun(){
        //匿名内部类(地位同局部变量,是一种特殊的局部内部类)
        //定义的是一个接口的实现类,或者是基类的派生类
        //匿名内部类的定义和对象的创建在同一个语句中
        //匿名内部类只有唯一的一个对象
        Itext iTest = new Itext() {
            //大括号里边就是匿名内部类的范围
            @Override
            public void test() {
                System.out.println("在匿名内部类中重写的方法");
            }
        };//不要丢分号(;)
        iTest.test();//执行的重写的方法
    }
}
4.静态内部类
  • 静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static
  • 静态内部类的对象可以直接生成。
  • 静态内部类能直接访问外部类的静态成员,不能直接访问外部类的非静态属性成员(外部类的对象访问)。
  • 静态内部类里面可以定义静态成员,其他内部类不可以。
  • 如果内部类中定义了静态成员,该内部类也必须定义为静态的。
public class OuterClassD {
    //成员属性和成员方法
    private String outerStr;

    public void setOuterStr(String outerStr) {
        this.outerStr = outerStr;
    }

    public String getOuterStr() {
        return outerStr;
    }
    public static void fun() {
        System.out.println("外部类的静态方法");
    }
    //静态内部类
    public static class InnerClassD{
        //成员属性和方法
        private String innerStr;
        private int num = 20;

        public void setInnerStr(String innerStr) {
            this.innerStr = innerStr;
        }

        public String getInnerStr() {
            return innerStr;
        }
        //可以定义静态的成员(其他内部类中不允许)
        public static void innerFun() {
            //静态内部类中不能访问外部类的非静态成员
            fun();
            System.out.println("静态内部类定义的静态方法");
        }
    }
}