
🏠个人主页:黎雁
🎬作者简介:C/C++/JAVA后端开发学习者
❄️个人专栏:C语言、数据结构(C语言)、EasyX、JAVA、游戏、规划、程序人生
✨ 从来绝巘须孤往,万里同尘即玉京

文章目录
- Java继承:成员变量访问(就近原则+this/super用法)
-
- [📝 文章摘要](#📝 文章摘要)
- [一、核心原则:成员变量访问的"就近原则" 🎯](#一、核心原则:成员变量访问的“就近原则” 🎯)
- [二、精准访问:this与super关键字的用法 🛠️](#二、精准访问:this与super关键字的用法 🛠️)
-
- [2.1 this关键字:访问当前类的成员变量](#2.1 this关键字:访问当前类的成员变量)
- [2.2 super关键字:访问父类的成员变量](#2.2 super关键字:访问父类的成员变量)
- [2.3 this与super访问成员变量的核心区别 🆚](#2.3 this与super访问成员变量的核心区别 🆚)
- [三、复杂场景实战:多层继承+多同名变量 🧩](#三、复杂场景实战:多层继承+多同名变量 🧩)
- [四、高频误区&避坑指南 ⚠️](#四、高频误区&避坑指南 ⚠️)
- [✍️ 写在最后](#✍️ 写在最后)

Java继承:成员变量访问(就近原则+this/super用法)
✨ 知识回顾
上一篇我们深挖了子类继承父类成员的底层逻辑,明确了"仅非私有成员变量和方法可继承、构造方法不能继承、静态成员类级别共享"的核心边界,还了解了虚方法表在继承中的作用。但实际开发中,常遇到父子类定义同名成员变量 的场景,此时如何区分访问?这篇我们聚焦成员变量的访问原则------就近原则 ,结合this和super关键字的用法,彻底解决"同名变量访问混乱"的问题,掌握继承中成员变量的精准访问技巧🎯!
📝 文章摘要
- 核心摘要 :本文从父子类成员变量的访问场景出发,讲解"就近原则"的核心逻辑及适用场景,重点拆解
this和super关键字访问成员变量的用法、区别与底层原理,结合同名变量、不同名变量的实战案例,帮你精准掌握继承中成员变量的访问规则,规避访问错误。 - 阅读时长:9分钟
- 适合人群&阅读重点
🎯 Java初学者:重点牢记就近原则,掌握this和super访问成员变量的基础用法,能区分父子类同名变量。
📚 高校计算机专业学生:理解就近原则的底层逻辑,理清this与super的访问机制,深化对继承体系的理解。
💻 初级开发工程师:解决实际开发中父子类同名变量的访问问题,规范代码编写,提升可读性。
📖 面试备考者:熟记就近原则、this与super的区别,应对"父子类同名变量如何访问"类面试题。
一、核心原则:成员变量访问的"就近原则" 🎯
在继承体系中,当访问一个成员变量时,JVM会遵循就近原则查找变量,优先级从高到低依次为:
- 当前方法的局部变量:先查找当前方法中是否定义了该名称的局部变量,找到则直接使用;
- 当前类的成员变量:若方法中无对应局部变量,查找当前类(子类)是否定义了该名称的成员变量,找到则使用;
- 父类的成员变量:若当前类无对应成员变量,查找父类(及上层父类)是否有非私有成员变量,找到则使用;
- 报错:若所有层级都无该名称的变量,编译报错"找不到符号"。
1.1 基础案例:无同名变量,验证就近原则
java
// 父类:Animal
public class Animal {
String name = "动物名称"; // 父类成员变量
int age = 1;
}
// 子类:Cat
public class Cat extends Animal {
String color = "橘色"; // 子类成员变量
// 测试方法:无局部变量,访问成员变量
public void show() {
System.out.println(name); // 父类变量(子类无name,找父类)
System.out.println(color); // 子类变量(当前类有color)
System.out.println(age); // 父类变量(子类无age,找父类)
}
// 测试方法:有局部变量,优先局部变量
public void showWithLocal() {
String color = "黑色"; // 局部变量
System.out.println(color); // 局部变量(优先级最高)
System.out.println(name); // 父类变量(无局部name,找父类)
}
}
// 测试类
public class TestNearRule {
public static void main(String[] args) {
Cat cat = new Cat();
cat.show();
System.out.println("========");
cat.showWithLocal();
}
}
运行结果
动物名称
橘色
1
========
黑色
动物名称
结果分析
show()方法中无局部变量,访问name时子类无对应变量,按就近原则找到父类的name;访问color时子类有对应变量,直接使用子类变量;showWithLocal()方法中有局部变量color,按就近原则优先使用局部变量,而非子类或父类的成员变量。
1.2 核心场景:父子类同名变量,就近原则的体现
当父子类定义同名成员变量时,就近原则会优先使用子类的成员变量,父类的同名变量会被"隐藏"(并非覆盖,仅访问优先级低)。
java
// 父类:Animal,定义name变量
public class Animal {
String name = "动物名称";
}
// 子类:Cat,定义同名name变量
public class Cat extends Animal {
String name = "加菲猫"; // 子类同名变量,隐藏父类name
public void show() {
System.out.println(name); // 子类name(就近原则,优先子类)
}
}
// 测试
public class TestSameName {
public static void main(String[] args) {
new Cat().show(); // 输出:加菲猫
}
}
关键说明
- 父子类同名变量时,父类的变量并未消失,只是按就近原则无法直接访问,需通过
super关键字专门访问父类的同名变量; - 此处的"隐藏"与后续方法重写的"覆盖"不同:变量是隐藏 (访问优先级问题),方法是覆盖(虚方法表地址替换),切勿混淆。
二、精准访问:this与super关键字的用法 🛠️
当需要打破就近原则,精准访问"当前类成员变量"或"父类成员变量"时,需使用this和super关键字,两者分工明确,是继承中成员访问的核心工具。
2.1 this关键字:访问当前类的成员变量
this代表当前对象,核心作用是访问当前类(子类)的成员变量,可用于:
- 区分"局部变量"与"当前类成员变量"(同名场景);
- 直接访问当前类的成员变量(无同名时,可省略
this)。
实战案例1:区分局部变量与当前类成员变量
java
public class Cat extends Animal {
String name = "加菲猫"; // 子类成员变量
// 局部变量与成员变量同名
public void setName(String name) {
// this.name:当前类成员变量;name:局部变量
this.name = name;
}
public void show() {
System.out.println(this.name); // 访问当前类成员变量
}
}
// 测试
public class TestThis {
public static void main(String[] args) {
Cat cat = new Cat();
cat.setName("橘猫");
cat.show(); // 输出:橘猫
}
}
实战案例2:无同名时,this可省略
java
public class Cat extends Animal {
String name = "加菲猫";
public void show() {
// this.name 与 name 等价(无局部变量同名)
System.out.println(this.name);
System.out.println(name);
}
}
2.2 super关键字:访问父类的成员变量
super代表父类对象的引用,核心作用是访问父类的非私有成员变量(尤其是父子类同名场景),可用于:
- 访问父类的同名成员变量(打破就近原则,穿透子类隐藏);
- 访问父类的非同名成员变量(无同名时,可省略
super)。
实战案例1:访问父类的同名成员变量
java
// 父类:Animal
public class Animal {
String name = "动物名称";
}
// 子类:Cat,同名变量
public class Cat extends Animal {
String name = "加菲猫";
public void show() {
System.out.println(name); // 子类name(就近原则)
System.out.println(this.name); // 子类name(this访问当前类)
System.out.println(super.name); // 父类name(super访问父类)
}
}
// 测试
public class TestSuper {
public static void main(String[] args) {
new Cat().show();
}
}
运行结果
加菲猫
加菲猫
动物名称
结果分析
- 无关键字时,按就近原则访问子类
name; this.name明确访问当前类(子类)的name,结果与无关键字一致;super.name明确访问父类的name,打破就近原则,获取父类被隐藏的变量。
实战案例2:访问父类的非同名成员变量
java
public class Animal {
int age = 1; // 父类非同名变量
}
public class Cat extends Animal {
String name = "加菲猫";
public void show() {
// super.age 与 age 等价(无同名)
System.out.println(super.age);
System.out.println(age);
}
}
// 测试
new Cat().show(); // 输出:1 1
2.3 this与super访问成员变量的核心区别 🆚
| 对比维度 | this关键字 | super关键字 |
|---|---|---|
| 代表对象 | 当前子类对象 | 父类对象的引用 |
| 访问目标 | 当前类(子类)的成员变量 | 父类的非私有成员变量 |
| 核心场景 | 区分局部变量与子类成员变量 | 区分子类与父类的同名成员变量 |
| 适用范围 | 可在子类的非静态方法中使用 | 可在子类的非静态方法中使用 |
| 静态方法中使用 | ❌ 禁止(静态方法无当前对象) | ❌ 禁止(静态方法无父类对象引用) |
💡 关键禁忌:this和super都不能在静态方法中使用 ,因为静态方法属于类级别,无对应对象(this无当前对象,super无父类对象引用),编译报错。
三、复杂场景实战:多层继承+多同名变量 🧩
当存在多层继承且多个层级定义同名变量时,this和super的访问规则依然适用,super仅访问直接父类 的变量,若需访问上层祖父类变量,需在直接父类中通过super转发。
实战案例:三层继承,访问祖父类变量
java
// 祖父类:Animal
public class Animal {
String name = "动物名称";
}
// 父类:Mammal,继承Animal,同名变量
public class Mammal extends Animal {
String name = "哺乳动物名称";
// 父类方法:访问祖父类name
public void showGrandParentName() {
System.out.println(super.name); // 访问祖父类Animal的name
}
}
// 子类:Cat,继承Mammal,同名变量
public class Cat extends Mammal {
String name = "加菲猫";
public void showAllName() {
System.out.println(name); // 子类name:加菲猫
System.out.println(this.name); // 子类name:加菲猫
System.out.println(super.name); // 直接父类Mammal的name:哺乳动物名称
showGrandParentName(); // 调用父类方法,访问祖父类name:动物名称
}
}
// 测试
public class TestMultiExtend {
public static void main(String[] args) {
new Cat().showAllName();
}
}
运行结果
加菲猫
加菲猫
哺乳动物名称
动物名称
核心规律
super关键字仅能访问直接父类的成员变量,无法直接跨层级访问祖父类变量;- 若需访问上层父类变量,需在对应层级的父类中提供方法,通过
super转发访问(如本例中Mammal类的showGrandParentName()方法)。
四、高频误区&避坑指南 ⚠️
误区1:认为super能访问祖父类变量
❌ 错误认知:super.super.name可直接访问祖父类变量;
✅ 正确结论:Java语法禁止super.super的用法,super仅能访问直接父类变量,跨层级需通过父类方法转发。
误区2:静态方法中使用this/super访问变量
❌ 错误示例:
java
public class Cat extends Animal {
static void show() {
System.out.println(this.name); // 报错:Cannot use 'this' in a static context
System.out.println(super.name); // 报错:Cannot use 'super' in a static context
}
}
✅ 正确做法:静态方法访问变量时,直接通过类名访问(静态变量),或创建对象后通过对象访问(非静态变量)。
误区3:混淆变量"隐藏"与方法"覆盖"
❌ 错误认知:父子类同名变量是覆盖关系,与方法重写一致;
✅ 正确结论:变量是隐藏 (访问优先级问题,父类变量仍存在),方法是覆盖 (虚方法表地址替换,父类方法被覆盖);super可访问被隐藏的父类变量,但无法访问被覆盖的父类方法(需特殊语法,后续讲解)。
误区4:不必要时过度使用this/super
❌ 错误示例:无同名变量时强行使用this/super,代码冗余;
java
public class Cat extends Animal {
String name = "加菲猫";
public void show() {
System.out.println(this.name); // 无必要,可简化为name
System.out.println(super.age); // 无必要,可简化为age
}
}
✅ 正确做法:仅在需要区分同名变量时使用this/super,无同名时省略,保持代码简洁。
✍️ 写在最后
- 继承中成员变量访问的核心是就近原则,优先级:局部变量>当前类成员变量>父类成员变量,同名时父类变量被隐藏;
this和super是精准访问变量的关键:this访问当前类变量,解决局部变量与成员变量同名问题;super访问父类变量,解决子类与父类同名变量问题;- 核心禁忌:
this和super均不能在静态方法中使用,super无法直接访问祖父类变量,需通过父类方法转发; - 开发规范:仅在必要时使用this/super(同名场景),无同名时省略,避免代码冗余;父子类尽量避免定义同名变量,减少访问混乱。
下一篇我们将聚焦继承中的核心考点------方法重写,讲解方法重写的定义、规则、底层原理,结合实战案例区分"方法重写"与"方法重载",彻底吃透继承中的方法特性💪!
❤️ 我是黎雁,专注Java基础与实战分享,关注我,一起从0到1吃透Java面向对象!
📚 后续文章预告:《Java方法重写Override:规则+底层本质+与重载区别》
💬 评论区交流:你在使用this/super访问变量时遇到过哪些问题?或者对就近原则有哪些疑惑,欢迎留言讨论~