内部类(成员内部类+静态内部类+局部内部类+匿名内部类)

内部类

 内部类概念:在一个类的内部再定义一个完整的类.
 特点: 编译之后可生成独立的字节码文件。
 	    内部类可直接访问外部类的私有成员,而不破坏封装。
 	    可为外部类提供必要的内部功能组件。

成员内部类

成员内部类:也称实例内部类
  • 在类的内部定义,与实例变量、实例方法同级别的类。

  • 外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象。

  • 当外部类、内部类存在重名属性时,会优先访问内部类属性

  • 成员内部类不能定义静态成员

    1.成员内部类在实例层级——加载成员内部类中内容是在外部类对象被创建时。

package com.qf.day19.text;
/*
 * 案例1,成员内部类
 */
public class TestInstanceInnerClass {
	public static void main(String[] args) {
		
	}
}
class Outer{

	int a =10;//实例变量
	
	public void m1() {//实例方法	
	}
	//成员内部类(实例层级)
	class Inner{
		
	}
}
  1. 成员内部类对象的创建,依赖于外部类对象的创建。
    成员内部类与外部类实例变量及方法是同一层级。
    成员内部类可直接访问外部类实例变量 //1 私有成员变量也可直接访问,并不破坏封装//4。
    成员内部类与外部类属性重名时,优先访问内部类属性//2。
    若仍需获取外部类实例变量时则可通过//3(特殊、不具普适性)访问外部内实例变量。
/*
 * 案例1,成员内部类
 */
public class TestInstanceInnerClass {
	public static void main(String[] args) {
		Outer out = new Outer();
		//1.   Outer.Inner in = new Outer.Inner();
		//2.实质上
		Outer.Inner in = out.new Inner();
		in.m2();
	}
}
class Outer{
	private int a =10;//实例变量//1    改为私有成员变量//4
	public void m1() {//实例方法	
	}
	//成员内部类(实例层级)
	class Inner{
		int a =20;
		public void m2() {
			System.out.println(a);//2
			System.out.println("Class Inner m2()"+a);
			System.out.println(Outer.this.a);//访问外部实例变量//3 特殊、不具普适性
		}
	}
}

3.成员内部类中不能定义静态成员//5,内部类属实例层级需要依赖于对象才能访问其值,但静态成员可用//6Outer.Inner.s;的方式来获取属性值,两者矛盾。不能定义静态成员,不能脱离外部类对象而独立存在。

/*
 * 案例1,成员内部类
 */
public class TestInstanceInnerClass {
	public static void main(String[] args) {
		Outer out = new Outer();
		//1.   Outer.Inner in = new Outer.Inner();
		//2.实质上
		Outer.Inner in = out.new Inner();
		in.m2();
		Outer.Inner.s;//6
	}
}
class Outer{
	private int a =10;//实例变量//1    改为私有成员变量//4
	public void m1() {//实例方法
	}
	//成员内部类(实例层级)
	class Inner{
		int a =20;
		static String s = "Null_kun";//5不能定义静态成员,不能脱离外部类对象而独立存在
		public void m2() {
			System.out.println(a);//2
			System.out.println("Class Inner m2()"+a);
			System.out.println(Outer.this.a);//访问外部实例变量//3
		}
	}
}

静态内部类

  • 不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。

  • 只能直接访问外部类的静态成员。(实例成员需实例化外部类对象)。

    1.不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。

    //1访问类中的静态属性 类名.属性名
    //2.访问静态内部类中属性,即静态内部类是外部类静态属性之一
    //3创建内部类实例对象
    //4使用静态内部类中的方法需先创建对象
    
public class TestStaticClass {
	public static void main(String[] args) {
		System.out.println(Outer.a);//1访问类中的静态属性 类名.属性名
		
		System.out.println(Outer.Inner.b);//2.访问静态内部类中属性,即静态内部类是外部类静态属性之一
		
		Outer.Inner in = new Outer.Inner();//3创建内部类实例对象
		in.m2();//4使用静态内部类中的方法需先创建对象
	}
}
class Outer{
	
	static int a = 10;

	static class Inner{	//静态内部类
		static int b =20;
		public void m2() {
			System.out.println("Inner.m2()");
		}
	}
}
  1. //5静态内部类只能直接访问外部类的静态成员,//6外部类静态成员私有也可直接访问。
    //7静态内部类中并直接访问外部类中的实例变量,静态不能访问非静态实例变量。
    //*比静态代码块功能更丰富。
    
public class TestStaticClass {
	public static void main(String[] args) {
		//System.out.println(Outer.a);//1访问类中的静态属性 类名.属性名
		
		System.out.println(Outer.Inner.b);//2.访问静态内部类中属性,即静态内部类是外部类静态属性之一
		
		Outer.Inner in = new Outer.Inner();//3创建内部类实例对象
		in.m2();//4使用静态内部类中的方法需先创建对象
	}
}
class Outer{
	
	private static int a = 10;//6外部内静态成员私有

	String s = "hello";//实例对象
	
	static class Inner{	//静态内部类
		static int b =20;
		public void m2() {
			System.out.println(Outer.a);//5.访问外部类静态属性
			System.out.println("Inner.m2()");
			System.out.println(Outer.s);//7访问外部类实例变量不行
		}
	}
}

局部内部类

  • 定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。

  • 局部内部类访问外部类当前方法中的局部变量时,因无法保证变量的生命周期与自身相同,变量必须修饰为final。

  • 限制类的使用范围。

    1. //1定义在外部内的方法中,只有当方法执行,才会执行局部内部类,即方法执行完毕前建内部类对象
    //2 只有创建外部类对象并执行内部类所在的方法,才执行局部内部类中代码。
    //3.局部内部类中访问外部类的实例成员
    //4.局部内部类中访问内部类的实例成员
    //5.局部内部类访问外部类的局部变量
    *//6 给m1方法中局部变量赋值,访问局部变量报错。JDK8以前版本中,int b 就会编译错误,必须将其修饰为final,JDK8会隐式加上final。

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

		Outer out = new Outer(); 
		out.m1();//2 只有创建外部类对象并执行内部类所在的方法
		
	}
}
class Outer{
	int a =10;//实例变量
	
	public void m1() {//外部类实例方法
		
		int b =20;//局部变量
		//b=88;//6.赋值 变量b必须是final修饰的常量
		
		class Inner{//局部内部类
			int c =30;
			
			public void m2() {
				System.out.println(Outer.this.a);//3.访问外部类的实例成员
				System.out.println(this.c);//4.访问内部类的实例成员
				System.out.println(b);//5.局部内部类访问外部类的局部变量
				System.out.println("Inner m2()");
			}
			
		}
		Inner in = new Inner(); //1
		
		System.out.println(in.c);
		in.m2();
		
	}
	
	public void m3() {}
}
  1. 存活周期JVM栈<Heap堆<方法区,局部内部类在内存中无对象或子类了才会回收。Inner对象在方法内的变量就必须在。
    在这里插入图片描述
    3.局部内部类继承接口。验证在外部实例方法结束后依然能存储局部变量值,若不加final局部变量生命周期早已结束。
public class TestLocalInner {
	public static void main(String[] args) {

		Outer out = new Outer(); 
		out.m1();//只有创建外部类对象并执行内部类所在的方法
		System.out.println(out.p);
		out.p.print();
	}
}
class Outer{
	printable p=null;
	int a =10;//实例变量
	
	public void m1() {//外部类实例方法
		
		int b =20;//局部变量
		
		class Inner implements  printable{//局部内部类
			
			public void print() {
		
				System.out.println(b);//局部内部类访问外部类的局部变量
			}
			
		}
		p= new Inner(); 
	}
}
interface printable{
	public void print();
}

4.限制类的使用范围
4.1例如:若实现分班,但依然无法规避家长直接new教师,因为此时校方的内部规则,仍然是公开类。教师信息没有对外界隐藏所以家长可自己new

public class TestInnerLocalForApply {
	public static void main(String[] args) {
		//学校开设新班
		/*1.
		Teacher teacher = new AdvancedTeacher();//家长提出意见需要高级教师
		teacher.teach();//问题就是校方没办法提供如此多的高级教师
		 */
		//校方出台了内部规则(按照班级的奇偶编号进行均匀分派,奇数初级,偶数高级)
		
		Teacher t =School.getTeacher(1);
		t.teach();
		
	}
}
class School{
	public static Teacher getTeacher(int classNo) {//使用静态方法,无需new School
		Teacher currentTeacher = null;
		if(classNo%2 !=0) {
			currentTeacher = new BeginnerTeacher();
		}else {
			currentTeacher = new AdvancedTeacher();
		}
		return currentTeacher;
	}
}

abstract class Teacher{
	public abstract void teach();
}
class BeginnerTeacher extends Teacher{
	@Override
	public void teach() {
		System.out.println("初级老师在上课");
	}
}
class AdvancedTeacher extends Teacher{
	@Override
	public void teach() {
		System.out.println("高级老师在上课");
	}
}

4.2 初高级教师类定义在getTeacher方法中。利用抽象类实现高级封装,隐藏类的信息。

public class TestInnerLocalForApply {
	public static void main(String[] args) {
		//学校开设新班
		/*1.
		Teacher teacher = new AdvancedTeacher();//家长提出意见需要高级教师
		teacher.teach();//问题就是校方没办法提供如此多的高级教师
		 */
		//校方出台了内部规则(按照班级的奇偶编号进行均匀分派,奇数初级,偶数高级)
		
		Teacher t =School.getTeacher(1);
		t.teach();
		Teacher t1 =School.getTeacher(2);
		t1.teach();
		
	}
}
class School{
	public static Teacher getTeacher(int classNo) {//使用静态方法,无需new School
		class BeginnerTeacher extends Teacher{
			@Override
			public void teach() {
				System.out.println("初级老师在上课");
			}
		}
		class AdvancedTeacher extends Teacher{
			@Override
			public void teach() {
				System.out.println("高级老师在上课");
			}
		}	
		Teacher currentTeacher = null;
		if(classNo%2 !=0) {
			currentTeacher = new BeginnerTeacher();
		}else {
			currentTeacher = new AdvancedTeacher();
		}
		return currentTeacher;
	}
}

abstract class Teacher{
	public abstract void teach();
}

匿名内部类

  • 没有类名的局部内部类(一切特征都与局部内部类相同)
  • 必须继承一个父类或者实现一个接口
  • 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象(类信息只用到一次)
  • 优点:减少代码量,书写思路流程。(编程思路可方便new对象)
  • 缺点:可读性较差

例如4.3:将初高级教师的类和其中实现以及创建此类合并,修改4.2中实例匿名内部类。

public class TestInnerLocalForApply {
	public static void main(String[] args) {
		//学校开设新班
		/*1.
		Teacher teacher = new AdvancedTeacher();//家长提出意见需要高级教师
		teacher.teach();//问题就是校方没办法提供如此多的高级教师
		 */
		//校方出台了内部规则(按照班级的奇偶编号进行均匀分派,奇数初级,偶数高级)
		
		Teacher t =School.getTeacher(1);
		t.teach();
		Teacher t1 =School.getTeacher(2);
		t1.teach();
		
	}
}
class School{
	public static Teacher getTeacher(int classNo) {//使用静态方法,无需new School
		Teacher currentTeacher = null;
		
		
		if(classNo%2 !=0) {
			currentTeacher = new Teacher() {
				@Override
				public void teach() {
					System.out.println("初级老师在上课");
				}
			};
		}else {
			currentTeacher = new Teacher() {
				@Override
				public void teach() {
					System.out.println("高级老师在上课");
				}
			};
		}
		return currentTeacher;
	}
}

abstract class Teacher{
	public abstract void teach();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章