当前位置: 首页 > news >正文

java面试题02访问修饰符有哪些?区别是什么?

访问修饰符是面向对象编程中实现封装的核心机制,用于控制类、属性、方法等成员的可见性(可访问范围)。不同的访问修饰符决定了其他类或代码在何处可以访问这些成员。

主要的访问修饰符及其区别如下(以 Java 和 C# 为代表,其他语言类似但可能有细微差异):

主要访问修饰符

  1. public (公共的)

    • 可见性范围: 最广。任何地方都可以访问(同一个包/命名空间内、不同包/命名空间内、其他程序集内)。
    • 用途: 定义类的公共接口(API),暴露给外部使用者。通常用于类本身(如果允许外部实例化)、构造方法、以及希望被广泛调用的核心方法或常量属性。
    • 示例:
      public class MyClass {public int publicField; // 任何地方都能读写public void publicMethod() { ... } // 任何地方都能调用
      }
      
  2. protected (受保护的)

    • 可见性范围:
      • 同一个类内部。
      • 同一个包/命名空间内部(Java 特有,C# 的 protected 默认不包括同一命名空间)。
      • 子类内部(无论子类在哪个包/命名空间)。这是 protected 最核心的含义。
    • 用途: 允许类将成员暴露给其子类,用于继承和扩展。通常用于需要被子类覆盖或直接使用的方法和属性,但不希望完全公开给外部。
    • 示例:
      public class Parent {protected int protectedField; // 子类和同包类可访问protected void protectedMethod() { ... } // 子类和同包类可调用
      }
      public class Child extends Parent {public void useProtected() {protectedField = 10; // 子类内部可直接访问父类的protected成员protectedMethod();   // 子类内部可直接调用父类的protected方法}
      }
      
  3. default (包私有 / 内部 - Java) / internal (内部 - C#)

    • Java (default - 无关键字):
      • 可见性范围: 同一个包(package)内部。同一个包内的类可以访问,包外的类(即使是子类)不能访问。
      • 用途: 实现包级别的封装,用于包内协作但不希望包外访问的成员。
      • 示例 (Java):
        class PackagePrivateClass { // 没有 public, 默认 defaultint defaultField; // 默认 default,同包可见void defaultMethod() { ... } // 默认 default,同包可见
        }
        
    • C# (internal):
      • 可见性范围: 同一个程序集(Assembly)内部。同一个项目(编译单元)内的类可以访问,不同程序集(如引用的DLL)中的类不能访问。
      • 用途: 实现组件或模块内部的封装,用于内部协作的成员,不暴露给外部使用者。
      • 示例 (C#):
        internal class InternalClass {internal int InternalField; // 同程序集可见internal void InternalMethod() { ... } // 同程序集可见
        }
        
  4. private (私有的)

    • 可见性范围: 最小,仅限于定义它的类(或结构体、枚举)内部。即使是同一个包/程序集内的其他类,或者它的子类,都不能直接访问。
    • 用途: 实现最严格的封装。用于隐藏类的实现细节(内部状态、辅助方法),只允许类自身的方法进行操作。这是保证数据安全性和一致性的关键手段。字段(属性背后的数据)通常应声明为 private,然后通过 publicprotected 的属性(getter/setter)或方法来提供受控的访问。
    • 示例:
      public class MyClass {private int privateField; // 只有MyClass内部的方法能访问private void privateHelperMethod() { ... } // 只有MyClass内部的方法能调用public void publicMethod() {privateField = 5; // 类内部方法可以访问private成员privateHelperMethod();}
      }
      // 外部代码尝试访问会编译错误
      // MyClass obj = new MyClass();
      // obj.privateField = 10; // 错误!
      // obj.privateHelperMethod(); // 错误!
      

访问范围总结表 (以 Java 为例)

修饰符当前类内部同一个包 (Package) 内部不同包的子类不同包的非子类
public
protected
default
private

C# 注意点:

  • protected 在 C# 中默认不包括同一命名空间内的其他类(只包括自身和子类)。如果需要 Java protected 的语义(自身+子类+同程序集),C# 提供了 protected internalprotectedinternal 满足其一即可访问)。
  • internal 是 C# 对应 Java default 包可见性的概念,但作用域是程序集而非包。

关键区别与设计原则

  1. 封装性控制: private 提供最强封装,public 最弱。选择哪种修饰符本质上是决定“谁有权知道和操作这个成员”。
  2. 信息隐藏: 使用 private 隐藏实现细节(如字段、内部状态、复杂算法的辅助方法),只通过 public/protected 方法暴露必要的、定义良好的接口(API)。这是 OOP 设计的基石。
  3. 安全性: 防止外部代码随意修改对象内部状态(尤其是 private 字段),保证对象状态的有效性和一致性(例如,通过 private setter 进行数据验证)。
  4. 灵活性与可维护性: 隐藏内部实现后,只要公共接口不变,内部实现的修改(如优化算法、改变数据结构)不会影响使用该类的代码,提高了代码的可维护性和可扩展性。
  5. 继承与扩展: protected 修饰符是专门为继承设计的,允许基类向子类暴露一些内部能力或状态,支持“白盒复用”,同时仍对非继承体系外的代码隐藏。

最佳实践建议

  • 字段优先 private 几乎总是将字段声明为 private,然后通过公共的属性(Property - C#)Getter/Setter 方法(Java) 来提供访问(可以在其中加入验证逻辑)。
  • 方法按需选择:
    • public: 类的主要功能、对外提供的服务。
    • protected: 供子类覆盖或调用的方法(模板方法模式常用)。
    • private: 内部辅助方法、实现细节。
    • default/internal: 包内/程序集内协作的辅助方法或类,不对外公开。
  • 类本身: 通常用 public(可被外部实例化)或 default/internal(仅包内/程序集内使用)。极少用 private/protected(嵌套类常用)。

理解并正确使用访问修饰符是编写健壮、可维护、符合面向对象设计原则代码的关键一步。 它直接体现了“什么该暴露,什么该隐藏”的设计决策。

http://www.lqws.cn/news/448273.html

相关文章:

  • 如何自建服务器并开启公网IP:本地内网网址让外网访问详细教学
  • 华为CE交换机抓包
  • 如何导出和迁移离线 Conda 环境
  • Java八股文——数据结构「排序算法篇」
  • 【目标检测】什么是目标检测?应用场景与基本流程
  • Spring 中的依赖注入(DI)详解
  • Transformer实战——Hugging Face环境配置与应用详解
  • 【编译原理】语句的翻译
  • Docker环境部署
  • Centos 离线部署(MQTT)EMOX脚本并设置开机自启
  • 4、做中学 | 二年级下期 Golang整型和浮点型
  • 高并发网络通信Netty之空轮询问题
  • 【LUT技术专题】采样间隔自适应3DLUT-AdaInt
  • STM32 HAL 初始化I2C启动DS1307
  • 第1章: 伯努利模型的极大似然估计与贝叶斯估计
  • apisix-使用hmac-auth插件进行接口签名身份验证\apisix consumer
  • 机构运动分析系统开发(Python实现)
  • 工程师生活:清除电热水壶(锅)水垢方法
  • 前端HTML学习笔记
  • 《思维力:高效的系统思维》
  • python画三维立体图
  • 【支持向量机】SVM线性可分支持向量机学习算法——硬间隔最大化支持向量机及例题详解
  • 打卡Day55
  • 【lenovo】LEGION 2020款跳过windows账号登录
  • 12.10 在主线程或子线程中更新 UI
  • 退出python解释器的四种方式
  • C#语言入门-task2 :C# 语言的基本语法结构
  • vue3 defineExpose的使用
  • 不同系统修改 Docker Desktop 存储路径(从C盘修改到D盘)
  • 解锁微服务潜能:深入浅出 Nacos