内部类

2016/01/01 Java

Java 中类可以定义在其他类里,称为内部类。

内部类的分类

Java 中内部类分为四种

  • 静态内部类static inner class (also called nested class)
  • 成员内部类member inner class
  • 局部内部类local inner class
  • 匿名内部类anonymous inner class

静态内部类

静态内部类是最简单的内部类形式,它定义时加上static关键字,会被编译成一个名称为OuterClass$InnerClass.class的完全独立的.class文件。 生成静态内部类对象的方式为:

OuterClass.InnerClass inner = new OuterClass.InnerClass();

注:不能通过外部类实例生成静态内部类对象。 静态内部类示例代码: ``` package com.admin.innerclass; public class OuterForStaticInner {

private static String name = "Admin";

//静态内部类
static class StaticInner{
    
    //静态内部类可以访问外部类的静态成员且只能访问静态成员
    public void sayHello(){
        System.out.println(name);
    }
} } ``` 测试代码: ``` package com.admin.innerclass;

import static org.junit.Assert.*;

import org.junit.Test;

import com.admin.innerclass.OuterForStaticInner.StaticInner;

public class OuterForStaticInnerTest {

@Test
public void test() {
	StaticInner inner = new OuterForStaticInner.StaticInner();
	inner.sayHello();
}

}


#### 成员内部类
成员内部类也是定义在另一个类中,但是定义时不用static修饰。成员内部类和静态内部类可以类比为非静态的成员变量和静态的成员变量。成员内部类就像一个实例变量。它可以访问它的外部类的所有成员变量和方法,不管是静态的还是非静态的都可以。
在外部类里创建成员内部类的实例:

this.new Inner();

在外部类之外创建内部类的实例:

(new Outer()).new Inner();

内部类访问外部类的成员:

Outer.this.member;

成员内部类示例代码:

package com.admin.innerclass; public class OuterForMemberInner {

private static String hello = "Hello";

private String me = "I'm in Outer";

public class Inner{
    
    public Inner(){
        System.out.println("Create one Inner");
    }
    
    private String me = "I'm in Inner";
        
    //直接访问外部类成员
    public void sayHello(){
        System.out.println(hello);
    }
    //如果重名,访问的是内部类的成员
    public void sayMe(){
        System.out.println(me);
    }
    //访问外部类成员
    public void sayOuterMe(){
        System.out.println(OuterForMemberInner.this.me);
    }
}

public Inner getInner(){
    return this.new Inner();
} } ``` 测试代码: ``` package com.admin.innerclass; import static org.junit.Assert.*; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import com.admin.innerclass.OuterForMemberInner.Inner; public class OuterForMemberInnerTest {

private static Inner inner = null;

//测试在外部类外创建内部类实例
@BeforeClass
public static void testCreate(){        
    OuterForMemberInner outer = new OuterForMemberInner();
    inner = outer.new Inner();
}

//测试内部类访问外部类成员
@Test
public void testSayHello(){
    inner.sayHello();
}
//测试内部类访问重名类成员
@Test
public void testSayMe(){
    inner.sayMe();
}
//测试内部类访问外部类重名成员
@Test
public void testSayOuterMe(){
    inner.sayOuterMe();
}
//测试外部类内建立内部类实例
@AfterClass
public static void testGetInner() {
    Inner inner = (new OuterForMemberInner()).getInner();
} } ```

局部内部类

局部内部类定义在方法中,比方法的范围还小。是内部类中最少用到的一种类型。像局部变量一样,不能被public, protected, private和static修饰。只能访问方法中定义的final类型的局部变量。局部内部类在方法中定义,所以只能在方法中使用,即只能在方法当中生成局部内部类的实例并且调用其方法。 示例代码:

package com.admin.innerclass;
import org.omg.CORBA.PUBLIC_MEMBER;
public class OuterForLocalInner {
    
    String me = "I'm in Outer";
    
    public void outerFunction(){
        String fun = "I'm in function";
        final String fin = "I'm final";
        
        class Inner{
             Inner(){
                System.out.println("Create on Inner'");
            }
             public void innerFunction(){
                //不可以访问非final局部变量
                //System.out.println(fun);
                 //可以访问外部类成员
                 System.out.println(me);
                 //可以访问final局部变量
                 System.out.println(fin);
             }
        }
        //只能在方法中生成局部内部类实例并调用其方法
        Inner inner = new Inner();
        inner.innerFunction();
    }
}

测试代码:

package com.admin.innerclass;

import static org.junit.Assert.*;

import org.junit.Test;

public class OuterForLocalInnerTest {

	@Test
	public void testOuterFunction() {
		OuterForLocalInner outer = new OuterForLocalInner();
		outer.outerFunction();
	}

}

匿名内部类

匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。匿名内部类隐式地继承了一个父类或者实现了一个接口。匿名内部类使用得比较多,通常是作为一个方法参数。

注:只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现,比如多线程的两种实现方式。匿名类会生成OuterClass$1.class文件,数字根据匿名类数量递增。
测试示例: ``` package com.admin.innerclass;

import static org.junit.Assert.*;

import org.junit.Test;

public class AnonymousInnerTest {

@Test
public void testAnonymousInner() {
	 Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
         t.start();     //	         Runnable r = new Runnable() { //	             public void run() { //	                 for (int i = 1; i <= 5; i++) { //	                     System.out.print(i + " "); //	                 } //	             } //	         }; //	         Thread t = new Thread(r); //	         t.start();
}

} ```

内部类作用

  1. 内部类可以很好的实现隐藏,一般的非内部类不允许有privateprotect权限,但内部类可以。
  2. 内部类拥有外围类的所有元素的访问权限。
  3. 可以实现多重继承
  4. 可以避免修改接口而实现同一个类中两种同名方法的调用。

Search

    Table of Contents