内部类和匿名类
转载请表明出处: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的一个匿名子类的实例对象,匿名子类的所有实现代码(包括成员方法和成员变量)都要在那对大括弧间增加即可。