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)
        {
         
        
        }
    }
  • 相关阅读:
    Python 学习日记 第七天
    Python 学习日记 第六天
    Python 学习日记 第五天
    Python 学习日记 第四天
    Redis 中的数据类型及基本操作
    Asp.net mvc 中View 的呈现(二)
    Asp.net mvc 中View的呈现(一)
    Asp.net mvc 中Action 方法的执行(三)
    Asp.net mvc 中Action 方法的执行(二)
    Asp.net mvc 中Action 方法的执行(一)
  • 原文地址:https://www.cnblogs.com/yiqiu2324/p/2950773.html
Copyright © 2011-2022 走看看