嵌套类_局部类..

1.嵌套类

嵌套类:定义在另一个类中的类
外部类:在嵌套类外部的类
顶级类:最外层的外部类

2.内部类

对于嵌套类 我们可以将其分成两类 一类是被static修饰的 一类是没有被static修饰的
其中没有被static修饰的嵌套类称之为内部类 也叫做非静态嵌套类

和实例变量、实例方法一样 内部类也需要和外部类的实例相关联(相关联的原因在于在内部类的实例中 会分配内存用于指向外部类实例)
必须先创建外部类实例 然后通过外部类实例去创建内部类实例(这是由于内部类中需要有一个指向外部类实例的引用 所以需要让外部类实例先存在才行)
内部类中不能定义除了编译时常量以外的static成员(有些ide允许但是不推荐这样写 这个说法是针对以前版本的一些ide)

public class Person {
	public class Hand{
		
	}
}
public static void main(String[] args) {
	Person person = new Person();
	Hand hand = person.new Hand();
}

内部类可以直接访问外部类中的所有成员(即使被声明为private也允许访问 因为内部类和外部类都处在同一个类中 并且由于内部类内存中分配内存用于指向外部类实例 所以允许访问外部类的所有成员)

public class Person {
	private int age = 10;
	public class Hand{
		public void show() {
			System.out.println(age);
		}
	}
}
public static void main(String[] args) {
	Person person = new Person();
	Hand hand = person.new Hand();
	hand.show();
}

上述代码的内存细节:首先为Person对象申请堆内存 接着通过外部类实例去创建内部类实例 并且为内部类对象分配堆内存 然后执行show方法中的逻辑 由于是访问age 所以会现在内部类中搜索 如果搜索失败的话 那么就会去相关联的外部类中搜索(这是通过内部类中指向外部类实例的引用实现的) 很显然从打印结果可以看出 这个age是从外部类实例中获取的

外部类可以直接访问内部类实例中的成员变量、方法(即使被声明为private 因为外部类和内部类属于同一个类中)

public class Person {
	private int age = 10;
	
	public void run(Hand h) {
		System.out.println(h.MY_COUNT);
	}
	public class Hand{
		private static final int MY_COUNT = 5;
	}
}
public static void main(String[] args) {
	Person person = new Person();
	Hand hand = person.new Hand();
	person.run(hand);
}

1.内部类细节一

public class Person {
	public int x = 2;
	public class Hand{
		public int x = 1;
		public void show() {
			System.out.println(x);
			System.out.println(this.x);
			System.out.println(Person.this.x);
		}
	}
}
public static void main(String[] args) {
	Person person = new Person();
	Hand hand = person.new Hand();
	hand.show();
}

上述代码的打印结果为:1 1 2
内部类和外部类同时存在同名变量的话 如果我们想要去访问外部类的该变量 书写形式为:外部类名.this.变量名

2.内部类细节二

只有当内部类实例销毁后 外部类实例才有可能销毁 这是因为外部类实例呗两个gc-root对象直接或者间接引用着 你只销毁其中一者 根本不算真正的销毁

3.静态嵌套类

静态嵌套类就是被static修饰的嵌套类
静态嵌套类在行为上就相当于顶级类(这是因为这二者都无需在其他实例创建以后在创建自身实例) 只不过代码定义在了其他类中
相对于顶级类 静态嵌套类多了一些特殊权限 即可以直接访问外部类除实例成员以外的成员(直接二字体现为不用冠以类名或者对象名 即使为私有成员也行)

4.使用嵌套类的情景

1.类a只用于类c

如果类a在程序运行过程中只用于类c的话 那么我们就可以直接将其定义在类a内部 并且为了外部无法访问类c 我们使得类c私有化

1.可以使得封装型更好

这是因为我们使得只在类c使用的类a私有化 防止类a以外的类访问

2.程序包更加简化

如果这些定义在类a内部的类c都定义为一个个单独的顶级类的话 那么将使得类所在包更加臃肿 不够简练

3.可以增强可读性

由于其定义在类内部并且由private修饰 所以我们一下子就可以识别出他的作用就是在类内部使用

2.类a需要经常访问类c的私有成员

如果定义为a定义在类c之外的顶级类 那么去访问类c中的私有成员就需要通过getter setter方法去访问这些私有成员 也就需要申请堆内存(因为需要通过实例访问实例getter setter)以及申请栈帧(java调用方法必备)等消耗性能得做法 相反将类a定义在类c中可以节约程序的性能的开销
另外也可以根据需要(类a只在类c中使用)讲类a私有化

3.内部类和静态嵌套类的使用场景

如果我们要频繁的访问外部类中的私有成员(如果这里使用静态嵌套类将频繁的申请堆内存 消耗性能)或者有先公司后员工(先外部类实例后内部类实例)的需求 就是用内部类 否则就是用静态嵌套类

5.局部类

所谓局部类 就是定义在代码块中的类(这边的代码块指的是包含可执行代码的{} 比如方法中、if-else语句中、for循环中 但是类中不算)

局部类中不能定义除了编译时常量以外的static成员(在现在一些新的ide可以 但是Java是不推荐这样子做的 但是在手机上的java n-ide是不允许这种行为的)

局部类只能访问final或者有效final的局部变量(编译器会将只进行一次赋值操作并且只在声明时或者声明后赋值这种行为上和final局部变量很相似的局部变量视为final修饰 即有效final)

public class Person {
	public void run(){
		int a;
		a = 10;
		class Hand{
			public void test() {
				System.out.println(a);
			}
		}
		Hand hand = new Hand();
		hand.test();
	}
}
public static void main(String[] args) {
	Person person = new Person();
	person.run();
}

局部类可以直接访问外部类的所有成员 但是当我们想要去访问外部类的实例成员时 我们需要将其定义在和实例相关的代码块中(初始化块、实例方法)(这是因为如果我们如果想要去访问实例成员的话 前提是必须要由一个实例 对于初始化块、实例方法这些代码块都是和实例相联系的 有他们就必然有实例存在)

public class Person {
	private int no = 1;
	public void run(){
		int a;
		a = 10;
		class Hand{
			public void test() {
				System.out.println(no);
			}
		}
		Hand hand = new Hand();
		hand.test();
	}
}
public static void main(String[] args) {
	Person person = new Person();
	person.run();
}

另外还需要注意的是 局部类是不能冠以任何的修饰符的 因为前面权限修饰符的定义是这样说的 权限修饰符是用来修饰类的成员的 包括成员变量、成员方法、嵌套类 而局部类不是类的成员

局部类不能被冠以static 原因在于它的作用域是代码块内 如果冠以static的话 那么它的作用域就是类内部了 并且它和内部类一样 其实例内部也有一个指向外部类实例的引用(其实局部类和内部类很相似 不同的地方在于他们定义的位置和他们的作用域 对于局部类来说 它的作用域仅限于代码块内部 但是对于内部类来说 取决于它的权限修饰符)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

axihaihai

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

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

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

打赏作者

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

抵扣说明:

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

余额充值