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

简介: Java 反射最终篇 - Mock 对象和桩(上)

Mock 对象和 **桩(Stub)**在逻辑上都是 Optional 的变体。他们都是最终程序中所使用的“实际”对象的代理。

不过,Mock 对象和桩都是假扮成那些可以传递实际信息的实际对象,而不是像 Optional 那样把包含潜在 null 值的对象隐藏。


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


Mock 对象往往是轻量级的,且用于自测试。通常,为了处理各种不同的测试场景,我们会创建出很多 Mock 对象。

桩只是返回桩数据,通常是重量级的,在多个测试中被复用。可以根据它们被调用的方式,通过配置进行修改。因此,桩是一种复杂对象,可以做很多事情。

至于 Mock 对象,如果你要做很多事,通常会创建大量又小又简单的 Mock 对象。

接口和类型

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

比如我们先写一个接口:

image.png

实现这个接口

image.png

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


这样的操作完全是合情合理的,但是你也许并不想让客户端开发者这么做,因为这给了他们一个机会,使得他们的代码与你的代码的耦合度超过了你的预期。

你可能认为 interface 关键字正在保护你,但其实并没有。另外,在本例中使用 B 来实现 A 这种情况是有公开案例可查的。


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


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

image.png

在包中唯一 public 的部分就是 HiddenC,在被调用时将产生 A接口类型的对象

即使你从 makeA() 返回的是 C 类型,你在包的外部仍旧不能使用 A 之外的任何方法,因为你不能在包的外部命名 C。


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

image.png

通过使用反射,仍然可以调用所有方法,甚至是 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();
}

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

目录
相关文章
|
5天前
|
安全 Java 编译器
java中类与对象回顾总结-2
java中类与对象回顾总结
14 3
|
5天前
|
Java 编译器
java中类与对象回顾总结-1
java中类与对象回顾总结
14 3
|
1天前
|
Java 编译器
【Java开发指南 | 第一篇】类、对象基础概念及Java特征
【Java开发指南 | 第一篇】类、对象基础概念及Java特征
9 4
|
2天前
|
安全 Java 数据安全/隐私保护
Java一分钟之-Java反射机制:动态操作类与对象
【5月更文挑战第12天】本文介绍了Java反射机制的基本用法,包括获取Class对象、创建对象、访问字段和调用方法。同时,讨论了常见的问题和易错点,如忽略访问权限检查、未捕获异常以及性能损耗,并提供了相应的避免策略。理解反射的工作原理和合理使用有助于提升代码灵活性,但需注意其带来的安全风险和性能影响。
17 4
|
4天前
|
Java
【JAVA基础篇教学】第五篇:Java面向对象编程:类、对象、继承、多态
【JAVA基础篇教学】第五篇:Java面向对象编程:类、对象、继承、多态
|
5天前
|
缓存 Java 程序员
关于创建、销毁对象⭐Java程序员需要掌握的8个编程好习惯
关于创建、销毁对象⭐Java程序员需要掌握的8个编程好习惯
关于创建、销毁对象⭐Java程序员需要掌握的8个编程好习惯
|
5天前
|
Java
从源码出发:JAVA中对象的比较
从源码出发:JAVA中对象的比较
19 3
|
8月前
|
存储 SQL Java
Java反射读取注解信息
Java反射读取注解信息
47 0
|
4月前
|
安全 Java API
Java中的反射(通过反射获取类的结构、invoke方法、获取注解)
Java中的反射(通过反射获取类的结构、invoke方法、获取注解)
|
10月前
|
JSON 安全 Java