|
|
1
50
为了回答标题上的问题,一般来说,Java方法应该 不 不过,你说的有点不同。你特别提到助手方法。 如果是 辅助方法 只需将值作为参数并返回值,而不访问状态,它们
完全明确的 在代码中 该方法不需要知道任何实例状态 .
如果确保该方法不依赖于外部或全局状态,则它是一个 纯函数 ,即 数学意义 三。优化优势如果方法是静态的并且是纯函数,那么在某些情况下它可能是静态的 memoized 4字节码级别差异
为了使本节更容易理解,让我们使用一个示例:
没有静态方法
在第一种情况下,如果没有静态方法,当您调用helper方法时,JVM需要将引用推送到实例以将其传递给
0(或1)处的指令,
现在,如果声明helper方法static,那么
区别在于:
helper函数的代码也有点不同:没有
从代码设计的角度来看,将helper方法声明为static更有意义:代码本身就说明了问题,它包含了更多有用的信息。它声明它不需要实例状态来工作。 在字节码级别,发生了什么更清楚,没有无用的代码(尽管我相信JIT没有办法对其进行优化,但不会产生显著的性能代价)。 |
|
|
2
16
如果一个方法不使用实例数据,那么它应该是静态的。如果函数是公共的,这将大大提高效率,您不需要创建多余的对象实例来调用函数。可能更重要的是自文档的优点:通过声明函数static,您可以电报告诉读者该函数不使用实例数据。 我不理解这里许多海报的观点,即在Java程序中使用静态函数有问题。如果函数在逻辑上是静态的,则使其成为静态的。Java库有许多静态函数。数学课几乎充满了静态函数。 如果我需要一个计算平方根的函数,合理的方法是:
当然,你可以做一个“更糟糕”的版本,看起来像这样:
但是除了尽可能满足使用OOP的抽象目标之外,这还有什么更好的呢?它需要更多的代码行,灵活性较差。 (是的,我现在在标准的数学课上有一个平方根函数。我只是用这个作为一个方便的例子。)
如果一个静态函数在逻辑上与一个类相关联,但是可以合理地从外部调用,那么就将其设为公共静态函数。比如,Java的parseInt函数是在Integer类中,因为它必须处理整数,所以这是一个合理的位置。 另一方面,在编写一个类时,您经常会意识到需要一些静态函数,但函数并没有真正绑定到这个类。这只是您第一次碰巧意识到您需要它,但是它可能会被其他与您现在所做的事情无关的类合理地使用。比如,回到平方根的例子,如果你有一个包含经纬度的“Place”类,你想要一个函数来计算两个地方之间的距离,你需要一个平方根作为计算的一部分(并且假装标准库中没有平方根函数),创建一个单独的平方根函数,而不是将其嵌入到更大的逻辑中,这是非常有意义的。但它不属于你的班级。这将是为“数学实用程序”或类似的东西创建一个单独类的时候。
我能想到的使它不是静态的唯一原因是如果子类想要重写它。 我想不出其他原因,但我不排除这种可能性。我不愿意说“在任何情况下都不可能”,因为通常有人会提出一些特殊情况。 |
|
|
3
9
有趣的问题。实际上,我不认为上课有什么意义
我不认为这是 最终会有大量的内部静态方法,但我也不知道从中得到什么好处。我说默认为非静态,除非你有充分的理由不这样做。 |
|
|
4
9
不,从来没有。静态方法应该是一个例外。OO就是让对象具有围绕对象状态的行为。理想情况下,不应该有任何(或很少)静态方法,因为所有与对象状态无关的东西都可以(并且为了避免引入对象的概念,应该)放在模块级的普通旧函数中。工厂可能例外,因为Complex.fromcortesian(以维基百科为例)读起来非常好。
|
|
5
6
我通常 根据需要依次执行以下步骤: a) 我在一个成员方法中编写了一些代码,发现我可能可以重用其中的一些代码 提取到非静态方法 b) 现在我来看看这个方法是否需要访问state,或者我是否可以将它的需要放入一个或两个参数和一个return语句中。如果是后者:
c) 如果我发现我可以在同一个包的其他类中使用这段代码,我将 使方法公开并将方法移动到具有默认可见性的包帮助器类
d) 如果我意识到我的应用程序需要这个功能,我 将helper类移到专用的实用程序包中
一般来说,我喜欢最小可能能见度的概念。那些不需要我的方法的人不应该看到它。这就是为什么我从私有访问开始,转到包访问,并且只在它们位于专用包中时才将其公开。 |
|
|
6
6
反静态的纯粹主义者可能希望将它们移除到一个实用类中,而反实用的纯粹主义者肯定反对这个类。但实际上,人为地将这些方法从它们唯一的调用位置移开,除了与新的实用程序类紧密耦合之外,还能实现什么呢。
|
|
|
7
5
我一般不会让它们静止,但可能应该。告诉下一个编码者这个方法不能修改你的对象的状态是很有价值的,当你修改这个方法来访问一个成员你正在改变这个方法的性质时给你一个警告也是很有价值的。 编码就是与下一个编码者通信——不用担心让代码运行,这很简单。所以,为了最大限度地进行交流,我想说,如果你真的需要这样一个助手,让它静态是一个好主意。保密也很重要,除非你在做数学题。就像上课一样。 |
|
|
8
5
Java将module、namespace、adt和class的概念混为一谈,声称某些面向类的OO纯度会阻止您将Java类用作模块、namespace或adt是荒谬的。 是的,方法应该是静态的。纯粹的内部支持方法应该是私有的;助手方法受保护;效用函数应该是公共的。此外,静态字段、静态常量和公共静态方法之间存在着巨大的差异。第一个只是“全局变量”的另一个词;而且几乎总是要避免的,即使访问器方法的中介也几乎不能限制损害。第二种方法是将java类视为符号常量的命名空间,完全可以接受。第三种方法是将java类视为函数的一个模块,作为一般规则,应该避免副作用,或者在必要时将副作用限制为传递给函数的任何参数。使用static将有助于确保您不会无意中通过访问对象的成员而破坏它。 另一种情况是,在用java编写函数代码时,静态方法非常有用。在这一点上,大多数由OO支持者开发的经验法则都已经过时了。您将发现自己的类中充满了静态方法,公共静态函数常量绑定到匿名内部函子。
|
|
|
9
5
我发现很难接受那些避免静态方法的理论。它们是为了促进一个完全卫生的面向对象模型,以防从对象关系中清除任何偏差。我看不出在实践对象导向中有任何反腐败的必要性。 无论如何,所有java.util.Arrays类都是静态的。数值类Integer、Boolean、String有静态方法。很多静态方法。这些类中的所有静态方法要么转换为它们各自的类实例,要么转换为它们各自的类实例。 由于GoodOldGosling等人被证明是拥有静态方法的非常有用的榜样,因此没有必要回避它们。我意识到有些人对我的回答感到困惑,他们投票否决了我的回答。许多程序员喜欢将尽可能多的成员转换为静态的,这是有原因和习惯的。
为什么方法是静态的,应该有一个一致的理由。当方法是静态的时,遵循标准的Java库模式是没有坏处的。 最重要的是编程效率和质量。在一个适应性和敏捷的开发环境中,不仅要调整项目的粒度以有效地响应需求的变化,还要调整编程环境,比如提供一个一致的编码模型以充分利用您拥有的编程技能集。在一天结束时(一个项目几乎永远不会结束),您希望团队成员高效高效,而不是不管他们是否避免静态方法。 因此,设计一个编程模型,不管你想要MVP、注入、方面驱动、静态避免/亲和力级别等等,并且知道你为什么想要它们——不是因为一些理论上的疯子告诉你你的编程实践会违反oo原则。请记住,如果你在一个行业工作,它总是质量和盈利能力,而不是理论纯度。
出于同样的原因,OS/2未能与微软竞争,因为IBM的正交性概念纯粹是基于机器和数据的,IBM非常自豪地宣称他们真正的面向对象性,而微软则是迎合人类视角的错误的面向对象性。他们忘记了我们人类有各自不同的信息正交视角,它们不符合数据和基于机器的正交性,甚至不符合彼此。 如果您熟悉树的拓扑结构,您会意识到您可以选择任何叶节点并使其成为根节点。或者任何节点,如果你不介意有一个多主干树的话。每个人都认为他/她的节点是根,而事实上任何节点都可能是根。如果你认为你的面向对象的观点是正典,再想想。更重要的是尽量减少被接受为候选根的节点数。 效率和效率之间需要折衷。拥有一个很难被其他程序员有效使用的高效数据或对象模型是没有意义的。 |
|
|
10
4
如果它不处理这个类的对象,但实际上属于这个类(我会考虑将它移到其他地方),那么它应该是静态的。 |
|
|
11
3
如果可以避免,就不要使用静电。它与继承冲突(重写)。 另外,不要问,但稍微相关,不要公开实用方法。 至于其余的,我同意马特b。如果你有一堆潜在的静态方法,这些方法不使用state,就把它们放在一个私有类中,或者可能是protected或package protected类中。 |
|
|
12
3
这取决于java.lang.Math没有非静态的方法。 (您可以执行静态导入来编写cos(),而不是Math.cos()) 这不应该被过度使用,但是作为一些打算作为实用程序调用的代码,它是可以接受的。I.g Thread.currentThread() |
|
|
13
3
静态方法用于标识与从该类创建的对象无关但与该类本身有关的方法(或变量)。例如,您需要一个变量来计算创建的对象数。您可以放置类似这样的内容:“private static int instances=0;”然后在该类的构造函数中放入一些递增“instances”的内容,这样您就可以计算它了。 |
|
|
14
1
在创建静态方法之前一定要仔细考虑,但有时它们是一个好的解决方案。 joshuabloch在中的“第1项:考虑静态工厂方法而不是构造函数” Effective Java 这是一个非常有说服力的案例,说明静态方法是非常有益的。他以java.util.Collections类的32个静态工厂方法为例。
在一个例子中,我有一个POJO类的层次结构,这些类的实例可以自动序列化为XML和JSON,然后反序列化为对象。我有使用Java泛型进行反序列化的静态方法:
其他几个例子:
但不要不假思索地使用静态,否则会有陷入更无序、更程序化编程风格的危险。 |
|
|
15
1
|
|
|
16
0
如果它只由A中的方法使用,并且在它之外没有任何用途,那么它应该是静态的(并且,可能,被放置在Helper类中)。除了现在,它没有任何用处,但也不能保证它永远不会有用处。否则,就不应该了。 如果它与A的状态无关,它可能在其他地方有用。。。
谈到最后一个问题,默认情况下它们不应该是静态的,因为必须编写“static”会让人们在编写静态方法之前进行思考。当您拥有异构团队(Java最有用的团队)时,这是一个很好的实践。 |
|
|
17
0
如果foo是私有的,它可以是任何东西,静态的或非静态的。但是,大多数时候都是这样 因为这些字少了一个字。然后,如果因为更改了代码而需要使用state,可以立即使用。 当它被保护或公开时,这取决于它做了什么。经验法则是 不是静态的 当它不是实例行为的一部分时,并使其 静止的 当它没有任何对象的时候。 |
|
|
18
0
|
|
|
19
0
当你写一个静态方法的时候,你应该记住你将在使用站点使用它和静态导入(使它看起来像类自由的),因此它应该像一个函数,它不做什么,可能返回什么,也可能不返回什么,并且与它所属的类的状态隔离。所以静态方法应该是一种罕见的情况。 如果您似乎正在创建许多helper方法,那么可以考虑使用包私有实例方法而不是私有实例方法。更少的输入,更少的样板文件,因为您可以将它们作为同一个包中其他类的助手重用。 |
|
|
20
0
我认为“私有静态”(edit:for methods)在Java中有点矛盾。我认为静态方法的要点是提供对对象实例上下文之外的函数的访问。换句话说,它们实际上只有在公开的情况下才有用。如果您只是从单个对象实例的上下文中调用一个方法,并且该方法是私有的,那么将其设置为静态是没有意义的(编辑:但是,这没有实际意义)。
|
|
|
21
0
大多数静态方法都是因为
第一个本身并不坏,但它往往是你丢失物品的一个迹象。不要使用诸如String或List之类的默认类型,而是尝试创建自己的类,并将静态方法移到这些类中。 第二个原因是产生了一直流行的StringUtil、DateUtil和FooUtil类。这些方法是有问题的,因为您无法发现它们的存在,所以程序员经常编写这些实用方法的副本。同样,解决方法是避免一直使用字符串和日期。开始创建自己的对象,也许可以通过包装原始对象。静态方法成为新对象的非静态方法。 |
|
|
22
-1
如果
|
|
|
23
-1
很多有趣的答案。
如果代码仅由单个类的实例方法使用,则将其作为实例方法—它只是从实例上下文中提取代码—可以重构回(或从)访问实例状态的方法。
故事结束了。 |
|
|
simply lemon · python上链表的添加方法 2 年前 |
|
|
Anonymous · 为什么在这个例子中self和类名的用法不同? 2 年前 |
|
|
P N Singh · 在CPP Oops中调用对象而不创建它 2 年前 |
|
|
Muthuraj · 如何创建一个通用工厂来创建某种类型的实例[重复] 2 年前 |
|
|
Andy Votava · 从父类定义调用学生方法 2 年前 |