【问题标题】:Usage of Instance Variable within the class for Java/C#Java/C# 类中实例变量的使用
【发布时间】:2012-08-25 10:45:07
【问题描述】:

假设两种不同的方法——一种是静态的,一种是非静态的——需要一个实例变量。

该变量在方法中被使用了 3-5 次以进行比较。

变量不会以任何方式改变。

变量的类型(字符串、集合、集合等)也会对其编码方式产生任何影响。

在私有方法(静态和非静态)中使用实例变量的最佳/正确方法是什么?

  1. 作为方法参数传递
  2. 本地存储,使用获取值的方法——this.getClaimPropertyVertices();
  3. 通过获取值本地存储 - this.claimPropertyVertices;
  4. 直接在方法中使用实例变量

当创建一个局部变量来存储值时,如果变量不会被改变,“final”关键字将提供任何优势。

编辑 1:根据评论,我正在添加其他信息 该值不能在方法中本地创建。它必须来自类或类访问的其他方法。

我基于答案的解决方案:
基于@EricJ 的回答。和@Jodrell。我选择了选项 1,并将其创建为私有静态方法。我还找到了一些细节here 来支持这一点。

【问题讨论】:

  • 静态方法不能访问实例字段,句号。
  • 这真的取决于使用变量的方法的上下文。传入值是否有意义,或者可以在本地创建?在不了解这些方法的上下文的情况下,很难回答这些问题。另外...这闻起来像早期的微优化...eeeeeviiiiillllll。而且静态方法只能访问静态变量。
  • @MattBall 谢谢。我从来没有这样做过,但想把它说出来,以便我可以学习/理解是否会有差异
  • @JasonDown 无法在本地创建值。我的目标不是优化,而只是尝试了解在这种情况下是否存在最佳/标准实践。
  • 答案是 1。静态方法不能访问实例成员,除非它们通过引用传递,这表明代码有异味。选项 1 将允许您稍后使用多线程(痛苦更少)并提供与生俱来的关注点。

标签: c# java methods instance-variables


【解决方案1】:

如果您尽可能使用 static 关键字编写函数,则有几个明显的好处。

  1. 很明显,哪些输入会影响签名中的功能。

  2. 您知道该函数不会有副作用(除非您通过引用传递)。这忽略了非功能性副作用,例如对 GUI 的更改。

  3. 该函数在程序上与类没有关联,如果您从逻辑上确定它的行为与另一个实体有更好的关联,您可以移动它。然后调整任何命名空间引用。

这些好处使函数易于理解并且更易于重用。它们还将使在多线程上下文中使用该函数变得更简单,您不必担心对不断传播的副作用的争用。


我会放弃这个答案。您应该使用 static 关键字编写潜在的可重用函数。简单或明显不可恢复的功能应该只访问私有成员或 getter(如果已实现)。

【讨论】:

    【解决方案2】:

    当创建一个局部变量来存储值时,“final”关键字将提供任何优势,如果变量不会被改变

    在 Java 中,final 为编译器提供了优化机会。它声明变量的内容不会改变。关键字 readonly 在 C# 中提供了类似的作用。

    额外的优化机会是否有意义取决于具体问题。在许多情况下,算法其他部分的成本将远远大于编译器由于 finalreadonly 而能够进行的优化。

    使用这些关键字还有另一个好处。他们创建了一个价值不会改变的合约,这有助于代码的未来维护者理解他们不应该改变价值(事实上,编译器不会让他们改变)。

    在私有方法(静态和非静态)中使用实例变量的最佳/正确方法是什么?

    作为方法参数传递

    该值已存储在实例中。为什么要通过?最好的情况是这并不比使用实例属性/字段更好。最坏的情况是 JITer 没有内联调用,并且会创建一个更大的堆栈帧,花费几个 CPU 周期。注意:如果你调用的是 static 方法,那么你必须传递变量,因为静态方法不能访问对象实例。

    本地存储,使用获取值的方法——this.getClaimPropertyVertices();

    这就是我通常所做的。 Getter/setter 用于为字段提供有意义的包装。在某些情况下,getter 将初始化支持字段(在 C# 中使用不调用对象构造函数的序列化程序时的常见模式。不要让我开始讨论该主题......)。

    通过获取值本地存储 - this.claimPropertyVertices;

    不,见上文。

    直接在方法中使用实例变量

    和上面的完全一样。使用 this 或不使用 this 应该生成完全相同的代码。

    更新(基于您的编辑)

    如果值在对象实例外部,并且不应与实例一起有意义地存储,则将其作为值传递给方法调用。

    【讨论】:

    • 不变性很好。它可以被反射覆盖,但你会得到你应得的。
    • @Jodrell: 同意......并且通过扩展,函数式编程 = 好 :)
    • @Jodrell:是的。 private 之类的访问器也可以被覆盖。反射绝对是邪恶的,除非你需要它,在这种情况下它是天赐之物...... :-)
    • @JasonDown,我很高兴多年前我在大学的第一个编程模块是一种名为 Meta 的抽象函数语言,而不是 Quick Basic 之类的语言。
    猜你喜欢
    • 1970-01-01
    • 2020-05-09
    • 1970-01-01
    • 2012-07-23
    • 2011-05-07
    • 2019-02-01
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多