zoukankan      html  css  js  c++  java
  • day09(上)_内部类

    成员内部类:

    /*
     内部类的访问规则:
     1.内部类(局部内部类和成员内部类)可以直接访问外部类中的成员,包括private
       之所以可以直接访问外部类中的成员,是因为内部类中持有了一个 外部类的 引用-->外部类.this
    
     2.外部类访问内部类非静态成员,必须建立内部类对象
     
     
     访问格式:
     当内部类定义在外部类的成员位置上,而且非私有,可以再外部其他类中,
     直接建立内部类对象来访问内部类成员
    外部类名.内部类名 变量名=外部类对象.内部类对象 Outer.Inner oi=new Outer().new Inner(); 3.当内部类在成员位置上,就可以被成员修饰符所修饰. 比如,private:将内部类在外部类中进行封装 static: 内部类就 具备static特性 当内部类被static修饰后,只能直接访问外部类中的static成员. 在外部其他类中,如何直接访问static内部类的非静态成员呢? new Outer.Inner().inMethod(); 注意:1.当内部类中定义了静态成员,该内部类必须是static的 2.当外部类中的静态方法访问内部类时,内部类也必须是静态的. 当描述事物时,事物的内部还有事物,该事物用内部类来描述. 因为内部事物在使用外内部事物的内容. 例如: class Body//人体 { private class Heart//更能反应事物之间的特性 { //这样心脏可以直接访问人体内的东西(例如血液) } public void show() { new Heart(); } } 什么时候定义内部类? 因此当一个类需要直接访问到另一个类中的成员时. 把这个类写到该类里面,把内部类封装不对外暴露, 对外提供方法来访问内部事物
    */ class Outer { private int x=3; private static int y=7; class Inner { int x=5; public void inMethod() { int x=6; System.out.println("this.x="+this.x+"\n"+"Outer.this.x="+Outer.this.x);//Outer.this.x访问外部类的x,Outer标识this是Outer的this //内部类可以直接访问外部类中的成员,包括private } } public static void outerMethod() { //当外部类中的静态方法访问内部类时,内部类也必须是静态的. //new inner().inMethod();//报错,inner加上静态 } static class Inner_2 { void function() { System.out.println("Inner_2 y="+y); } } static class Inner_3 { static void inMethod()//静态内部类的静态方法 { System.out.println("Inner_3 y="+y); } } } class InOutDemo { public static void main(String[] args) { new Outer().new Inner().inMethod();//非静态内部类 new Outer.Inner_2().function();//静态内部类 //new Outer().new Inner_2().function();//不能通过对象访问静态内部类 //报 限定的新静态类 Outer.Inner_3.inMethod();//访问静态内部类中的静态方法 } }
    Inner

    局部内部类:

    /*
    局部内部类
    1.不可以被成员修饰符修饰
    2.可以直接访问外部类中的成员,因为持有外部类中的引用.
      但是不可以访问它所在局部中的变量.只能访问被final修饰的局部变量
    */
    class Outer
    {
      int x=3;
      void method(final int a)//a必须为finnal才能被内部类访问
     {
        class Inner//局部内部类
        {
          
          final int y=6;//必须为final 原因在下面
          void function()//不能为static
          {              //如果为static,Inner必须为static
                         //static为成员修饰符,不能修饰局部Inner
           System.out.println("x="+Outer.this.x+"\ny="+y+"\na="+a);
          
          }
          
        }
        new Inner().function(); 
      }
      
    } 
    class Demo
    {
        public static void main(String[] args) 
        {
            new Outer().method(10);
        }
    }
    /*
    局部类访问局部变量,该变量必须被声明为final
    1. 经研究,Java虚拟机的实现方式是,
     编译器会探测局部内部类中是否有直接使用外部定义变量的情况,
     如果有访问就会定义一个同类型的变量(也有final修饰),然后在构造方法中用外部变量
     给自己定义的变量赋值。
    
    2.局部内部类对象中包含有 要访问的final型局部变量的一个拷贝,
      成为它的数据成员。因此,正是在这个意义上,final型局部变量的生命期,超过其方法的一次调用。
      严格来说,方法调用结束,所有的局部变量(含final)全死亡了。但:局部内部类对象中有final型局部变量的拷贝。
    
    以上为两种理解方式(大体相同)
    
    */
    LocalInnerClass

    3.匿名(无名)内部类

    /*
    匿名(无名)内部类:
    1.匿名内部类其实就是内部类的简写格式
    2.匿名内部类前提:
      内部类必须继承一个类或实现接口
    3.匿名内部类格式:
      new 父类或者接口(){定义子类的内容}
    
    4.其实匿名内部类就是一个匿名子类对象
      (带内容的对象)
    
    5.匿名内部类中定义的方法最好<3个(超出3个代码将变得冗长)
    */
    abstract class AbsDemo//抽象类
    {
      abstract void show();
    }
    
    class Outer
    {
        int x=5;
    /*
     ①
      class Inner extends AbsDemo
      {
        void show()
        {
         System.out.println("show:"+x);
        
        }
      
      }
      */
    
      public void function()
        {
          //② new Inner().show();
          //把① ②注释简写为:
         
          new AbsDemo()//匿名对象
          {
            void show()
           {
             System.out.println("x="+x);
    
           }
           
          }.show();
          //以上是一个对象,是AbsDemo子类的对象
          
          //通过匿名对象调用子类特有方法
           new AbsDemo()
          {
            void show()
           {
             System.out.println("x="+x);
    
           }
         
           void son()//子类特有方法
           {
            System.out.println("son");
           }
                 
     }.son();
         
          //通过父类的引用来调用
         AbsDemo ab= new AbsDemo()//多态 父类引用指向子类对象
         {
            void show()
           {
             System.out.println("x="+x);
    
            }
            void son()
            {
             System.out.println("son");
            }
         };
         ab.show();
         //ab.son();//编译失败,父类中无son()
                    //并且无法通过向下转型来调用son();
        }           //因为子类没名字!
    }
    class AnonyInnerDemo
    {
      public static void main(String[] args)
      {
       new Outer().function();
      }
    
    }
    AnonymousInnerClass2

    4.根据Test.function().method();填充代码:

    interface Inter
    {
      public abstract void method();
    
    }
    class Test
    {
      //法一:通过匿名内部类实现
      public static Inter function()
      {
        return 
        new Inter()
         {
              public void method()     
              {
              System.out.println("success");
              }
         };//整体为一个匿名子类对象,返回该对象
        
      }
       
       
       //法二:通过成员内部类来实现
        static class Inner implements Inter
         {
             public void method()     
              {
              System.out.println("Inner success");
              }
         }
        public static Inter function_2()
        {
          return new Inner();
          //如果不想把该Inner用static修饰,还可以通过外部类实例.内部类实例.method();
     //return new Test().new Inner().method();    
        }
         
    }
    class InnerTest
    {
        public static void main(String[] args) 
        {
            Test.function().method();
            
            Test.function_2().method();
      
          
          show(
             new Inter()
           {
            public void method()     
              {
              System.out.println("show success");
              }
     
           }
          );//可采用这种方式调用函数
        
         }
     
     //什么时候用匿名内部类?
    //当参数类型为接口类型,并且接口中的方法<3个
         public static void show(Inter in)//形参为接口类型
          {
            in.method(); 
          
          }
    
    
    }
    
    /*
    分析过程:
    Test.function()-->通过类名直接调用-->function一定有静态修饰符
    Test.function().method()-->说明function返回值为类 类型(对象)
                            -->这里要用匿名内部类-->一定为Inter类型
    */
    
     
     
     
     //当一个类没有声明父类,也可以用匿名内部类
    class Inner
    {
      public static void main(String[] args)
        {
             new Object()//Object所有类的父类 
            {
             void function()//子类特有方法
             {
              System.out.println("function()");
             }
          
            }.function();
        }
    
    }

                    InnerTest

    易错例子:

    //例一
    class Outer
    {
        class Inner
        {
     
        }
        public void func()
        {
        
          new Inner();
        }
        public static void main(String[] args)
        {
          Outer d=new Outer();
          new Outer().new Inner();//ok
          // new Inner();//不可以,内部类必须为static
          
          //类似于
          d.func();//ok,因为func()属于对象new Outer(),指明了对象
          func();//必须为static
        
        
         //new d.Inner();//格式错误->new new Outer().new Inner();
        }
    }
    //例二
    interface Test
    {
       public abstract void func();
    }
    class Demo
    {
        public static void main(String[] args)
        {
         //补足代码,匿名内部类-->调用show()
          new Demo().show(
            new Test()
            {
              public void func(){}
          
            });
        }
        void show(Test t)
        {
         
        
        }
    }
  • 相关阅读:
    从 0 开始带你成为消息中间件实战高手
    jenkins升级2.249版本后 节点(Node)配置的启动方式中没有Launch agent via Java Web Star
    Gradle build daemon disappeared unexpectedly (it may have been killed or may have crashed)
    centOS7 gradle版本升级
    使用PDB调试Python程序
    pytest在控制台的方式下提示找不到包
    docker-compose文件详解
    storm案例分析
    strom 简单案例
    springboot实现读写分离
  • 原文地址:https://www.cnblogs.com/yiqiu2324/p/2950773.html
Copyright © 2011-2022 走看看