Java 反射最终篇 - Mock 对象和桩

Mock 对象和 **桩(Stub)**在逻辑上都是 Optional 的变体。他们都是最终程序中所使用的“实际”对象的代理。
不过,Mock 对象和桩都是假扮成那些可以传递实际信息的实际对象,而不是像 Optional 那样把包含潜在 null 值的对象隐藏。

Mock 对象和桩之间的的差别在于程度不同。

  • Mock 对象往往是轻量级的,且用于自测试。通常,为了处理各种不同的测试场景,我们会创建出很多 Mock 对象。
  • 桩只是返回桩数据,通常是重量级的,在多个测试中被复用。可以根据它们被调用的方式,通过配置进行修改。因此,桩是一种复杂对象,可以做很多事情。
    至于 Mock 对象,如果你要做很多事,通常会创建大量又小又简单的 Mock 对象。

接口和类型

interface 关键字的一个重要目标就是允许程序员隔离组件,进而降低耦合度。使用接口可以实现这一目标,但是通过类型信息,这种耦合性还是会传播出去——接口并不是对解耦的一种无懈可击的保障。
比如我们先写一个接口:


实现这个接口

通过使用 RTTI,我们发现 a 是用 B 实现的。通过将其转型为 B,我们可以调用不在 A 中的方法。

这样的操作完全是合情合理的,但是你也许并不想让客户端开发者这么做,因为这给了他们一个机会,使得他们的代码与你的代码的耦合度超过了你的预期。
你可能认为 interface 关键字正在保护你,但其实并没有。另外,在本例中使用 B 来实现 A 这种情况是有公开案例可查的。

一种解决方案是直接声明,如果开发者决定使用实际的类而不是接口,他们需要自己对自己负责。这在很多情况下都是可行的,但“可能”还不够,你或许希望能有一些更严格的控制方式。

最简单的方式是让实现类只具有包访问权限,这样在包外部的客户端就看不到它了:

在包中唯一 public 的部分就是 HiddenC,在被调用时将产生 A接口类型的对象
即使你从 makeA() 返回的是 C 类型,你在包的外部仍旧不能使用 A 之外的任何方法,因为你不能在包的外部命名 C

现在如果你试着将其向下转型为 C,则将被禁止,因为在包的外部没有任何 C 类型可用:

通过使用反射,仍然可以调用所有方法,甚至是 private 方法!如果知道方法名,你就可以在其 0Method 对象上调用 setAccessible(true),就像在 callHiddenMethod() 中看到的那样。

你可能觉得,可以通过只发布编译后的代码来阻止这种情况,但其实这并不能解决问题。因为只需要运行 javap(一个随 JDK 发布的反编译器)即可突破这一限制。
使用 javap

javap -private C

-private 标志表示所有的成员都应该显示,甚至包括私有成员。下面是输出:

class C extends
java.lang.Object implements typeinfo.interfacea.A {typeinfo.packageaccess.C();public void f();public void g();void u();protected void v();private void w();
}

因此,任何人都可以获取你最私有的方法的名字和签名,然后调用它们。

那如果把接口实现为一个私有内部类,又会怎么样呢?下面展示了这种情况:

public C.f()
InnerA$C
public C.g()
package C.u()
protected C.v()
private C.w()

这里对反射仍然没有任何东西可以隐藏。那么如果是匿名类呢?

输出结果:

public C.f()
AnonymousA$1
public C.g()
package C.u()
protected C.v()
private C.w()

看起来任何方式都没法阻止反射调用那些非公共访问权限的方法。对于字段来说也是这样,即便是 private 字段:
输出结果:

i = 1, I'm totally safe, Am I safe?
f.getInt(pf): 1
i = 47, I'm totally safe, Am I safe?
f.get(pf): I'm totally safe
i = 47, I'm totally safe, Am I safe?
f.get(pf): Am I safe?
i = 47, I'm totally safe, No, you're not!

但实际上 final 字段在被修改时是安全的。运行时系统会在不抛出异常的情况下接受任何修改的尝试,但是实际上不会发生任何修改。

通常,所有这些违反访问权限的操作并不是什么十恶不赦的。如果有人使用这样的技术去调用标志为 private 或包访问权限的方法(很明显这些访问权限表示这些人不应该调用它们),那么对他们来说,如果你修改了这些方法的某些地方,他们不应该抱怨。
另一方面,总是在类中留下后门,也许会帮助你解决某些特定类型的问题(这些问题往往除此之外,别无它法)。
总之,不可否认,反射给我们带来了很多好处。

程序员往往对编程语言提供的访问控制过于自信,甚至认为 Java 在安全性上比其它提供了(明显)更宽松的访问控制的语言要优越。然而,正如你所看到的,事实并不是这样。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用聊天机器人假扮人类

日前看到新闻,某企业用聊天机器人假扮人类,蒙骗消费者。使用聊天机器人服务消费者没有错,但是现在这样用,技术明显是跑在法律前面了,至少在中国还没有立法,禁止机器人假扮人类。 2019年,美国加…

chatgpt赋能python:如何用Python赚取合法收入

如何用Python赚取合法收入 随着技术的飞速发展,Python作为一种简洁易读的高级编程语言,一直以来受到了广大工程师、开发人员和数据科学家的青睐。应用广泛,从网站开发到机器学习,从自然语言处理到大数据分析,Python都…

你需要了解的 50 个 ChatGPT 统计数据和事实

Rest assured that with the ChatGPT statistics you’re about to read, you’ll confirm that the popular chatbot from OpenAI is just the beginning of something bigger. Since its launch in November 2022, ChatGPT has broken unexpected records. For example, it r…

做设计师要用到的工具软件

1.图形处理工具 这就是 UI 设计师的核心了,PS 是使用最广泛的,用 Sketch(Mac)和 XD(Windows)的也很多,Sketch/XD 比较轻量级,基本能满足 UI 设计师的日常工作需要。 2.信息架构工具…

解决论文查重时参考文献被标红的方法

1. 有明显的“参考文献”标记,参考文献4个字独占一行,不要有其他任何字符 2. 尽量不要用谷歌学术、NoteExpress、EndNote等工具来生成参考文献,很容易在查重时被标红 2.1 如果用NoteExpress插入参考文献时,最好清除域代码&#…

借助ChatGPT的「代码解释器」,菜鸟玩下数据分析

大家好,我是Yuan,这篇文章主要是介绍,借助ChatGPT的「代码解释器」,如何进行数据分析。 概述 代码解释器对于经常使用代码和数据的专业人士和爱好者都非常有用,这是一个多功能的工具,可以用于分析数据、创…

微信小程序云开发———云数据库

1.微信小程序注册 官方注册文档:[https://developers.weixin.qq.com/miniprogram/introduction/] 微信小程序注册地址:[https://mp.weixin.qq.com/] 进去以后点击立即注册 ​​​​​​​ 点击立即注册后会转跳到选择注册的帐号类型 ,在这个页面…

小程序(四):微信登录功能的实现+云开发数据库

目录 好文推荐: 完整代码gitee仓库查看:https://gitee.com/CMD-UROOT/xzyy.git 一、微信登录 1.点击按钮(或其他),获取用户信息(昵称、头像等)。 2.通过微信官方文档搜getUserProfile 3.给点击登录绑定事件 点击登…

微信小程序云开发之云函数的大坑

不知道大家在弄使用云函数的时候有没有看日志的习惯,看这个日志是要钱的,真是无语了,微信开发者工具上面没有任何的提示,我是今天敲代码的时候突然那发现云函数查不出数据了,打开控制台发现说我欠费了,但是…

网页中文翻译成英文简单方法

利用谷歌浏览器的翻译功能可以比较快键的把网页翻译成其他语言。 首先,打开需要翻译的网页。右键一键翻译。 会出现这个选择框,选择选项 改成需要的语言,再按f12。 选择copy 整个html元素,建立一个记事本,复制粘贴。放…

利用python批量将excel中文翻译成英文

目录 操作过程中不断遇到新的问题,思路的转换过程背景第一天 操作过程第二天正则表达式是个好东西第三天第四天第五天遇到的小问题操作过程中不断遇到新的问题,思路的转换过程 背景 今天接到一个任务,需要将EXCEL文件中的中文翻译成英文,由于表格内容非常大,我想着 这要…

用python做一个文本翻译器,自动将中文翻译成英文,超方便的

translate非标准库是python中可以实现对多种语言进行互相翻译的库,使用时只需要设置目标语言(比如:中文、英文)后,会自动将原始文本翻译成我们需要的目标语言。 【阅读全文】 使用pip的方式安装translate非标准库。 …

无手机号注册Outlook邮箱方法

目前,拥有电子邮件地址已成为一项基本需求,因为有必要其他平台上注册,App注册等等。 创建电子邮件帐户很简单,但同时在安全性方面可能会变得有些微妙,因为我们的电子邮件通常包含与我们公开使用的银行数据、家庭数据或…

配置cloudreve邮箱发信用outlook邮箱时的权限异常,做个记录

介绍 之前用163的默认邮箱发信,改用outlook的自定域名后缀发信但是居然后台出现错误,现现以下错误提示 既然发送失败,第一时间就是拉取日志查看异常原因了,异常原因“Caused by: javax.mail.AuthenticationFailedException: 535…

.Net使用163smtp发送邮件时错误:邮箱不可用. has no permission解决方法

C#实现简单邮件发送代码如下 public static void SendAsync(string emailTo, string subject, string mailBody){var msg new MailMessage();msg.To.Add(emailTo);//msg.From new MailAddress(_userNameForEmail, "显示的发件人名称", System.Text.Encoding.UTF8);…

Foxmail登陆报错outlook邮箱报错:foxmail,C4 NO LOGIN failed.

1 事件 Foxmail登陆报错outlook邮箱报错: foxmail,C4 NO LOGIN failed. 2 原因 这是由于outlook邮箱设置了双重验证登陆,foxmail无法弹出验证登陆窗口 3操作方法 方法一:更换邮箱客户端 方法二: (1)网页登陆…

文心一言 VS chatgpt (13)-- 算法导论3.1 8题 3.2 1题

八、可以扩展我们的记号到有两个参数n和m的情形,其中的n和m可以按不同速率独立地趋于无穷。对于给定的函数g(n, m),用O(g(n, m))来表示以下函数集: O(g(n, m)) { f(n, m): 存在正常量c、和,使得对所有n>n0或m>m0&#xff…

Windows中文账户名修改为英文

原理:使用第三者管理员账户对当前中文名管理员账户的名称进行修改。 1、创建新的管理员账户 在Windows开始菜单处点击右键,选择Windows PowerShell(管理员),输入以下命令,创建tempuser管理员用户&#xff…

win10修改用户名||user中文名改英文名

操作可能有系统重装风险,修改需谨慎! 1.修改注册表 winR 打开regedit: 打开路径:计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion,双击RegisteredOwner将其值改为要改成的新名字name&#…

chatgpt赋能python:Python聊天机器人:让沟通变得更加智能

Python 聊天机器人:让沟通变得更加智能 随着人工智能的快速发展,聊天机器人正在变得越来越流行。Python 作为一种简单易用的编程语言,也在聊天机器人的开发中得到了广泛应用。本篇文章将介绍 Python 聊天机器人,并探讨它的优势以…