内部类

分类

大部分时候,内部类都被作为成员内部类定义,而不是局部内部类

成员内部类分为两种

①非静态内部类
②静态内部类

非静态内部类

★定义内部类有什么好处?

  • 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
  • 内部类成员可以直接访问外部类的私有数据,因为内部类被当成外部类成员,同一个类的成员之间可以互相访问。
  • 匿名内部类适合用于创建那些仅需要一次使用的类。

★内部类与外部类的区别

  • 内部类比外部类多三个修饰符:private、protected、static----外部类不能使用这三个修饰符。
  • 非静态内部类不能拥有静态成员。

★非静态内部类的方法访问某个变量时的优先级

若出现外部类成员变量、内部类成员变量、内部类方法里的局部变量同名的情况

  • 优先在方法里找是否存在该名字的局部变量(存在,则使用)
    【直接使用】
  • 再到该方法的内部类中找是否存在该名字的成员变量(存在,则使用)
    【this.变量名】
  • 最后到该内部类所存在的外部类中找是否存在该名字的成员变量(存在,则使用)
    【外部类类名.this.变量名】
  • 若都没找到,则系统将出现编译错误。

★总结

【总结】

  • 如果外部类需要访问非静态内部类的成员,则必须显式创建非静态内部类对象来调用访问其实例变量。
  • 静态成员不能访问非静态成员变量,外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例等
public class StaticTest
{
	//定义一个非静态内部类
	private class In{}
	//外部类的静态方法
	public static void main(String[]args)
	{
	//下面代码引发编译错误,因为静态成员(main()方法)无法访问非静态成员(In类)
		new In();
	}
}
  • 非静态内部类里不能有静态方法、静态成员变量、静态初始化块。

静态内部类

★概念

【答:】如果使用static修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象。被static修饰的内部类被称为:类内部类或者静态内部类

★静态内部类与外部类成员的关系

  • 静态内部类可以包含静态成员,也可以包含非静态成员。
  • (根据静态成员不能访问非静态成员的规则):静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。
  • 即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员。
public class StaticInnerClassTest
{
	private int prop1 = 5;
	private static int prop 2 = 9;
	static class StaticInnerClass
	{
		//静态内部类里可以包含静态成员
		private static int age;
		public void accessOuterProp()
		{
			//下面代码错误;静态内部类不能访问外部类的实例变量
			System.out.println(prop1);
			//下面代码正确
			System.out.println(prop2);
		}
	}
}
  • 外部类依然不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例变量。
public class AccessStaticInnerClass
{
	static class StaticInnerClass
	{
		private static int prop1 = 5;
		private int prop2 = 6;
	}
	public void accessInnerProp()
	{
		//System.out.println(prop1);
		//上面代码错误,应该改为如下形式
		//通过类名访问内部类的静态成员
		System.out.println(StaticInnerClass.prop1);
		//System.out.println(prop2);
		//上面代码错误,应该改为如下形式
		//通过实例访问静态内部类的实例成员
		System.out.println(new StaticInnerClass().prop2 );
	}
}

使用内部类

★在外部类内部使用内部类

【注】不要再外部类的静态成员(包括静态方法和静态初始化块)中使用非静态内部类,因为静态成员不能访问非静态成员
爷爷的财富(静态成员)可以被孙子(非静态成员)继承
孙子的财富(非静态成员)不能被爷爷(静态成员)继承

★在外部类以外使用非静态内部类

●分别被3种修饰符修饰的内部类

  • 省略访问控制符的内部类,只能被与外部类同一个包中的其他类访问。
  • 使用protected修饰的内部类,可被与外部类处于同一个包中的其他类和外部类的子类所访问。
  • 使用public修饰的内部类,可以在任何地方被访问。

●在外部类以外的地方定义内部类(包括静态和非静态两种)变量的语法格式如下

包名.OuterClass.InnerClass varName

●在外部类以外的地方创建非静态内部类实例的语法

在外部类以外的地方创建非静态内部类实例必须使用外部类实例和new来调用非静态内部类的构造器。

OuterInstance.new InnerConstructor()

【例子:】

class Out
{
	//定义一个内部类,不使用访问控制符
	//即只有同一个包中的其他类可访问该内部类
	class In
	{
		public In(String msg)
		{
			System.out.println(msg);
		}
	}
}
public class CreatInnerInstance
{
	public static void main(String []args)
	{
		Out.In in = new Out().new In("外部类以外创建非静态内部类实例");
		/*
		 *上面代码可改为如下三行代码
		 *使用OutterClass.InnerClass的形式定义内部类变量
		 *Out.In in;
		 *创建外部类实例,非静态内部类实例将寄生在该实例中
		 *Out out = new Out();
		 *通过外部类实例和new来调用内部类构造器创建非静态内部类实例
		 *in = out.new In("外部类以外创建非静态内部类实例");
	}
}

●在外部类以外创建一个非静态内部类的子类

class Out
{
	class In
	{
		public In(String msg)
		{
			System.out.println(msg);
		}
	}
}
public class SubClass extends Out.In
{
	//显式定义SubClass的构造器
	public SubClass (Out out)
	{
		//通过传入的 Out对象 显式调用 In 的构造器
		out.super("hello");
	}
}

★在外部类以外使用静态内部类

【语法】

new OuterClass .InnerConstrctor()

【例子】

class StaticOut
{
	//定义一个静态内部类,不使用访问控制符
	//即只有同一个包中的其他类可访问该内部类
	static class StaticIn
	{
		public StaticIn()
		{
			System.out.println("静态内部类的构造器");
		}
	}
}
public class CreatStaticInnerInstance
{
	public static void main(String[]args)
	{
		StaticOut.StaticIn in = new StaticOut.StaticIn();
		/*上面代码等同于下面代码
		 *StaticOut.StaticIn in;
		 *in = new StaticOut .StaticIn();
		 */
	}
}

【总结】

  • 不管是静态内部类还是非静态内部类,它们申明变量的语法完全一样。
  • 区别在于:静态内部类只需要使用外部类即可调用构造器;而非静态内部类必须使用外部类对象来调用构造器。

★匿名内部类

  • 匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。
  • 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象。
  • 匿名内部类不能定义构造器。
  • 当通过接口来创建匿名内部类时,匿名内部类也不能显式创建构造器,因此匿名内部类只有一个隐式的无参数构造器,故new接口名后的括号里不能传入参数。
  • 如果通过继承父类来创建匿名内部类时,匿名内部类将拥有和父类一样的构造器。
  • 被匿名内部类访问的局部变量必须使用final修饰。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值