Java的内部类一共有四种,分别是静态内部类,成员内部类,局部内部类和匿名内部类。有时候,我们很难记住四种内部类,不妨这样想,四种内部类对应了Java类的四种组成,Java有静态方法和静态变量,那静态内部类就是和这个对应着,而类有成员函数和成员变量那一定也就有成员内部类;Java有局部变量也就对应了局部内部类;最后,匿名内部类对应了我们new一个对象,这样想,四种内部类就比较好掌握了。废话少说,逐一介绍。
静态内部类:
静态内部类有两个特点:
1. 静态内部类使用static修饰,声明在类体中
2. 静态内部类可以访问外部累的静态成员(就好像静态方法可以访问静态变量一样)
看代码:
- public class StatClas {
- public static int w=9;
- static class Test{
- private int i=9;
- public static int j=8;
- public int get(){
- System.out.println("内部类的J是"+j);
- return i;
- }
- public static int get0(){
- System.out.println("外部类W的值是"+w);
- return j;
- }
- }
- public static void main(String args[]){
- /***可以通过调用静态方法的办法调用静态内部类,然后调用其静态方法**/
- StatClas.Test.get0();
- /***
- * 静态内部类:
- * StatClas相当于Test类的包,为Test声明一个命名空间
- * 静态内部类的作用域,类似于静态变量,类加载以后就存在
- * 可以在静态内部类中访问静态成员和静态方法。
- * 静态内部类的好处是:将内部类封装入外部类,为内部类声明一个命名空间
- *
- * */
- //直接在本包中声明内部类的对象
- Test t= new Test();
- //通过对象调用内部类的成员方法
- t.get();
- //通过外部类名.内部类 声明对象
- StatClas.Test t0= new StatClas.Test();
- t0.get();
- }
- }
成员内部类
成员内部类有两个特点:
1. 声明在类体中,不使用static,具有类的成员特征,也就是,必须使用外部类的实例才能创建内部类实例
2. 内部类实例可以访问外部类的成员变量
看代码:
- public class InClass {
- private int i=9;
- public String name= "inclass";
- public static String name0="test";
- public class Test{
- private String name="test";
- public int j=9;
- public void get(){
- System.out.println("name的值"+name+" "+"i的值"+i+" "+"name0的值"+name0);
- }
- }
- public static void main(String args[]){
- //不可以像静态内部类的声明一样声明Test对象
- //Test t= new Test();
- //声明内部类对象的方式,也不可以,因为内部类是成员内部类,需要有外部类的实例
- //Test t= new InClass.Test();
- /****
- * 成员内部类是外部类的成员,是依据于外部类对象而存在的,所以声明内部类对象的时候要通过外部累对象来声明
- * ***/
- InClass ic= new InClass();
- Test t= ic.new Test();
- t.get();
- System.out.println(t.getClass());
- /**输出为
- * name的值test i的值9 name0的值test
- * class com.innnerclass.zhuxuli.InClass$Test
- *
- * */
- }
- }
局部内部类
把类声明在方法中,就是局部内部类,作用域类似局部变量
看代码
- public class LoClass {
- private final int i=9;
- private int d=3;
- private final String name="loclass";
- public void testClass(){
- int j=10;
- //int d=5;
- final int w=2;
- final String name="testclass";
- class Test{
- /***
- * 局部内部类访问的方法中的局部变量必须为final类型
- * 然而,局部变量可以访问成员变量,成员变量无须final定义
- * 成员变量中的声明的变量被方法中重新声明为局部变量,如果需要在局部内部类中访问,必须定义为final类型
- * ***/
- public int get(){
- return w+name.length();
- }
- public int get0(){
- return i+w;
- }
- public int get1(){
- return d+w;
- }
- }
- Test t= new Test();
- System.out.println("get方法"+t.get()+"\r\n get0方法"+t.get0()+"\r\n get1方法"+t.get1());
- }
- public static void main(String args[]){
- LoClass lc= new LoClass();
- lc.testClass();
- /**
- * 输出结果是:
- * get方法11
- * get0方法11
- * get1方法5
- * ***/
- }
- }
匿名内部类
在长篇幅的说明匿名内部类这个非常重要的概念前,我们先用简单的话说明什么是匿名内部类。
举例子
- public class NimClass {
- private int w=9;
- private final int z=10;
- private static int x=4;
- public static void main(String args[]){
- int i=5;
- final int j=8;
- final String name="测试匿名内部类";
- Test t= new Test(){
- int get(){
- System.out.println("匿名内部类实现了Test");
- /**
- * 1、虽然局部内部类的所有规则适用于匿名内部类
- * 但是匿名内部类不能访问外部类的成员变量和成员函数,但是可以访问方法中的final变量
- * 2、匿名内部类是实现的某一个抽象类或者接口,所以他不能定义任何静态方法,成员方法
- * 匿名内部类不能是public,protected,private,static
- * 3、匿名内部类只能访问外部累的静态变量和静态方法
- *
- * ***/
- System.out.println(j+x);
- return 1;
- }
- };
- Test0 t0= new Test0(){
- public int get(){
- System.out.println();
- return 2;
- }
- };
- }
- }
- abstract class Test{
- abstract int get();
- }
- interface Test0{
- int get();
- }
匿名类是不能有名称的类,所以没有办法引用他们。必须在创建时,作为new语句的一部分类声明匿名类,这就要采用另一种形式的new语句,如下所示: new <类或接口> <类的主体> 这种形式的new语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口。它还创建那个类的一个新实例,并把它作为语句的结果而返回。要扩展的类和要实现的接口是new语句的操作数,后跟匿名类的主体。如果匿名类对另一个类进行扩展,它的主体可以访问类的成员、覆盖它的方法等等,这和其他任何标准的类都是一样的。如果匿名类实现了一个接口,它的主体必须实现接口的方法。
注意匿名类的声明是在编译时进行的,实例化在运行时进行。这意味着for循环中的一个new语句会创建相同匿名类的几个实例,而不是创建几个不同匿名类的一个实例。
在使用匿名内部类时,要记住以下几个原则:
1、匿名内部类不能有构造方法。
2、匿名内部类不能定义任何静态成员、方法和类。
3、匿名内部类不能是public,protected,private,static。
4、只能创建匿名内部类的一个实例。
5、一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
6、因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。内部类只能访问外部类的静态变量或静态方法。
匿名类和内部类中的中的this :有时候,我们会用到一些内部类和匿名类。当在匿名类中用this时,这个this则指的是匿名类或内部类本身。这时如果我们要使用外部类的方法和变量的话,则应该加上外部类的类名。