首页 > 代码库 > Java笔记十八.内部类和匿名类

Java笔记十八.内部类和匿名类

内部类和匿名类
转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空)
一、内部类
1.定义
    在一个类内部定义类,即为嵌套类(内部类)。有如下几点特点:(1)嵌套类可以直接访问嵌套它的类的成员(变量和方法),包括private成员。但是,嵌套类的成员却不能被嵌套它的类直接访问。(2)内部类使得程序代码更为紧凑,程序更具模块化。
2.内部类实现方法
(1)类中定义和使用一个内部类
    在类中直接定义的嵌套类的使用范围,仅限于这个类的内部。内部类的定义和普通类的定义没有什么区别,内部类可以直接访问和引用它的外部类的所有变量和方法,就像外部类中的其他非static成员的功能一样,和外部类不同的是,内部类可以声明为private或protected
a.内部类被外部类引用
源码:innerClassDemo.java
//外部类
class Outer
{
  String name="我是外部类成员变量";
  void outerMethod()	//在外部类定义一个成员方法,实现创建一个内部类实例并调用其成员方法
  {
   inner in=new inner();
   in.dispaly();
  }
  //内部类
  class inner
  {
   void display()
   {
    System.out.println("Method of inner class print 'name'="+name);
   }
  }
}
/*-------------------------------------------*/
public class innerClassDemo {
 public static void main(String[] args)
 {
  Outer outer = new Outer();
  outer.outerMethod();
 }
}

打印信息:
技术分享
技术分享
分析:该源码实现了在外部类Outer中实现一个内部类inner,且在该内部类中定义一个成员方法来使用外部类的Outer的成员name。另外,只能在外部类Outer实例化内部类inner对象,在外部类之外实例化该内部类是不允许的,除非将inner声明为public(后面介绍)。
    从内存分布的角度分析,实际上在内部类对象保存了一个对外部类对象的引用(Outer.this),当内部类的成员方法中访问某一变量(方法)时,如果在该方法和内部类中都没有定义过这个变量调用就会被传递给内部类中保存的哪个外部类对象的引用。通过哪个外部类对象的引用调用这个变量(方法)。
技术分享
技术分享
注释:只有放this.变量不存在的情况下,传递给Outer.this.变量。
b.内部类被外部类以外的类引用
    内部类可以通过创建对象从外部类之外被调用.
(1)将内部类声明为public;
(2)在外部类以外的类,先创建一个外部类的实例再通过该实例创建内部类的实例
形式:
Outer outer = new Outer(); 
Outer.Inner inner=outer.new Inner(); 
源码:InnerClassDemo
//外部类
class Outer
{
 private int number=100;
 public class Inner
 {
  private int number=200;
  void print(int number)
  {
   System.out.println("I am innerClass"+"\n"+"参数number="+number+"\n"+"内部类成员         number="+this.number+"\n"+"外部类成员number="+Outer.this.number);
  }
 }
}
//外部以外的类
public class InnerClassDemo {
 public static void main(String[] string)
 {
  Outer outer = new Outer();	 //实例化一个Outer对象
  Outer.Inner inner=outer.new Inner();	//实例化一个Inner对象
  inner.print(300);//调用外部类的成员方法
 }
}

打印信息:
技术分享
技术分享
分析:观察上面的程序,你会发现三个number变量,其区别为:
number:引用的是print函数的形参;
this.number:引用的是Inner类中的成员变量;
Outer.this.number:引用的外部类Outer中的成员变量。
2.方法中定义的内部类
    嵌套类并非智能在类里定义,也可以在几个程序块的范围之内定义内部类。
源码:InnerDemo.java
//外部类
class Outer
{
 private String str="姚明";
 public void outerPrint()
 {
    int i=10; 
   //内部类
   class Inner
   {
    void dispaly(final int number)
    {
     
     System.out.println(str);
     System.out.println(number);
    //System.out.println(i);//这条语句是错误的,方法中的内部类不能访问方法的非final变量
    }
   }
   //实例化内部类并调用其成员方法
   Inner inner = new Inner();
   inner.dispaly(11);
 }
}
public class InnerDemo
{
 public static void main(String[] args)
 {
  Outer outer = new Outer();
  outer.outerPrint();
 }
}

打印信息:
技术分享
技术分享
分析:在方法汇总定义的内部类智能访问方法中的final类型的局部变量(不能访问i),因为用final定义的局部变量就相当于一个常量,它的声明周期查处方法运行的生命周期。

二、匿名内部类
1.匿名类
    在学习匿名内部类之前,我们先看下这样一个实例,即实现一个内部类,该内部类继承于另外一个类,表述为在类Outer中定义一个内部类Inner,Inner类又继承了类A。
源码:Outer.java
//类A
abstract class A
{
 abstract void display();
}
//Outer类,在其main方法中定义一个内部类,该内部类继承于类A
public class Outer {
 //main成员方法
 public static void main(String[] args)
 {
   //内部类
   class Inner extends A
   {
    void display() {
     System.out.println("I am Inner Class.");
    }
   }
   new Outer().callInner(new Inner());	//创建Outer实例并调用其成员方法,方法参数为内部类对象
 }
 //callInner成员方法
 public void callInner(A a)
 {
  a.display();
 }
}
打印信息:
技术分享
技术分享
分析:由new Outer().callInner(new Inner());可知在Outer.main方法中调用了Outer.callInner方法,传递给callInner方法的参数要求是一个实现了类A中的方法的子类对象。所以,我们在Outer.main方法中定义了一个继承于A类的内部类Inner,该Inner类仅在这里被使用了一次。
    对于上面的程序感觉太复杂了,那么我们有什么办法简写它呢?当然。其实,我们在调用callInner方法时,不用实现定义类的Inner,可以在给callInner方法传递参数时,临时创建一个类A的匿名子类的实例对象,代码如下:
源码:Outer.java
//类A
abstract class A
{
 abstract void display();	//声明一个抽象类
}
//外部类
public class Outer {
 //main成员方法
 public static void main(String[] args)
 {
  new Outer().callInner(new A(){
   void display() {
    System.out.println("I am childclass of A,but I have not name -'Inner'");
   }
  });
 }
 //callInner成员方法
 public void callInner(A a)
 {
  a.display();
 }
}
打印信息:
技术分享
技术分享
分析:  由程序打印的结果,我们可以看出Outer.main方法中调用了Outer.callInner方法,传递给callInner方法的参数要求是一个实现了类A中的方法的子类对象。在上面的程序中就相当于定义了一个类A的子类,但是这个子类是没有类名的,并且接着又创建了这个子类的一个实例对象,这样的类即为匿名类。
2.匿名类的形式
    假如我们实现实现了一个类A,那么它的匿名子类的一个实例对象可以这样表示。
形式:new A() { }
作用:产生一个类A的一个匿名子类的实例对象,匿名子类的所有实现代码(包括成员方法和成员变量)都要在那对大括弧间增加即可。

Java笔记十八.内部类和匿名类