大部分时候,类被定义成一个独立的程序单元。在某些情况下,也会把一个类放在另一个人类的内部定义,这个定义在其他类内部的类就被称为内部类,包含内部类的类也被称为外部类,内部类主要有如下作用:

1:内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。

2:内部类成员可以直接访问外部类的私有数据,因为内部类被当成其成员,同一个类的成员之间可以互相访问。但外部类不能访问内部类的实现细节,例如内部类的成员变量。

3:匿名内部类适合用于创建那些仅需要一次使用的类。

从语法角度来看,定义内部类与定义外部类的语法大致相同,内部类除了需要定义在其他类里面之外,还存在如下两点区别。

1:内部类比外部类可以多使用三个修饰符:private,protected,static  外部类不可以使用这三个修饰符。

2:非静态内部类不能拥有静态成员。

 

非静态内部类

定义内部类非常简单,只要把一个类放在另一个类内部定义即可。此处的“类内部”包括类中的任何位置,甚至在方法中也可以定义内部类(方法里定义的内部类被称为局部内部类)。

大部分时候,内部类都被作为成员内部类定义,而不是作为局部内部类。成员内部类是一种与成员变量,方法,构造器和初始化块相似的类成员:局部内部类和匿名内部类则不是类成员。

成员内部类分为两种:静态内部类和非静态内部类,使用static修饰的成员内部类是静态内部类,没有使用static修饰的成员内部类是非静态内部类。

 

下面程序在Cow类里定义了一个CowLeg非静态内部类,并在CowLeg类的实例方法中直接访问Cow的private访问权限的实例变量。

 1 public class Cow 
 2 {
 3     private double weight;
 4     
 5     //外部类的两个重载的构造器
 6     public Cow(){}
 7     public Cow(double weight)
 8     {
 9         this.weight = weight;
10     }
11     
12     //定义一个非静态内部类
13     private class CowLeg
14     {
15         //非静态内部类的两个实例变量
16         private double length;
17         private String color;
18         //非静态内部类的两个重载的构造器
19         public CowLeg(){}
20         public CowLeg(double length, String color)
21         {
22             this.length = length;
23             this.color = color;
24         }
25         
26         //省略set和get方法
27         
28         
29         //非静态内部类的实例方法
30         public void info()
31         {
32             System.out.println("当前牛腿的颜色是:" + color + ", 高: " +length);
33             
34             //直接访问外部类的private修饰的成员变量
35             System.out.println("本牛腿所在的奶牛重:" + weight);
36         }
37     }
38     
39     public void test()
40     {
41         CowLeg c = new CowLeg(1.12, "黑白相间");
42         c.info();
43     }
44     
45     public static void main(String[] args)
46     {
47         Cow cow = new Cow(378.9);
48         cow.test();
49     }
50 }

当在非静态内部类的方法内访问某个变量时,系统优先在该方法内查找是否存在该名字的局部变量,如果存在就使用该变量;如果不存在,则到该方法所在的内部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;如果不存在,则到该内部类所在的外部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;如果依然不存在,系统将出现编译错误:提示找不到该变量。

因此,如果外部类成员变量,内部类成员变量与内部类里方法的局部变量同名,则可通过使用外部类类名.this作为限定来区分。如下程序所示:

 1 public class DiscernVariable 
 2 {
 3     private String prop = "外部类的实例变量";
 4     
 5     private class InClass
 6     {
 7         private String prop = "内部类的实例变量";
 8         
 9         public void info()
10         {
11             String prop = "局部变量";
12             //通过外部类类名.this.VarName访问外部类实例变量
13             System.out.println("外部类的实例变量值: " + DiscernVariable.this.prop);
14             //通过this.varName访问内部类实例的变量
15             System.out.println("内部类的实例变量值: " + this.prop);
16             //直接访问局部变量
17             System.out.println("局部变量的值: " + prop);
18         }
19     }
20     public void test()
21     {
22         InClass in = new InClass();
23         in.info();
24     }
25     public static void main(String[] args)
26     {
27 //        DiscernVariable dv = new DiscernVariable();
28 //        dv.test();
29         new DiscernVariable().test();
30     }
31 }

 

非静态内部类的成员可以访问外部类的private成员,但反过来就不成立了。非静态内部类的成员只在非静态内部类范围内是可知的,并不能被外部类直接使用。如果外部类需要访问非静态内部类的成员,则必须显式创建非静态内部类对象来调用访问其实例成员。下面程序示范了这个规则。

 1 public class Outer 
 2 {
 3     private int outProp = 9;
 4     
 5     class Inner
 6     {
 7         private int inProp = 5;
 8         public void acessOuterProp()
 9         {
10             //非静态内部类可以直接访问外部类的private成员变量
11             System.out.println("外部类的outProp值:" + outProp);
12         }
13     }
14     public void accessInnerProp()
15     {
16         //外部类不能直接访问非静态内部类的实例变量
17         //下面代码编译错误
18 //        System.out.println("内部类的值:" + inProp);
19         
20         //如需访问内部类的实例变量,必须显式创建内部类对象
21         System.out.println("内部类的inProp值:" + new Inner().inProp);
22     }
23     
24     public static void main(String[] args)
25     {
26         //执行下面代码,只创建了外部类对象,还未创建内部类对象
27         Outer out = new Outer();
28         out.accessInnerProp();
29     }
30 }

 

根据静态成员不能访问非静态成员的规则,外部类的静态方法,静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量,创建实例等,总之,不允许在外部类的静态成员中直接使用非静态内部类。如下程序所示:

 1 public class StaticTest 
 2 {
 3     //定义一个非静态的内部类,是一个空类
 4     private class In
 5     {
 6         
 7     }
 8     
 9     //外部类的静态方法
10     public static void main(String[] args)
11     {
12         //下面代码引发编译异常,因为静态成员main方法
13         //无法访问非静态成员In类
14         
15         new In();
16     }
17 }

 

java不允许在非静态内部类里定义静态成员。

非静态内部类里不能有静态方法,静态成员变量,静态初始化块。

 

posted on 2016-02-25 01:22  所谓荣耀  阅读(284)  评论(0编辑  收藏  举报