内部类 (2)
辽宁经济职业技术学院信息系
硕士、副教授 陈英
InnerClasstEest内部类实例分析
public void actionPerformed(ActionEvent event)
{
double interest = BankAccount.this.balance *this,rate / 100;
BankAccount.this.balance += interest;
NumberFormat formatter =
NumberFormat.getCurrencyInstance();
System.out.println("balance=" +
formatter.format(BankAccount.this.balance));
}
新创建的 InterestAdder对象中的外部类应用被设置成
创建该对象方法中的 this引用:
ActionListener adder = this.new InterestAdder(rate);
因为它是在
BankAccount对象的
环境中生成的一个
类型为
InterestAdder的对
象。
InnerClasstEest内部类实例分析
内部类 InterestAdder嵌套在 BankAccount类中。
如果已经生成了一个 BankAccount类型的对象,
则可以采用下列语句生成一个类型为
InterestAdder的对象:
BankAccount,InterestAdder adder
=BankAccount,new InterestAdder();
这里生成了一个嵌套类的对象,它与前面生
成的 BankAccount对象关联。因为它是在
BankAccount对象的环境中生成的一个类型为
InterestAdder的对象。
InnerClasstEest内部类实例分析
在 BankAccount的非静态方法中,我们可以使
用类名 InterestAdder而不需要加任何限制词,
因为编译器会自动为它加上 this变量作为限定
词。因此可以在对象 BankAccount的方法中生
成新的 InterestAdder对象:
InterestAdder adder =new InterestAdder();
这也就相当于:
This.InterestAdder adder =this.new
InterestAdder();
局部内部类
内部类可以定义在一个语句块内,这时内部类可
以存取语句块中的局部变量,但这只限于在语句
块的生命期内。
在一个方法里定义的内部类则称之为局部内部类。
它们的范围总是限定在声明它们的程序块中。局
部类不会使用访问提示符 (如 public或者 private)
来声明。
局部类有一个重大优点,它们能够对外部世界完
全隐藏起来。即使 BankAccount类中的其它代码
也不能访问它们。
除了 start 方法以外,谁也不知道 InterestAdder
类的存在。
局部内部类
public void start(double rate)
{
class InterestAdder implements ActionListener {
public InterestAdder(double aRate) {
rate = aRate; }
public void actionPerformed(ActionEvent event) {
double interest = balance * rate / 100;
balance += interest;
NumberFormat formatter = NumberFormat.getCurrencyInstance();
System.out.println("balance=" + formatter.format(balance)); }
private double rate; }
ActionListener adder = new InterestAdder(rate);
Timer t = new Timer(1000,adder);
t.start();
}
局部内部类
相对于内部类来说,局部类还有一个优点,
就是它们不仅能够访问它们的外部类中的
字段,它们甚至于能够访问局部变量。然
而,那些局部变量必须声明为 final。
在 InterestAdder类中不再需要保存一个 rate
实例变量。它只是简单地指向包含类定义
方法的参数变量。
局部内部类
public void start( final double rate)
{
class InterestAdder implements ActionListener
{
public void actionPerformed(ActionEvent event) {
double interest = balance * rate / 100;
balance += interest;
NumberFormat formatter = NumberFormat.getCurrencyInstance();
System.out.println("balance=" + formatter.format(balance)); }
}
ActionListener adder = new InterestAdder();
Timer t = new Timer(1000,adder);
t.start();
}
匿名内部类
创建了一个实现
了 ActionListener
接口的类的新对
象。
如果只需要内部类的一个对象,那么你不必给该类一个名字。
这时候我们称为匿名内部类。
public void start( final double rate)
{
ActionListener adder = new ActionListener ();
{
public void actionPerformed(ActionEvent event) {
double interest = balance * rate / 100;
balance += interest;
NumberFormat formatter = NumberFormat.getCurrencyInstance();
System.out.println("balance=" + formatter.format(balance)); }
}
Timer t = new Timer(1000,adder);
t.start();
}
匿名内部类
用于构造对象的任何参数都要放在跟在超类名字后面的
括号中。一般情况下,使用语句如下:
New SuperType(construction parameters)
{
inner class methods and data
}
在这里 SuperType可以是一个接口,例如 ActionListener,
那么内部类实现该接口;或者 SuperType是一个类,那
么内部类扩展该类。匿名内部类不能有构造器,这是因
为构造器必须同类名相同。而类根本没有名字。取而代
之的是,构造器参数被给到超类的构造器中。特别是,
如果一个内部类实现一个接口,那么该类构造器不能有
任何参数。
静态内部类
若需要通过使用内部类把一个类隐藏在另一个
类中,但同时该内部类不需要有一个对外部类
对象的引用。此时,可以通过把内部类声明为
static,来去掉自动生成的引用。
具有 static属性的内部类变成顶层类,不能再引
用外部类对象。这是因为,在 java虚拟机中,
一个内部类的对象存在着对其外部类的对象的
一个引用,以至于内部类可以存取外部类的成
员。而被声明为 static属性的内部类却不会生成
这个引用,这是顶层类的特性。
只有在顶层类中才可以声明 static成员。如果想
在内部类中声明任何 static成员,则该内部类本
身必须声明为 static属性。
静态内部类
Class Outside
{
static class Skinside
{
}
class Inside
{
}
}
顶级类
非静态嵌套
类可以访问
任何顶级类
成员,不论
它们有什么
访问属性。
一个非静态
嵌套类可以
访问位于相
同顶级类下
的任何静态
嵌套类的成

静态嵌套类的成员可以
访问顶级类的静态成员
static members
non-static members
non-static members
non-static members
非静态嵌套类不
能有静态成员
static members
protected变量和方法
有时需要让超类的某些方法或者字段只允
许子类访问,而对于其他任何类来说都不
可见。在这种情况下,需要把类定义为受
保护的,prodected。
如果一个类中变量或方法有修饰符
protected,同一类,同一包可以使用。不
同包的类要使用,必须是该类的子类可以
存取变量或调用。
这种限制保证你不会滥用受保护机制并且
规范子类只能获取受保护字段的访问。
protected变量和方法
在实际中,要小心使用 proteced属性。
假设你的类给其他程序员所用并且你在其中设
计了受保护字段,那么其他程序员就可以在你
的类上派生新类,并且开始访问你的受保护字
段。
这样你就不再能够在不通知其他程序员的情况
下,改变你的类实现。这有违 OOP精神,因为
它破坏了数据封装。
受保护方法可能更有意义。如果要限制一个方
法的使用那么在类中可以把方法声明为
proteced。这表示子类(可能很熟悉祖先类)
被信任可以使用这些方法,而其他类则不可以。