24、Java程序中各部分名称的共享

Java程序中各部分名称的共享

1. 引言

在日常交流中,我们常常会谈到个人隐私被侵犯的问题。有人说“他们能读取你的电子邮件”,还有人提到“他们知晓你访问的每一个网站,了解你购买的产品、晚餐吃什么、穿什么、想什么,甚至知道你最深藏的秘密”。这就如同在Java编程里,我们也需要考虑如何保护代码中的信息,避免被随意访问。

2. 访问修饰符

在面向对象编程中,隐藏细节是非常重要的。这并非是为了安全和保密,而是为了实现模块化。当我们隐藏细节时,可以防止一个代码片段中的复杂内容被另一个代码片段破坏,使代码更易于管理,减少错误,节省成本,甚至有助于促进世界和平(夸张说法,强调其重要性)。

Java中有几种访问修饰符,下面为你详细介绍:
- private :当一个字段被声明为private时,它会对所有外部访问隐藏。例如:

class SomeClass {
    private int myField = 10;
}
class SomeOtherClass {
    public static void main(String args[]) {
        SomeClass someObject = new SomeClass();
        // 这行代码会出错,因为myField是private的
        System.out.println(someObject.myField);
    }
}
  • public :一个被声明为public的字段就像公众人物一样,完全开放,任何代码都可以直接引用。例如:
class SomeClass {
    public int myField = 10;
}
class SomeOtherClass {
    public static void main(String args[]) {
        SomeClass someObject = new SomeClass();
        // 这行代码可以正常工作
        System.out.println(someObject.myField);
    }
}
  • default :如果一个字段或方法在声明时没有使用访问修饰符,它就具有默认访问权限。默认访问权限是包级别的访问权限,即只有在同一个包中的代码才能访问。
  • protected :这是另一种访问修饰符,在之前的例子中可能未使用过,后续会详细介绍其相关内容。

下面用表格总结不同访问修饰符的访问范围:
| 访问修饰符 | 同一类中 | 同一包中 | 不同包的子类 | 不同包的非子类 |
| ---- | ---- | ---- | ---- | ---- |
| private | 可以 | 不可以 | 不可以 | 不可以 |
| default | 可以 | 可以 | 不可以 | 不可以 |
| protected | 可以 | 可以 | 可以 | 不可以 |
| public | 可以 | 可以 | 可以 | 可以 |

3. 类、访问和多部分程序

3.1 基本概念

在Java中,有字段和方法局部变量两种变量。这里主要讨论的是方法和字段,它们被统称为类的成员。例如下面的代码:

class MyClass {
    int myField;              // 一个字段(成员)
    void myMethod() {         // 一个方法(另一个成员)
        int myOtherField;     // 一个方法局部变量(不是成员)
    }
}

3.2 成员与类的区别

Java中的 public 关键字有两种不同的含义,一种用于成员,另一种用于类。例如:
- 用于成员:

public static void main(String args[]) {
public amountInAccount = 50.22;
  • 用于类:
public class Drawing {
    // 你的代码写在这里
}

大部分情况下,我们主要关注 public (以及其他类似关键字)对成员的含义,而关于类的访问修饰符含义会在后面单独介绍。

3.3 成员的访问修饰符

判断是否可以在代码的特定位置使用某个成员名称,首先要检查该位置是在成员所在类的内部还是外部:
- 如果成员是private,只有成员所在类内部的代码才能直接引用该成员的名称。
- 如果成员是public,任何代码都可以直接引用该成员的名称。

下面是类和子类的关系图(mermaid格式):

graph LR
    class1 --> classA
    classA --> classX
    class2 --> classB
    classB --> classY
    class3 --> classC
    classC --> classZ

4. 在框架上绘制图形示例

4.1 显示框架

下面的代码用于显示一个ArtFrame,ArtFrame上有一个Drawing。

import com.burdbrain.drawings.Drawing;
import com.burdbrain.frames.ArtFrame;
class ShowFrame {
    public static void main(String args[]) {
        ArtFrame artFrame = new ArtFrame(new Drawing());
        artFrame.setSize(200, 100);
        artFrame.setVisible(true);
    }
}

代码说明:
- 代码开头的两个import声明,分别用于缩写 com.burdbrain.drawings 包中的 Drawing 类和 com.burdbrain.frames 包中的 ArtFrame 类。
- 创建一个新的 ArtFrame 实例,并调用 setSize setVisible 方法使其显示。

4.2 绘图类

下面是 Drawing 类的代码:

package com.burdbrain.drawings;
import java.awt.Graphics;
public class Drawing {
    public int x = 40, y = 40, width = 40, height = 40;
    public void paint(Graphics g) {
        g.drawOval(x, y, width, height);
    }
}

代码说明:
- 代码顶部的包声明表明 Drawing 类属于 com.burdbrain.drawings 包。包名的命名遵循Java的约定,先反转域名,再添加描述性名称。
- Drawing 类被声明为public,因为如果不这样做,不在 com.burdbrain.drawings 包中的类将无法使用该类。
- paint 方法使用 Graphics 对象在屏幕上绘制一个椭圆。

4.3 目录结构

当把一个类放入一个包中时,需要创建一个与包名对应的目录结构。对于 com.burdbrain.drawings 包,需要创建 com burdbrain drawings 三个目录。如果代码没有放在正确的目录中,会出现 NoClassDefFoundError 错误。

4.4 创建框架类

下面是 ArtFrame 类的代码:

package com.burdbrain.frames;
import java.awt.Graphics;
import javax.swing.JFrame;
import com.burdbrain.drawings.Drawing;
public class ArtFrame extends JFrame {
    private static final long serialVersionUID = 1L;
    Drawing drawing;
    public ArtFrame(Drawing drawing) {
        this.drawing = drawing;
        setTitle("Abstract Art");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    public void paint(Graphics g) {
        drawing.paint(g);
    }
}

代码说明:
- ArtFrame 类继承自 JFrame ,用于创建一个浮动窗口。
- 构造函数接收一个 Drawing 对象,并将其赋值给 drawing 字段。
- paint 方法调用 Drawing 对象的 paint 方法,在窗口中绘制图形。

4.5 修改绘图类

如果想修改椭圆的外观,使其更宽,可以创建一个 Drawing 类的子类 DrawingWide

import java.awt.Graphics;
import com.burdbrain.drawings.Drawing;
public class DrawingWide extends Drawing {
    int width = 100, height = 30;
    public void paint(Graphics g) {
        g.drawOval(x, y, width, height);
    }
}

同时,需要修改 ShowFrame 类中的代码:

ArtFrame artFrame = new ArtFrame(new DrawingWide());

并移除 com.burdbrain.drawings.Drawing 的导入声明。

4.6 默认访问权限

如果 Drawing 类中的字段没有声明为public,而是使用默认访问权限,会出现问题。例如:

package com.burdbrain.drawings;
import java.awt.Graphics;
public class Drawing {
    int x = 40, y = 40, width = 40, height = 40;
    public void paint(Graphics g) {
        g.drawOval(x, y, width, height);
    }
}

当创建 DrawingWide 子类时:

import com.burdbrain.drawings.*;
import java.awt.Graphics;
public class DrawingWide extends Drawing {
    int width = 100, height = 30;
    public void paint(Graphics g) {
        g.drawOval(x, y, width, height);
    }
}

代码将无法编译,会出现以下错误信息:

x is not public in com.burdbrain.drawings.Drawing; cannot be accessed from outside package
y is not public in com.burdbrain.drawings.Drawing; cannot be accessed from outside package

这是因为具有默认访问权限的字段不能在其所在包之外直接引用,即使是子类也不行。

下面用mermaid图展示包和子类的关系:

graph LR
    class1 --> classA
    classA --> classX
    class2 --> classB
    classB --> classY
    class3 --> classC
    classC --> classZ
    style class1 fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    style classA fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    style classX fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    style class2 fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    style classB fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    style classY fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    style class3 fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    style classC fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    style classZ fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    subgraph 包1
        class1
        classA
        classX
    end
    subgraph 包2
        class2
        classB
        classY
    end
    subgraph 包3
        class3
        classC
        classZ
    end

综上所述,在Java编程中,合理使用访问修饰符对于代码的模块化和可维护性至关重要。我们需要根据实际需求选择合适的访问修饰符,以确保代码的安全性和可扩展性。

5. 包和类路径的重要性

5.1 类路径的作用

在编译和运行Java程序时,编译器和Java虚拟机(JVM)需要知道在哪里找到所需的类文件。为了解决这个问题,Java定义了一个名为 CLASSPATH 的概念,它是一个包含编译器和JVM查找代码的位置列表。

如果没有设置 CLASSPATH ,编译器和JVM将不知道去哪里查找类,会导致 cannot find symbol NoClassDefFoundError 错误。设置 CLASSPATH 有多种方式,一些程序员在每次运行Java程序时创建新的 CLASSPATH ,而另一些则创建系统范围的 CLASSPATH 变量。

5.2 包的使用

包可以帮助组织代码,避免命名冲突。在前面的例子中, Drawing 类属于 com.burdbrain.drawings 包, ArtFrame 类属于 com.burdbrain.frames 包。使用包时,需要遵循以下规则:
- 包名通常是反转的域名加上描述性名称,例如 com.burdbrain.drawings
- 类文件需要放在与包名对应的目录结构中,例如 com/burdbrain/drawings

下面是一个总结包和类路径相关要点的表格:
| 要点 | 描述 |
| ---- | ---- |
| 包名约定 | 反转域名 + 描述性名称 |
| 目录结构 | 与包名对应 |
| 类路径 | 编译器和JVM查找代码的位置列表 |
| 错误处理 | 未设置CLASSPATH会导致找不到类的错误 |

6. 受保护的访问修饰符

6.1 受保护访问的概念

除了 private public 和默认访问修饰符外,Java还有 protected 访问修饰符。当一个成员被声明为 protected 时,它可以被同一包中的所有类访问,也可以被不同包中的子类访问。

6.2 示例代码

以下是一个使用 protected 访问修饰符的示例:

package com.example.parent;
public class ParentClass {
    protected int protectedField = 10;
    protected void protectedMethod() {
        System.out.println("This is a protected method.");
    }
}
package com.example.child;
import com.example.parent.ParentClass;
public class ChildClass extends ParentClass {
    public void accessProtectedMembers() {
        System.out.println(protectedField);
        protectedMethod();
    }
}
package com.example.other;
import com.example.parent.ParentClass;
public class OtherClass {
    public static void main(String[] args) {
        ParentClass parent = new ParentClass();
        // 下面这行代码会报错,因为在不同包的非子类中不能直接访问protected成员
        // System.out.println(parent.protectedField); 
    }
}

在这个示例中, ChildClass ParentClass 的子类,它可以访问 ParentClass protected 成员。而 OtherClass 不是 ParentClass 的子类,并且在不同的包中,所以不能直接访问 ParentClass protected 成员。

下面用mermaid图展示受保护访问的范围:

graph LR
    classDef samePackage fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef differentPackageSubclass fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
    classDef differentPackageNonSubclass fill:#FFEBEB,stroke:#E68994,stroke-width:2px
    A(ParentClass):::samePackage --> B(ChildClass - 同一包):::samePackage
    A --> C(ChildClass - 不同包):::differentPackageSubclass
    A --> D(OtherClass - 不同包非子类):::differentPackageNonSubclass
    linkStyle 0 stroke:#00FF00,stroke-width:2px
    linkStyle 1 stroke:#00FF00,stroke-width:2px
    linkStyle 2 stroke:#FF0000,stroke-width:2px

7. 访问修饰符的最佳实践

7.1 最小化访问权限

为了提高代码的安全性和可维护性,应该尽量使用最小的访问权限。例如,如果一个字段或方法只需要在类内部使用,就应该声明为 private ;如果只需要在同一包中使用,就使用默认访问权限;如果需要被不同包中的子类访问,使用 protected ;只有在确实需要被所有类访问时,才使用 public

7.2 遵循封装原则

封装是面向对象编程的重要原则之一,它要求将数据和操作数据的方法封装在一起,并通过访问修饰符控制对数据的访问。通过合理使用访问修饰符,可以隐藏类的内部实现细节,只暴露必要的接口给外部使用。

7.3 代码示例

以下是一个遵循最佳实践的代码示例:

public class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    public double getBalance() {
        return balance;
    }

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    public boolean withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            return true;
        }
        return false;
    }
}

在这个示例中, balance 字段被声明为 private ,外部类不能直接访问它。通过 getBalance deposit withdraw 方法,外部类可以安全地操作账户余额。

8. 总结

8.1 访问修饰符总结

访问修饰符 同一类中 同一包中 不同包的子类 不同包的非子类
private 可以 不可以 不可以 不可以
default 可以 可以 不可以 不可以
protected 可以 可以 可以 不可以
public 可以 可以 可以 可以

8.2 关键要点回顾

  • 合理使用访问修饰符可以提高代码的模块化和可维护性。
  • 包和类路径对于组织代码和查找类文件非常重要。
  • 遵循最小化访问权限和封装原则是良好的编程实践。

通过掌握这些知识,你可以编写更安全、更易于维护的Java代码。在实际开发中,根据具体需求选择合适的访问修饰符和包结构,将有助于提高代码的质量和可扩展性。

内容概要:本文是一篇关于使用RandLANet模型对SensatUrban数据集进行点云语义分割的实战教程,系统介绍了从环境搭建、数据准备、模型训练与测试到精度评估的完整流程。文章详细说明了在Ubuntu系统下配置TensorFlow 2.2、CUDA及cuDNN等深度学习环境的方法,并指导用户下载和预处理SensatUrban数据集。随后,逐步讲解RandLANet代码的获取与运行方式,包括训练、测试命令的执行与参数含义,以及如何监控训练过程中的关键指标。最后,教程涵盖测试结果分析、向官方平台提交结果、解读评估报告及可视化效果等内容,并针对常见问题提供解决方案。; 适合人群:具备一定深度学习基础,熟悉Python编程和深度学习框架,从事计算机视觉或三维点云相关研究的学生、研究人员及工程师;适合希望动手实践点云语义分割项目的初学者与进阶者。; 使用场景及目标:①掌握RandLANet网络结构及其在点云语义分割任务中的应用;②学会完整部署一个点云分割项目,包括数据处理、模型训练、测试与性能评估;③为参与相关竞赛或科研项目提供技术支撑。; 阅读建议:建议读者结合提供的代码链接和密码访问完整资料,在本地或云端环境中边操作边学习,重点关注数据格式要求与训练参数设置,遇到问题时参考“常见问题与解决技巧”部分及时排查。
内容概要:本文详细介绍了三相异步电机SVPWM-DTC(空间矢量脉宽调制-直接转矩控制)的Simulink仿真实现方法,结合DTC响应快与SVPWM谐波小的优点,构建高性能电机控制系统。文章系统阐述了控制原理,包括定子磁链观测、转矩与磁链误差滞环比较、扇区判断及电压矢量选择,并通过SVPWM技术生成固定频率PWM信号,提升系统稳态性能。同时提供了完整的Simulink建模流程,涵盖电机本体、磁链观测器、误差比较、矢量选择、SVPWM调制、逆变器驱动等模块的搭建与参数设置,给出了仿真调试要点与预期结果,如电流正弦性、转矩响应快、磁链轨迹趋圆等,并提出了模型优化与扩展方向,如改进观测器、自适应滞环、弱磁控制和转速闭环等。; 适合人群:电气工程、自动化及相关专业本科生、研究生,从事电机控制算法开发的工程师,具备一定MATLAB/Simulink和电机控制理论基础的技术人员。; 使用场景及目标:①掌握SVPWM-DTC控制策略的核心原理与实现方式;②在Simulink中独立完成三相异步电机高性能控制系统的建模与仿真;③通过仿真验证控制算法有效性,为实际工程应用提供设计依据。; 阅读建议:学习过程中应结合文中提供的电机参数和模块配置逐步搭建模型,重点关注磁链观测、矢量选择表和SVPWM调制的实现细节,仿真时注意滞环宽度与开关频率的调试,建议配合MATLAB官方工具箱文档进行参数校准与结果分析。
已经博主授权,源码转载自 https://pan.quark.cn/s/bf1e0d5b9490 本文重点阐述了Vue2.0多Tab切换组件的封装实践,详细说明了通过封装Tab切换组件达成多Tab切换功能,从而满足日常应用需求。 知识点1:Vue2.0多Tab切换组件的封装* 借助封装Tab切换组件,达成多Tab切换功能* 支持tab切换、tab定位、tab自动化仿React多Tab实现知识点2:TabItems组件的应用* 在index.vue文件中应用TabItems组件,借助name属性设定tab的标题* 通过:isContTab属性来设定tab的内容* 能够采用子组件作为tab的内容知识点3:TabItems组件的样式* 借助index.less文件来设定TabItems组件的样式* 设定tab的标题样式、背景色彩、边框样式等* 使用animation达成tab的切换动画知识点4:Vue2.0多Tab切换组件的构建* 借助运用Vue2.0框架,达成多Tab切换组件的封装* 使用Vue2.0的组件化理念,达成TabItems组件的封装* 通过运用Vue2.0的指令和绑定机制,达成tab的切换功能知识点5:Vue2.0多Tab切换组件的优势* 达成多Tab切换功能,满足日常应用需求* 支持tab切换、tab定位、tab自动化仿React多Tab实现* 能够满足多样的业务需求,具备良好的扩展性知识点6:Vue2.0多Tab切换组件的应用场景* 能够应用于多样的业务场景,例如:管理系统、电商平台、社交媒体等* 能够满足不同的业务需求,例如:多Tab切换、数据展示、交互式操作等* 能够与其它Vue2.0组件结合运用,达成复杂的业务逻辑Vue2.0多Tab切换组件的封装实例提供了...
代码下载地址: https://pan.quark.cn/s/41cd695ddf65 `htmldiff` 是一个以 Ruby 语言为基础构建的库,其主要功能是在 HTML 文档中展示文本之间的差异。 该库的一个显著特点在于它不仅能够识别出不同之处,还会借助 HTML 标签来呈现这些差异,从而让用户能够直观地观察到文本的变化情况。 这种特性使得 `htmldiff` 在版本控制、文档对比或任何需要展示文本变动场景的应用中显得尤为有用。 `htmldiff` 的核心作用是对比两个字符串,并生成一个 HTML 输出结果,这个结果会明确地指出哪些部分被添加、哪些部分被删除以及哪些部分被修改。 此外,通过运用 CSS,用户可以进一步调整差异展示的样式,使其与项目或网站的现有设计风格相协调。 在使用 `htmldiff` 之前,需要先完成该库的安装。 如果项目已经配置了 Ruby 环境和 Gemfile,可以在 Gemfile 文件中添加 `gem htmldiff` 语句,随后执行 `bundle install` 命令进行安装。 如果没有 Gemfile 文件,也可以直接采用 `gem install htmldiff` 命令来进行全局安装。 在编程实现时,可以通过调用 `Htmldiff.diff` 方法来对比两个字符串,并获取相应的 HTML 输出。 例如:```rubyrequire htmldiffstr1 = "这是一个示例文本。 "str2 = "这是一个示例文本,现在有更多内容。 "diff_html = Htmldiff.diff(str1, str2)puts diff_html```上述代码将会输出两个字符串之间的差异,其中新增的内容会被 `<ins>` 标签所包围,而...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值