java学习笔记内部类总结


内部类

内部类(inner class)是定义在另一个类中的类。

内部类对象有一个隐式引用。他引用了实例化该内部类对象的外围类对象。通过这个指针可以访问外围内部类的全部状态。


内部类使用的主要原因

使用内部类的主要原因有以下三种:

1、内部类方法可以访问该内部类定义所在类的作用域中的数据,包括私有数据。

2、内部类可以对同一包中的其他类隐藏起来。

3、当想要定义一个回调函数(GUI设计时)且不想编写大量代码时,使用匿名内部类比较便捷。


内部类的种类

java中内部类分为四种:成员内部类、静态内部类、局部内部类和匿名内部类。


创建内部类的格式及引用格式

要创建内部类对象,可以用outer.inner obj = outerobj.new inner();

使用外围类的引用正规语法的表达式为:OuterClass.this

如当外部类为TalkingClock内部类为TimePrinter

TalkingClock jabberer = new TalkingClock();

TalkingClock.TimePrinter listener = jabberer.new TimePrinter();



1、成员内部类

成员内部类就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的。同时外部类要访问内部类的所有成员变量/方法则需       要通过内部类的对象来获取。注意:成员内部类中不能出现static的变量和方法,因为成员内部类要先创建外部类,才能创建内部类。在成员内部类要引用外围类对象时,使用outer.this来表示外部类对象。

如下例所示:

如下示例演示一个每隔十秒发一次通告的小测试程序。


package innerClass;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

public class InnerClassTest {
public static void main(String[] args) {
// TODO 自动生成的方法存根
TalkingClock clock = new TalkingClock(1000,true);
clock.start();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}

TalkingClock类的定义
class TalkingClock    // 定义类
{
private int interval;   // 类中有两个实例域
private boolean beep;
public TalkingClock(int interval,boolean beep)     // 定义了构造方法

this.interval = interval;
this.beep = beep;
}
public void start()    // 类中方法定义
{
ActionListener listener = new TimePrinter();
Timer t = new Timer(interval,listener);  // 实例定时器对象
t.start();    // 调用Timer对象的start方法,启动定时器

}
public class TimePrinter implements ActionListener     // 定义一个内部类,实现ActionListener接口用于通知定时器知道调用哪个方法
{

/*

外围类的引用在构造器中设置。编译器修改了所有的内部类的构造器,添加一个外围类引用的参数。因为TimePrinter类没有定义构造器,所                 以编译器为这个类生成了一个默认的构造器:

public TimePrinter(TalkingClock clock)  自动生成的代码

{

outer = clock;

}

*/
public void actionPerformed(ActionEvent event)
{
Date now = new Date();     // 实例化日期对象
System.out.println("At the tone,the time is"+now);
if(beep)     // if(TalkingClock.this.beep) Toolkit.getDefaultToolkit().beep();
Toolkit.getDefaultToolkit().beep();
}
}
}

2、局部内部类

局部内部类不能用public和private访问说明符进行声明。他的作用域被限定在声明这个局部内部类的块中。

局部内部类有一个优势:即对外部世界可以完全地隐藏起来。只对定义他的方法可见。且局部内部类不仅能够访问包含他们的外部类,还可以访问局部变量,但注意那些局部变量一定要被声明为final。

局部内部类可以定义在方法中:

public class Parcel4{
    public Destination destination(String s){
        class PDestination implements Destionation{
            private String label1;
            private Destination (String whereTo){
                label1 = whereTo;
            }
            public String readLabel(){
                return label;
            }
        }
        return new PDestination(s);
    }
    public static void main(String[] args){
        Parcel4 p = new Parcel4();
        Destination d = p.destination("Tasmanis");
    }
}

也可以定义在作用域里:

public class Parcel4{
    private void internalTracking(boolean){
        if(b){
           class TrackingSlip{ 
               private String id;
               TrackingSlip(String s){
                   id=s;
               }
               String getSlip(){
                   return id;
               }
            }
            TrackingSlip ts=new TrackingSlip("slip");
            String s=ts.getSlip();
         }
     }
     public void track(){
         internalTracking(true); 
     }


     public static void main(String[] args){
         Parcel5 p = new Parcel5(); 
         p.track();
     }
}


3、匿名内部类

匿名内部类是不能加访问修饰符的。将局部内部类的使用在深入,加入只创建这个类的一个对象,就不必命名了。 如下实例:

public void start()    // 含义为:创建一个实现ActionListener接口的类的新对象,需要实现的方法actionPerformed定义在括号{}内
{
ActionListener listener = new TimePrinter();

{

Date now = new Date();     // 实例化日期对象
System.out.println("At the tone,the time is"+now);
if(beep)     // if(TalkingClock.this.beep)  Toolkit.getDefaultToolkit().beep();
Toolkit.getDefaultToolkit().beep();

}

Timer t = new Timer(interval,listener);  // 实例定时器对象
t.start();    // 调用Timer对象的start方法,启动定时器

}


匿名内部类的通用格式:newSuperType(construction parameters){inner class methods an data}

SuperType可以是ActionListener这样的接口,于是内部类就要实现这个接口。SuperType也可以是一个类,于是内部类就要扩展它。


由于构造器的名字必须与类名相同,而匿名内部类没有类名,所以,匿名类不能有构造器。取而代之的是,将构造器参数传递给超类构造器,尤其是在内部类实现接口的时候,不能有任何构造参数。不仅如此还要像下面这样提供一组括号:

new InterfaceType()

{

methods an data

}

匿名内部类和局部内部类一样也像别的类一样进行编译,但只是作用域不同而已,只在该方法或条件的作用域内才能使用,退出这些作用域后无法引用的。但有时final限制显得不太方便,假设想更新在一个封闭作用域内的计数器。如下例所示:

int counter = 0;

Date[] dates = new Date[100];

for(int i = 0li<dates.length;i++)

dates[i] = new Date()

{

public int compareTo(Date other)

{

counter++;     //  错误,只能访问final修饰的局部变量。由于counter需要变化却不能声明为final。补救措施为让他引用一个数组。

return super.compareTo(other);

}

};

补救改良:(数组变量被final修饰,仅仅代表不可以让他在引用另外一个数组,数组中的数据可以自由地更改)

final int[] counter = new int[1];

for(int i =0;i<dates.length;i++)

dates[i] = new Date()

{

public int compareTo(Date other)

{

counter++;     //  错误,只能访问final修饰的局部变量。由于counter需要变化却不能声明为final。补救措施为让他引用一个数组。

return super.compareTo(other);

}

};


4、静态内部类(嵌套类)

有时候,使用内部类只是为了把一个类隐藏在另一个类的内部,并不需要内部类引用外围类对象。为此可以将内部类声明为static。

声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说我们可以直接引用outer.inner,即不需要创建外部类,也不需要创建内部类。静态 类和普通的内部类还有一个区别:普通内部类不能有static数据和static属性,也不能包含嵌套类,但嵌套类可以。而嵌套类不能声明为private,一般声明为public,方便调用。
注意:内部类对象是在静态方法中构造的内部类必须声明为静态内部类。

           声明在接口中的内部类自动称为static和public类。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值