本节内容
1.内部类定义
2.常规内部类
3.静态内部类
4.局部内部类
5.匿名内部类
一、内部类定义
将一个类定义在另一个类的内部,这就是内部类。
//外部类 public class Dog{ //内部类 class subDog{ } }
为什么要使用内部类
为什么要使用内部类?在《Think in java》中有这样一句话:使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
在我们程序设计中有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。
其实使用内部类最大的优点就在于它能够非常好的解决多重继承的问题,但是如果我们不需要解决多重继承问题,那么我们自然可以使用其他的编码方式,但是使用内部类还能够为我们带来如下特性(摘自《Think in java》):
1、内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
2、在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
3、创建内部类对象的时刻并不依赖于外围类对象的创建。
4、内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
5、内部类提供了更好的封装,除了该外围类,其他类都不能访问。
1.常规内部类;
常规内部类(成员内部类):成员内部类也是最普通的内部类,它是外围类的一个成员,所以他是可以无限制的访问外围类的所有 成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。
在成员内部类中要注意两点,第一:成员内部类中不能存在任何static的变量和方法;第二:成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。

public class OuterClass { private String str; public void outerDisplay(){ System.out.println("outerClass..."); } public class InnerClass{ public void innerDisplay(){ //使用外围内的属性 str = "chenssy..."; System.out.println(str); //使用外围内的方法 outerDisplay(); } } /*推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 */ public InnerClass getInnerClass(){ return new InnerClass(); } public static void main(String[] args) { OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.getInnerClass(); inner.innerDisplay(); } } -------------------- chenssy... outerClass...
2.局部内部类
有这样一种内部类,它是嵌套在方法和作用于内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。
1.定义在方法体,甚至比方法体更小的代码块中
2.类比局部变量。
3.局部内部类是所有内部类中最少使用的一种形式。
4.局部内部类可以访问的外部类的成员根据所在方法体不同。
如果在静态方法中:
可以访问外部类中所有静态成员,包含私有
如果在实例方法中:
可以访问外部类中所有的成员,包含私有。
局部内部类可以访问所在方法中定义的局部变量,但是要求局部变量必须使用final修饰。

** *局部内部类 * */ public class LocalInnerTest { private int a = 1; private static int b = 2; public void test() { final int c = 3; class LocalInner { public void add1() { System.out.println("a= " + a); System.out.println("b= " + b); System.out.println("c= " + c); } } new LocalInner().add1(); } static public void test2() { final int d = 5; class LocalInner2 { public void add1() { // System.out.println("a= " + a); System.out.println("b= " + b); System.out.println("c= " + d); } } new LocalInner2().add1(); } public static void main(String args[]) { // LocalInnerTest() lc = new LocalInnerTest(); new LocalInnerTest().test2(); new LocalInnerTest().test(); } }
3.静态内部类:
1.声明在类体部,方法体外,并且使用static修饰的内部类
2.访问特点可以类比静态变量和静态方法
3.脱离外部类的实例独立创建
在外部类的外部构建内部类的实例
new Outer.Inner();
在外部类的内部构建内部类的实例
new Inner();
4.静态内部类体部可以直接访问外部类中所有的静态成员,包含私有

/** * *静态内部类 */ public class StaticInnerTest { public static void main(String[] args) { StaticOuter.StaticInner si = new StaticOuter.StaticInner(); si.test2(); //StaticOuter.StaticInner.test(); System.out.println("si.b = "+si.b); System.out.println("si.a = "+si.a); // System.out.println("StaticOuter.b = "+StaticOuter.b); 这里报错 } } class StaticOuter { private int a = 100; private static int b = 150; public static void test(){ System.out.println("Outer static test ..."); } public void test2(){ System.out.println("Outer instabce test ..."); } static class StaticInner { public int a = 200; static int b =300; public static void test(){ System.out.println("Inner static test ..."); } public void test2(){ System.out.println("Inner instance test ..."); StaticOuter.test(); new StaticOuter().test2(); System.out.println("StaticOuter.b = "+StaticOuter.b); } } }
4.匿名内部类
1.没有名字的局部内部类。
2.没有class,interface,implements,extends关键字
3.没有构造器。
4.一般隐式的继承某一个父类或者实现某一个接口
5.吃货老师讲的一个很生动的例子
/**
* 匿名内部类,我只会使用一次的类
* 假如我想吃一个泡面,但我不可能建一个厂,制造一个流水线,生产一包泡面之后就在也不去使用这个泡面厂了
* 所以这里引申出匿名内部类 ,而我们建立的泡面厂就像这里构建的一个类Pencil 铅笔类一样
*/

** * 匿名内部类,我只会使用一次的类 * * 就假如我想吃一个泡面,但我不可能建一个厂,制造一个流水线,生产一包泡面之后就在也不去使用这个泡面厂了 * 所以这里引申出匿名内部类 ,而我们建立的泡面厂就像这里构建的一个类Pencil 铅笔类一样 */ interface Pen { public void write(); } class Pencil implements Pen { @Override public void write() { //铅笔 的工厂 } } class Person { public void user(Pen pen) { pen.write(); } } public class AnyInnerTest { public static void main(String args[]) { Person guo = new Person(); guo.user(new Pen() { @Override public void write() { System.out.println("写子"); } }); } }