JavaSE:内部类

内部类是指在一个外部类的内部再定义一个类。
内部类的作用:

1). 内部类可以很好的实现隐藏,也就是封装性。一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
2). 内部类可以直接访问外部类的所有属性和方法,即使是private修饰的

3). 可以实现多重继承
4). 可以不修改接口而实现同一个类中有两个同名方法

 

一、成员内部类(外部类的成员变量)

说明:编译之后,内部类字节码文件是:Outer$Inner.class

1)内部类可以直接访问外部类中的私有属性。实际上内部类已经破坏了一个类的基本结构,因为类是由属性及方法组成的,这是内部类的缺点;内部类可以直接访问外部类中的私有属性,这是其最大的优点

package com.wbf.test1;

class Outer{
	private String info = "hello world!!!";//外部类的私有属性
	class Inner{
		public void print(){
			System.out.println(info);//直接访问外部类的私有属性
		}
	};
	
	public void fun(){
		new Inner().print();//内部类的实例化对象调用自身的方法
	}
};

public class InnerClassDemo01 {
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.fun();
	}
}

 

2)一个内部类除了可以通过外部类访问,也可以直接在其他类中进行调用

package com.wbf.test3;

class Outer{
	private String info = "hello world!!!";//外部类的私有属性
	class Inner{
		public void print(){
			System.out.println(info);//直接访问外部类的私有属性
		}
	};
};

public class InnerClassDemo03 {
	public static void main(String[] args) {
		/*
		Outer.Inner in = new Outer.Inner();//error, No enclosing instance of type Outer is accessible, 必须先有Outer类的实例
		in.print();
		*/
		Outer out = new Outer();
		Outer.Inner in = out.new Inner();
		in.print();
	}
}

一个内部类除了可以通过外部类访问,也可以直接在其他类中进行调用
格式:外部类.内部类 内部类对象 = 外部类实例.new 内部类();
以上的格式中,首先要找到外部类的实例化对象之后,才可以通过外部类的实例化对象去实例化内部类的对象
注意:此时的Inner类非static
如果Inner类用static修饰,那么在类加载的之后,对于Outer类来说,即使没有Outer类的实例化对象,Inner这个成员变量已经存在
反之,Inner类没有用static修饰,那么在没有Outer类实例化对象的情况下,对于Outer类来说,Inner这个成员变量根本就不存在,此时要直接实例化Inner,肯定是不行的
所以在一般情况下,当先有外部类的实例化对象之后,再通过外部类的对象去实例化内部类

 

三、静态内部类(用static声明内部类)

说明:静态内部类和普通的内部类一个区别:普通内部类不能有static方法和static属性,也不能包含静态内部类,但静态内部类可以。而静态内部类不能声明为private,一般声明为public,方便调用。编译之后,内部类字节码文件是:Outer$Inner.class

package com.wbf.test2;

class Outer{
	private static String info = "hello world!!!";//外部类的私有属性
	static class Inner{
		public void print(){
			System.out.println(info);//直接访问外部类的私有属性,同时这里info属性用static修饰
		}
	};
};

public class InnerClassDemo02 {
	public static void main(String[] args) {
		new Outer.Inner().print();//通过new Outer.Inner()来实例化内部类,同时调用内部类的方法
		/*
		Outer.Inner in = new Outer.Inner();
		in.print();
		*/
	}
}

 

static可以声明属性或方法,而是用static也可以声明内部类
用static声明的内部类成为外部类,但是用static声明的内部类不能访问外部类的非static属性

四、局部内部类(在方法中定义内部类)

说明:编译之后,内部类字节码文件是:Outer$1Inner.class

package com.wbf.test4;

class Outer{
	private String info = "hello world!!!";//外部类的私有属性
	public void fun(final int temp){
		class Inner{
			public void print(){
				System.out.println("方法中的参数: " + temp);//访问方法中的final参数
				System.out.println("类中的属性: " + info);//直接访问外部类的私有属性
			}
		};
		
		new Inner().print();
	}
};

public class InnerClassDemo04 {
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.fun(20);
	}
}

可以在一个方法中定义一个内部类,但是在方法中定义的内部类不能够直接访问方法中的参数;如果方法中的参数要想被内部类所访问,则参数前必须加上final关键字

 

五、匿名内部类

说明:编译之后,内部类字节码文件是:X$1.class

1)未使用匿名内部类

package com.wbf.test5;

interface A {
	public void printInfo();
}

class B implements A {
	public void printInfo(){
		System.out.println("hello world!!!");
	}
}

class X {
	public void fun1(){
		this.fun2(new B());
	}
	
	public void fun2(A a){
		a.printInfo();
	}
}

public class AnonymousInnerClassDemo {
	public static void main(String[] args) {
		new X().fun1();
	}
}

 

但是现在如果接口的实现类B只使用一次,那么还有必要单独定义一个子类B吗?很明显没有必要,所以此时就要使用匿名内部类完成

2)使用匿名内部类

package com.wbf.test6;

interface A {
	public void printInfo();
}

class X {
	public void fun1(){
		this.fun2(new A(){//匿名内部类
			public void printInfo(){//实现接口中的抽象方法
				System.out.println("hello world!!!");
			}
		});
	}
	
	public void fun2(A a){
		a.printInfo();
	}
}

public class AnonymousInnerClassDemo {
	public static void main(String[] args) {
		new X().fun1();
	}
}

 

六、Java通过内部类变相实现多重继承

package com.wbf.test7;

abstract class Father{
	public abstract void run();
};

abstract class Mother{
	public abstract void say();
};

class Son extends Father{
	public void run(){
		System.out.println("running...");
	}
	
	Mother getMother(){
		return new Mother(){
			public void say(){
				System.out.println("saying...");
			}
		};
	}
};

public class DuplicateExtendsDemo {
	public static void main(String[] args) {
		Son s = new Son();
		s.run();
		s.getMother().say();
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值