不正确使用 public、private、protected,导致封装性差或无法访问

news2024/11/14 14:32:32

在Java学习中,封装(Encapsulation)是面向对象编程的重要特性之一。它通过隐藏对象的内部细节,并通过公开的接口与外界交互,从而提高代码的安全性、可维护性和模块化。

然而,如果不正确地使用访问修饰符(publicprivateprotected等),会导致封装性差、类的成员变量和方法暴露过多,甚至可能导致无法访问需要访问的数据。这不仅影响代码的安全性,还会影响系统的灵活性和可维护性。

1. Java中的访问修饰符简介

在Java中,访问修饰符用于控制类、方法和成员变量的可见性。常见的访问修饰符包括:

  • public: 公开访问,任何类都可以访问。
  • private: 私有访问,只有类自身可以访问。
  • protected: 受保护访问,只有同一个包中的类或子类可以访问。
  • 默认(包级访问): 如果未指定任何修饰符,则默认为包级访问,即同一个包中的类可以访问。

每种访问修饰符都有其特定的应用场景,滥用或误用这些修饰符可能导致封装性差或访问控制问题。

2. 常见的访问修饰符误用场景

场景一:滥用public导致封装性差

在编写Java代码时,初学者常常会为了方便,直接将类中的成员变量和方法设置为public,从而允许外部任何类对其进行访问。例如:

public class Person {
    public String name;
    public int age;
}

在上述代码中,Person类的nameage属性都是public的。这意味着其他类可以随意修改Person对象的这些属性:

Person person = new Person();
person.name = "Tom";
person.age = 30;

问题分析

  1. 封装性差public使得类的内部细节完全暴露,其他类可以不受限制地修改对象的属性,破坏了类的封装性。
  2. 缺乏控制:外部类可以直接操作对象的属性,类无法对数据的合法性进行校验,可能导致不合理的数据状态。例如,age可以被赋值为负数。

改进方法: 应将类的成员变量设置为private,并通过public的getter和setter方法对外提供访问接口。这样可以在getter和setter方法中对数据进行校验,保护类的封装性。

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 0) {
            this.age = age;
        } else {
            System.out.println("Age cannot be negative");
        }
    }
}
场景二:滥用private导致无法访问

private修饰符用于隐藏类的成员变量和方法,只允许类自身访问。然而,如果过度使用private,可能导致类与类之间无法正常交互。例如:

public class Car {
    private String model;
    private int year;

    private void startEngine() {
        System.out.println("Engine started");
    }
}

问题分析

  1. 功能被限制:由于startEngine方法被定义为private,外部类无法调用该方法启动引擎,导致功能受限。
  2. 类之间的协作受阻private修饰符使得类的内部状态和行为无法被外部访问,某些必要的功能也可能因此无法正常实现。

改进方法: 应合理区分哪些方法或变量需要对外暴露,将需要被其他类访问的功能设置为publicprotected,而不是一味地将所有成员都设为private。例如:

public class Car {
    private String model;
    private int year;

    public void startEngine() {
        System.out.println("Engine started");
    }
}

在这个例子中,startEngine方法被设为public,这样外部类可以调用该方法,启动引擎功能得以正常实现。

场景三:滥用protected导致访问权限失控

protected修饰符允许同包中的类和子类访问类的成员变量和方法,但初学者在使用protected时常常忽略其适用范围,导致不必要的访问权限暴露。例如:

public class Animal {
    protected String species;

    protected void eat() {
        System.out.println("Eating...");
    }
}

问题分析

  1. 访问权限过宽protected修饰符允许同一个包中的所有类访问specieseat方法。如果包中有其他不相关的类,也可以访问这些成员,可能导致不安全的数据修改或方法调用。
  2. 继承链混乱:在继承关系中,子类可以访问父类的protected成员,但在复杂的继承结构中,过度暴露的protected成员可能导致子类过度依赖父类的实现,降低了代码的灵活性。

改进方法: 应谨慎使用protected,只在确实需要子类访问父类的成员时才使用protected。对于不需要暴露的成员,依然应保持private访问级别,通过适当的getter和setter进行访问控制。例如:

public class Animal {
    private String species;

    public String getSpecies() {
        return species;
    }

    public void setSpecies(String species) {
        this.species = species;
    }

    public void eat() {
        System.out.println("Eating...");
    }
}

3. 正确使用访问修饰符的建议

为了更好地利用Java中的访问修饰符,提升代码的封装性,以下是一些实用的建议:

建议一:成员变量应尽可能使用private

将类的成员变量设为private是封装的重要步骤。通过private,我们可以隐藏对象的内部状态,防止外部类直接修改或访问对象的属性。这样一来,类的内部实现可以随时更改,而不影响外部代码的运行。

public class Employee {
    private String name;
    private int salary;

    // 使用getter和setter方法访问成员变量
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        if (salary >= 0) {
            this.salary = salary;
        }
    }
}
建议二:对外暴露的接口应使用public

如果类的方法或变量需要被外部类访问,则应使用public修饰符。但是,在使用public时应保持谨慎,确保只对必要的接口进行公开,避免不必要的暴露。例如:

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    // 这个方法不需要对外暴露,因此保持为private
    private int subtract(int a, int b) {
        return a - b;
    }
}
建议三:使用protected时应考虑继承结构

protected主要用于父类与子类之间的访问控制。当设计类的继承结构时,只有当子类确实需要访问父类的成员时才应使用protected,避免子类过度依赖父类实现。否则,尽量使用private,保持类的独立性。

public class Shape {
    protected double area;

    public double getArea() {
        return area;
    }
}

在Java编程中,合理使用publicprivateprotected访问修饰符对于保持类的封装性至关重要。滥用public会导致封装性差,滥用private会导致无法访问,滥用protected则可能带来不必要的访问权限暴露。在实际编程中,应根据类的设计意图,合理选择访问修饰符,以保证类的封装性、安全性和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2117919.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ROS2图形化方式新建功能包工具- Turtle Nest

提示:全文AI生成。 链接: https://github.com/Jannkar/turtle_nest 配置 Turtle Nest 使用说明(中文版) 一、Turtle Nest 简介 正如海龟巢是幼海龟的诞生地,ROS 2 Turtle Nest 是 ROS 2 包的诞生和成长之地。Turtl…

JavaEE:多线程进阶(线程安全的集合类)

文章目录 线程安全的集合类多线程环境使用ArrayList多线程环境使用队列多线程环境使用哈希表HashtableConcurrentHashMap 线程安全的集合类 之前学习的集合类大部分都不是线程安全的. 比如ArrayList,Queue,HashMap等等,这都是线程不安全的. Vector,Stack,Hashtable,这些集合类…

使用Git进行版本控制:前端开发者的最佳实践

聚沙成塔每天进步一点点 本文回顾 ⭐ 专栏简介使用Git进行版本控制:前端开发者的最佳实践1. 引言2. Git的基本概念2.1 版本控制系统的作用2.2 Git 的基本操作 3. Git最佳实践3.1 使用有意义的提交信息3.2 小步提交,频繁提交3.3 使用分支进行开发3.4 代码…

SparkSQL SET和RESET

前言 我们在用代码写spark程序的时候,如果要设置一些配置参数,可以通过: SparkConf val conf = new SparkConf().setMaster("local[2]").setAppName("CountingSheep") val sc = new SparkContext(conf)spark-submit ./bin/spark-submit --name "M…

一个vue前端的例子(六)如何获取table一行的id

比如我们要删除列表一行 vue中template中的scope到底是个什么&#xff1f;_vue template scope-CSDN博客 <el-button click"edit_tool(scope.$index)" type"warning" icon"el-icon-edit">编辑</el-button> 获取列表下标

报错module ‘markdown‘ has no attribute ‘version‘解决方法

问题&#xff1a; 在配置环境时&#xff0c;遇到报错 module markdown has no attribute version 解决方法&#xff1a; 1.打开报错目录下的文件compat.py 2.将 markdown.version 更改为 markdown.__version__ (注意是双下划线&#xff09;

2005-2020年各省乡村高质量发展指数数据

2005-2020年各省乡村高质量发展指数数据 1、时间&#xff1a;2005-2020年 2、来源&#xff1a;农村年鉴、统计年鉴、人口和就业统计年鉴 2、指标&#xff1a;乡村高质量发展指数、每公顷农业机械动力&#xff08;千瓦/公顷&#xff09;、农田节水灌溉率、人均粮食产量&#…

OpenGL/GLUT实践:GLUT环境配置+实现反弹运动的三角形动画与键盘控制(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub&#xff1a;A-UESTCer-s-Code 文章目录 1 运行效果2 实验过程2.1 环境配置2.2 绘制三角形2.2.1 渲染函数2.2.2 主函数2.2.3 运行结果 2.3 调整窗口大小2.4 简单动画与按键控制2.4.1 简单旋转2.4.2 键盘控制 2.5 窗口反弹动画2.5.1 处理窗口大小变化2.5.2 渲染函数…

使用 `Vitesse Uni App` 创建微信小程序并配置 uview-plus 和 alovajs

使用 Vitesse Uni App 创建微信小程序 Vitesse Uni App&#xff1a;https://vitesse-docs.netlify.app/ UI&#xff1a;https://uview-plus.jiangruyi.com/components/intro.html 编辑器&#xff1a;VScode 安装 Volar&#xff08;Vue Offices&#xff09;插件 创建项目 pnpm …

并发编程:ReentrantLock

一、ReentrantLock 是什么&#xff1f; ReentrantLock 实现了 Lock 接口&#xff0c;是一个可重入且独占式的锁&#xff0c;和 synchronized 关键字类似。不过&#xff0c;ReentrantLock 更灵活、更强大&#xff0c;增加了轮询、超时、中断、公平锁和非公平锁等高级功能。 pu…

十一、C语言:字符串函数

目录 一、strlen 二、strcpy 三、strcat 四、strcmp 五、strstr 六、strtok 七、strerror 一、strlen 注意&#xff1a;strlen()函数的返回值是size_t&#xff0c;两个size_t相减仍为无符号数 int main() {char arr[10] "abc";char brr[10] "abc123&quo…

高基数 GroupBy 在 SLS SQL 中的查询加速

作者&#xff1a;顾汉杰&#xff08;执少&#xff09; 什么是高基数 GroupBy 简单来说&#xff0c;想要分析的数据&#xff0c;拥有超多的“唯一值计数”&#xff08;Distinct Count&#xff09;&#xff0c;而我们需要对这些数据进行分组分析&#xff08;如统计次数、排名、…

如何高效调试JavaScript代码:从Console到断点调试

聚沙成塔每天进步一点点 本文回顾 ⭐ 专栏简介如何高效调试JavaScript代码&#xff1a;从Console到断点调试1. 引言2. 基本调试工具概览2.1 浏览器开发者工具&#xff08;DevTools&#xff09;如何打开浏览器开发者工具&#xff1f; 2.2 常用的调试面板 3. 基本调试方法3.1 使用…

Springboot邮箱发送:如何快速集成并发信?

Springboot邮箱发送性能如何&#xff1f;怎么用SpringBoot发信&#xff1f; Springboot作为一款流行的Java框架&#xff0c;提供了简便的方式来集成邮件发送功能。AokSend将详细介绍如何快速集成Springboot邮箱发送功能&#xff0c;并实现高效的邮件发送。 Springboot邮箱发送…

考拉悠然产品发布会丨以悠然远智全模态AI应用平台探索AI行业应用

9月6日&#xff0c;成都市大模型新技术新成果发布暨供需对接系列活动——考拉悠然专场&#xff0c;在成都市高新区菁蓉汇盛大举行。考拉悠然重磅发布了悠然远智丨全模态AI应用平台&#xff0c;并精彩展示了交通大模型应用——智析快处等最新的AI产品和技术成果。 在四川省科学…

警用车载4G5G无线视频监控技术方案

目录 一、背景 二、系统方案设计 1.1系统架构 1.2车载终端 1.3监控中心 1.4传输网络 三、警用车载监控功能特点 2.1警用车载监控功能 &#xff08;1&#xff09;实时视频监控 &#xff08;2&#xff09;录像存储回放 &#xff08;3&#xff09;车载报警联动 &#…

如何清理C盘临时文件,释放10G以上空间

在我们日常使用电脑系统的过程中&#xff0c;想必大家都曾遇到过这样的情况&#xff1a;明明没有主动安装任何软件&#xff0c;然而 C 盘的可用空间却逐渐减少&#xff0c;甚至有时会收到系统发出的空间不足的提醒。 其实&#xff0c;在系统中存在这样一个至关重要的临时文件夹…

【Prometheus】PromQL聚合函数详细用法与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

基于springboot+vue乒乓球预约管理系统

基于springbootvuemysql实现的乒乓球预约管理系统&#xff08;源码数据库部署视频&#xff09; ### 主要技术 SpringBoot、LayUI、Vue、MySQL ### 系统角色 用户、管理员 ### 系统功能 前台&#xff1a; 首页、乒乓球场、公告信息、留言反馈、个人中心 后台&#xff1a; …

Nginx解析:入门笔记

&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索nginx之旅✨ &#x1f44b; 大家好&#xff01;文本学习和探索Nginx配置。…