我经常遇到将实例作为参数传递给函数的情况。我想到,同样可以转发对象的参数,并在方法内初始化。
示例:
class MyCanvas extends JComponent {
private static final long serialVersionUID = 1L;
private static ArrayList<String> textData;
private static ArrayList<Rectangle> rectData;
@Override
public void paintComponent(Graphics g) {
if(g instanceof Graphics2D){
//Draw the rectangles and text
}
}
public void addText(int x, int y, String text){
textData.add(text);
}
//Do this:
public void addRect(Rectangle rect){
rectData.add(rect);
}
//Or do this?
public void addRect(int x, int y, int z, int q){
rectData.add(new Rectangle(x, y, z, q);
}
}
在这种情况下,传递四个整数可以减少可变性。从理论上讲,错误表面积应该随着潜在漏洞的减少而减少。
JVM 如何以不同的方式处理这两个示例?
是否真的不易出现错误/漏洞?
在性能方面,其中一种会比另一种更高效吗?
注意:这不是一个关于设计偏好的问题。有多种方式包装或绑定(bind)参数,使得任一示例都灵活且高效。我想知道的是字节码级别上的差异是什么,以及在字节码级别上是否明显更高效/更安全。
最佳答案
从 API 设计的角度来看,传递 Rectangle
(或 Shape
)更好。它支持coding to an interface, not an implementation.从某种意义上说,指定一个角和尺寸是一种实现;不同的实现将指定对角。通过传递形状,您可以使代码更具适应性。
这里的主要问题是由于 Rectangle
的可变性。对此存在效率争论,但我想知道如果现在设计的话 Shape
是否会可变。对于许多应用程序来说,不可变数据类型提供了许多好处,更安全的数据共享就是其中之一。
由于您正在实现 MyCanvas
,因此您可以确信 Rectangle
实例没有被修改,因此是“安全的”。但是,如果其他人正在编写调用者,并且 MyCanvas 是一个他们不能完全信任的黑匣子,那么有两件事可以提供帮助。
首先,您可以记录接受形状的 MyCanvas
方法,并指定不修改形状。在Java中,这个规范应该放在Javadoc comments中关于方法和类。这是一种常见的做法;除非您正在编写一个可能执行由不值得信赖的作者编写的代理的插件系统,否则程序员通常依赖此 promise ,或 contract,在 API 中。
其次,如果调用者没有这种保证,他们可以将“他们的”Rectangle
实例复制到临时副本,并将该副本传递给您。因为在方法返回后它们永远不会读取 Rectangle 的状态,所以无论您对其执行什么操作都无关紧要。因为矩形
是可变的,所以这可以相当有效地完成。
从字节码的角度来看,传递矩形
更快。对于传递的每个参数都会执行一条单独的指令。更多参数,更多说明。此外,传递Rectangle
允许重用调用者的实例,而传递原始元素需要分配一个可能不必要的新Rectangle
。
当您说“在本例中传递四个整数可以减少可变性时,我不知道您在说什么。从理论上讲,错误表面积应该随着潜在漏洞的减少而减少。”
我确实知道,在现实世界中,具有相同类型的多个参数(例如四个 int
参数)的方法极其容易出错。将它们命名为 q
和 z
之类的无意义名称会使问题变得更糟。利用参数的强类型可以消除编译时的错误,从而使您的程序更安全。
关于java - 将实例传递给方法 Vs。转发参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38355470/