疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java中内部类详解


 

 
/*
 内部类的访问规则:
 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+" "+"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();//访问静态内部类中的静态方法
    }
 
}
 
 
 
局部内部类:
 
 
/*
局部内部类
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+" y="+y+" a="+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型局部变量的拷贝。
 
以上为两种理解方式(大体相同)
 
*/
 
 
 
 
 
 
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();
  }
 
}
 
 
 
 
 
 
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();
    }
}
 
 
 
                
 
 
易错例子:
 
 
//例一
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)
    {
     
    
    }}