内部类的使用(成员、静态、局部、匿名内部类)

内部类

概述: 在一个类的内部又创建了类,创建的类就叫做内部类

特点:

  • 内部类会产生独立的class文件
  • 外部内的资源可以直接在内部类中使用,而不破坏封装性
  • 外部类的一些组件功能,可以交给内部类来完成
  • 分类:成员内部类,静态内部类,局部内部类(了解),匿名内部类(重点)

一、成员内部类

在一个类中创建的普通的类

在Java中使用成员内部类时,需要注意以下几点:

  1. 访问内部类: 成员内部类可以访问外部类的所有成员(变量和方法),包括私有成员。但是,要从外部类外部访问内部类,需要使用语法“OuterClass.InerClass”。
  2. 实例化内部类: 要创建内部类的实例,首先需要实例化外部类。然后,使用外部类的实例,可以创建内部类的实例。语法为OuterClass.InnerClass innerObject=outerObject.new InnerClass();
  3. 可见性: 可见性修饰符(public、private、protected)可以像任何其他类一样应用于成员内部类。但是,需要注意的是,如果内部类被声明为私有,则只能在外部类中访问它。
  4. 生存期: 内部类的实例与外部类的实例绑定。如果没有外部类的实例,它就不可能存在。这意味着内部类可以访问外部类的实例变量,即使它们没有声明为final。
  5. 命名冲突: 如果内部类的成员与外部类中的成员同名,则内部类成员优先。要显式引用外部类成员,可以使用语法OuterClass.this.member
class Outter{
	private String name="凤姐";
	
	public void print() {
		new Inner().test();  //外部类的一些功能,可以交给内部类来完成
	}
	class Inner{  //成员内部类
		String name = "芙蓉";
		//static int age = 30; //在成员内部类中,不能使用静态变量--加载时机有关
		public void test() {
			System.out.println(name);  //可以调用外部类的属性
			System.out.println(Outter.this.name); //调用外部类的属性
		}
	}
}
public class Test1 {
	public static void main(String[] args) {
		Outter out = new Outter();  //1.使用外部类来调用内部类方法
		out.print();
		
		//2.直接调用内部类方法: 通过外部类对象,产生内部类对象
		Outter.Inner inner = new Outter().new Inner();
		inner.test();
	}
}

二、静态内部类

在一个类的内部创建一个static修饰的内部类

在Java中使用静态内部类时,需要注意以下几点:

  1. 访问内部类: 静态内部类独立于外部类,可以在不实例化外部类的情况下访问。您可以使用语法“OuterClass.InerClass”访问静态内部类。
  2. 实例化内部类: 要创建静态内部类的实例,可以使用语法OuterClass.InnerClass innerObject=new OuterClass.INerClass();直接实例化它。
  3. 可见性: 与其他类类似,您可以将可见性修饰符(public、private、protected)应用于静态内部类。但是,请注意,如果内部类被声明为private,则只能在外部类中访问它。
  4. 生存期: 静态内部类的生存期独立于外部类。即使没有外部类的实例,它们也可以存在。
  5. 访问外部类成员: 静态内部类不能直接访问外部类的非静态成员(变量或方法)。但是,他们可以通过创建外部类的实例来访问它们。
  6. 命名冲突: 如果静态内部类有一个成员与外部类中的成员同名,则不会有任何命名冲突,因为它们是独立的实体。
class Outter2{
	private String name="凤姐";
	private static int    age = 30;
	static class Inner2{ //静态内部类
		public void print() {
			//System.out.println(name); //在静态内部类中不能使用成员变量
			System.out.println(age);    //可以使用外部类的静态成员变量
			System.out.println("内部类方法的调用");
		}
	}
}
public class Test2 {
	public static void main(String[] args) {
		//调用静态内部类1:通过类名来调资源
		Outter2.Inner2 inner2 = new Outter2.Inner2();
		inner2.print();
		
		//简化版:直接导包 ...Outter2.Inner2
		Inner2 in = new Inner2();
		in.print();
	}
}

三、局部内部类

在Java中使用本地内部类时,需要注意以下几点:

  1. 作用域: 本地内部类是在外部类的方法、块或构造函数中定义的。它们的范围有限,只能在定义它们的范围内访问。
  2. 可访问性: 本地内部类可以访问外部类的所有成员(变量和方法),包括私有成员。但是,如果它们被声明为final或实际上是final,则它们只能访问封闭范围的局部变量和参数。
  3. 生存期: 与其他类型的内部类相比,本地内部类的生存期更短。它们在执行封闭作用域时创建,在退出作用域时销毁。
  4. 实例化: 不能从封闭范围之外实例化本地内部类。它们只能在定义它们的范围内实例化。
  5. 命名冲突: 本地内部类可以与封闭范围内的其他类或变量同名。在命名冲突的情况下,本地内部类在其作用域内具有优先权。
//局部内部类:在外部类的方法中定义的类
//应用:在外部类的方法中,才能使用局部内部类(很少用);不能使用public修饰
class Outter3{
	String name = "张三";
	public void show() {
		int age = 30;
		class Inner3{ //局部内部类
			public void test() {
				System.out.println("调用局部内部类--"+name);
				//age = 40; //外部类方法中定义的变量,会自动变为常量  +final
				//原因是age的作用域要与局部内部类保持一致
				System.out.println(age);
			}
		}
		
		new Inner3().test();  //在当前方法中,才能调用局部内部类
	}
}
public class Test3 {
	public static void main(String[] args) {
		new Outter3().show();;
	}
}

四、匿名内部类

匿名内部类在设计上和局部内部类相似;但是本质为多态,也就是能用多态的案例,肯定能用匿名内部类

回顾多态案例(接口或抽象类都可以),有直接引用,传参多态,返回值多态

匿名内部类是一种特殊的内部类,它没有显式的类名,直接在代码中定义并实例化。使用匿名内部类时,需要注意以下几点:

  1. 语法: 匿名内部类通常用于创建接口或抽象类的实例,并在实例化时提供具体的实现。语法上,可以在创建对象的地方使用关键字 new ,后跟要实现的接口或抽象类,并在大括号内提供具体的实现代码
  2. 生命周期: 匿名内部类的生命周期与其创建的位置有关。它们的作用域仅限于创建它们的方法或代码块,并且不能被其他方法或代码块访问。
  3. 访问外部变量: 匿名内部类可以访问外部类的成员变量和方法,以及外部方法中的 final 或 effectively final 的局部变量。如果要在匿名内部类中使用非 final 的局部变量,该变量必须是事实上的 final,即在定义后不再修改。
  4. 限制: 匿名内部类不能是抽象类,因为它们是直接实例化的。另外,一个匿名内部类只能继承一个类或实现一个接口
  5. 代码可读性: 由于匿名内部类没有类名,因此在代码阅读和维护时可能会变得复杂。因此,建议在简单的情况下使用匿名内部类,而对于复杂的逻辑,最好使用具名的内部类或独立的类。

直接引用

应用场景:

  • 实例化一次对象,倾向于用匿名内部类;写法上简单,节约资源
  • 实例化多次对象,倾向于用多态;结果清晰,无需创建多个class资源

案例:

  • 描述: 喷火娃具有喷火的能力
interface Fireable{
	void fire();
}
class WaWa implements Fireable{
	@Override
	public void fire() {
		System.out.println("喷火娃正在喷火...");
	}
}
public class Test1 {
	public static void main(String[] args) {
		//1.接口直接引用的多态
		Fireable able = new WaWa();
		able.fire();
		//2.匿名内部类的方式
		Fireable able2 = new Fireable() {
			@Override
			public void fire() {
				System.out.println("匿名内部类的喷火..");
			}
		};
		able2.fire();
	}
}

传参多态

案例:

  • 描述: 直接调方法,多态传参;接口为USB标准;实现类为Disk
interface USB{
	void run();
}
class Disk implements USB{
	@Override
	public void run() {
		System.out.println("硬盘正在运转");
	}
}
public class Test2 {
	public static void main(String[] args) {
		//传参多态:将Test2看成第三方类来使用
		Test2.connect(new Disk());
		
		//匿名内部类实现
		Test2.connect(new USB() {
			@Override
			public void run() {
				System.out.println("匿名设备正在运转");
			}
		});
	}
	private static void connect(USB u) {
		u.run();  //接口回调
	}
}

结论:多态有什么应用场景,那么匿名内部类就有什么场景

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值