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

相关推荐
咩咩啃树皮8 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
炸膛坦客8 小时前
单片机/C/C++八股:(二十六)IIC 专题(I²C)---- 上集
c语言·c++·单片机
旖-旎8 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
灯澜忆梦8 小时前
GO_并发编程---定时器
开发语言·后端·golang
鱟鲥鳚8 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
-银雾鸢尾-8 小时前
C#中的StringBuilder相关方法
开发语言·c#
Henry Zhu1238 小时前
C++中的特殊成员函数与智能指针
c++
-银雾鸢尾-9 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#
大模型码小白9 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司10 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求