Java关于内部类的学习

内部类顾名思义就是指在类里面的类,内部类分为以下四种:

①成员内部类

②局部内部类

③匿名内部类

④静态内部类

问题来了,为什么要使用内部类呢?

每个内部类都能够独立地继承一个(接口的)实现,无论外围类是否已经继承(接口的)实现,对其都不影响。内部类能够十分好的解决多重继承的问题。创建内部类的对象的时候,并不依赖于外围类对象的创建,内部类就是一个独立的实体。内部类除了其的外围类,其它类都不能够访问它。

内部类可以很轻松地访问外围类的属性等,就算外围类属性等用的private修饰,这是因为在创建一个外围类的内部类的对象时,此时内部类对象会捕获指向外围类对象的引用,只要我们在访问外围类的属性等时,就会用这个引用来选择外围类的属性等。

内部类是个编译时的概念,只要编译成功,它就与其的外围类属于两个不同的类(还有一定的联系)。会生成两个.class文件。外围类.class和外围类$内部类.class。

一、成员内部类:

成员内部类是最普通的内部类,也就是在一个类里面定义一个类。成员内部类使用外围类的成员方法、成员变量等无条件限制,无论是用private修饰的还是static修饰的。

如果成员内部类的方法名或者成员变量同名,那么,会发生隐藏现象,要使用如下方法来访问:外围类.this.成员方法---外围类.this.成员变量。

内部类访问外围类的成员方法、变量无限制,但是外围类访问内部类的成员方法、变量却不能随心所欲了,但是值得注意的是:外围类访问成员内部类的方法,必须先创建一个成员内部类的对象,再通过这个对象来访问,成员内部类是依托外部类而存在的,如果要创建成员内部类的对象,前提是必须存在一个外围类的对象。

package com.qianfeng.innerClass;

import com.qianfeng.innerClass.MemberInnerClass.InnerClass;

/**
 * 成员内部类
 * @author littledyf
 *
 */
public class MemberInnerClass {
	private String a;
	//外围类的方法
	public void outMethod(){
		System.out.println("我是外部类的方法...");
	}
	//与内部类同名的外围类的方法
	public void method(){
		System.out.println("我是外部类的同名方法...");
	}
	//通过getxxxx来访问成员内部类
	public InnerClass getInnerClass(){
		return new InnerClass();
	}
	//成员内部类
	public class InnerClass{
		public void innerMethod(){
			//使用外围类的属性,无条件使用,不管是private还是static
			a = "我是内部类使用外围类的属性";
			System.out.println(a);
			//使用外围类的的方法
			outMethod();
			//使用外围类的同名方法要使用如下形式,因为同名,会发生隐藏现象
			MemberInnerClass.this.method();
			
		}
		//与外围类同名的成员内部类的方法
		public void method(){
			System.out.println("我是内部类的同名方法...");
		}
		
	}
}
package com.qianfeng.innerClass;

import org.junit.Test;

/*
 * 测试成员内部类
 */
public class MemberInnerClassTest {
	
	@Test
	public void t(){
		/**
		 * 外围类访问成员内部类的方法,必须先创建一个成员内部类的对象,再通过这个对象来访问
		 * 成员内部类是依托外部类而存在的,如果要创建成员内部类的对象,前提是必须存在一个外围类的对象
		 */
		//外围类访问成员内部类的第一种访问方式
		System.out.println("第一种方式访问...");
		MemberInnerClass mic1 = new MemberInnerClass();
		MemberInnerClass.InnerClass ic = mic1.new InnerClass();
		ic.innerMethod();
		ic.method();
		System.out.println("-----------分割线-----------");
		//外围类访问成员内部类的第二种访问方式
		System.out.println("第二种方式访问...");
		MemberInnerClass mic2 = new MemberInnerClass();
		MemberInnerClass.InnerClass ic1 = mic2.getInnerClass();
		ic1.innerMethod();
		ic1.method();
	}
}

 

二、局部内部类

局部内部类是定义在方法中的或者一个作用域里的内部类,局部内部类的访问仅限于方法内或者该作用域内。

局部内部类不能被public、private、static等修饰符修饰。

局部内部类访问作用域的局部变量,该局部变量需要用final修饰。

外部类不能访问局部内部类,只能在方法体中访问局部内部类,且访问必须在内部类定义之后,即创建局部内部类的对象只能在局部内部类的作用域里,且要在内部类定义之后。

局部内部类访问外部类中同名的方法或者变量时,如下:OutClass.this.method()----OutClass.this.变量。

package com.qianfeng.innerClass;
/**
 * 局部内部类
 * @author littledyf
 *
 */
public class PartInnerClass {
	//与局部内部类同名的变量s1
	private String s1 = "我是外部类与局部内部类同名的变量s1";
	//外部类变量s2
	private String s2 = "我是外部类用private修饰的变量s2";
	//与局部内部类同名的method1
	public void method1(){
		System.out.println("我是外部类的method1");
	}
	//与局部内部类同名的method2
	public void method2(){
		System.out.println("我是外部类的method2");
	}
	//有局部内部类的method3
	public void method3(){
		//方法中用final修饰的变量
		final String s3 = "我是局部类外部方法中用final修饰的变量s3";
		class InnerClass{
			private String s1 = "我是局部内部类中与外部类同名的变量s1";
			public void method1(){
				//局部内部类可以直接访问外部类的变量,即使是private和static
				System.out.println(s2);
				//局部内部类访问外部方法的变量需要有final修饰
				System.out.println(s3);
				//局部内部类和外部类有同名的变量和方法时
				System.out.println(s1);//实际就是this.s1
				System.out.println(PartInnerClass.this.s1);
				method2();
				PartInnerClass.this.method2();
			}
			public void method2(){
				System.out.println("我是局部内部类的method2");
			}
		}
		InnerClass ic = new InnerClass();
		ic.method1();
	}
}
package com.qianfeng.innerClass;

import org.junit.Test;

/**
 * 测试局部内部类
 * @author littledyf
 *
 */
public class PartInnerClassTest {
	@Test
	public void t(){
		PartInnerClass pic = new PartInnerClass();
		pic.method3();
	}
}

 

 三、匿名内部类

匿名内部类不能有访问修饰符和static修饰符的。匿名内部类也就是没有名字的内部类。因为没有名字,所以匿名内部类只能使用一次,通常用来简化代码编写。

匿名内部类是唯一一种没有构造器的类,因为没有构造器,所以其的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候,系统自动起名为OutClass$1.class。一般来说,匿名内部类用于继承其它类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或者重写。

匿名内部类不能定义任何静态成员、方法和类。因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。)一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。

package com.qianfeng.innerClass;
/**
 * 匿名内部类的使用
 * @author littledyf
 *
 */
public class AnonymityInnerClass {
	public void Method(){
		AnonymityInnerClassOther aico = new AnonymityInnerClassOther(){
			public void print(){
				System.out.println("我是匿名内部类");
			}
		};
		aico.print();
	}
	
}

package com.qianfeng.innerClass;
/**
 * 匿名内部类将通过重写其方法来获得实现
 * @author littledyf
 *
 */
public class AnonymityInnerClassOther {
	public void print(){
		System.out.println("我是已经存在的类,让匿名内部类来重写实现");
	}
}
package com.qianfeng.innerClass;

import org.junit.Test;

/**
 * 测试匿名内部类
 * @author littledyf
 *
 */
public class AnonymityInnerClassTest {
	@Test
	public void t(){
		AnonymityInnerClass aic = new AnonymityInnerClass();
		aic.Method();
	}
	
}

匿名内部类对于接口和抽象方法的实现也是跟上面差不多。实现抽象方法重写时,不需要在里面用abstract修饰。

四、静态内部类。

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。

静态内部类的创建不依赖外部类。使用static来修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象,不需要依赖外部类。静态内部类不能访问外部类的非静态成员和非静态方法。因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

猜你喜欢

转载自blog.csdn.net/qq_41061437/article/details/81326860