Java核心类库――内部类那点事儿 (一)

2014-11-24 07:45:44 · 作者: · 浏览: 1

内部类 ———定义在类的内部的类
为什么需要内部类?
  典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。
  java中的内部类和接口加在一起,可以实现多继承。
  可以使某些编码根简洁。
  隐藏你不想让别人知道的操作。
使用内部类最吸引人的原因是:
  每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
 内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。
特点:
  一、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类命和$符号。
  二、内部类可以直接或利用引用访问外部类的属性和方法,包括私有属性和方法(但静态内部类不能访问外部类的非静态成员变量和方法)。内部类所访问的外部属性的值由构造时的外部类对象决定。  
  三、而外部类要访问内部类的成员,则只能通过引用的方式进行,可问内部类所有成员
   四、访问机制:
  System.out.println(this.x);或System.out.println(x);//内部类访问内部类的成员变量或成员方法可用此方法。
  System.out.println(OuterClass.this.x);//内部类访问外部类的同名变量时可用此方法,如果没有同名可用System.out.println(x);
  五、内部类可以使用任意的范围限定:public/private/protected class InnerClass,且严格按照这几种访问权限来控制内部类能使用的范围。普通类的范围限定只可以是public或者不加。
   六、内部类的命名不允许与外部类 重名,内部类可以继承同级的内部类,也可继承其它类(除内部类和外部类)。
  七、内部类可以定义为接口,并且可以定义另外一个类来实现它
  八、内部类可以定义为抽象类,可以定义另外一个内部类继承它
  九、内部类使用static修饰,自动升级为顶级类,外部类不可以用static修饰,用OuterClass.InnerClass inner=new OuterClass.InnerClass();创建实例。内部类还可定义为final.

  十、内部类可以再定义内部类(基本不用)
十一、方法内的内部类:
 方法内的内部类不能加范围限定(protected public private)
 方法内的内部类不能加static修饰符
  方法内的内部类只能在方法内构建其实例
  方法内的内部类如果访问方法局部变量,则此局部变量必须使用final修饰

1)静态内部类(静态嵌套类)
  从技术上讲,静态嵌套类不属于内部类。因为内部类与外部类共享一种特殊关系,更确切地说是对实例的共享关系。而静态嵌套类则没有上述关系。它只是位置在另一个类的内部,因此也被称为顶级嵌套类。
  静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类不能访问外部类的成员和方法。
语法
1 package com.tarena.day13;
2
3 import com.tarena.day13.Foo.Koo;
4 /**
5 * 静态类内部语法演示
6 */
7 public class StaticInner {
8 public static void main(String[] args) {
9 Koo koo = new Koo();
10 System.out.println(koo.add());//4
11 }
12
13 }
14 class Foo{
15 int a = 1;
16 static int b = 3;
17 /** 静态内部类,作用域类似于静态变量,属于类的 */
18 static class Koo{
19 public int add(){
20 //a ,不能访问a
21 return b+1;
22 }
23 }
24 }

2)成员内部类
* 1 成员内部类必须利用外部类实例创建
* 2 成员内部类可以共享外部类的实例变量
1 import com.tarena.day13.inn.Goo.Moo;
2
3 public class InnerClassDemo {
4 public static void main(String[] args) {
5 //Moo moo = new Moo(); //编译错误,必须创建Goo的实例
6 Goo goo = new Goo();
7 Moo moo = goo.new Moo();//利用goo实例创建Moo实例
8 Moo moo1 = goo.new Moo();
9 //moo和moo1共享同一个goo实例的实例变量
10 System.out.println(moo.add());//2
11 System.out.println(moo1.add());//2
12 Goo goo1 = new Goo();
13 goo1.a = 8;
14 Moo m1 = goo1.new Moo();
15 Moo m2 = goo1.new Moo();
16 System.out.println(m1.add());//9
17 System.out.println(m2.add());//9
18
19 }
20 }
21 class Goo{
22 int a = 1;
23 /**成员内部类*/
24 class Moo{
25 public int add(){
26 return a+1;
27 }
28 }
29 }

3)局部内部类(方法内部类)
 (1)、方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
  (2)、方法内部类对象不能使用该内部类所在方法的非final局部变量。
  因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。用法
1 package com.tarena.day13.inn;
2
3 import java.util.Comparator;
4
5 /**
6 * 局部内部类
7 */
8 public class LocalInnerClassDemo {
9 public static void main(String[] args) {
10 int a = 5;
11 final int b = 5;
12 //局部内部类,定义在方法内部,作用域类似于局部变量
13 //仅仅在方法内部可见
14 //在局部内部类中可以访问方法中的局部final变量
15 class Foo{
16 public int add(){
17 return b;//正确 www.2cto.com
18 //return a;//编译错误
19 }
20 }
21
22 Foo foo = new Foo();
23 //临时的自定义比较规则
24 class ByLength im