Java与C++多态访问成员变量/方法 对比

在 Java 中,情况与 C++ 非常相似 ,但也存在一个关键的语法区别 (关键字不同)和一个根本的机制区别(访问权限)。

核心结论速查表

特性 C++ Java
现象名称 变量隐藏 (Hiding) 变量隐藏 (Hiding) / 遮蔽 (Shadowing)
内存情况 父类和子类各存一份,互不干扰 父类和子类各存一份,互不干扰
访问子类变量 obj.varptr->var obj.varthis.var
访问父类变量 obj.Parent::var super.var (关键区别!)
多态性 ❌ 无 (静态绑定,看引用类型) ❌ 无 (静态绑定,看引用类型)
能否通过父类引用访问子类变量? ❌ 不能 (编译报错) ❌ 不能 (编译报错)

1. 代码实战演示

假设我们有以下类结构:

java 复制代码
class Parent {
    int value = 100; // 父类变量
}

class Child extends Parent {
    int value = 200; // 子类变量 (隐藏了父类的 value)

    public void show() {
        // 1. 访问子类变量 (默认)
        System.out.println("Child value: " + this.value); // 输出 200
        System.out.println("Child value: " + value);      // 输出 200 (省略 this)

        // 2. 访问父类变量 (关键语法)
        System.out.println("Parent value: " + super.value); // 输出 100
    }
}

public class Main {
    public static void main(String[] args) {
        Child obj = new Child();
        Child cRef = obj;   // 子类引用
        Parent pRef = obj;  // 父类引用 (指向同一个对象)

        System.out.println("=== 1. 通过子类引用访问 ===");
        System.out.println("cRef.value: " + cRef.value); // 输出 200 (看引用类型 Child)

        System.out.println("\n=== 2. 通过父类引用访问 ===");
        System.out.println("pRef.value: " + pRef.value); // 输出 100 (看引用类型 Parent)
        
        // pRef.super.value; // ❌ 错误!外部代码不能使用 super 关键字
        // pRef.Child::value; // ❌ 错误!Java 没有 :: 语法
        
        // 如果非要通过父类引用访问子类变量,需要强制类型转换
        System.out.println("((Child)pRef).value: " + ((Child)pRef).value); // 输出 200
    }
}

2. 关键区别解析

A. 语法关键字:super vs ::

这是最直观的区别:

  • C++ :使用作用域解析运算符 ::
    • 写法:obj.Parent::valueptr->Parent::value
    • 逻辑:明确指定"我要 Parent 命名空间下的 value"。
  • Java :使用 super 关键字。
    • 写法:super.value
    • 限制:super 只能在子类的方法内部使用 。你不能在 Main 类或其他外部类中写 obj.super.value,这会编译报错。外部只能通过强制类型转换 ((Child)obj).value 来访问子类变量,或者根本无法直接访问被隐藏的父类变量(除非父类提供了 getter 方法)。
B. 访问权限的严格性
  • C++ :只要继承方式是 publicprotected,且成员变量不是 private,子类就可以通过 Parent::value 访问父类变量。
  • Java
    • 如果父类变量是 private:子类完全无法访问 ,连 super.value 都会报错。必须通过父类的 public/protected 方法(如 getValue())访问。
    • 如果父类变量是 default (包私有):只有当子类和父类在同一个包下时,才能访问。
    • 如果父类变量是 protectedpublic:可以通过 super.value 访问。
C. "多态"的缺失 (与 C++ 一致)

这一点 Java 和 C++ 完全一样成员变量没有多态性

  • 无论你实际创建的是 new Child() 还是 new Parent()
  • 编译器只看引用变量的声明类型
    • Parent p = new Child(); -> p.value 永远访问父类的那份数据 (100)。
    • Child c = new Child(); -> c.value 永远访问子类的那份数据 (200)。
  • 这与方法(Method)的重写(Override)完全不同,方法是根据实际对象类型动态绑定的。

3. 如何在外部访问被隐藏的父类变量?

在 Jav中,如果你在 main 方法里有一个 Parent 类型的引用指向 Child 对象,你想访问父类的那个 value

  1. 直接访问pRef.value -> 得到的就是父类的值 (100)。这通常就是你想要的。
  2. 如果你想访问子类的值 :需要强转 ((Child)pRef).value -> 得到 200。
  3. 如果你想在子类方法内部访问父类值 :使用 super.value

注意 :Java 不支持 像 C++ 那样在外部通过 obj.Parent::value 这种语法来"穿透"子类的遮挡去显式读取父类变量(虽然在这个特定场景下,用父类引用 pRef 直接读到的本来就是父类变量,所以通常不需要这种语法)。

总结

你的需求 C++ 写法 Java 写法
在子类方法内访问父类变量 Parent::value super.value
在外部通过对象访问父类变量 obj.Parent::value 无法直接写 (需用父类类型引用 parentRef.value)
在外部通过对象访问子类变量 obj.value (需子类指针) obj.value (需子类类型引用)
核心机制 静态绑定 (看引用类型) 静态绑定 (看引用类型)

一句话记住:

Java 中变量也是隐藏 而非重写,没有多态。在子类内部用 super.变量名 访问父类变量;在外部则完全取决于你手里拿的是父类引用 还是子类引用

拥有子类的引用或者指针,在c++中能通过作用域限定访问父类的变量,而java中只能访问子类变量

相关推荐
2501_933329551 天前
媒介宣发技术实践:Infoseek舆情系统的AI中台架构与应用解析
开发语言·人工智能·架构·数据库开发
雨奔1 天前
Kubernetes DNS 完全指南:服务发现核心机制与实践
java·kubernetes·服务发现
[J] 一坚1 天前
嵌入式高手C
c语言·开发语言·stm32·单片机·mcu·51单片机·iot
odoo中国1 天前
Odoo 19技术教程 : 如何在 Odoo 19 中创建 Many2one 组件
开发语言·odoo·odoo19·odoo技术·many2one
借雨醉东风1 天前
程序分享--常见算法/编程面试题:旋转矩阵
c++·线性代数·算法·面试·职场和发展·矩阵
逻辑驱动的ken1 天前
Java高频面试考点场景题14
java·开发语言·深度学习·面试·职场和发展·求职招聘·春招
阿冰冰呀1 天前
互联网大厂Java求职面试实录:谢飞机的“水货”之路
java·mybatis·dubbo·springboot·线程池·多线程·hashmap
水无痕simon1 天前
1.单机部署Nacos1.3.2
java
云泽8081 天前
笔试算法 - 双指针篇(二):四大经典求和题型 + 有效三角形计数问题
c++·算法
techdashen1 天前
Cloudflare 如何把一个大型代理拆成三个小服务来提升可靠性
开发语言·rust