Java继承:成员变量访问(就近原则+this/super用法)

🏠个人主页:黎雁

🎬作者简介:C/C++/JAVA后端开发学习者

❄️个人专栏:C语言数据结构(C语言)EasyXJAVA游戏规划程序人生

✨ 从来绝巘须孤往,万里同尘即玉京

文章目录

Java继承:成员变量访问(就近原则+this/super用法)

知识回顾

上一篇我们深挖了子类继承父类成员的底层逻辑,明确了"仅非私有成员变量和方法可继承、构造方法不能继承、静态成员类级别共享"的核心边界,还了解了虚方法表在继承中的作用。但实际开发中,常遇到父子类定义同名成员变量 的场景,此时如何区分访问?这篇我们聚焦成员变量的访问原则------就近原则 ,结合thissuper关键字的用法,彻底解决"同名变量访问混乱"的问题,掌握继承中成员变量的精准访问技巧🎯!

📝 文章摘要

  • 核心摘要 :本文从父子类成员变量的访问场景出发,讲解"就近原则"的核心逻辑及适用场景,重点拆解thissuper关键字访问成员变量的用法、区别与底层原理,结合同名变量、不同名变量的实战案例,帮你精准掌握继承中成员变量的访问规则,规避访问错误。
  • 阅读时长:9分钟
  • 适合人群&阅读重点
    🎯 Java初学者:重点牢记就近原则,掌握thissuper访问成员变量的基础用法,能区分父子类同名变量。
    📚 高校计算机专业学生:理解就近原则的底层逻辑,理清thissuper的访问机制,深化对继承体系的理解。
    💻 初级开发工程师:解决实际开发中父子类同名变量的访问问题,规范代码编写,提升可读性。
    📖 面试备考者:熟记就近原则、thissuper的区别,应对"父子类同名变量如何访问"类面试题。

一、核心原则:成员变量访问的"就近原则" 🎯

在继承体系中,当访问一个成员变量时,JVM会遵循就近原则查找变量,优先级从高到低依次为:

  1. 当前方法的局部变量:先查找当前方法中是否定义了该名称的局部变量,找到则直接使用;
  2. 当前类的成员变量:若方法中无对应局部变量,查找当前类(子类)是否定义了该名称的成员变量,找到则使用;
  3. 父类的成员变量:若当前类无对应成员变量,查找父类(及上层父类)是否有非私有成员变量,找到则使用;
  4. 报错:若所有层级都无该名称的变量,编译报错"找不到符号"。

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关键字的用法 🛠️

当需要打破就近原则,精准访问"当前类成员变量"或"父类成员变量"时,需使用thissuper关键字,两者分工明确,是继承中成员访问的核心工具。

2.1 this关键字:访问当前类的成员变量

this代表当前对象,核心作用是访问当前类(子类)的成员变量,可用于:

  1. 区分"局部变量"与"当前类成员变量"(同名场景);
  2. 直接访问当前类的成员变量(无同名时,可省略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代表父类对象的引用,核心作用是访问父类的非私有成员变量(尤其是父子类同名场景),可用于:

  1. 访问父类的同名成员变量(打破就近原则,穿透子类隐藏);
  2. 访问父类的非同名成员变量(无同名时,可省略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关键字
代表对象 当前子类对象 父类对象的引用
访问目标 当前类(子类)的成员变量 父类的非私有成员变量
核心场景 区分局部变量与子类成员变量 区分子类与父类的同名成员变量
适用范围 可在子类的非静态方法中使用 可在子类的非静态方法中使用
静态方法中使用 ❌ 禁止(静态方法无当前对象) ❌ 禁止(静态方法无父类对象引用)

💡 关键禁忌:thissuper不能在静态方法中使用 ,因为静态方法属于类级别,无对应对象(this无当前对象,super无父类对象引用),编译报错。

三、复杂场景实战:多层继承+多同名变量 🧩

当存在多层继承且多个层级定义同名变量时,thissuper的访问规则依然适用,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,无同名时省略,保持代码简洁。

✍️ 写在最后

  1. 继承中成员变量访问的核心是就近原则,优先级:局部变量>当前类成员变量>父类成员变量,同名时父类变量被隐藏;
  2. thissuper是精准访问变量的关键:this访问当前类变量,解决局部变量与成员变量同名问题;super访问父类变量,解决子类与父类同名变量问题;
  3. 核心禁忌:thissuper均不能在静态方法中使用,super无法直接访问祖父类变量,需通过父类方法转发;
  4. 开发规范:仅在必要时使用this/super(同名场景),无同名时省略,避免代码冗余;父子类尽量避免定义同名变量,减少访问混乱。

下一篇我们将聚焦继承中的核心考点------方法重写,讲解方法重写的定义、规则、底层原理,结合实战案例区分"方法重写"与"方法重载",彻底吃透继承中的方法特性💪!


❤️ 我是黎雁,专注Java基础与实战分享,关注我,一起从0到1吃透Java面向对象!

📚 后续文章预告:《Java方法重写Override:规则+底层本质+与重载区别》

💬 评论区交流:你在使用this/super访问变量时遇到过哪些问题?或者对就近原则有哪些疑惑,欢迎留言讨论~

相关推荐
别或许2 小时前
python中的异步调用(直接使用教程)
java·前端·python
ShineWinsu2 小时前
对于C++:模版初阶的解析
开发语言·c++·面试·笔试·函数··模版
CodeAmaz2 小时前
文件断点续传完整方案
java·文件断点上传
Max_uuc2 小时前
【C++ 硬核】告别 Excel 生成数组:利用 constexpr 实现编译期计算查找表 (LUT)
开发语言·c++·excel
像少年啦飞驰点、2 小时前
零基础入门 Spring Boot:从‘Hello World’到可部署微服务的完整学习路径
java·spring boot·web开发·编程入门·后端教程
m0_748248652 小时前
C++正则表达式攻略:从基础到高级应用
java·c++·正则表达式
墨雨晨曦882 小时前
leedcode刷题总结
java·开发语言
嫂子开门我是_我哥2 小时前
第十六节:异常处理:让程序在报错中稳定运行
开发语言·python
qq_12498707532 小时前
基于SpringBoot的闪电队篮球俱乐部管理系统的设计与开发(源码+论文+部署+安装)
java·数据库·spring boot·后端·spring·毕业设计·计算机毕业设计