Java内部类

package innerclass;

//在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类
public class Outter {
    /*private可以修饰数据成员,构造方法,方法成员,不能修饰类(此处指外部类,不考虑内部类)
    protected可以修饰数据成员,构造方法,方法成员,不能修饰类(此处指外部类,不考虑内部类)。
    内部类(静态/成员)可以看为是外部类的一个成员因此可以拥有private访问权限、protected访问权限、public访问权限及default(包访问权限)
    局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的*/
    static int a=1;
    int b=5;
    static void t1(){
        System.out.println("外部类的静态方法");
    }
    void t2(){
        System.out.println("外部类的非静态方法");
    }
    /*1.静态内部类:作为类的静态成员,存在于某个类的内部。
      静态内部类虽然是外部类的成员,但是在未创建外部类的对象的情况下,可以直接创建静态内部类的对象。静态内部类可以引用外部类的静态成员变量和静态方法,但不能引用外部类的普通成员。*/
    static class Inner1{
      public void test1(){
          System.out.println("直接访问外部类的静态成员变量:a的值为"+a);//直接引用外部类的静态成员变量
          t1();//直接引用外部类的静态方法
          //System.out.println("b的值为"+b);//试图引用外部类的非静态成员变量,不能通过编译
          //t2();//试图引用外部类的非静态方法,不能通过编译
          System.out.println("不能直接访问,只能通过 new 外部类().成员的方式访问外部类的非静态成员:b的值为"+new Outter().b);//静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员的方式访问
          new Outter().t2();
          System.out.println("静态内部类的方法~~~~~~~~~~~~~~~");
      }
    }
    /*2.成员内部类:作为类的成员,存在于某个类的内部。
      成员内部类可以调用外部类的所有属性和成员方法(包括private成员和静态成员),但只有在创建了外部类的对象后,才能创建成员内部类的对象。因此成员内部类不能包含静态方法和
      静态成员变量,因为静态变量是要占用内存的,在编译时只要是定义为静态变量了,系统就会自动分配内存给他,这也就成员内部类是外部类编译完编译的,也就是说,必须有外部类存在后
      才能有内部类,因为系统执行:运行外部类->静态变量内存分配->内部类,而此时内部类的静态变量先于内部类生成,这显然是不可能的,所以不能定义静态变量!*/
    class Inner2{
        public void test2(){
            int a = 20;
            int b=28;
            System.out.println("要访问外部类的同名成员,需要通过外部类().this.静态成员变量的方式:a的值为"+Outter.this.a);//访问外部类的静态成员变量
            System.out.println("发生隐藏现象访问的是成员内部类的静态成员变量:a的值为"+a);//发生隐藏现象访问的是成员内部类的成员
            t1();//调用外部类的静态方法
            System.out.println("要访问外部类的同名成员,需要通过外部类().this.非静态成员变量的方式:b的值为"+Outter.this.b);//访问外部类的非静态成员变量
            System.out.println("发生隐藏现象访问的是成员内部类的非静态成员变量:b的值为"+b);//发生隐藏现象访问的是成员内部类的成员
            t2();//调用外部类的非静态方法
            Outter.this.t2();
            System.out.println("成员内部类的方法~~~~~~~~~~~~~~~");
        }
       /*当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要进行访问:外部类().this.成员*/      
        void t2(){
            System.out.println("成员内部类的非静态方法");
        }
    }
    
    /*3.局部内部类:存在于某个方法的内部。
      局部内部类只能在方法内部中使用,一旦方法执行完毕,局部内部类就会从内存中删除。
      必须注意:如果局部内部类中要使用他所在方法中的局部变量,那么就需要将这个局部变量定义为final的。它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域*/
    public void test(){
        final int c=5;
        System.out.println("在外部类的方法中");
        class Inner3{
             void test3(){
                System.out.println("直接访问外部类的静态成员变量a的值为"+a);//访问外部类的静态成员变量
                t1();//调用外部类的静态方法
                System.out.println("直接访问外部类的非静态成员变量b的值为"+b);//访问外部类的非静态成员变量
                t2();//调用外部类的非静态方法
                System.out.println("访问他所在方法中的局部变量(必须用final修饰):c的值为"+c);//注意:如果局部内部类中要使用他所在方法中的局部变量,那么就需要将这个局部变量定义为final的(当局部内部类访问 局部变量 时,会扩大局部变量的作用域)。
                System.out.println("局部内部类的方法~~~~~~~~~~~~~~~");
             }
        }
        Inner3 inner3=new Inner3();
        inner3.test3();//局部内部类只能在方法内部中使用
    }
    
    public void Out(){
        //在外部类中如果要访问内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:
        new Inner2().test2();
        new Inner1().test1();
    }
    
    public static void main(String[] args) {
      Inner1 in1=new Inner1();//静态内部类的对象可以直接创建,无需先创建外部类的对象
      in1.test1();
      
      //Inner2 in=new Inner2();成员内部类的对象不能直接创建,会报错
      Outter out1=new Outter();//先创建外部类的对象
      Inner2 in2=out1.new Inner2();//注意:!!成员内部类的对象必须通过外部类的对象创建
      in2.test2();
      
      out1.test();
      
      /*4.匿名内部类:存在于某个类的内部,但是无类名的类。1)匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。
      2)匿名内部类不等定义构造器(构造方法,唯一一个有构造器的类),因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块。3)匿名内部类也是不能有访问修饰符和static修饰符的。*/
      Outter out2=new Outter(){
          public void test(){
              System.out.println("匿名内部类的方法test");
          }
      };
     /* say方法在Outter方法中不存在,只能通过下面的方法调用匿名内部类的自定义的方法say()非匿名内部类的对象。匿名内部类没有名字的内部类,无法用实例对象去调用它的方法,
      但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类继承了类Outter(抽象类和接口都可以)的test方法,因此可以借助Outter的对象去调用。*/
      new Outter(){
          public void test(){
              System.out.println("匿名内部类的方法test");
          }
          public void say(){
              System.out.println("匿名内部类的方法say");
          }
      }.say();//其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用say()和test()方法;
      out2.test();
    }
}

运行结果如下

直接访问外部类的静态成员变量:a的值为1
外部类的静态方法
不能直接访问,只能通过 new 外部类().成员的方式访问外部类的非静态成员:b的值为5
外部类的非静态方法
静态内部类的方法~~~~~~~~~~~~~~~
要访问外部类的同名成员,需要通过外部类().this.静态成员变量的方式:a的值为1
发生隐藏现象访问的是成员内部类的静态成员变量:a的值为20
外部类的静态方法
要访问外部类的同名成员,需要通过外部类().this.非静态成员变量的方式:b的值为5
发生隐藏现象访问的是成员内部类的非静态成员变量:b的值为28
成员内部类的非静态方法
外部类的非静态方法
成员内部类的方法~~~~~~~~~~~~~~~
在外部类的方法中
直接访问外部类的静态成员变量a的值为1
外部类的静态方法
直接访问外部类的非静态成员变量b的值为5
外部类的非静态方法
访问他所在方法中的局部变量(必须用final修饰):c的值为5
局部内部类的方法~~~~~~~~~~~~~~~
匿名内部类的方法say
匿名内部类的方法test

参考博客链接:

https://www.cnblogs.com/hapjin/p/5744478.html

https://www.cnblogs.com/dolphin0520/p/3811445.html

转载请于明显处标明出处:

http://www.cnblogs.com/AmyZheng/p/8442927.html

原文地址:https://www.cnblogs.com/AmyZheng/p/8442927.html