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中只能访问子类变量

相关推荐
kkeeper~21 小时前
0基础C语言积跬步之深入理解指针(5下)
c语言·开发语言
一直不明飞行21 小时前
Java的equals(),hashCode()应该在什么时候重写
java·开发语言·jvm
REDcker21 小时前
有限状态机与状态模式详解 FSM建模Java状态模式与C++表驱动模板实践
java·c++·状态模式
盲敲代码的阿豪1 天前
Python 入门基础教程(爬虫前置版)
开发语言·爬虫·python
你的保护色1 天前
【无标题】
java·服务器·网络
basketball6161 天前
C++ 构造函数完全指南:从入门到进阶
java·开发语言·c++
互联科技报1 天前
2026超融合选型:Top5品牌与市场格局解读
开发语言·perl
weixin199701080161 天前
[特殊字符] 智能数据采集:数字化转型的“数据石油勘探队”(附Python实战源码)
开发语言·python
淘矿人1 天前
Claude辅助DevOps实践
java·大数据·运维·人工智能·算法·bug·devops
想唱rap1 天前
IO多路转接之poll
服务器·开发语言·数据库·c++