假设我们想制作一个你必须收集宝石的游戏。所以我们需要一个Gem类,一个GemSpawner类,当然还有MainActivity类。
public class MainActivity {
public static void main(String[] args) {
List<Gem> gems = new ArrayList<Gem>();
GemSpawner gs = new GemSpawner(gems);
//...
}
}
在这种情况下,我们使用gems创建了一个List,并通过它的构造函数将其传递给GemSpawner,因此gs可以使用以下命令将gems添加到列表中:
gems.add(new Gem(10, 50, "red")); //should represent Xpos, Ypos, and color.
但这不会更好:
public class MainActivity {
public static List<Gem> gems = new ArrayList<Gem>();
public static void main(String[] args) {
GemSpawner gs = new GemSpawner();
//...
}
}
现在,GemSpawner(gs)可以使用:
添加宝石MainActivity.gems.add(new Gem(10, 50, "red"));
朋友只向我展示并解释了上述方法,但下面的方法不是更有效吗?
答案 0 :(得分:7)
效率论证并不含水。它是一个单一的引用,所以32位(如果你在64位机器上,64位)在开始时被解析一次,所以它没有任何(可测量的)性能影响。
但是,如果使用大量静态函数,代码的设计可能会变得混乱。例如,通过使其静态,没有简单的方法来跟踪什么是添加到您的列表的东西(可能是一个晚上测试你随机添加宝石然后忘记的东西。几个月后,你无法解决为什么这个宝石一直出现!)
看起来很傻但通过限制对事物的访问可以真正帮助调试。如果你知道唯一可以添加gem的东西是GemSpawner
,那么你就可以将基于宝石的潜在错误隔离到一个类。如果它可能来自任何地方,那么调试会变得更加困难,特别是当您的项目变得复杂时。
答案 1 :(得分:5)
静态数据成员在您的程序中引入了我们称之为全局状态的内容。一般来说,全球国家被认为是坏的,原因有几个:
另一方面,如果您将所需的状态作为参数传递给每个方法,那么您将创建一个安全网,自动使上述所有内容更不可能发生并威胁程序的正确性。
我怀疑在选择全球国家而不是通过国家方面有显着的绩效优势(或任何好处)。如果你最终遇到过度的全局状态验证,或者更糟糕的是,引入锁定和障碍(两种情况都非常昂贵),你将取消你可能获得的任何好处。
坚持不引入全球国家的良好做法更值得。
答案 2 :(得分:4)
public static
变量本质上是一个全局变量。
在有经验的程序员中,全局变量被认为是非常差的编程风格。
Here is an article which describes some reasons why they are bad
面向对象的解决方案是将您的gems列表封装为GemManager类中的私有集合,该类通过方法公开对gem的任何访问。然后,您将创建一个GemManager实例,并将该实例传递给需要它的每个类或方法。
答案 3 :(得分:3)
这是一个比你可能意识到的要复杂得多的问题。
许多开始使用Java编写的人开始完全创建所有内容static
,因为您不必传递引用 - 这会使您的代码“更简单”。
但是当您的代码变得更复杂时,您就开始遇到问题。这些问题出现了3条主线:
这是Object
不应该允许直接访问其成员的想法,应该告诉它“做事”,然后它会在内部完成,而不会暴露如何完成。
这背后的想法是你试图避免过于紧密地将你的类彼此耦合。
这引导我们进入下一点
在Java中,这通过abstract
类和interfaces
表示。
这个想法是你的GemSpawner
只是产生宝石的定义。内部如何做到这一点真的不是一个人的事,而是它自己的事。
在Java中,你无法真正地将static
方法与关键的OO继承理念进行协调。
static
方法是继承的,但是它们被遮蔽而不是被覆盖,因此您不能(轻松)修改它们的行为。
这导致我们进入
<强>测试强>
随着程序变得越来越复杂,这个主题越来越多。
您如何测试“Hello World”计划?好吧,你运行它,看它是否打印“Hello Wrld” - 在这种情况下有一个错误。
一旦程序变得更复杂,你就不能简单地做到这一点。你需要分开你的程序并测试“单位”。被称为Unit Testing。
此处您的static
引用确实会引发问题。您无法将程序分离为离散单元,因为所有内容都通过直接类引用绑定在一起。而且你不能模仿static
方法的行为,因为它们不容易被覆盖。
所以,总结一下。是;将static
放在任何地方并且不传递引用可能会更快更容易。 但是,如果你打算写一些像游戏一样复杂的东西,你应该考虑使用Java来充分发挥它的潜力。
答案 4 :(得分:0)