文章目录
- 零、关于继承的补充
- 一、final
- 二、嵌套类(Nested Class)
- 三、内部类(Inner Class)
- 四、内部类内存布局
- 五、静态嵌套类(Static Nested Class)
- 六、什么情况使用嵌套类?
- 七、局部类(Local Class)
零、关于继承的补充
❓ 子类对象的内存中是否包含父类中定义的 private
成员变量 ?
📋 有。只是不能够直接访问而已,可让父类提供
public
的成员方法以访问private
的成员变量。
一、final
✏️ 被 final
修饰的 类不能被继承
✏️ 被 final
修饰的 方法不能被重写
✏️ 被 final
修饰的 变量只能进行1次赋值
📋
final
可修饰局部变量
📋final
可修饰成员变量
✏️ Java 中的 常量(Constant)指 :同时被 static
和 final
修饰的成员变量
📋 若将 基本类型或 字符串定义为常量(
static final
),并且在 编译时就能确定值:编译器会使用 常量值替换各处的 常量名(类似 C 语言中的 宏替换)
📋 这种常量被称作 编译时常量(compile-time constant)
二、嵌套类(Nested Class)
✏️ 嵌套类:定义在另一类中的类
public class OuterClass {
static class StaticNestedClass {
}
class InnerClass {
}
}
✏️ 没有被 static
修饰的嵌套类叫做内部类
✏️ 嵌套类外层的类叫做 外部类(Outer Class)
✏️ 最外层的外部类叫做 顶级类(Top-level Class)
三、内部类(Inner Class)
✏️ 内部类:没有被 static
修饰的嵌套类(也叫做非静态嵌套类)
✏️ 与实例变量、实例方法一样,内部类与外部类的实例挂钩
✒️ 必须先创建外部类实例,然后通过 外部类实例创建内部类实例
✏️ 内部类不能 定义除 编译时常量之外的任何 static
成员
✏️ 内部类可以直接访问外部类中的所有成员(即使是
private
成员)✏️ 外部类可以直接访问内部类 实例的成员变量和方法(即使是
private
)
先创建外部类实例,然后通过外部类实例创建内部类实例:
public class Person {
public class Hand {
}
}
class TestDemo {
public static void main(String[] args) {
Person p = new Person();
System.out.println("\n人 " + p);
Person.Hand hand = p.new Hand();
System.out.println("手 " + hand);
}
}
内部类可以直接访问外部类中的所有成员(即使是 private 成员)
外部类可以直接访问内部类实例中的成员变量和成员方法(即使是 private)
public class Computer {
private int price = 8989;
public static String brand = "苹果";
private void showComputer(Mouse mouse) {
System.out.println("Computer - openComputer()");
System.out.println("mouse.mousePrice = " + mouse.mousePrice);
mouse.printMouse();
}
public class Mouse {
private int mousePrice = 111;
private void printMouse() {
System.out.println("printMouse()_Mouse.mousePrice = " + mousePrice);
}
public void printOuterClassMember() {
System.out.println("\nComputer.price = " + price);
System.out.println("Computer_static_brand: " + brand);
showComputer(this);
}
}
}
class DemoTest {
public static void main(String[] args) {
Computer computer = new Computer();
Computer.Mouse mouse = computer.new Mouse();
mouse.printOuterClassMember();
}
}
外部类的成员变量和内部类的成员变量重名的时候,如何访问外部类的成员变量?
public class OuterClass {
private int n = 1;
public class InnerClass {
private int n = 0;
public void test() {
System.out.println(n);
System.out.println(this.n);
System.out.println(OuterClass.this.n);
}
}
}
四、内部类内存布局
✏️ 通过外部类实例创建内部类实例后,内部类实例的内存中会有一个指针指向外部类实例
画下面代码的内存布局图:
public class Computer {
public int price = 8989;
public class Mouse {
public String color = "黑";
}
}
class DemoTest {
public static void main(String[] args) {
Computer computer = new Computer();
Computer.Mouse mouse1 = computer.new Mouse();
Computer.Mouse mouse2 = computer.new Mouse();
System.out.println("\ncomputer.price = " + computer.price);
System.out.println("mouse.color = " + mouse1.color);
}
}
五、静态嵌套类(Static Nested Class)
✏️ 静态嵌套类:被 static
修饰的嵌套类
✏️ 静态嵌套类在行为上就是一个 顶级类,只是定义的代码写在了另一个类中
✏️ 与一般的顶级类不同,静态嵌套类有一些特殊权限
📝 可以直接访问或调用 外部类中的 静态成员(即使是
private
)
📝 若想访问或调用 外部类中的 实例成员必须先创建外部类的实例,然后通过外部类的实例访问外部类的实例成员(即使是private
成员)
普通顶级类相比静态嵌套类的区别1:
public class Person {
private String name = "张浩男";
private int age = 16;
private static final char GENDER = '男';
private static String father = "庆医";
private static int familyNo = 9521;
private void play() {
System.out.println("Person_play()");
}
}
✏️ 上面的 Person 类中的属性 name、属性 age 和方法 play 都被
private
关键字修饰
✏️ 在其他类中无法访问 Person 类中的私有成员变量或私有方法(如下图)
普通顶级类相比静态嵌套类的区别2(静态嵌套类的好处):
public class Person {
private String name = "张浩男";
private int age = 16;
private static final char GENDER = '男';
private static String father = "庆医";
private static int familyNo = 9521;
private void play() {
System.out.println("Person_play()");
}
public static void run() {
System.out.println("Person_run()");
}
public static class Phone {
public void showInfo() {
System.out.println("\n----------- showInfo()");
System.out.println("GENDER = " + GENDER);
System.out.println("father = " + father);
System.out.println("familyNo = " + familyNo);
run();
System.out.println();
Person person = new Person();
System.out.println(person.name);
System.out.println(person.age);
person.play();
System.out.println("----------- showInfo()");
}
}
}
public class TestDemo {
public static void main(String[] args) {
Person.Phone phone = new Person.Phone();
phone.showInfo();
}
}
六、什么情况使用嵌套类?
✏️ 若类 A 只在类 C 内部被使用,可以考虑把类 A 嵌套到类 C 中
📝 封装性更好
📝 程序包更加简洁
📝 增加可读性和维护性
✏️ 若类 A 需要经常访问类 C 中的 非共有成员(被 private
修饰的成员),可以考虑将类 A 嵌套到类 C 中
📝 可根据需要将类 A 隐藏起来(不堆外暴露)
✏️ 若需要经常访问非公共的 实例成员,设计成内部类(非静态嵌套类),否则设计成静态嵌套类
📝 若必须先有 C 实例才能创建 A 实例,那么可以考虑把 A 设计为 C 的内部类
七、局部类(Local Class)
✏️ 定义在 代码块中的类叫 局部类(可定义在 方法中, for
循环中, if
语句中)
📝 You can define a local class inside any block. You can define a local class in a method body, a for loop, or an if clause.
✏️ 局部类的作用域只在定义它的代码块中
✏️ 局部类中不能定义除 编译时常量之外的其他 static
成员
📝 编译时常量:若将基本类型或字符串定义为常量(
static final
),并且在编译时就能确定值,则编译器会使用常量值替换各处的常量名(类似 C 语言中的宏替换)
📝 被static
修饰的成员可以通过类名访问或调用,但局部类的作用域只在定义它的代码块中,产生矛盾。
✏️ 局部类内部只能访问 final
或 有效 final 的局部变量
📝 有效 final:虽然没有被
final
修饰,但只进行了 一次赋值(若被赋值了不止一次,则不是有效 final)
📝 从 Java8 开始,如果局部变量没有被第二次赋值,则该局部变量会被认定为是【有效 final】
✏️ 局部类可以直接访问外部类中的所有成员(即使是 private
成员)
📝 局部类只有定义在实例相关的代码块中才能直接访问外部类中的实例成员(实例变量、实例方法)
public class OuterClass {
private String outerName = "龙行天下";
public void testMethod() {
int number = 123;
final int count = 666;
class LocalClassTest {
private static final int num = 22;
private void show() {
System.out.println("LocalClassTest_show()");
System.out.println("number = " + number);
System.out.println("count = " + count);
System.out.println("outerName = " + outerName);
}
}
LocalClassTest localClass = new LocalClassTest();
localClass.show();
System.out.println(LocalClassTest.num);
}
}
class TestDemo {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.testMethod();
}
}
🎁 结束:如有错误,请不吝赐教!
Original: https://blog.csdn.net/m0_54189068/article/details/126815766
Author: new Handsome()
Title: 19、Java 中的 final 关键字、嵌套类、内部类、静态嵌套类、局部类
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/542919/
转载文章受原作者版权保护。转载请注明原作者出处!