内部类

                       内部类 

在一个类中定义另外一个类,这个类就叫做内部类或内置类(inner class)。

内部类可以让我们将逻辑上相关的一组类组织起来,并由外部类(outer class)来控制内部类的可见性。

当我们建立一个inner class时,其对象就拥有了与外部类对象之间的一种关系,这是通过一个特殊的this reference形成的,使得内部类对象可以随意的访问外部类中所有成员。

在内部类中可以去随意的访问外部类中的所有成员变量和成员方法。

代码
public class Outer {
private int index = 100;
class Inner {
void print() {
System.out.println(Outer.index);
}
}

public void print() {
Inner obj
= new Inner();
obj.print();
}
}

class Test {
public static void main(String[] args) {
Outer o
= new Outer();
o.print();
}
}

 

 

说明在内部类中可以去访问外部类的私有的成员变量和成员方法 。可以将上面的内部类看做是java的一个成员,因为它的声明和成员方法成员变量都是一样的等级,都是在类体中的。只要想到了这点,那么很多事情都很好解决。

 

代码
class Outer {
private int index = 100;// Outter类的成员变量

class Inner {
private int index = 50;// Inner类的成员变量
void print() {
int index = 30;// Inner类的局部变量
System.out.println(index);
System.out.println(Inner.
this.index);
System.out.println(Outer.
this.index);
}
// 其实,除了本地的不用加this外,其他的都加this
}

public void print() {
Inner obj
= new Inner();
obj.print();
}
/**返回Inner对象*/
public Inner getInner() {
return new Inner();
}
}

class Test {
public static void main(String[] args) {
Outer o
= new Outer();
//o.print();// 第一种方法

Outer.Inner i
= o.getInner(); // Outer.Inner,把Inner当作成员变量来调用
i.print();

}
}

 

不能直接产生内部类的一个对象。

 

代码
public class Outer {
private int index = 50;

class Inner {
void print() {
System.out.println(index);
}
}
}

class Test {
public static void main(String[] args) {
Outer.Inner i
= new Outer().new Inner();// 这就完全是将Inner看作了一个成员。
i.print();
}
}

个人观点:本人认为如果内部类也是直接定义在外部类中的,我们就可以把它也相当于一个成员,要使用它,当然要用外部类的对象去像调用变量或方法那样去做。下面这个代码是本人去写的,感觉到要简单点。

 

 

代码
public class Outer {
private int index = 100;
class Inner {
void print() {
System.out.println(Outer.
this.index);
}
}

public Inner getInner() {// 获得内部类的对象
return new Inner();
}
}

class Test {
public static void main(String[] args) {
Outer o
= new Outer();// 先实例化外部类
o.getInner().print();
//使用外部类对象来调用它里边的方法来获得内部类对象,再获得内部类的方法。
}
}

 

当一个内部类被声明为static之后,它就相当于一个外部类了。可以直接使用外部类名称去调用。

 

代码
class Outer {
private static int index = 50;

static class Inner {
private int index=20;
void print() {
System.out.println(Outer.index);
// ok
System.out.println(Inner.this.index); // ok
//System.out.println(Outer.this.index);// error
/*
* this是一个非静态的变量,它不能在一个静态的上下文中被引用。
* static 是全局变量,而this是当前对象变量
*/
}
}
}

class Test {
public static void main(String[] args) {
Outer.Inner i
= new Outer.Inner();
i.print();
}
}

这也主要是要明白应该将它理解成为一个成员来的。

 

想想你是怎么调用方法的吧!

只能调用成员变量和成员方法但是它不可以直接调用类,所以这就是为什么要Outer.Inner();,千万注意,这里是调用的是Inner类的无参构造方法,如果Inner类提供了一个有参构造方法,那么上面的程序就要报告异常了。

内部类的位置:内部类可以放在任意一个{}中进行声明。

不论内部类的嵌套层次有多深,都能访问外部类的成员。

将一个内部类定义在静态块中,当然静态块中也不能有静态的成员。当然也不能有静态的类存在。

 

代码
public class Outer {
private static int index = 100;
static {
class Inner {
void print() {
System.out.println(Outer.index);
//System.out.println(Outer.this.index);// error
}
}
new Inner().print();
}
}

class Test {
public static void main(String[] args) {
Outer o
= new Outer();
}
}

 

感言:其实将一个内部类定义在静态块中要简单一点,因为在main方法中只需要实例化外部类。So easy!当然也有局限性。

 

一个内部类如果直接定义在外部类当中,那么它就相当于一个成员变量,那么成员变量是可以由很多修饰符的,例如:private、protected、static、abstract、default(缺省)等,也就是说内部类也可以有这些修饰符

static innerclass中可以有static的成员,但是在一个非static inner class当中不能去定义一个静态的变量(这是为什么呢?)。因为在这个非staticinner class中的变量是一个局部的,然而类变量也相当于是成员变量,成员变量怎么能落到局部变量的位置呢?前面已经讲到。

一个类派生自内部类的问题讲解(重要)

 

class Car {
class Wheel {
    
System.out.println("Wheel");
}
}
class PlaneWheel extends Car.Wheel {//PlaneWheel继承自Car.Wheel
public static void main(String[] args) {
PlaneWheel pw
= new PlaneWheel();
}
}

编译时报告异常:

 

分析:当产生一个派生类的对象的时候,它会调用基类的构造函数,产生一个基类的对象,然而这里基类Wheel是一个内部类,前面说过,要产生一个内部类的对象,首先需要去产生一个外部类的对象,然后才能产生内部类的对象。从而建立起内部类到外部类对象的一种引用关系,然而这里当派生类产生了对象的时候外部类还没有产生对象,当然内部类对象就无法产生了,因此会出现错误了。所以首先要产生外部类对象,然后与内部类对象的引用关系建立起来。

修改方法1:

代码
public class Car {
class Wheel {
}
}
class PlaneWheel extends Car.Wheel {
public PlaneWheel(Car car) {
car.
super();//通过这条语句去建立从内部类对象到一个指定的外部类对象的引用关系。这是为什么呢?
}

public static void main(String[] args) {
Car c
= new Car();
PlaneWheel pw
= new PlaneWheel(c);
}
}
其实car.super();是在调用Wheel类的无参数的构造函数,怎么能验证呢?你可以在Wheel类中加入一个含参数的构
造方法就知道了。

 

修改方法2(最简单的一种):

class Car {
static class Wheel {//使用static修饰该类,该类就相当于一个静态方法。可以直接使用类名来调用。前面已经将过。
void run() {
System.out.println(
"Wheel");
}
}
}
class PlaneWheel extends Car.Wheel {//PlaneWheel继承自Car.Wheel
public static void main(String[] args) {
Car.Wheel cw
= new PlaneWheel();
cw.run();
}
}

 

用内部类实现一个接口

 

代码
interface Animal {
void eat();
void sleep();
}

class Zoo {
class Tiger implements Animal {
public void eat() {
System.out.println(
"tiger eat");
}

public void sleep() {
System.out.println(
"tiger sleep");
}
}

Animal getAnimal() {
//Tiger getAnimal() {// 由于Tiger是Animal的实现类,所以这里可以是Tiger
return new Tiger();
}
}

class Test {
public static void main(String[] args) {
Zoo z
= new Zoo();
Animal an
= z.getAnimal(); // 接口的引用指向实现类
an.eat();
an.sleep();
}
}

 

为什么要使用内部类?

1.      在内部类中可以随意的访问外部类的成员,这可以让我们更好地组织管理我们代码,增强代码的可读性。

2.        内部类可以用于创建适配器类,适配器类是用于实现接口的类。使用内部类来实现接口,可以更好的定位与接口关联的方法在代码中的位置。

3.        内部类的更多的用法。

  将Tiger声明为private,那么这个类就不能在Zoo类的外部被访问了,也就是不能Zoo.Tiger来定义Tiger对象的变量了,只能通过接口获取Tiger类的对象,也就是z.getAnimal()间接获取实现类的对象。

 

代码
interface Animal {
void eat();
void sleep();
}

class Zoo {
private class Tiger implements Animal {
public void eat() {
System.out.println(
"tiger eat");
}

public void sleep() {
System.out.println(
"tiger sleep");
}
}

Animal getAnimal() {
return new Tiger();
}
}

class Test {
public static void main(String[] args) {
Zoo z
= new Zoo();
Animal an
= z.getAnimal();
an.eat();
an.sleep();
}
}

 

所以通过将实现类声明为private,就可以很好的隐藏实现的细节。让用户通过接口去访问内部类的实现方法。

      派生一个类,但同时又要去实现一个接口,如果基类当中的一个方法与接口当中的一个方法同名了,但它们的用法又不一样,这个时候就可以用内部类来解决这个问题。Java中不允许多继承,但是利用内部类就弥补了这一点。

 

代码
interface Machine {
void run();
}

class Person {
void run() {
System.out.println(
"run");
}
}

class Robat extends Person {
private class MachineHeart implements Machine {
public void run() {
System.out.println(
"heart run");
}
}

public Machine getMachine() {
return new MachineHeart();
}
}

class Test{
public static void main(String[] args) {
Robat r
= new Robat();
Machine m
= r.getMachine();
m.run();
r.run();
}
}

 

  如果说在一个类C中,它需要从类A派生,同时又需要有一个类B的对象,那么我们就可以用内部类来解决这个问题。(重点)

 

代码
public class A {
void fn1() {
}
}

abstract class B {
abstract void fn2();
}

class C extends A {
B getB() {
return new B(){
public void fn2() {
}
};
}
}

class Test {
static void method1(A a) {//需要A的一个对象
a.fn1();
}

static void method2(B b) {//需要B的一个对象
b.fn2();
}

public static void main(String[] args) {
C c
= new C();
method1(c);
// 因为C是A的派生类。所以可以直接传入c。
method2(c.getB());//c.getB()用于获取B的一个对象。
}
}

 

posted @ 2010-12-21 14:18  meng72ndsc  阅读(226)  评论(0编辑  收藏  举报