内部类,顾名思义,就是在内部定义的类,可以定义在类的内部,也可以定义在方法的内部
java中得内部类分为四种:1、静态内部类,2、成员内部类,3、局部内部类,4、匿名内部类
一、静态内部类 static inner class
静态内部类只能访问外部类静态的属性和方法,只有内部类可以定义为静态的,换言之,一个类如果定义为静态的,必然是内部类
简单的测试类如下,包括了如何定义以及如何使用:
/** * Created by charleszhu on 14-2-16. * 测试静态内部类 */ class StaticInner{ private static int a = 4; // 定义一个静态内部类 public static class Inner{ // 只能调用静态属性和方法 public void test(){ System.out.println(a); } } } public class StaticInnerClassTest { public static void main(String[] args) { // 创建内部类实例的方法,必须从通过外部类.静态内部类的方式才可以创建 StaticInner.Inner inner = new StaticInner.Inner(); inner.test(); } }
编译之后,内部类的class文件命名为 StaticInner$Inner.class。
二、成员内部类
调用方式和静态内部类不同,因为是非静态的,所以可以使用非静态的方法和属性
简单测试用例:
/** * Created by charleszhu on 14-2-16. * 测试成员内部类 */ class MemberInner{ private int a = 4; public class Inner2{ private int a = 5; public void doSomething(){ // 因为是非静态的,所以可以访问非静态的类 System.out.println("I am invoked!! a=" + a); //当内部类有与外部类同名的变量,而又想访问外部的变量时; System.out.println(MemberInner.this.a); } } } public class MemberInnerClassTest { public static void main(String[] args) { //成员内部类的调用和静态内部类的方法有所不同,静态内部类可以通过类名直接调用,因为静态内部类是属于外部类本身的。可以像调用静态方法一样调用 // 而成员内部类是属于对象的,需要new MemberInner.Inner2 inner2 = new MemberInner().new Inner2(); inner2.doSomething(); } }
当内部类有与外部类同名的变量,而又想访问外部的变量时,需要从外部类开始访问
System.out.println(MemberInner.this.a);
如果要在外部类中得某个方法创建内部类的实例
Inner2 inner2 = this.new Inner2();//此处不用写作MemberInner.Inner,应为内部可看做同级
三、局部内部类(用的最少的类)是为了第四种内部类,匿名内部类做铺垫:定义在方法中,不能加访问修饰符,且只能访问方法中的final类型的变量
/** * Created by charleszhu on 14-2-17. */ class LocalClass{ private int a = 4; public void test(){ // 定义局部内部类 class Inner3{ final int b= 4; public void doSomething(){ // 只能访问final类型的变量 System.out.println("LocalInnerClass b=" +4); } } // 内部类无法在外部使用,只能在方法内部定义使用 Inner3 inner3 = new Inner3(); inner3.doSomething(); } } public class LocalInnerClassTest { public static void main(String[] args) { LocalClass localClass = new LocalClass(); //如此才能让Test方法中的Inner3的doSomeThing执行 localClass.test(); } }
四 、匿名内部类:是使用最多的一种内部类:是表示一个没有名字的特殊的局部内部类类,所以,没有构造方法,也没有class关键字
但是:匿名内部类会隐士的继承一个类或者实现一个借口,具体实现了什么接口或者继承了什么类,要看test(new Date(){//可以重写父类方法 }),中new之后是什么类或者接口
此处是Date,则生成的匿名内部类就是Date的子类
import java.util.Date; /** * Created by charleszhu on 14-2-17. */ public class AnonymousInnerClassTest { public String get(Date date){ return date.toString(); } public static void main(String[] args) { AnonymousInnerClassTest test = new AnonymousInnerClassTest(); // 此处做了2件事儿:1定义了一个匿名内部类,2这个内部类继承了Date这个类,所以生成的实例是一个继承自Date类的子类的实例, // 到底继承了什么或是实现了什么,就看new后面是什么类或者接口 String str = test.get(new Date(){ // 因为这个内部类继承了Date这个类,所以可以重写其中的方法,重写我们要用的方法 @Override public String toLocaleString() { return "hello world"; } }); // 此时结果应该输出的是hello world System.out.println(str); } }
结果输出为:hello world
get(new Date()) 和get(new Date(){ })
是两个完全不同的意思,前者是新建了一个Date对象,传递给了方法
后者是新建了一个继承自Date匿名内部类,并且创建一个对象实例,传给方法。
内部类 在日常开发用的不是很多,但了解,对将来学习框架,阅读别人的代码,无疑是有好处的。