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)
    {
     
    
    }
}
posted @ 2013-03-08 21:12  伊秋  阅读(263)  评论(0编辑  收藏  举报