将实例传递给方法 Vs。转发参数

Passing an instance to a method Vs. forwarding parameters

我经常遇到将实例作为参数传递给函数的情况。我突然想到,同样可以转发对象的参数,而不是在方法内初始化。

示例:

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 如何以不同方式处理这两个示例?

真的 error/vulnerability 更少吗?

就性能而言,一种会比另一种更有效率吗?

注意:这不是关于设计偏好的问题。有多种包装或绑定参数的方式,使得任一示例都灵活高效。我只想知道字节码级别的区别是什么,以及在字节码级别是否明显更多 efficient/secure。

警惕架构安全和语言安全之间的区别。事实上,大多数计算机科学教授并没有意识到这一点。

如果你想"securely"传递一个对象,你可以在键盘上提示输入加密密钥;领取钥匙;加密对象;并通过它。然后接收函数可以重新提示并反转加密!这完全取决于您要实现的目标。

对象的生命周期是最关心的问题。一旦传递,参数值就位于堆栈中;如果我们假设一个观察者可以查看属于 JVM 的内存位置,那么我们就完蛋了。因此,一旦检索到该值,就就地用垃圾覆盖它。我们称之为 "object reuse" 考虑因素,尽管我们通常在将对象释放回系统时牢记这一点:我们不会隐含地假设某个人共享我们的地址 space 并不断地在这里偷看和戳那里。

从 API 设计的角度来看,传递 Rectangle(或 Shape)更好。它支持 coding to an interface, not an implementation. 从某种意义上说,指定角和尺寸是一种实现;不同的实现会指定对角。通过传递形状,您可以使代码更具适应性。

这里的主要问题是由于 Rectangle 的可变性。对此有效率争论,但我想知道 Shape 如果今天设计它是否会可变。对于许多应用程序,不可变数据类型提供了许多好处,更安全的数据共享就是其中之一。

由于您正在实施 MyCanvas,您可以确信 Rectangle 实例未被修改,因此 "secure." 但是,如果其他人正在编写调用者,并且MyCanvas 是一个他们不能完全信任的黑匣子,有两件事可以提供帮助。

首先,您可以记录接受形状的 MyCanvas 方法,指定不修改形状。在Java中,这个规范应该放在Javadoc comments on methods and classes. This is a common practice; unless you are writing a plugin system that might execute agents that are written by untrustworthy authors, programmers typically rely on this commitment, or contract,中的一个API.

其次,如果调用者没有那种保证,他们可以将"their" Rectangle 实例复制到一个临时副本,然后将副本传递给您。因为他们从不在方法 returns 之后读取 Rectangle 的状态,所以不管你对它做什么。因为 Rectangle 是可变的,所以这可以相当有效地完成。


从字节码的角度来看,传递 Rectangle 更快。为传递的每个参数执行单独的指令。更多参数,更多指令。此外,传递 Rectangle 允许调用者的实例被重新使用,而传递原始元素需要分配一个新的 Rectangle,这可能是不必要的。

我不知道你在说什么,"Passing four integers, in this case, reduces the variability. Theoretically speaking, the error surface area should be reduced along with the potential for vulnerabilities."

我知道在现实世界中,具有多个相同类型参数的方法,例如四个 int 参数,极度 容易出错。将它们命名为 qz 之类的废话会使问题变得更糟。利用强类型参数可以消除编译时的错误,从而使您的程序更安全。

一开始你有 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 class

的业务