Java 中的运算符重载

    在这篇文章中,我们将深入探讨 Java 中 Operator 重载的迷人世界。尽管 Java 本身不支持运算符重载,但我们将发现 Manifold 如何使用该功能扩展 Java。我们将探讨它的好处、局限性和用例,尤其是在科学和数学代码方面。

06ec9abbd8c02dc7cf99a3fe4d9f4064.png

    我们还将探索 Manifold 提供的三个强大功能,这些功能增强了默认的 Java 类型安全性,同时支持令人印象深刻的编程技术。我们将讨论单元表达式、类型安全的反射编码以及编译期间修复 equals 等方法。此外,我们将介绍 Manifold 提供的解决方案,以解决关键字的一些限制

    在我们开始之前,与往常一样,您可以在我的 GitHub 页面上找到本文和本系列中其他视频的代码示例。请务必查看该项目,给它加个星标,并在 GitHub 上关注我以保持更新!

算术运算符

    运算符重载允许我们在代码中使用熟悉的数学符号,使其更具表现力和直观性。虽然 Java 默认不支持运算符重载,但 Manifold 提供了此限制的解决方案。

    为了演示,让我们从一个执行向量算术运算的简单类开始。在标准 Java 代码中,我们定义变量,在构造函数中接受它们,并实现向量加法等方法。但是,这种方法可能很冗长且可读性较差。Vectorplus

1
public class Vec {
2private float x, y, z;
34public Vec(float x, float y, float z) {
5this.x = x;
6this.y = y;
7this.z = z;
8}
910public Vec plus(Vec other) {
11return new Vec(x + other.x, y + other.y, z + other.z);
12}
13
}

    使用 Manifold,我们可以显着简化代码。使用 Manifold 的算子重载功能,我们可以直接使用算子将向量相加,如下所示:

1
Vec vec1 = new Vec(1, 2, 3);
2
Vec vec2 = new Vec(1, 1, 1);
3
Vec vec3 = vec1 + vec2;

    Manifold 将运算符无缝映射到适当的方法调用,使代码更简洁。这种流畅的语法类似于数学表示法,增强了代码的可读性。

    此外,Manifold 可以优雅地处理反向表示法。假设我们颠倒操作数的顺序,例如标量加向量,Manifold 交换顺序并正确执行操作。这种灵活性使我们能够以更自然、更直观的方式编写代码。

假设我们将以下内容添加到 Vec 类中:

1
public Vec plus(float other) {
2return new Vec(x + other, y + other, z + other);
3
}这将使所有这些行都有效:
爪哇岛
1
vec3 += 5.0f;
2
vec3 = 5.0f + vec3;
3
vec3 = vec3 + 5.0f;
4
vec3 += Float.valueOf(5.0f);

    在此代码中,我们演示了 Manifold 可以交换顺序以无缝调用。我们还表明 plus 等于运算符支持内置于 plus 方法支持中Vec.plus(float)

    正如前面的代码所暗示的那样,Manifold 还支持原始包装器对象,特别是在自动装箱的上下文中。在 Java 中,原始类型具有相应的包装器对象。Manifold 可以无缝地处理 primitives 及其包装器对象之间的转换,这要归功于自动装箱和取消装箱。这使我们能够在代码中互换地使用对象和基元。这有一些注意事项,我们会发现的。

BigDecimal 支持

    Manifold 超越了简单的算术,支持更复杂的场景。例如,依赖项包括对 arithmetic 的内置支持。Java 类是否用于涉及大数或金融计算的精确计算?通过使用 Manifold,我们可以使用熟悉的运算符(如 、、 和 )对 BigDecimal 对象执行算术运算。Manifold 的集成简化了代码并确保了准确的计算。manifold-scienceBigDecimalBigDecimal+-*/BigDecimal

    一旦我们添加了正确的依赖项集,这些依赖项将方法扩展添加到类中,以下代码是合法的:BigDecimal

1
var x = new BigDecimal(5L);
2
var y = new BigDecimal(25L);
3
var z = x + y;

    在后台,Manifold 将适用的 plus、minus、times 等方法添加到类中。它通过利用我之前讨论过的类扩展来实现这一点。

装箱的限制

    我们还可以扩展现有类以支持运算符重载。Manifold 允许我们扩展类并添加接受自定义类型或执行特定操作的方法。例如,我们可以扩展该类并添加一个接受 BigDecimal 作为参数并返回结果的方法。此扩展使我们能够无缝地在不同类型的之间执行算术运算。目标是让这段代码编译:IntegerplusBigDecimal

1
var z = 5 + x + y;

不幸的是,这不会与该更改一起编译。数字 5 是 primitive,而不是 Integer,让该代码工作的唯一方法是:

1
var z = Integer.valueOf(5) + x + y;

    这不是我们想要的。但是,有一个简单的解决方案。我们可以为自己创建一个扩展,并依赖于订单可以无缝交换的事实。这意味着这个简单的扩展可以在不更改的情况下支持表达式:BigDecimal5 + x + y

1
@Extension
2
public class BigDecimalExt {
3public static BigDecimal plus(@This BigDecimal b, int i) {
4return b.plus(BigDecimal.valueOf(i));
5}
6
}

算术运算符列表

    到目前为止,我们专注于 plus 运算符,但 Manifold 支持广泛的运算符。下表列出了方法名称及其支持的运算符:

算子方法
+,+=plus
-,-=minus
*,*=times
/,/=div
%,%=rem
-aunaryMinus
++inc
--dec

    请注意,递增和递减运算符在前缀和后缀定位之间没有区别。两者都会导致该方法。a++++ainc

索引运算符

    当我看到它时,对 index 运算符的支持让我完全措手不及。这完全改变了游戏规则......index 运算符是我们用来按索引获取数组值的方括号。为了让您了解我在说什么,这是 Manifold 中的有效代码:

1
var list = List.of("A", "B", "C");
2
var v = list[0];

    在这种情况下, will be ,并且代码等效于调用 .索引运算符无缝映射到 get 和 set 方法。我们也可以使用以下方法进行作业:v“A”list.get(0)

1
var list = new ArrayList<>(List.of("A", "B", "C"));
2
var v = list[0];
3
list[0] = "1";

    请注意,我必须将 List 包装在 since 中,返回一个不可修改的 List。但这不是我要纠结的部分。这段代码很 “不错”。这段代码绝对令人惊叹:ArrayListList.of()

1
var map = new HashMap<>(Map.of("Key", "Value"));
2
var key = map["Key"];
3
map["Key"] = "New Value";

    您正在 Manifold 中读取有效代码。索引运算符用于在 map 中查找。请注意,map 具有 method,而不是 method。这是一个令人讨厌的不一致,Manifold 用扩展方法解决了这个问题。然后,我们可以通过 operator 使用对象在 map 中查找。put() set

关系运算符和相等运算符

我们还有很多事情要讲......我们是否可以编写这样的代码(参考前面的对象):

1
if(vec3 > vec2) {
2// …
3
}

    请注意,该类具有 times 方法的多个重载版本,它们接受不同的对象类型。一个时代会产生 。A 倍导致 。VelocityMassMomentumVelocityForcePower即使在早期实验阶段,此软件包也支持许多单元,请在此处查看它们。

您可能会注意到这里的一个大遗漏:Currency。我很想有这样的东西:

1
var sum = 50 USD + 70 EUR;

    如果您查看该代码,问题应该很明显。我们需要一个汇率。如果没有汇率和可能的转换成本,这就没有意义。财务计算的复杂性并不能很好地转化为代码的当前状态。我怀疑这就是这仍然是实验性的原因。我很好奇如何优雅地解决这样的事情。

操作员超载的陷阱

    虽然 Manifold 提供了强大的操作员超载功能,但重要的是要注意潜在的挑战和性能考虑因素。Manifold 的方法可能会导致额外的方法调用和对象分配,这可能会影响性能,尤其是在性能关键型环境中。考虑优化技术(例如减少不必要的方法调用和对象分配)以确保高效的代码执行至关重要。

让我们看看这段代码:

1
var n = x + y + z;

从表面上看,它似乎高效而简短。它物理转换为以下代码:

var n = x.plus(y).plus(z);

    这仍然很难发现,但请注意,为了创建结果,我们调用了两个方法并分配了至少两个对象。更有效的方法是:

var n = x.plus(y, z);

    这是我们经常为高性能矩阵计算所做的优化。您需要注意这一点,并了解如果性能很重要,操作员在后台做什么。我不想暗示 Operator 天生就慢。事实上,它们与方法调用一样快,但有时调用的特定方法和分配数量并不直观。

类型安全特性

    以下内容与运算符重载无关,但它们是第二个视频的一部分,因此我认为它们作为关于类型安全的广泛讨论的一部分是有意义的。我最喜欢 Manifold 的一点是它支持严格的类型化和编译时错误。对我来说,两者都代表了 Java 的核心精神。

JailBreak:类型安全反射

    @JailBreak是一项功能,用于授予对类中 private 状态的访问权限。虽然这听起来很糟糕,但提供了比使用传统反射访问私有变量更好的替代方案。通过越狱一个类,我们可以无缝地访问它的私有状态,而编译器仍然执行类型检查。从这个意义上说,它是两害相权取其轻的。如果你要做一些糟糕的事情(访问私有状态),那么至少让编译器检查它。@JailBreak

    在下面的代码中,value 数组是 String 的私有数组,但我们可以借助注释来操作它。此代码将打印 :@JailBreak“Ex0osed…”

1
@Jailbreak String exposedString = "Exposed...";
2
exposedString.value[2] = '0';
3
System.out.println(exposedString);

    JailBreak 也可以应用于静态字段和方法。但是,访问静态成员需要为变量分配 null,这似乎有悖常理。尽管如此,此功能提供了一种更可控且类型安全的方法来访问内部状态,从而最大限度地降低了与使用反射相关的风险。

1
@Jailbreak String str = null;
2
str.isASCII(new byte[] { 111, (byte)222 });

    最后,Manifold 中的所有对象都注入了一个方法。此方法可以像这样使用(请注意,这是一个私有字段):jailbreak()fastTime

1
Date d = new Date();
2
long t = d.jailbreak().fastTime;

自注释:强制方法参数类型

    在 Java 中,某些 API 接受对象作为参数,即使可以使用更具体的类型也是如此。这可能会导致运行时出现潜在问题和错误。但是,Manifold 引入了 Comments,这有助于强制执行作为参数传递的对象类型。@Self

    通过使用 注释参数,我们明确表示仅接受指定的对象类型。这确保了类型安全并防止意外使用不兼容的类型。使用此注释,编译器可以在开发过程中捕获此类错误,从而降低在生产中遇到问题的可能性。@Self

让我们看看我之前的帖子:MySizeClass

1
public class MySizeClass {
2int size = 5;
34public int size() {
5return size;
6}
78public void setSize(int size) {
9this.size = size;
10}
1112public boolean equals(@Self Object o) {
13return o != null && ((MySizeClass)o).size == size;
14}
15
}

请注意,我添加了一个 equals 方法,并使用 Self 注释了该参数。如果我删除 Self 注释,此代码将编译:

1
var size = new MySizeClass();
2
size.equals("");
3
size.equals(new MySizeClass());

使用 annotation 时,字符串比较在编译过程中将失败。@Self

auto 关键字:var 的更强替代方案

    我不是这个关键词的忠实粉丝。我觉得它并没有简化太多,而且价格是编码到实现而不是接口。我理解 Oracle 的开发人员为什么选择这条路。保守的决定是我觉得 Java 如此吸引人的主要原因。Manifold 的好处是可以在这些约束之外工作,并且它提供了一个更强大的替代方案,称为 。可用于字段和方法返回值,使其比 var 更灵活。它提供了一种简洁而富有表现力的方式来定义变量,而不会牺牲类型安全性。varautoauto

    Auto 在使用 Tuples 时特别有用,这是本文尚未讨论的功能。它允许使用优雅简洁的代码,从而提高可读性和可维护性。您可以有效地将 auto 用作 var 的直接替代品。

最后

    Manifold 的运算符重载为 Java 带来了富有表现力和直观的数学符号,增强了代码的可读性和简单性。虽然 Java 本身不支持运算符重载,但 Manifold 使开发人员能够实现类似的功能并在其代码中使用熟悉的运算符。通过利用 Manifold,我们可以编写更流畅、更具表现力的代码,尤其是在科学、数学和金融应用中。

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

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

相关文章

高清8k电脑壁纸分享

Hello&#xff01;欢迎各位新老朋友来看小弟博客&#xff0c;祝大家事业顺利&#xff0c;财源广进&#xff01;&#xff01; 主题&#xff1a;高清壁纸分享 文件太大上传不上去&#x1f605;&#x1f605;&#x1f605;&#x1f605;&#x1f605;&#xff0c;需要的朋友自取&…

国货美妆品牌整合营销多少钱?

合作咨询联系竑图 hongtu201988 化妆品品牌线上推广费用到底高不高&#xff0c;需要多少钱&#xff0c;是每个经营者最为关注的问题。结合中小美妆品牌在网络上的费用投入&#xff0c;有一个大致的范围&#xff1a;几千元到几十万不等/年&#xff01;品牌越大&#xff0c;投入越…

什么鬼?主备同步正常,备库查询表空间使用结果却是空的?

作者介绍&#xff1a;老苏&#xff0c;10余年DBA工作运维经验&#xff0c;擅长Oracle、MySQL、PG、Mongodb数据库运维&#xff08;如安装迁移&#xff0c;性能优化、故障应急处理等&#xff09; 公众号&#xff1a;老苏畅谈运维 欢迎关注本人公众号&#xff0c;更多精彩与您分享…

Centos Stream 9根目录扩容

要将 sda 的剩余空间扩展给 cs-root&#xff0c;可以按照以下步骤进行操作。假设你已经有剩余的未分配空间在 sda 上。 步骤 1&#xff1a;查看当前磁盘分区情况 首先&#xff0c;确保你有未分配的空间在 sda 上。 lsblk步骤 2&#xff1a;创建新的分区 使用 fdisk 或 par…

C++vector类的模拟实现

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 模拟实现vector类 收录于专栏【C语法基础】 本专栏旨在分享学习C的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 前置说明 1. vecto…

数据结构2——单链表

目录 1.链表 1.1链表的概念及结构 1.2 链表的分类 ​编辑2.无头单链表的实现 1. 节点 2.遍历链表 3.动态增加新节点 4.查找&#xff08;修改&#xff09; 5.插入 5.1 尾插 5.2 头插 5.3 在pos之前插入x 5.4 在pos之后插入x 6.删除 6.1 尾删 6.2 头删 6.3 删除…

YOLOv10改进,YOLOv10损失函数更换为Powerful-IoU(2024年最新IOU),助力高效涨点

改进前训练结果: 改进后的结果: 摘要 边界框回归(BBR)是目标检测中的核心任务之一,BBR损失函数显著影响其性能。然而,观察到现有基于IoU的损失函数存在不合理的惩罚因子,导致回归过程中锚框扩展,并显著减缓收敛速度。为了解决这个问题,深入分析了锚框扩展的原因。针…

狂神说多线程01

线程实现&#xff08;重点&#xff09; 多线程三个方法 继承Thread类 ⭐️实现Runnable 实现callable&#xff08;了解&#xff09; 线程状态 出生-&#xff1f; 线程同步&#xff08;重点&#xff09; &#xff08;多个线程操作同一个对象&#xff0c;那个对象出现了不安…

RP2040 CXX SDK PIO应用例程

RP2040 CXX SDK PIO应用例程 &#x1f4cd;DS18B20 PIO参考项目例程&#xff1a;https://github.com/jondurrant/RP2040PIO-DS18B20&#x1f4cd;DHT11 PIO 参考项目例程&#xff1a;https://github.com/vmilea/pico_dht 在官方的SDK pico-examples中有关PIO的例程有20个&#…

828华为云征文 | 云服务器Flexus X实例,Docker集成搭建Halo博客平台

828华为云征文 | 云服务器Flexus X实例&#xff0c;Docker集成搭建Halo博客平台 Halo博客平台是一款基于Java的开源博客系统&#xff0c;以其简单易用、功能强大、美观大方等特点而受到广泛欢迎&#xff0c;采用了多种先进的技术框架&#xff0c;包括Freemarker模板引擎、Vue.j…

【STM32】【rt-thread】startup_stm32f405xx.S文件解读

startup_stm32f405xx.S文件解读 一、代码全文 /********************************************************************************* file startup_stm32f405xx.s* author MCD Application Team* brief STM32F405xx Devices vector table for GCC based toolcha…

每日OJ题_牛客_ 游游的you(贪心+模拟)

目录 牛客_ 游游的you&#xff08;贪心模拟&#xff09; 解析代码 牛客_ 游游的you&#xff08;贪心模拟&#xff09; 游游现在有a个y&#xff0c;b个o&#xff0c;c个u&#xff0c;他想用这些字母拼成一个字符串。 三个相邻的字母是"you"可以获得2分&#xff0c…

室内院内常见的不知名蚊虫(昆虫)图鉴和防治方法

文章目录 蟑螂形态特征出现源头危害性防治方法 跳蚤形态特征出现源头危害性防治方法 臭虫&#xff0c;又名木蚤、床虱、壁虱形态特征出现源头危害性防治方法 尘螨形态特征出现源头危害性防治方法 蛾蚋&#xff08;ru&#xff09;&#xff0c;又名蛾蠓&#xff08;měng&#xf…

解密.baxia勒索病毒:.baxia勒索病毒的攻击手法及防护建议

导言 在当前网络安全形势日益严峻的背景下&#xff0c;勒索软件的威胁正不断升级&#xff0c;其中.baxia勒索病毒尤为突出。作为一种新型恶意软件&#xff0c;.baxia病毒通过加密用户的文件并要求支付赎金来获取解密密钥&#xff0c;对个人和企业的安全构成了严重威胁。随着其…

医院预约|基于springBoot的医院预约挂号系统设计与实现(附项目源码+论文+数据库)

私信或留言即免费送开题报告和任务书&#xff08;可指定任意题目&#xff09; 目录 一、摘要 二、相关技术 三、系统设计 四、数据库设计 五、核心代码 六、论文参考 七、源码获取 一、摘要 近年来&#xff0c;信息化管理行业的不断兴起&#xff0c;使得人们的日…

国庆节适合买什么东西?精选五款实用又优惠的多功能好物!

临近国庆&#xff0c;我猜很多朋友已经开始为假期做好准备&#xff0c;计划开启出游和购物的节奏了&#xff01;大家都希望在国庆期间&#xff0c;买到一些平时因为价格太贵而舍不得下单的好物&#xff01;作为一名家居兼数码博主&#xff0c;每年国庆的时候我都会疯狂采购各种…

Ansible流程控制-条件语句_循环语句

文章目录 Ansible流程控制条件语句且、或、非、是模糊条件when指令的详细使用方法 循环语句如何使用使用item变量结合with_items或loop指令item变量有固定子元素&#xff1f; 实例-服务器安装基础环境优化需求部分实现换指定新仓库安装基础软件包 Ansible流程控制 一、 1. 条件…

文件服务器FastDFS 消息队列中间件RabbitMQ

新标签页 (chinaunix.net) FastDFS - Browse Files at SourceForge.net 一、FastDFS Tracker和Storage&#xff1a; tracker用来管理所有的storage&#xff0c;只是管理服务器&#xff0c;负责负载均衡。 storage是存储服务器&#xff0c;每一个storage服务器都是一个单独的个…

Cilium + ebpf 系列文章-什么是ebpf?(一)

前言&#xff1a; 这篇非常非常干&#xff0c;很有可能读不懂。 这里非常非常推荐&#xff0c;建议使用Cilium官网的lab来辅助学习&#xff01;&#xff01;&#xff01;Resources Library - IsovalentExplore Isovalents Resource Library, your one-stop destination for ins…

828华为云征文|华为云Flexus云服务器X实例部署Xnote笔记应用

828华为云征文&#xff5c;华为云Flexus云服务器X实例部署Xnote笔记应用 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、Note Mark 介绍2.1 Xnote简介2.2 Xnote特点2.3 主要使用场景 三、本次实…