欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java中的内部类

程序员文章站 2022-07-12 13:30:40
...
内部类(inner class)

内部类(inner class)是定义在另一个类中的类。

代码结构形式如下
class ClassType{
    //注意这并不是声明一个成员属性,而是定义一个内部类
    private class InnerClassType{

    }
}


内部类又分为:普通内部类,局部内部类,匿名内部类,静态内部类,每一种内部类都有自己独特的应用场景。

1.为什么需要使用内部类?

  内部类方法可以访问此类定义所在的作用域中所有成员属性,包括私有成员属性。
  内部类可以对一个包中的其他类不可见。
  想定义一个代码短小的回调函数时,可以使用匿名内部类比较便捷。


2.普通内部类

  定义普通内部类的代码结构如下
 class ClassType{
   //private修饰内部类,说明只能由ClassType内部来创建这个内部类的对象。
   //外部不能创建这个内部类的对象
   private class InnerClassType{

   }
  }


  定义在一个类中的内部类,可以有访问权限修饰符修饰,内部类与所属的外部类,可以相互访问,无权限限制.具体来说:

  (1).内部类可以通过ClassType.this.outerVar 或者ClassType.this.outerMethod()来访问外部类的属性和方法; 如果内部类没有方法或者属性与外部类在命名上相冲突,则可以直接使用outerVar,调用outerMethod()进行访问。

  (2).同样外部类,在创建内部内对象后,也可以直接访问内部内的属性和方法,无论是不是private.

  (3).内部类如果使用private修饰,则只能由外部类内部来创建,如果使用public修饰则可以在直接创建一个内部类对象,前提要求必须先创建外部类对象,然后利用外部类对象来创建内部类对象,OuterClass.InnerClass obj = outerClassInstance.new InnserClass();
(纯粹个人观点,外部类与内部类存在着一对一的引用关系)

  (4).从传统意义上讲,一个方法可以引用调用这个方法的对象数据域。而内部类既可以访问自身的数据域,也可以访问创建它的外围类的数据域。内部类的对象有一个隐式引用,指向了创建它的外围类对象的数据域.编译器会对内部类的构造函数进行修改,添加一个外围类引用的参数this指针到内部类当中,这解释了为什么内部类可以访问外部类的成员。

实例:

class OuterClass{
	
	private String outerVar = "outerVar";
	
        //定义一个内部类
	public class InnerClass{
		
		private String innerVar = "innerVar";
		
		private void visitOuter(){
			//或者访问outerVar使用OuterClass.this.outerVar
			System.out.println("内部类访问外部变量:"+outerVar);
		}
	}
	//外部类访问内部类的方法visitInnerClass()
	public void visitInnerClass(){
		InnerClass inner = new InnerClass();
		System.out.println("外部类访问内部类变量:"+inner.innerVar);
		inner.visitOuter();	
	}
}

public class CommonInnerClass {
	
	public static void main(String[] args) {

		OuterClass ct = new OuterClass();
           //可以直接创建内部类OuterClass.InnerClass inner = ct.new InnerClass();
		ct.visitInnerClass();
	}

}


  输出:
  外部类访问内部类变量:innerVar
  内部类访问外部变量:outerVar



2.局部内部类:可以在一个方法中定义局部类,局部类不能用public或者private访问修饰符进行修饰声明。它的作用域被限定在此声明此局部类的块或者方法中。局部类有一个优势,即对外部可以完全地隐藏起来。局部类还有另一个优势,它们不仅能访问包含它们的外围类的域,而且还可以访问局部变量。不过局部变量必须声明为final。


实例:
public class TestLocalClass {

        private  String outerVar = "outerVar";
    
        //局部方法test()
	public void test(){

		 final String localVar = "localVar";
		 
                 //在方法test()中定义局部类LocalClass
		 class LocalClass{
			
			private void testAccess(){
				System.out.println("局部类访问外部类变量:"+TestLocalClass.this.outerVar);
				System.out.println("局部类访问方法中变量:"+localVar);
			}
		}
		
		LocalClass lc = new LocalClass();
		lc.testAccess();
	}
	
	
	public static void main(String[] args) {

		TestLocalClass tl = new TestLocalClass();
		tl.test();
	}

}



输出:
局部类访问外部类变量:outerVar
局部类访问方法中变量:localVar


3.匿名内部类:将局部内部类使用再深入一步,如果只创建此类的一个对象,就不必为这个类命名,这种类被称为匿名内部类(anonymous inner class).适用于比较短小的代码类。

通常语法格式为:
new SuperType(){

	inner class emthods and data;
}




  superType可以是接口,那么内部类就相当于实现了这个接口;如果superType是一个类,那么内部类相当于继承并且扩展它

  由于构造函数的名字必须与类名相同,而匿名类是没有类名,所以,匿名类不能有构造器。类是匿名的,无法定义构造函数来传递参数。

  构造一个类的新对象与构造一个扩展了那个类的匿名内部类对象之间有什么差别。如果构造参数的()后面跟着一个{},那么正在定义的就是匿名内部类。
  Person queue = new Person();
  Person count = new Person(){};

示例:

interface AnonymousInterface{
	public void testAnonymousClass();
}


class AnonymousClass{
	
	public void dump(){
		System.out.println("call dump() of AnonymousClass");
	}
}

public class TestAnonymousClass {	
	
	public static void main(String[] args) {

	    //测试实现接口的匿名类
		AnonymousInterface obj = new AnonymousInterface(){

			public void testAnonymousClass() {
				System.out.println("匿名类中实现接口testAnonymousClass()方法");
			}
		};
		
		obj.testAnonymousClass();
				
		//测试继承并扩展父类的匿名类
		AnonymousClass anonymousObj = new AnonymousClass(){
			
			public void dump(){
				super.dump();
				System.out.println("call dump of extended AnonymousClass");
			}
		};
		
		anonymousObj.dump();	
	}
}



输出:

匿名类中实现接口testAnonymousClass()方法
call dump() of AnonymousClass
call dump of extends AnonymousClass




4.静态内部类

  有时候,使用内部类只是为了把一个类隐藏在另一个类的内部,并不需要内部类引用外围对象。为此,可以将内部类声明为static,以取消产生的外部类引用,使用得内部类无法访问外部类对象(但是可以访问外部类的静态成员变量和方法,其实相当于没有静态内部类没有外部类的this指针)。静态内部类的对象除了没有对生成它的外围类对象的引用特权外,与其他所有内部类完全一样。

class ClassType{

   public static class InnerClassType{

   }
}


示例:
public class TestStaicClass {

	private static String outerStaticVar = "outerStaticVar";
	private String outerVar = "outerVar";
	
	private static void outerStaticMethod(){
		System.out.println("call outerStaticMethod()");
	}
	
        //静态内部类访问外部类的静态变量outerStaticVar和静态方法outerStaticMethod()
	private static class StaticClass{
		
		public void testAccess(){
                         //不能访问外部类的非静态成员
			//System.out.println(outerVar);
			System.out.println(outerStaticVar);
			outerStaticMethod();
		}
	}
	
	public static void main(String[] args) {
		
		StaticClass sc = new StaticClass();
		sc.testAccess();
	}
}


输出:
outerStaticVar
call outerStaticMethod()