内部类

一、设计模型之模板模型

  1. 定义
    • 使用接口制定规则,然后子类根据接口实现不同的方法的内部代码
    • 实现类暴露的可用方法必须和接口中的相同
  2. 案例
    • 执行汽车接口,里面规定的是汽车的基本要素
    • 子类根据规则,实现不同功能的模板

二、成员内部类

  1. 定义

    • 内部类就是类的内部定义另一个类
    • 当一个类中的成员过多的时候,再次对类中的成员进行分组
  2. 使用

    • 内部类可以直接访问外部类的成员,包括私有的

      • 外部类名.this.成员
    • 外部类调用内部类成员,必须先创建对象

      • 内部类 对象 = 内部类对象
      • 内部类 对象名 = new内部类()
      public class Outer{
          //外部类非静态方法
          public void outerMethod(){
              System.out.println("外部类方法");
              //外部类调用内部类方法,必须先创建内部类对象
              Inner inner = new Inner();
              inner.innerMerthod();
          }
          
          class Inner{
              //内部类非静态方法
              public void innerMethod(){
                  //内部类调用外部类非静态方法
                  //Outer.this.outerMethod();
                  //如果没有相同的方法,可以省略前缀
                  outerMethod();
              }
          }
      }
      
    • 别的类要访问内部类的成员,就必须创建对象

      • 外部类名.内部类名 对象名 = 外部类对象.内部类对象

      • 外部类.内部类. 对象名 = new 外部类().new 内部类()

        public static void main(String[] args){
            //创建内部类对象,必选先创建外部类对象
            Outer.Inner inner = new Outer().new Inner();
            //调用内部类的方法
            inner.innerMethod();
        }
        
  3. 内部类的权限

    • 内部类的权限和成员方法一样,可以有private、默认、protected、public
    • 外部类只能是public和默认的
    • private效果等同于私有化方法,别的类无法直接调用,但是外部类可以调用,可以通过方法return回去
    • 我们完全可以把内部类当做是一个类中的方法看待
    • 内部类同时具备方法和类的所有权益
  4. 演示

    public class Outer{
        //外部类非静态方法
        public void outerMethod(){
            //私有的内部类只能在外部类中使用
            Inner inner = new Inner();
            inner.innerMethod();
        }
        //只能在内部使用
        private class Inner{
            //内部类非静态方法
            public void innerMethod(){
                
            }
        }
    }
    
    public static void main(String[] args){
        //外部类直接调用private修饰的内部类时,会报错
        Outer.Inner inner = new Outer().new Inner();//报错
    }
    
  5. 总结

    • 为什么使用成员内部类?

      • 当一个类中的成员过多的时候,再次对类中的成员进行分组
    • 特性:怎么样创建内部类的对象?

      • 外部类对象.内部类对象

        Outer.Inner inner = new Outer().new Inner();
        
    • 内部类的类名是什么?

      • 外部类名.内部类名

        Outer.Inner
        
  6. 测试题

    判断输出结果

    public class Outer{
        public void method(){
            System.out.println("外部类method方法");
            method2();
        }
        public void method2(){
            System.out.println("外部类method2方法");
        }
        public class Inner{
            public void method(){
                 System.out.println("内部类method方法");
             method2();
             }
             public void method2(){
                 System.out.println("内部类method2方法");
                 Outer.this.method2();
             }   
        }
    }
    
    public static void main(String[] args){
        Outer.Inner inner = new Outer().new Inner();
        inner.method();
    }
    

三、静态内部类

  1. 定义

    • 使用static关键字修饰内部类
  2. 使用

    • 调用静态内部类内部的非静态方法

      • 外部类名.内部类名 对象名 = new 外部类名.内部类名();
      public class Outer {
         //静态内部类
         public static class Inner{
             //静态内部类的非静态方法
             public void innerMethod(){  
             }
         }
      }
      
      public static void main(String[] args) {
         //创建内部类对象 
         Outer.Inner inner = new Outer.Inner();
         //调用内部类的方法
         inner.innerMethod();
      }
      
    • 调用静态内部类内部的静态方法

      • 外部类名.内部类名.方法()
      public class Outer {
         //静态内部类
         public static class Inner{
             //静态内部类的静态方法
             public static void innerMethod(){
                 
             }
         }
      }
      public static void main(String[] args) {
         //类名调用
         Outer.Inner.innerMethod();
      }
      
    • 静态内部类调用外部类的非静态方法

      • 必须先new出外部类然后才能调用
      public class Outer {
         //外部类非静态方法
         public void outerMethod(){
             System.out.println("外部类的非静态方法");
         }
         //静态内部类
         public static class Inner{
             //静态内部类非静态方法
             public void innerMethod(){
                 //必须先创建外部类的对象
                 new Outer().outerMethod();
             }
         }
      }
      
  3. 注意事项

    • 内部类如果有静态方法,那么内部类就必须也是静态的
    • 内部类时静态的,并不意味着内部类中的方法都是静态的,只是说明我们可以绕过外部类对象之间找到内部类来使用

四、局部内部类

  1. 定义

    • 定义在类中的方法中的内部类叫做局部内部类(用的很少)
  2. 使用

    • 局部内部类的作用范围仅限于本方法中
    • 局部内部类在访问他所在方法中的局部变量必须用final修饰
      • 因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用
      • jdk1.8 取消了这个定义,其实不是取消了,而是设置了隐式的
  3. 演示

    public static void main(String[] args) {
     //局部内部内使用局部变量必须是final的
     final String name = "小红";
     
     //局部内部类
     class Inner{
         public void method(){
             System.out.println("局部内部类");
         }
         public String method2(){
             return name + "我爱你";
         }
     }
     Inner inner = new Inner();
     inner.method();
     inner.method2();
    }
    

五、匿名内部类

  1. 定义

    • 匿名内部类就是内部类的简写形式,相当于是一个没有名字的子类
    • 匿名内部类用于定于接口的或者类的子类
  2. 使用

    • 前提是必须存在一个类,或者接口
    • 这里的类可以是具体的类也可以是抽象类
    • 相当于是有一个没有名字的子类继承或者实现一个类或接口,然后重写里面的方法,本质是一个继承了该类或者实现了该接口的匿名子类对象
    • 对用于规则简单,子类是有很少的接口应用中
  3. 格式

    new 类名或者接口名(){

    ​ 重写方法;

    }

  4. 演示

    public static void main(String[] args) {
     //匿名部内部类
     MyInterface mi = new MyInterface() {
         @Override
         public void method() {  
             System.out.println("重写接口的方法");
         }
     };
    }
    

总结

  1. 成员内部类
    • 对类的成员在分组
    • 分组完成之后,内部类中的成员没有办法直接调用了,必须先创建外部类对象
    • 外部类对象.内部类对象
    • 内外部类成员之间互相调用的问题
      • 内部类成员可以直接使用外部类的成员,外部类成员不能直接使用内部类的成员,如果要使用,必须先创建对象
      • 如果内部类中出现了和外部类相同的名称的成员(就近原则),如果内部类必须要调用外部类的同名成员时,使用外部类名.this.成员
  2. 静态内部类
    • 成员内部类的写法造成了内部类的静态成员无法使用
    • 将内部类也变成静态的
    • 其他的成员之间的调用遵循的是静态的特性
  3. 局部内部类
    • 当一个类只在当前方法内使用的时候
    • 局部内部类使用局部变量的时候,变量要加上final关键字
    • jdk1.8 版本之后,编译器如果发现局部内部类中使用到了局部变量,会自动添加final关键字,否则不添加,为了提高内存利用率和简化书写
  4. 匿名内部类
    • 当一个类只使用一次的时候(省的起名字)
    • 局部内部类有的特性,匿名内部类都有
  5. 简写的一定有局限性
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354