Java 中的面向数据编程

Groovy语言的面向对象编程 Groovy是一种基于Java虚拟机的动态语言,旨在提高开发者的生产力。它对Java进行了扩展,并引入了一些现代编程语言的特性,如闭包、运算符重载、元编程等。Groovy的语法相对简洁,特别适合快速开发和脚本编写。由于其良好的兼容性,Groovy能够无缝地使用Java库,并可以在Java项目中逐步集成。 阅读详情

近年来, Amber 项目为 Java 带来了许多新特性—— 局部变量类型推断 、 文本块 、 记录类 、 封印类 、 模式匹配 等等。虽然这些特性都是独立的,但也可以组合在一起使用。具体地说,记录类、封印类和模式匹配组合在一起让 Java 的面向数据编程变得更容易。在本文中,我们将讨论什么是面向数据编程,以及它如何影响 Java 的编程方式。

面向对象编程

任何一种编程范式的目标都是管理复杂性。但复杂性会以多种形式出现,并不是所有的范式都能同等处理好所有形式的复杂性。大多数编程范式都有一个口号:“一切皆……”面向对象编程的口号是“一切皆对象”,函数式编程的口号是“一切皆函数”,基于 Actor 的系统的口号是“一切皆 Actor”等等。(当然,这些都是为了达到某种效果而夸大的说法。)

OOP 鼓励我们使用定义了状态和行为的对象对复杂的实体和过程进行建模。OOP 鼓励封装性(协调对对象状态的访问)和多态性(使用公共接口与多种实体交互),尽管实现这些目标的机制因面向对象编程语言而异。当我们用对象对世界进行建模时,我们被鼓励按照 is-a(储蓄帐户是一个银行帐户)和 has-a(储蓄帐户有一个所有者和账号)的关系来思考问题。

虽然一些开发者大声宣告面向对象编程是一次失败的试验,但事实却很微妙。与其他所有的工具一样,它非常适合用来做一些事情,但也不太适合用来做另一些事情。OOP 做不好的事情可能可以用糟糕来形容,许多人都曾见过被运用得荒谬至极的 OOP 原则。但是,如果我们了解 OOP 的优点和缺点,就可以在它提供更多价值的地方使用它,在它提供较少价值的地方使用其他语言。

OOP 在定义和保持边界方面做得很出色——维护的边界、版本控制的边界、封装的边界、编译的边界、兼容性的边界、安全性的边界,等等。独立维护的库独立于依赖它们的应用程序(以及库彼此之间)而构建、维护和演化,如果我们希望能够自由地从库的一个版本迁移到下一个版本,就需要确保库和它们的客户端之间有清晰的、定义良好的和深思熟虑的边界。平台库可能有访问底层操作系统和硬件的特权,这些权限必须加以小心的控制。我们需要在平台库和应用程序之间建立一个牢固的边界来保持系统的完整性。OO 语言为我们提供了精确定义和保持这些边界的工具。

将一个大程序划分为具有明确边界的部分,有助于我们管理复杂性,因为它支持模块化推理——一次只分析程序的一部分,但仍然具备对整个程序进行推理的能力。对于单体程序来说,设置合理的内部边界有助于我们构建跨多个团队的更大的应用程序。Java 在单体时代兴盛并非偶然。

从那时起,程序变得越来越小,我们不再构建大单体,而是将许多较小的服务组合成较大的应用程序。在小型服务中,对内部边界的需求较少,足够小的服务可以由单个团队(甚至一个开发人员)维护。类似地,在这些较小的服务中,我们对长时间运行的有状态流程进行建模的需求也较少。

面向数据编程

Java 的强静态类型和基于类的模型对于较小的程序仍然非常有用,只是发挥作用的方式不同。OOP 鼓励我们使用类对业务实体和流程进行建模,而具有更少内部边界的小代码库通常会从使用类来建模数据的方式中获得更多好处。我们的服务负责处理来自外部的请求,例如带有非类型化 JSON/XML/YAML 有效载荷的 HTTP 请求。但是,只有最简单的服务才会直接使用这种数据。我们希望数字能够被表示成 int 或 long,而不是数字字符串,日期被表示成像 LocalDateTime 这样的类,列表被表示成集合,而不是用逗号分隔的长字符串。(并且,在处理数据之前,我们希望在边界上对数据进行验证。)

面向数据编程鼓励我们将数据建模为不可变数据,并单独保留包含操作数据的业务逻辑代码。随着小型程序趋势的发展,Java 提供了新的工具,可以更容易地将数据建模为数据(记录),直接建模替代实体(封印类),以及灵活地分解多态数据模式(模式匹配)。

面向数据编程鼓励我们将数据建模为不可变数据,而记录类、封印类和模式匹配使这方面的工作变得更容易。但这并不意味着要放弃静态类型。我们可以只使用非类型化的 Map 和 List 进行面向数据编程(通常在 JavaScript 等编程语言中这样做的),但静态类型在安全性、可读性和可维护性方面仍然提供了很多东西,即使我们只对普通数据建模。(无原则的面向数据编程通常被称为“字符串类型”,因为它使用字符串来建模不应该被建模为字符串的东西,如数字、日期和列表。)

Java 中的面向数据编程

记录类、封印类和模式匹配可以组合在一起支持面向数据编程。我们可以用记录类来进行简单的数据建模,用封印类来进行选择建模,模式匹配为我们提供了一种简单且类型安全的方式来处理多态数据。对模式匹配的支持是逐步实现的,第一个迭代只添加了类型测试模式,并且只能在 instanceof 中使用,第二次迭代支持 switch 中的类型测试模式,最近,Java 19 中添加了 记录类的解构模式 。本文中的示例将使用所有这些特性。

虽然记录类的语法比较简洁,但它们的主要优点是我们可以干净而简单地对聚合进行建模。与其他的数据建模一样,我们都需要做出创造性的决策,总有一些建模方式比其他的更好。组合使用记录类和封印类还更容易让非法状态变得无法表示,从而进一步提高安全性和可维护性。

示例:命令行选项

作为第一个例子,我们来看一下如何对命令行程序的选项进行建模。有些选项有参数,有些没有。有些参数可以是任意字符串,有些是更结构化的格式,如数字或日期。在处理命令行选项时,我们必须在程序执行的早期拒绝错误的选项和格式错误的参数。一种快速而粗暴的方法是循环遍历命令行参数,对于遇到的每一个选项,将它们存在或不存在的状态以及选项的参数保存在变量中。这很简单,但问题在于我们的程序依赖了一组字符串类型的全局变量。如果我们的程序很小,这可能没有问题,但它的伸缩性不是很好。随着程序的增长,这不仅会降低可维护性,也会降低程序的可测试性——我们只能通过命令行来测试整个程序。

一种不那么快速和复杂的方法是创建一个表示命令行选项的类,然后将命令行解析为选项对象列表。假设我们有一个类似 cat 的程序,它可以将一个或多个文件中的行复制到另一个文件中,将文件裁剪到特定的行数,并选择性地包含行号,我们可以使用 enum 和 Option 类对这些选项进行建模:

enum MyOptions { INPUT_FILE, OUTPUT_FILE, MAX_LINES, PRINT_LINE_NUMBERS }
复制代码

这是对前一种方法的改进,至少现在在命令行选项的解析和使用之间有了清晰的分离,这意味着我们可以通过向命令行 shell 提供选项列表来测试业务逻辑。但这仍然不够好,有些选项是没有参数的,但我们从选项的 enum 中看不出这一点,我们仍然需要用一个带有 optionValue 字段的 OptionValue 对象。而有参数的选项总是字符串类型。

更好的方法是直接对每个选项进行建模。在以前,这么做可能会很冗长,但幸运的是,现在已经不是这样了。我们可以使用一个封印类来表示一个选项,并且每个选项都有一个记录类:

sealed interface Option {
复制代码

Option 的子类是纯数据。选项的值有漂亮干净的名称和类型,有参数的选项使用了适当的类型来表示参数,没有参数的选项不需要使用可能会被错误解释的无用参数变量。此外,使用模式匹配 switch 处理选项变得很容易(通常每个选项需要一行代码)。因为 Option 是封印类,所以编译器会进行类型检查,一个 switch 可以处理所有的选项类型。(如果以后添加更多的选项类型,编译器会提醒我们哪些 switch 需要扩展。)

我们可能都写过与上述两个版本类似的代码,尽管我们可能知道的更多。如果无法清晰、简洁地对数据进行建模,要“正确”实现这个目标通常需要做很多的工作(或写很多的代码)。

我们所做的是将来自调用边界(命令行参数)混乱、无类型的数据转换为强类型的、经过验证的、容易操作的(通过模式匹配)数据,并让非法状态(例如指定--input-file,而不是提供有效路径)变得不可表示。程序的其余部分可以安全地使用它。

代数数据类型

这种组合使用记录类和封印类型就是代数数据类型(ADT)的一个例子。记录类是“乘积类型”的一种形式,之所以这么说,是因为它们的状态空间是它们组件状态空间的笛卡尔乘积。封印类是“和类型”的一种形式,之所以这么说,是因为值的集合是备选值集合的和(并集)。这种简单的机制组合(聚合和选择)比看上去的更加强大,在许多编程语言中都有出现。(我们的例子仅限于一个层级,但这并不一定是一般的情况。一个封印接口的子类型也可以是另一个封印接口,可以对更复杂的结构进行建模。)

在 Java 中,代数数据类型可以被精确地建模成封印的层次结构,其叶子是记录类。在解释代数数据类型方面,Java 具有许多理想的属性。它们具有名词性质,类型和组件具有人类可读的名称。它们是不可变的,因此它们更简单、更安全,并且可以自由共享,而不用担心受到干扰。它们很容易测试,因为它们只包含数据(可能附带一些从数据派生出来的行为)。我们可以很容易地将它们序列化到磁盘或通过网络传输。它们具有很强的表现力,可在广泛的数据领域中建模。

应用:复杂的返回类型

复杂返回类型是代数数据类型最简单但最常用的应用之一。由于一个方法只能返回一个值,我们总是喜欢通过复杂的方式来表示返回值,例如使用 null 表示“Not Found”,将多个值编码成一个字符串,或用一个抽象的类型(数组、List 或 Map)将方法返回的所有不同类型的信息填充到单个载体对象中。代数数据类型可以很容易地实现这些目的,让之前的这些方法变得不那么诱人。

我们给出了一个例子,说明如何使用封印类在不使用异常的情况下抽象成功和失败条件:

sealed interface AsyncReturn<V> {
复制代码

这种方法的优点是,客户端可以通过对结果进行模式匹配来统一处理成功和失败,而不是当有返回值时表示调用成功,当 catch 块捕捉到异常时表示调用失败:

AsyncResult<V> r = future.get();
复制代码

封印类的另一个好处是,如果 switch 中没有 default,编译器会提醒你是否忘记了一个 case。(在有检查异常时,编译器也会提醒你,但以一种更具有侵入性的方式。)

另一个例子,假设我们有一个服务,它根据名称查找实体(用户、文档、组等),结果分别是“未找到匹配项”、“找到精确匹配项”和“没有找到精确匹配项,但有接近匹配项”。我们可以考虑将它们塞进一个列表或数组,虽然这样可能更容易编写搜索 API,但却难以理解、使用或测试。代数数据类型很容易就可以解决这个问题。我们可以编写一个简洁的 API 来准确表达我们的意图:

sealed interface MatchResult<T> {
复制代码

如果我们在浏览代码或 JavaDoc 时遇到这个层次结构,我们会很容易知道这个方法可能返回的是什么,以及如何处理它的结果:

Page userSearch(String user) {
复制代码

这种清晰的返回值提升了 API 的可读性和易用性,也更容易编写,因为代码实际上是根据需求编写的。与之相反的是,试图想出(和记录)“聪明”的编码,将复杂的结果塞进像数组或 Map 这样的抽象载体中需要做更多的工作。

应用:临时的数据结构

代数数据类型对于建模临时通用的数据结构来说也很有用。常用的 Optional 类可以被建模为代数数据类型:

sealed interface Opt<T> {
复制代码

(这实际上是大多数函数式语言对 Optional 的定义方式。)针对 Opt 的常见操作可以通过模式匹配来实现:

static<T, U> Opt<U> map(Opt<T> opt, Function<T, U> mapper) {
复制代码

类似地,二叉树可以这样表示:

sealed interface Tree<T> {
复制代码

我们可以通过模式匹配实现通常的操作:

static<T> boolean contains(Tree<T> tree, T target) {
复制代码

像遍历这样的常见行为“显然”应该作为接口的抽象方法,将它写成静态方法似乎有些奇怪。的确,将一些方法放到接口中是没有问题的。但记录类、封印类和模式匹配的组合为我们提供了新的选择。我们可以用老方法实现它们(将抽象方法放在基类中,在子类中实现具体的方法),也可以作为抽象类的默认方法在一个地方实现模式匹配,也可以实现为静态方法,或者(如果不需要递归)在使用的地方进行临时内联遍历。

因为数据结构是专门为这种情况而设计的,我们可以选择是否将行为与数据放在一起。这种方法与 OO 并不矛盾,它是我们的工具箱的一个有用的补充,让我们可以根据实际需要与 OO 一起使用。

示例:JSON

如果你仔细看过 JSON规范 ,你会发现 JSON 也是一个 ADT:

sealed interface JsonValue {
复制代码

如果使用了这种表示,从 JSON 中提取相关信息的代码就会非常简单。如果我们想匹配 JSON {"name":"John", "age":30, "city":"New York"}就是:

if (j instanceof JsonObject(var pairs)
复制代码

当我们将数据建模为不可变数据,创建聚合和提取内容(或将其重新打包为另一种形式)就变得很简单,而且由于当某些内容不匹配时模式匹配会优雅地失败,分解这个 JSON 的代码相对来说就没有复杂的控制流程。(虽然我们可能倾向于使用比这个示例更具有工业强度的 JSON 库,但实际上我们只需要额外的几十行解析代码就可以实现一个解析工具,不仅遵循 JSON 规范中列出的词法规则,而且可以将它们转换为 JsonValue。)

更加复杂的领域

到目前为止,我们看到的例子要么是跨整个调用边界使用返回值,要么是建模通用领域(如列表和树结构)。但其实同样的方法对于更复杂的应用程序特定领域也很有用。如果我们想要对一个算术表达式进行建模,可以这样做:

sealed interface Node { }
复制代码

有了抽象了加法和乘法的封印接口 BinaryNode,我们在匹配 Node 时就有了更多选择。我们可以通过匹配 BinaryNode 来同时处理加法和乘法,或者根据情况分别处理它们。语言本身仍然会确保我们涵盖了所有的情况。

为这些表达式编写求值器很简单。由于表达式中有变量,我们需要存储它们,并将其传给求值器:

double eval(Node n, Function<String, Double> vars) {
复制代码

定义终端节点的记录类实现了 toString,但输出可能比我们想要的更详细。我们可以编写一个格式化器来生成看起来更像数学表达式的输出:

String format(Node n) {
复制代码

和以前一样,我们可以将它们作为静态方法,或作为基类的实例方法,但只提供一个实现,或作为普通的实例方法——我们可以自由选择对领域来说最具可读性的方法。

在抽象地定义了领域之后,我们还可以轻松地添加其他操作。我们可以很容易地对单个变量进行符号微分:

Node diff(Node n, String v) {
复制代码

在记录类和模式匹配出现之前,编写这种代码的标准方法是访问者模式。模式匹配显然比访问者模式更简洁,也更灵活和强大。访问者模式需要为访问构建领域,并添加严格的约束。模式匹配支持更多的临时多态。最关键的是,模式匹配具有更好的可组合性,我们可以使用嵌套模式来表达复杂的条件,而这在使用访问者模式时要复杂得多。例如,当一个乘法节点的一个子节点是常数时,上面的代码将生成混乱的树结构。我们可以使用嵌套模式更容易地处理这些特殊情况:

Node diff(Node n, String v) {
复制代码

如果使用访问者模式——尤其是在多个层次的嵌套中——很快就会变得相当混乱和容易出错。

这不是一种或的关系

这里阐述的许多想法可能看起来有点“不像 Java”,因为我们大多数人都被教导将实体和过程建模成对象。但在现实中,我们的程序通常使用相对简单的数据,这些数据通常来自“外部世界”,我们不能指望它完全与 Java 的类型系统相匹配。(在我们的 JSON 示例中,我们将数字建模为双精度值,但实际上 JSON 规范对数值范围并没有特别说明,系统边界的代码将不得不做出决定是否截断或拒绝难以表示的数值。)

当我们在建模复杂的实体或编写像 java.util.stream 这样的库时,OO 技术为我们提供了很多东西。但是,当我们在构建处理普通数据的简单服务时,面向数据编程技术可能会为我们提供一条更直接的路径。类似地,在跨 API 边界交换复杂的结果时(例如我们的匹配结果示例),使用 ADT 定义一个特别的数据模式通常比将结果和行为交织成一个有状态的对象更加简单和清晰(Java Matcher API 就是这样做的)。

OOP 和面向数据编程技术并不矛盾,它们分别针对不同的粒度和场景。我们可以根据具体情况随意混合搭配。

跟随数据

无论是建模一个简单的返回值,还是一个更复杂的领域(如 JSON 或我们的表达式树),都有一些简单的原则可以让我们得到简单、可靠的面向数据的代码。

  • 只对数据建模。使用记录类对数据进行建模,每个记录类只建模一项内容,明确每个记录类的内容,并为组件选择明确的名字。如果存在多个选项,比如“纳税申报单要么由纳税人提交,要么由法人代表提交”,将这些选项建模为封印类,并将每个选项建模为一个记录类。记录类的行为应该仅限于从数据本身实现派生量,比如格式化。
  • 数据是不可变的。如果我们想要对数据建模,就不应该担心数据会发生变化。记录类为我们提供了一些帮助,因为它们是不可变的,但仍然需要一些规则来避免让可变性注入到我们的数据模型中。
  • 在边界处验证数据。在将数据注入系统之前,我们需要确保它们是有效的。这可以在记录类的构造函数中完成(如果验证逻辑被应用在所有的实例上),或者通过从另一个数据源接收数据的边界代码来完成。
  • 让非法状态无法被表示。记录类和封印类让错误的状态无法被表示出来。这比一直要检查数据有效性要好得多!就像不变性消除了程序中许多常见的错误来源一样,避免对无效数据进行建模也起到了类似的作用。这种方法的一个潜在好处是可测试性。当代码的输入和输出是简单且定义良好的数据时,不仅测试代码很容易,而且为生成式测试(通常可以比手动编写测试用例更有效地发现 Bug)打开了大门。

记录类、封印类和模式匹配的组合使得遵循这些原则变得更加容易,从而获得更简洁、可读和可靠的程序。考虑到 Java 面向对象编程根深蒂固的基础,面向数据编程可能有点陌生,但这些技术非常值得被添加到我们的工具箱中。

 

20、Java面向对象编程中的数据隐藏、封装及抽象类 本文深入探讨了Java面向对象编程中的核心概念,包括类和成员的访问控制机制、数据封装的实践方法、抽象类与接口的定义及比较,以及java.lang.Object类中重要方法的重写与应用。通过示例代码和详细解析,帮助开发者更好地理解如何构建安全、可维护且具有良好设计结构的Java程序。 阅读详情

相关推荐

16、Java 面向对象编程中的方法重写、数据隐藏与访问控制

本博客深入探讨了 Java 面向对象编程中的核心概念,包括方法重写与方法重载的区别、字段隐藏与方法重写的机制、虚拟方法查找的实现原理、密封类的使用以及数据隐藏与访问控制的最佳实践。通过代码示例和详细解析,帮助开发者更好地理解如何编写安全、可维护和高质量的 Java 代码。

rnn9storyteller的博客 133

面向数据编程 Data-Oriented Programming [1]

面向数据的编程原则 0.1 简介

unity尧明的博客 6928

Java面向对象编程的全面理解

本文是一本关于Java面向对象编程的书籍的读后感与总结。书籍内容详尽介绍了Java编程语言的基础知识,包括计算机和编程语言简介、面向对象编程概念、Java程序开发的入门指导,以及更高级的概念如数值数据处理、自定义类的定义、选择和重复语句的使用、异常处理、字符和字符串操作以及数组和集合的处理。作者C. Thomas Wu以其丰富的教学经验和对Java语言的深刻理解,为读者提供了一个学习Java面向对象编程的全面视角。

weixin_42113456的博客 488

面向数据编程 Data-Oriented Programming [2]

0.2.3 原则#1的好处   当我们小心翼翼地将代码与数据分开时,我们的程序就会受益: 代码可以在不同的环境下重复使用 代码可以单独测试 系统趋于不那么复杂 好处#1:代码可以在不同的环境中重复使用   想象一下,在我们的程序中,除了作者实体之外,还有一个与作者无关的用户实体,但在名字和姓氏方面,它有与作者实体相同的数据字段:firstName和lastName字段。   作者和用户计算全名的逻辑是相同的。但是,在有createAuthorObject的版本中,不能直接重用代码。   当代码和数据混合

unity尧明的博客 866

宋浩线性代数笔记

Miao-A-SongHao-Linear-Algebra-Notes bilibili 宋浩老师 “惊叹号” 系列 《线性代数》网课 笔记及时间点目录 Github项目地址:https://github.com/cy69855522/Miao-A-SongHao-Linear-Algebra-Notes ???? 前言 我发现吧,线代没记笔记真不行。 浩浩学习,天天向上。数学网课推荐????宋浩老师的免...

Knife丶小刀博客 4万+

IFIX数据库Datebase当前值问号

IFIX数据库Datebase当前值问号,已解决,亲测有效 在OPC PowerTool有数据的情况下,IFIX数据库Datebase当前值显示???? 问题分析及解决方法 我的IFIX5.8版本,其它版本可参考 打开IFIX工作台:应用程序–任务控制–I/O驱动–OPC Client;查看OPC驱动是否被禁用,点击启动,变成激活状态即可;若点击启动无法激活OPC驱动,需要重新安装OPC驱动,方法如下: 下载I/O Driver文件 下载链接:https://download.youkuaiyun.com/down

Ron_Tso的博客 2760

C++ 面向数据编程(DOP)与面向对象编程(OOP)

摘要:面向数据编程(DOP)与面向对象编程(OOP)是两种不同的编程范式。DOP以数据为中心,优化内存布局和缓存利用率,适合数据密集型场景;OOP以对象为中心,强调封装和多态,便于建模复杂业务逻辑。

平平无奇的小甜菜 1271

Embarcadero Dev-C++ 6.3安装教程【保姆级】

Embarcadero Dev-C++ 6.3安装教程,保姆级教程~

Thebest_jack的博客 1万+

游戏设计模式——面向数据编程(转)

作者:KillerAery出处:http://www.cnblogs.com/KillerAery/ 随着软件需求的日益复杂发展,远古时期面的向过程编程思想才渐渐萌生了面向对象编程思想。 当人们发现面向对象在应对高层软件的种种好处时,越来越沉醉于面向对象,热衷于研究如何更加优雅地抽象出对象。 然而现代开发中渐渐发现面向对象编程层层抽象造成臃肿,导致运行效率降低,而这是性能要求高的游戏编程领域不想看到的。 于是现代游戏编程中,面向数据编程的思想越来越被接受(例如Unity2018更新的ECS框架就是.

mozhi 3488

脑电时频分析I:谱分析

1、EEG频带划分 自发的EEG活动在活体大脑中持续存在,通常通过频率进行分类(也叫神经振荡活动) 特定频段的脑活动,即节律性的活动,具有特定的头皮分布和生物学意义 最后还有一个γ波,主要是指30hz~100hz的一个波段,通常这个波段也包含了噪声唁电的成分,比较难提取处理,比较少用到这个波段 这个波段主要是有可能躯体感觉皮层,进行一个多通道的感觉输入的i信号处理,比如我们同时处理视觉和听觉信号的处理,而且γ波与我们记忆的形成有关 除此之外,还有一个特殊的波段,8~12hz的Mu波段主要是特指我们

Kobe123brant的博客 1万+

作为一名爬虫人如何实现千万级数据爬取?

爬虫门槛不高,高就高在往后余生的每一次实操都随时会让你崩溃!Bro

吴秋霖的博客 1万+

ECS与DOP(面向数据编程)浅析

ECS以及DOP浅析

qq_33445510的博客 3747

视觉Transformer实战 | Transformer详解与实现

本文系统介绍了 Transformer 架构的核心原理与实现。相比传统 RNN 和 CNN,Transformer 凭借自注意力机制有效捕捉序列中的长距离依赖关系,支持并行训练,显著提升效率。其核心创新在于通过查询、键、值向量计算注意力权重,理解单词间的语义关联。架构包含编码器-解码器结构:编码器通过多头自注意力和前馈网络提取输入特征;解码器利用掩码自注意力和交叉注意力生成输出。本文使用 PyTorch 实现了缩放点积注意力、位置编码、层归一化等关键模块,并构建了完整的 Transformer 模型。

盼小辉丶的博客 4万+

面向对象编程:Java中的抽象数据类型

google_ad_client = "pub-8800625213955058";/* 336x280, 创建于 07-11-21 */google_ad_slot = "0989131976";google_ad_width = 336;google_ad_height = 280;//<script type="text/java

java专栏 283

【Proteus仿真】点亮小灯系列仿真——小灯闪烁/流水灯/交通灯

本文介绍了基于AT89C51单片机的LED控制案例,共包含5个实例:1)单个LED闪烁;2)共阳极流水灯;3)共阴极流水灯;4)花样流水灯;5)交通灯模拟。每个案例详细说明了电路原理图、接线方式和控制程序实现,其中重点讲解了PWM调光原理及其在LED控制中的应用。案例由简至繁,从基础I/O控制到复杂花样显示,最后实现交通灯逻辑控制,展示了单片机在LED控制中的典型应用方法。文中提供了完整的源代码,便于读者理解和实践。

XU157303764的博客 1884

Python爬虫抓取学术期刊数据(Springer、Elsevier)

本文详细介绍了如何使用Python爬虫抓取学术期刊网站(如Springer、Elsevier)上的文章信息,并进行数据清洗和存储。我们使用了requestsSeleniumpandas等技术,通过模拟浏览器行为来绕过反爬虫机制,并将数据保存为Excel文件,方便后续分析。未来,我们可以通过加入更多的期刊网站数据源,扩展爬虫的功能,抓取更多的学术数据。同时,结合自然语言处理(NLP)技术,可以对抓取的文章进行自动化的摘要提取和主题分类,为学术研究提供更多的支持。

2201_76125261的博客 1487

深入理解 Java 中的面向对象编程

在 Java 的世界里,面向对象编程(OOP)是其核心思想,掌握它对于成为一名优秀的 Java 开发者至关重要。今天,就让我们一起深入探讨面向对象编程。

weixin_45969711的博客 660

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java中的面向对象编程思想

在Java中,类使用class关键字定义,其结构包含类名、变量、构造器和方法。可以通过publicprotected或private等访问修饰符,来控制类的访问权限。public class 类名 {// 变量类型 变量名;// 构造器public 类名() {// 初始化操作// 方法返回类型 方法名(参数) {// 方法体面向对象编程通过封装、继承和多态构建出模块化、易维护的代码结构。封装保护了数据安全性,继承实现了代码复用,而多态带来了代码的灵活性。

weixin_46873915的博客 1061

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C++面向接口编程浅谈

大家都知道C++和java都是面向对象的编程语言。面向对象语言的三个特征:继承、封装和多态,但是java和C++还是有许多的不同之处,除了语法之外还有一点不同就是java中有的接口这个概念和关键词,但是C++却没有接口这个概念。 既然它们都是面向对象语言,也就有面向对象编程的特征,也就是把数据和对数据的处理(算法)封装在一起了。通过定义类使用类来定义类对象,然后这个对象就有了封装的数据和对数据的这...

qq_40183315的博客 320

【Java基础-17】带你进入Java 中的面向对象编程

在计算机科学中,程序(Program)是一个指令序列,用于指导计算机执行特定的任务。程序是计算机软件的核心组成部分,它定义了计算机如何处理数据、执行操作以及实现特定的功能。程序通常由编程语言编写,并通过编译或解释的方式转换为计算机可以执行的机器代码。一切客观存在的事物都是对象,万物皆对象。任何对象,一定具有自己的特征和行为。

weixin_39033358的博客 471

Java面向对象和数据库的脚本开发项目的不同

   先说Java面向对象,面向对象是围绕现实世界中的概念来组织系统模型的一种崭新的思维方式,其基本构造是对象,这些对象把特定的数据以及与该数据相关的行为或叫操作、方法紧密的结合在一起组成单一实体,而面向对象把这些相互独立的对象有效的紧密结合在一起组织系统。简单的就是对一种事物的认识。我们认识这个事物的状态和行为,我们又来用数据来描述它的状态.举例一个,比如我们手中的一支笔,状态就是什么样的笔,钢

zhaohezhi的专栏 651

java面向对象编程的阐述

面向对象编程是一种编程范式,它使用“对象”作为基本构建块。与传统的过程化编程不同,OOP强调将数据与操作数据的代码结合在一起,从而提高代码的可重用性和可维护性。在Java中,OOP的核心概念包括类(Class)、对象(Object)、继承(Inheritance)、多态(Polymorphism)和封装(Encapsulation)。

m0_73934887的博客 327

面向对象 vs 面向过程:Java 编程范式深度解析

Java 是一门典型的面向对象编程(Object-Oriented Programming, OOP)语言,其设计哲学与传统的面向过程编程(Procedural Programming)有本质区别。理解这两种编程范式的差异,有助于开发者在不同场景下选择合适的抽象方式,提升代码的可读性、可维护性和可扩展性。→ 如果只是把函数塞进类里,没有封装、继承、多态的设计,仍是“面向过程披着类的外衣”。(如静态工具方法),关键在于是否合理运用 OOP 原则。复杂系统用面向对象更可控。,不直接暴露余额字段。

2203_75696125的博客 690

java面向接口的编程_面向接口编程的好处

面向接口的编程正是java的优点,首先 用起来方便,结构清晰在j2ee中的接口也就是类,类与类之间的通信因为接口而变的简单易懂呵呵,像J2EE中的API规范基本上都是接口,由各应用服务器来实现,比如:WebSphere按照这个接口实现自己的,WebLogic也按照这个接 口实现自己的,作为开发者来说我们根本就不用去管谁是怎样实现的,只要按照J2EE的API来写就可以了,根本用不着导入它们的实现包,...

weixin_33954881的博客 435
上一篇: 99%的Java程序员会踩的六个坑
下一篇: 从 B 站崩溃报告看分布式系统的技术栈
程序员职业指南
博客等级 码龄4年 2138粉丝 960原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值