java类的五大特性(属性,方法,构造器,代码块,内部类)之内部类详解

        文章内容比较基础,并不设计到源码部分,只告诉读者怎么和如何去用,适合于刚学习的小伙伴,内容难免有部分遗留和不足,还请各位及时批评指正。

java类有五大特效,属性,方法,构造器,代码块,内部类。

本文主要介绍的便是其中的内部类。

内部类的使用目的:减少代码的冗余量简化开发

内部类根据其所在的位置和相应语法有着不同的分类,其中主要可划分为以下四类:

定义在外部类(平时定义的类)的局部位置上的(方法中或者外部类属性的位置):

1.局部内部类(有类名)

       类似于C语言中的局部变量,只不过此处我们把整个类当成局部的,本质上还是一个类,在外部类中我们可以访问内部类创建的对象以及使用相关的方法,也可以在内部类中用外部类类名.this.属性方法来使用外部类属性。

public class InnerClass {
	public static void main(String[] args) {
		new A().w1();
	}
}

//A类为外部类
class A {
	//A类的属性
	private int A_num = 100;

	public void w1() {
		//A的内部类A_In
		class A_In {
			//内部类属性
			private int A_In_num = 200;

			//以下皆为内部类方法
			public int getA_In_num() {
				return A_In_num;
			}

			public void setA_In_num(int a_In_num) {
				A_In_num = a_In_num;
			}

			public void w2() {
				System.out.println("在内部类A_In中调用外部类A的num值: " + A.this.A_num);
			}
		}
		//创建内部类对象
		A_In my_In = new A_In();

		System.out.println("内部类A_In的属性A_In_num = " + my_In.getA_In_num());

		my_In.w2();

	}
}

  此处我们是在方法中创建了内部类,在方法外的位置创建也可以调用之后我们可以看到输出结果

     值得一提的是,虽然内部类用法看上去和类一样,有着近乎一样的用法,但二者在细节上仍有差异。

        1.内部类不能添加访问修饰符,除了final(在方法中)。

        2.内部类可以继承,保留了外部类的特性。

        

      可以看到idea自动对方法中的内部类public修饰符进行报错,并且内部类之间是可以继承的,方法外的内部类(即成员内部类,后面会涉及到)正常


 2.匿名内部类( 无类名)

顾名思义,匿名表示类没有名字,即没有相对应的类名(由系统进行取名)

同时匿名内部类是一个对象。

当我们想利用接口时,传统方法是创建一个类继承接口实现方法,匿名内部类可以简化这种操作,直接实现接口的方法,示例如下

public class AnonymousClass {
	public static void main(String args[]) {
		Animal animal = new Animal();
		animal.m1();
	}
}

class Animal {

	public void m1() {
		Act cat = new Act() {
			@Override
			public void cry() {
				System.out.println("小猫在哭。");
			}
		};
		cat.cry();
		System.out.println("匿名内部类的运行类型为" + cat.getClass());
	}
}

interface Act {
	public void cry();
}

运行结果如下

可以看到运行类型为Animal$1,我们并没有设计这个类,为系统自己创建的类。

当后续再创建时,会变成Animal$2。

类与接口的方式类似,均可由这种方式创建匿名内部类,如下

public class AnonymousClass02 {
	public static void main(String[] args) {
		Animal animal = new Animal();
		animal.sayHi();
	}
}

class Animal{
	public void sayHi(){
		//创建匿名内部类
		Monkey monkey = new Monkey(){
			@Override
			public void hi() {
				System.out.println("匿名内部类的hi()方法..");
			}
		};
		monkey.hi();
	}

}

class Monkey{
	//提供方法
	public void hi(){};
}

运行结果如下

细节:

1.内部类可以在访问外部类的变量,包括私有变量。

2.匿名内部类不能添加访问修饰符。

3.如果想访问外部类,可以采用外部类.this.类名的方法访问,如上述类似

public class AnonymousClass02 {
	public static void main(String[] args) {
		Animal animal = new Animal();
		animal.sayHi();
		animal.sayHi2();
	}
}

class Animal{
	private int num = 100;
	public void sayHi(){
		//创建匿名内部类
		Monkey monkey = new Monkey(){
			@Override
			public void hi() {
				System.out.println("第一个匿名内部类的hi()方法..");
				System.out.println("Animal类的num = " + num);
			}
		};
		monkey.hi();
		System.out.println(monkey.getClass());
	}
	public void sayHi2(){
		Monkey monkey2 = new Monkey(){
			@Override
			public void hi() {
				System.out.println("第二个匿名内部类hi()方法");
			}
		};
		monkey2.hi();
		System.out.println(monkey2.getClass());
	}

}

class Monkey{
	//提供方法
	public void hi(){};
}

运行结果如下

匿名内部类可以明显减少代码量,以下给出实例

public class test {
	public static void main(String[] args) {
		M1(new IA() {
			@Override
			public void hi() {
				System.out.println("why so serious?");
			}
		});
	}

	public static void M1(IA ia){
		ia.hi();
	}
}
interface IA{
	public void hi();
}

       传统代码需要创建类实现接口,并创建对象调用方法,无疑会增加很多代码量,采用内部类可以大大加快开发速率,减少代码量。

        以下为运行结果


3.成员内部类(定义在外部类局部位置

        成员内部类的位置也在外部类中,只不过与局部内部类(通常定义在方法内)不同,是定义在局部位置上的。成员内部类可以调用外部类的方法和属性。下面给出例子

        

public class memberInnerClass {
	public static void main(String[] args) {
		Member_1 member_1 = new Member_1();
		member_1.show();
	}
}

class Member_1{
	//外部类私有变量
	private int num_1 = 100;
	//成员内部类
	class Member_2{
		private int num_2 = 200;
		//成员内部类方法
		public void show_num(){
			System.out.println("成员内部类的show_num方法");
			System.out.println("获取到的num值为:" + num_1);
		}
	}
	//外部类方法
	public void show(){
		Member_2 member_2 = new Member_2();
		member_2.show_num();
	}
}

        可以用修饰符修饰成员内部类,本文采用的默认修饰符修饰。通过调用外部类的show方法使用成员内部类的show_num方法。以下为运行结果。 

 

成员内部类的关键在于内部类的创建。我们有两种方式实现。

1.在主方法中先生成外部类,再生成成员内部类,即连续new 两个类。

2.通过外部类方法返回成员内部类。

细节:访问相同变量名的时候采用的就近原则,如果想访问外部类的变量名采用和局部内部类一样的方法即可。

public class memberInnerClass {
	public static void main(String[] args) {
		//连续new两个类创建成员内部类
		Member_1.Member_2 member_2_1 = new Member_1().new Member_2();
		System.out.println("获得的member_2_1的类为" + member_2_1.getClass());
		//调用外部类的方法创建成员内部类
		Member_1.Member_2 member_2_2 = new Member_1().getInstanceMember_2();
		System.out.println("获得的member_2_2的类为" + member_2_2.getClass());
		//成员内部类方法
		member_2_2.show_num();
	}
}

class Member_1{
	//外部类私有变量
	private int num_1 = 100;
	//成员内部类
	class Member_2{
		private int num_2 = 200;
		private int num_1 = 300;
		//成员内部类方法
		public void show_num(){
			System.out.println("成员内部类的show_num方法");
			//当方法重名时,就近原则获取值
			System.out.println("获取到的num_1值为:" + num_1);
			System.out.println("获取到的外部类num_1" + Member_1.this.num_1);
		}
	}
	//外部类方法
	public void show(){
		Member_2 member_2 = new Member_2();
		member_2.show_num();
	}
	//外部类方法返回成员内部类
	public Member_2 getInstanceMember_2(){
		return new Member_2();
	}
}

下面是运行结果


4.静态内部类(定义在外部类局部位置,用static修饰

        使用了static修饰,使用方法和细节与成员内部类相似,就不再赘述,在类中只可访问成员内部类的静态属性和方法,不可访问非静态的属性和方法,下面给出例子

public class StaticClass {
	public static void main(String[] args) {
		S s = new S();
		S.S_1.say();
	}
}

class S{
	private int num = 100;

	private static String name = "lyz";

	//静态内部类,只能访问外部类静态成员
	static class S_1{
		public static void say(){
			System.out.println("name = " + name);
		}
	}
}

运行结果如下

 静态内部类中不能访问非静态的属性,符合java的语法规范,使用时idea会给出错误信息。

同样,静态内部类的使用也有两种方式

1.通过new静态类成员对象。

2.通过方法返回对象实例。

public class StaticClass {
	public static void main(String[] args) {
		//1.通过外部类.静态内部类直接创建对象
		S.S_1 s_1 = new S.S_1();
		s_1.say();
		//2.编写方法返回对象实例
		S.S_1 s_2 = new S().getInstance();
		s_2.say();
	}
}

class S{
	private int num = 100;

	private static String name = "lyz";

	//静态内部类,只能访问外部类静态成员
	static class S_1{
		public static void say(){
			System.out.println("name = " + name);
		}
	}
	public S_1 getInstance(){
		return new S_1();
	}
}

运行结果如下

 

        同样,静态内部类如果访问相同类名时仍然遵循就近原则,与成员内部类一样,访问外部时采用外部类.类名即可访问外部类的属性。

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

		S.S_1 s_1 = new S.S_1();
		s_1.say();

	}
}

class S{
	private static int num = 100;

	private static String name = "lyz";

	//静态内部类,只能访问外部类静态成员
	static class S_1{
		private static int num = 200;
		public static void say(){
			System.out.println("静态内部类num = " + num);
			System.out.println("外部类num = "+ S.num);
		}
	}
}

运行结果如下 

 

作者能力有限,内容难免有所疏漏,欢迎读者及时批评指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyz_Ay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值