1.1 概述
1、什么是内部类?
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
2、为什么要声明内部类呢?
总的来说,遵循高内聚低耦合的面向对象开发总原则。便于代码维护和扩展。
具体来说,当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,不在其他地方单独使用,那么整个内部的完整结构最好使用内部类。而且内部类因为在外部类的里面,因此可以直接访问外部类的私有成员。
3、内部类都有哪些形式?
根据内部类声明的位置(如同变量的分类),我们可以分为:
(1)成员内部类:
- 
静态成员内部类 
- 
非静态成员内部类 
(2)局部内部类
- 
有名字的局部内部类 
- 
匿名的内部类 
1.2 成员内部类
如果成员内部类中不使用外部类的非静态成员,那么通常将内部类声明为静态内部类,否则声明为非静态内部类。
语法格式:
【修饰符】 class 外部类{
    【其他修饰符】 【static】 class 内部类{
    }
}
1、静态内部类
有static修饰的成员内部类叫做静态内部类。它的特点:
- 
和其他类一样,它只是定义在外部类中的另一个完整的类结构 - 
可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关 
- 
可以在静态内部类中声明属性、方法、构造器等结构,包括静态成员 
- 
可以使用abstract修饰,因此它也可以被其他类继承 
- 
可以使用final修饰,表示不能被继承 
- 
编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名和$符号。 
 
- 
- 
和外部类不同的是,它可以允许四种权限修饰符:public,protected,缺省,private - 
外部类只允许public或缺省的 
 
- 
- 
只可以在静态内部类中使用外部类的静态成员 - 
在静态内部类中不能使用外部类的非静态成员哦 
- 
如果在内部类中有变量与外部类的静态成员变量同名,可以使用“外部类名."进行区别 
 
- 
- 
在外部类的外面不需要通过外部类的对象就可以创建静态内部类的对象(通常应该避免这样使用) 
其实严格的讲(在James Gosling等人编著的《The Java Language Specification》)静态内部类不是内部类,而是类似于C++的嵌套类的概念,外部类仅仅是静态内部类的一种命名空间的限定名形式而已。所以接口中的内部类通常都不叫内部类,因为接口中的内部成员都是隐式是静态的(即public static)。例如:Map.Entry。
2、非静态成员内部类
没有static修饰的成员内部类叫做非静态内部类。非静态内部类的特点:
- 
- 
可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关 
- 
可以在非静态内部类中声明属性、方法、构造器等结构,但是不允许声明静态成员,但是可以继承父类的静态成员,而且可以声明静态常量。 
- 
可以使用abstract修饰,因此它也可以被其他类继承 
- 
可以使用final修饰,表示不能被继承 
- 
编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名和$符号。 
 
- 
- 
和外部类不同的是,它可以允许四种权限修饰符:public,protected,缺省,private - 
外部类只允许public或缺省的 
 
- 
- 
还可以在非静态内部类中使用外部类的所有成员,哪怕是私有的 
- 
在外部类的静态成员中不可以使用非静态内部类哦 - 
就如同静态方法中不能访问本类的非静态成员变量和非静态方法一样 
 
- 
- 
在外部类的外面必须通过外部类的对象才能创建非静态内部类的对象(通常应该避免这样使用) - 
如果要在外部类的外面使用非静态内部类的对象,通常在外部类中提供一个方法来返回这个非静态内部类的对象比较合适 
- 
因此在非静态内部类的方法中有两个this对象,一个是外部类的this对象,一个是内部类的this对象 
 
- 
public class TestMemberInnerClass {
    public static void main(String[] args) {
        Outer.outMethod();
        System.out.println("-----------------------");
        Outer out = new Outer();
        out.outFun();
        System.out.println("####################################");
        Outer.Inner.inMethod();
        System.out.println("------------------------");
        Outer.Inner inner = new Outer.Inner();
        inner.inFun();
        System.out.println("####################################");
        Outer outer = new Outer();
//        Outer.Nei nei = outer.new Nei();
        Outer.Nei nei = out.getNei();
        nei.inFun();
    }
}
class Outer{
    private static String a = "外部类的静态a";
    private static String b  = "外部类的静态b";
    private String c = "外部类对象的非静态c";
    private String d = "外部类对象的非静态d";
    static class Inner{
        private static String a ="静态内部类的静态a";
        private String c = "静态内部类对象的非静态c";
        public static void inMethod(){
            System.out.println("Inner.inMethod");
            System.out.println("Outer.a = " + Outer.a);
            System.out.println("Inner.a = " + a);
            System.out.println("b = " + b);
//            System.out.println("c = " + c);//不能访问外部类和自己的非静态成员
//            System.out.println("d = " + d);//不能访问外部类的非静态成员
        }
        public void inFun(){
            System.out.println("Inner.inFun");
            System.out.println("Outer.a = " + Outer.a);
            System.out.println("Inner.a = " + a);
            System.out.println("b = " + b);
            System.out.println("c = " + c);
//            System.out.println("d = " + d);//不能访问外部类的非静态成员
        }
    }
    class Nei{
        private String a = "非静态内部类对象的非静态a";
        private String c = "非静态内部类对象的非静态c";
        public void inFun(){
            System.out.println("Nei.inFun");
            System.out.println("Outer.a = " + Outer.a);
            System.out.println("a = " 