我经常遇到将实例作为参数传递给函数的情况。在我看来,同样可以转发对象的参数,并在方法中初始化。
示例:
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如何以不同方式处理这两个示例?
是否真正减少了错误/漏洞?
在性能方面,一个人会比另一个人更有效吗?
注意:这不是关于设计偏好的问题。有多种方式包装或绑定参数,使得任何一个例子都是灵活和有效的。我想知道的是字节代码级别的不同之处,以及在字节码级别是否明显更高效/安全。
答案 0 :(得分:1)
警惕架构安全性与语言安全性之间的区别。事实上,大多数计算机科学教授都没有意识到这一点。
如果要“安全”传递对象,可以在键盘上提示加密密钥;领取钥匙;加密对象;并通过它。接收功能然后可以重新提示并反转加密!这一切都取决于你想要完成的事情。
对象的生命周期是最大的问题。一旦传递,参数值就位于堆栈上;如果我们假设一个可以查看属于JVM的内存位置的观察者,那么我们就会被软管化。因此,一旦检索到该值,就用垃圾覆盖 in situ 。我们将此称为“对象重用”考虑因素,尽管我们在将对象释放回系统时通常会考虑到这一点:我们并没有隐含地假设某个人共享我们的地址空间并不断窥视这里并戳到那里。
答案 1 :(得分:1)
从API设计的角度来看,传递Rectangle
(或Shape
)会更好。它支持coding to an interface, not an implementation.在某种意义上,指定一个角和尺寸是一种实现;不同的实现将指定对角。通过传递形状,可以使代码更具适应性。
这里的主要问题是Rectangle
的可变性。对此有效率论据,但我想知道Shape
如果今天设计的话会是否可变。对于许多应用程序,不可变数据类型提供了许多好处,更安全的数据共享就是其中之一。
由于您正在实施MyCanvas
,因此您可以确保Rectangle
实例未被修改,因此是“安全的”。但是,如果其他人正在写呼叫者,并且MyCanvas
是一个他们无法完全信任的黑匣子,那么有两件事可以帮助。
首先,您可以记录接受形状的MyCanvas
方法,指定不修改形状。在Java中,此规范应放在方法和类的Javadoc comments中。这是一种常见的做法;除非您正在编写可能执行由不值得信任的作者编写的代理的插件系统,否则程序员通常会依赖此承诺,或者在API中contract,。
其次,如果调用者没有这种保证,他们可以将“他们的”Rectangle
实例复制到临时副本,并将副本传递给您。因为它们在方法返回后从未读过Rectangle
的状态,所以对它做什么并不重要。因为Rectangle
是可变的,所以可以相当有效地完成。
从字节码的角度来看,传递Rectangle
的速度更快。为传递的每个参数执行单独的指令。更多参数,更多说明。此外,传递Rectangle
允许重新使用调用者的实例,而传递原始元素则需要分配可能不必要的新Rectangle
。
当你说“通过四个整数,在这种情况下,减少变异性时,我不知道你在谈论什么。从理论上讲,误差表面积应该随着潜在的漏洞而减少。”
我知道在真实的实际世界中,具有相同类型的多个参数的方法(如四个int
参数)极容易出错。将它们命名为q
和z
这样的废话会使问题更严重。利用参数的强类型,可以在编译时消除错误,从而使程序更安全。
答案 2 :(得分:1)
一开始你有4个整数,最后需要一个矩形。 这一切都归结为谁负责验证输入并进行转换。
虽然这个特殊的例子很简单,但你可以做到 更有趣的是:
public void addRect(String rect){
// e.g. rect = "4 2 3 7"
}
public void addRect(int[] rect){
// e.g. rect = [4 2 3 7]
}
// etc...
在这种情况下,可以认为调用者不应该关心矩形如何
构建,这是MyCanvas
类