为什么通过静态方法传递对象会有好处?


9

为什么使用静态方法并将引用作为参数传递给对象而不是在对象上调用该方法会有好处?

为了阐明我的意思,请考虑以下课程:

public class SomeClass {
    private double someValue;

    public SomeClass() {
        // Some constructor in which someValue is set
    }

    public void incrementValue() {
        someValue++;
    }
}

与使用静态方法的此替代实现相比:

public class SomeClass {
    private double someValue;

    public SomeClass() {
        // Some constructor in which someValue is set
    }

    public static void incrementValue(SomeClass obj) {
        obj.someValue++;
    }
}

我的问题不仅限于此类。我感兴趣的是在什么地方传递对象而不是在方法上调用它。这是否有优势?如果是这样,为什么?


1
感觉像是代码气味,用两种方法做完全相同的事情。如果将静态方法简单地委派给另一种方法,则它会觉得无用,但不一定是“坏的”
Nathan Merrill

13
@NathanMerrill我认为您错过了重点。他问是否有可能创建和使用第二种方法而不是第一种方法更合适。

@Mego不仅示例中给出的方法;我问是否有任何时候使用静态方法和传递对象比在对象上调用方法更好?
Addison Crump

想必您是专门要求Java吗?
enderland

3
我认为这个问题是默认的,即面向对象的代码是最佳的。更具程序性或功能性的方法自然会导致使用静态方法。...但是,在静态方法和实例方法之间复制功能非常愚蠢。我希望这只是一个例子,您所讨论的实际代码只有静态的。
jpmc26,2013年

Answers:


34

一个简单的示例:当传递的实例可以合法为null时,您要将对此的(非平凡的)处理合并到方法中。


1
示例:C#中的String.Compare(我认为Java中有类似的东西)
edc65

Objects.equals()和Objects.compare()是Java中的示例-但它们不在原始类中。至少在Java标准库中,通常在Object之类的对象上有一个实例方法,而在Object 类上有一个静态方法。
daboross 16-3-12

20

在您的示例中,实例方法无疑是赢家。

在一般情况下,我可以想到一些适合使用静态方法的原因:

  • 您希望将静态方法放在另一个类中,因为您有一种情况需要将逻辑与数据分开(请注意:您的示例不是其中之一)。

  • 您正在传递两个或多个对象,并想强调它们是同等重要的。

  • null 是有效值(如用户9000所述)。


5

将改变对象状态的方法包括为实例方法而不是静态方法是明智的。

但是,我们可以找到静态方法的示例,这些方法是pure将对象作为输入的方法,例如,当我们需要基于某些验证规则实例化对象时。例如,.NET具有DateTime.TryParse(String s, DateTime d)验证和实例化对象的方法。但是该参数DateTime d已明确标记为out

另一种情况是当我们比较对象并希望获得所需的对象作为返回值,而不是比较结果的布尔/整数值时,例如Team.GetHigherScorer(teamA, teamB).IncreaseRanking()。这将比:

int compareResult = teamA.compareScoreWith(teamB);
if (compareResult == 1)
    teamA.IncreaseRanking();
else if (compareResult == -1) 
    teamB.IncreaseRanking();

(为简单起见,省略了案例)。


1
一个不会传递“整个对象”。您将引用传递到内存中的某个位置,这是正在传递的少量数据。我不确定这会对性能产生影响,但是......此外,“ out”标记意味着什么?
Addison Crump'3

1
我从声明中删除了“整个”一词,这很令人困惑。我从没打算过性能或规模,答案纯粹是基于编程实践。无论如何,out.Net用作参数修饰符的关键字。它指出参数是通过引用传递的。有关详细信息,请参见msdn.microsoft.com/en-us/library/t3c3bfhx.aspx
wonderbell

4
第一句话是完全错误的。如果我们有,class C { int x; static void M() { 那么M完全可以访问x。例如int y = (new C()).x;是合法的。
埃里克·利珀特

@EricLippert :)我确定你知道我的意思。大师如何在字里行间阅读,真是太神奇了。可能是我需要编辑该句子。为了澄清,这样的事情 static void M() { this.x = 1; }是不可能的。
wonderbell

1
@wonderbell:不,我确定我不知道你的意思。我知道你写了什么 我注意到这this.x是错误的,不是因为x无法访问而是因为this不存在。这根本不是访问的问题,而是存在的问题。
埃里克·利珀特

4

依赖注入将是执行对静态方法的调用的一个很好的理由。假设的具体实现SomeClass具有一个继承链或是另一个类的实现。您可以使用对象的模拟,将其传递以用于测试目的,以确保您的方法达到了预期的效果,然后报告该状态。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.