静态方法对可扩展性有好处吗?

Posted

技术标签:

【中文标题】静态方法对可扩展性有好处吗?【英文标题】:Are static methods good for scalability? 【发布时间】:2010-11-20 01:27:50 【问题描述】:

静态方法和类是否有利于可伸缩性?我认为静态类/方法提高了应用程序的可扩展性,而实例方法的扩展性不大。那么在可能的情况下编写静态方法是一种好的编程习惯吗?

【问题讨论】:

是什么让您认为静态方法提高了可扩展性或实例方法不能很好地扩展? 任何无状态的东西都可以很好地扩展。因此,如果 util 类包含所有没有静态状态的静态方法,那么它的扩展性很好。我可能错了。喜欢被纠正。 我认为这个问题不应该被否决。当我第一次学习 OO/Java 时,我担心实例方法的内存使用,并记得在这个问题上进行了很多搜索 - OP 对我的回答的回应似乎是问题背后的类似问题。 (即使没有,这里还有其他关于静态与实例方法的好答案。) @Anon:我同意你的看法。 【参考方案1】:

静态方法和类好不好 可扩展性?

一个与另一个无关。

我认为是静态类/方法 提高应用程序的可扩展性 并且实例方法无法扩展 很多。

错了。你为什么这么认为?

那么这是一种好的编程习惯吗? 在任何地方编写静态方法 可能吗?

没有。事实上,这是一种非常糟糕的做法,因为它放弃了面向对象编程的可维护性优势。

【讨论】:

为什么静态方法放弃了面向对象编程的可维护性优势?? @zPesk:首先,它们显然不是面向对象的。 因为 OOP 的全部意义在于将逻辑与它所操作的数据封装起来以生成对象。实例字段是数据,实例方法是逻辑。这使您可以隐藏实现细节并在更高、更抽象的层次上考虑对象交互。静态方法和字段基本上是一种进行过程(非 OO)编程的方法。 他为什么错了?花时间解释你自己的观点。 OP 对 OOP 知之甚少,但为什么还要问呢?只需解释一下即可。 @RabbitBones22:如果 OP 没有给出相信“实例方法的扩展性不大”的原因,就不可能说为什么 OP 是错误的。这不是真的,没有什么可以解释的。【参考方案2】:

这取决于为什么该方法是静态的。如果它是静态的,因为它确实不需要上下文,那么与具有类似复杂性但因为需要上下文而不是静态的东西相比,它可能会很好地扩展。

但是,如果它是静态的仅仅是因为您无法保留所需的上下文并且仍然必须将其传入,或者因为具有更多静态方法的人为目标,那么我怀疑它实际上会比可比较的方法扩展更少作为非静态的。

事实上,我认为 ASP Classic 证明了这一点。

【讨论】:

@RBarry Young:这里我假设静态方法没有任何上下文,这是认为静态方法可以很好地扩展的唯一原因。 既没有,也没有需要上下文(这两件事之间有区别)。例如,一个 SIN() 既没有也不需要上下文,应该像任何东西一样扩展。另一方面,文件操作通常并且需要一个上下文(有问题的文件),在没有任何上下文的情况下实现它(通过使用文件句柄或通道号,如我们必须在 OO 之前这样做)不会以任何方式使它更好地扩展,并且很好地使其扩展更糟【参考方案3】:

使用静态方法需要考虑三个问题:

    如果您的静态方法具有较大的临界区,您可能会引入瓶颈。最大的当然是声明整个方法同步了。如果它一次只能执行一个,那么这是一个潜在的问题; 如果您在不同的虚拟机和不同的机器上运行相同的方法,它所做的一切是否仍然一致?和 任何依赖静态方法的方法都存在单元测试问题。

这通常不是最佳实践,但静态辅助方法很常见。太复杂了,应该考虑另一种方法。

【讨论】:

我之前没听过#3。你能详细说明一下吗? -- thnx 虽然一个独立的、自包含的静态方法很容易进行单元测试,但任何使用的方法都无法与之分离。如果你有一个静态方法相互调用 5 个(或 10 个或更多......)级别,那么你实际上根本无法隔离(并因此隔离测试)应用程序逻辑的部分。【参考方案4】:

没有静态方法本质上不能更好地扩展。事实上,编程风格(命令式或面向对象)并没有真正对缩放产生任何影响。扩展有两个主要方面,如何提高规模取决于我们的意思:

1 按每秒处理的请求数缩放

这种类型的扩展通常是关于向集群添加更多计算机以提高系统的整体吞吐量。增加扩展通常是指最初通过使用缓存来减少共享资源的使用量,然后再将数据访问拆分为分片。

2 数据缩放

这是当系统随着时间的推移获得越来越多的数据并且访问数据的操作(搜索、过滤等)变得更慢时,因为算法比 O(1) 更复杂。这种情况下正常的策略是增加读写点的数量,使用Map/Reduce等并行算法。

但是这些方面都与您是否使用静态方法无关,只是多个请求是处理大型数据集还是单一数据源。

【讨论】:

【参考方案5】:

没有。我想你可能会假设每个实例都有自己的方法定义副本,为每个实例占用了这么多空间,但事实并非如此。

编辑添加:

如果您想知道如何在实例之间实际共享实例方法:这是因为对实例方法的每次调用都会隐式地将对该实例对象的引用传递给该方法。这通常被称为“隐式 this” 换句话说——当你定义或调用一个带有 myMethod(a, b) 之类的两个参数的实例方法时,你可以认为它实际上是 myMethod(this, a, b) ,而 Java 会为您处理 this 参数,而无需您显式定义或传递它。

(顺便说一下,这在 Python 中的处理方式有所不同,您必须将对象引用显式放入实例方法定义的第一个参数中,尽管不在调用中。)

有关 Java 字节码级别发生的事情的说明,请点击以下链接: http://www.artima.com/underthehood/invocationP.html (见周围的东西:“objectref 是传递给任何实例方法的隐式 this 指针。”)

【讨论】:

@Anon:你认为是对的。我认为非静态对象需要为与实例关联的每个属性分配内存。我可能错了。但只是想知道其他人对此的看法。 您的想法对于实例变量是正确的,但是对于要为每个实例复制的每个实例都相同的实例方法,这是没有意义的。您所需要的只是指向同一方法的指针。例如,请参阅此链接中的讨论:developer.com/java/other/article.php/1025601 (每个实例都知道它的类,并且可以通过这种方式访问​​共享方法 - 所以我的“你所需要的只是一个指针”可能会产生误导。但请参阅链接以获取有关实例方法的引用正在共享。)【参考方案6】:

您指的是哪种形式的可扩展性?可伸缩性,即代码在大小项目中可维护和可扩展?然后只使用静态方法会受到伤害。你是说性能吗?如果实例方法较慢(我不相信这种普遍性),那么这并不意味着它们不能扩展。如果它们需要两倍于静态方法的时间,那么如果您将它们全部调用 10000 次,它们也需要两倍的时间。选择正确的算法和数据表示在很大程度上决定了性能的可扩展性。

最后,如果您认为静态方法是可行的方法,那么您不应该使用像 Java 这样的面向对象语言。试试 C 或 Pascal 或经典的基本方言。

【讨论】:

【参考方案7】:

我认为你找错树了:

在现实世界中,可扩展性(或缺乏可扩展性)通常源于算法的适当性和对数据存储进行的操作的效率(想想:良好的 SQL 查询)。

诸如方法是否为静态(或静态方法的百分比)之类的事情通常与系统的可伸缩性无关。您当然可以拥有一个不使用静态方法的超级可扩展系统,或者专门使用它们的超级可扩展系统。

【讨论】:

【参考方案8】:

投了反对票。 OP显然不太了解OO。创建实例对象时,实例方法不会占用任何额外空间。除非您还避免创建任何实例,否则静态方法不会为您节省任何东西,在这种情况下,您与构建 OO 语言的目标相去甚远,这是毫无意义的讨论。

【讨论】:

“OP 显然不太了解 OO” ...这可能就是他问这个问题的原因 @Chris Kessel:实例方法不占用任何额外空间,但实例变量占用每个实例的空间。 *** 似乎不是理解基本 OO 的正确位置。有大量学习 OO 的网站和书籍。如果 OP 认为他需要对所有事情都使用静态(全局),那么他显然需要先停下来学习 OO。我明白他为什么问这个问题。我投了反对票,因为 *** 似乎不是学习他需要学习的内容的错误场所。

以上是关于静态方法对可扩展性有好处吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java反射

静态代理与动态代理模式

静态代理动态代理和cglib代理

CPU支持SSE3有啥作用?对游戏有好处吗?

可以用动态部分扩展静态 SQL 语句吗?

你真的了解扩展方法吗?