说你写方法 foo() 中类 a。富不访问任何的状态。你知道什么什么富不,或它的行为方式有关。它可以做任何事情。
应富始终是静态的不管的任何其它考虑因素吗?为什么不呢?
看来我类总是在我打破任务以及一只写-它-次原则适用于累积很多的私人的帮助器方法。其中的大部分不依赖于该对象的状态,但永远不会有用以外的类的方法。他们应该静态默认情况下呢?不对最终有大量的内部的静态方法呢?
因为写入最静态方法
第一是不坏本身,但通常是你缺少的对象的一个标志。而不是使用默认的类型如字符串或列表,请尝试创建您自己的类和移动到这些类的静态方法。
第二个原因产生,总是受欢迎的 StringUtil DateUtil,FooUtil 类。这些都是有问题的因为你有没有发现他们的存在,所以程序员经常写这些实用程序方法中的重复项的方法。在解决办法也避免使用字符串和日期,所有的时间。开始创建您自己的对象可能由环绕原始对象。静态方法成为新对象的非静态方法。
很多有趣的答案。
如果你迫切地寻求一条规则,然后使用该命令:
如果只有一个类的实例方法的使用的代码,则然后又使其实例方法 — — 它是只是一种提取出实例上下文-可访问实例状态的重构的后到 (或转出) 方法的代码。
如果代码使用的详细丹一类,包含不能访问该方法所驻留的类中的实例变量为然后进行静态。
故事的结尾。
我认为"私有静态"(编辑: 方法) 是种在 Java 中的一个矛盾。在我心中的静态方法的重点是提供对对象实例的上下文以外的功能的访问。在其它说他们实际上只当他们是公共的以往任何时候都有用。如果您只调用从一个的单个对象实例的上下文中的一种方法,并且该方法是私人没有意义,使它静态。(编辑: 但没有实际的区别)。
在这个情况下我通常尝试使该方法不够抽象它们在其他情况下很有用,公开他们的一个实用程序类。看着它作为编写支持库代码和认真思考您的 api。
当您编写一个静态方法你应该牢记在心,反响在静态导入使用网站会使用它 (使其看起来类免费),因此它应该表现得像一个函数的东西不会和可能或不可能返回的东西,是它所属的类的状态与隔离。静态方法应该是一个罕见的情况。
如果似乎赚了很多的帮助器方法然后请考虑使用包私营实例方法,而不私人的。少键入较少的样板,因为您可以重新使用它们作为一个帮助者相同的包中的其他类。
如果是专用的 foo 它可能是任何静态或不。但大部分的时间是 不静态,这些是较少的一个单词键入。然后要使用状态,因为您已经更改了您的代码可以马上做。
当受保护或公众,它取决于它做什么。一个经验法则是行为的使它 不静态 时不是行为的该实例的一部分,使它 静态 时,它调用不带任何对象有意义。如果您无法确定,问自己如果很有意义,子类中的方法重写。
如果它是只过方法中使用的并不会有任何外面的使用它应该是静态 (然后,可能,放在一个帮助器类。它不具有任何一个的现在以外的使用,但不能保证它将永远不会有。否则,它不应该。
如果它没有什么事要做 A 的状态,则可能是有用在其它地方 … …
不管怎么说,这不会使 Java 方法是静态的默认情况下,一个好的理由。
浅谈这最后一个问题,他们不应该是静态默认情况下,因为不必编写 '静' 令人觉得前写的静态方法。当您有异构团队 (如 Java 是最有用的链接) 时,这是一个好的做法。
不,静力学的使用应该是很小。
在这种情况下,操作是在传递到静态方法的参数中的可能隐藏状态。造成这个问题的方法,使这不明显 (foo() 有没有输入或输出),但我认为在现实世界的示例中,实际上都应该为对象的状态的一部分的事情很快会掉。
在一天结束时,每次调用 obj.method(param) 将解析为 method(obj, param),但这不是我们应该在设计一个方式较低级别进行下去。
在创建一个静态的方法之前想硬但很的多次,当他们是一个很好的解决方案。
约书亚布洛赫的"项目 1: 考虑静态工厂方法而不建设者"的有效 使一例很有说服力的静态方法可以是非常有利。他给了 java.util.Collections 类的 32 静态工厂方法为例。
我谨此陈一案有 POJO 类的实例可以自动序列化到 XML 和 JSON,然后反序列化到对象的层次结构。我要做 deserialization 使用 Java 泛型的静态方法: fromXML(String xml) 和 fromJSON(String json)。POJO 他们返回的类型不已知先验,但由 XML 或 JSON 文本。(我最初打包成一个的帮助器类的这些方法,但它是将这些静态方法移动到根 POJO 类语义上清洁)。
几个其他示例:
this-到其参数列表中的等效 !但不要使用静态 unthinkingly,或者您运行落入杂乱无章更多和更多程序的编程风格的危险。
如果您可以避免它,不要使用静态。它的冲突与继承 (重写)。
此外,不问,但稍有相关不要公开的实用方法。
至于,其余部分我同意马特 b。如果您有的可能静态负载不使用状态的方法只是将它们放在一个私人的类可能保护或包受保护的类。
静态方法用来标识方法 (或那件事的变量),则不必跟从这类,但类本身创建的对象。为例,您需要一个变量来创建的对象的计数。你把类似: '专用的静态 int 实例 = 0 ;' 然后将东西放入该递增实例,因而您可以保持它的计数的类的构造函数。
Java conflates 模块、 命名空间、 adt,如要声称一些面向类的面向对象纯度应防止您使用 java 类作为一个的模块名称空间,或 adt 是荒谬的类的概念。
是的方法应是静态的。纯粹的内部支持方法应是私有的 ;帮助器方法保护 ;和实用程序函数应该是公共的。此外,有一个静态字段、 一个静态的常量和静态的公共方法之间的差异的世界。第一个是全局变量' ; 只是另一个词几乎总是勉强甚至调解的访问器方法,避免限制的损害。第二个 java 类视为一个完全可以接受的符号常量的命名空间。第三治疗 java 类作为一个的功能模块的一般规则副作用应避免,或如有必要,局限于传递给函数的任何参数。静态的使用将有助于确保您不会无意中打破这通过访问对象的成员。
在 java 编写功能代码时,您会发现的静态方法的宝贵的其他情况。此时的规则-的-拇指开发的面向对象的支持者大部分出去窗口。你会发现自己完全静态的方法和绑定到匿名内部函子的公共静态函数常数的类。
最终 java 有 conflating 多概念下相同的类和接口语法很弱的作用域构造。你不这么多的默认到静态,因为感觉免费使用设施 java 提供提供命名空间,先进的数码,模块,等作为,当你觉得他们的需要。
这取决于能 java.lang.Math 有没有一种方法不是静态的。(您可以做一个静态导入到写而不是 Math.cos()) cos()这不会过度使用,但有些是静默的代码,作为一个实用程序,调用会接受。I.g Thread.currentThread()
除非您传递一个对象的引用在一个 static 一类上的方法强制实施方法本身不能发生变异的对象,因为它缺少访问 this。方面的 static 修饰符的方法的意图的程序员提供了信息,是自由的副作用。
防静电的纯化论者可能想删除那些到一个实用程序类的 anti-utility 的纯化论者当然反对。但在现实,什么不会人为地离开他们唯一的调用站点移动这些方法实现,紧密耦合到新的实用程序类以外的其他。
与盲目提取到其自己的类的常用实用程序方法的一个问题是这些实用程序真的被视为一个新的公共 API 即使它只消耗的原始代码。执行在重构时的几个商不能考虑这。快进,其他真的使用烂的实用程序类。稍后某人进行更改以适合自己的扩展名。如果你幸运测试或两个休息,但不可能。
我通常
根据需要,顺序,请执行以下步骤:
a) 我编写一些代码中成员的方法找出我可能可以重用此代码的一些和
解压缩到的非静态方法
b) 现在我将看到是否此方法需要能够访问状态或如果我可以适合其需要一个或两个参数和返回语句。如果后者是这种情况:
使静态方法 (专用)
c) 如果再找我可以在其它类别的我相同的包中使用此代码
公开方法并移动到包帮助器类的方法,具有默认可见性
例如在包 com.mycompany.foo.bar.phleeem 将创建是一类 PhleeemHelper 或 PhleeemUtils 与默认可见性。
d) 如果我那时才认识到我对我的应用程序都需要此功能我
移动到一个专用的实用程序包的帮助器类
例如:com.mycompany.foo.utils.PhleeemUtils
通常我喜欢尽可能少的可见性的概念。那些人不需要我的方法不能看到它。这就是为什么私人访问开始将移动到包访问和仅公开的东西时在专用软件包中。
我觉得难订阅这些避免静态方法理论。他们在那里,促进 anti-septically 洁净的任何偏离对象关系的完全卫生的面向对象模型。我看不到任何重要的方式是在实践对象-新规 anti-septically 纯的。
不管怎么说,所有的 java.util.Arrays 类是静态的。数字类整数,布尔值、 字符串具有静态方法。有很多的静态方法。这些类中的所有静态方法或转换,或从它们各自的类的实例。
良好的旧鹅,自报,证明这种有用的作用模型的有静态方法是避免他们没有点。我知道有些人是困惑,足够否决我的响应。有理由和习惯很多程序员为什么爱将尽可能多的静态成员。
我一次在一个建立在项目领导人想我们使静态方法尽可能多地工作和完成它们。在另一方面,我不是那一个极端。像关系数据库架构设计,一切取决于您的数据建模策略。
应该有一个一致的原因为何进行静态方法。它不会伤害进行静态方法时,请遵循标准 Java 库模式。
最重要编程的生产率和质量。在一个自适应和灵活发展的环境中,它将是不仅适应有效地应付需求的变化,项目的粒度而且还适应编程气氛像提供一个符合国情的编码模型,以充分利用您的编程技能集。在到 (几乎永远不会结束的一个项目) 的一天要不高效和有效,他们是否避免静态方法的团队成员。
因此,制定一个的编程模型,是否您想 MVP 注射,驱动方面的亲和/静态-避免等水平和知道为什么要他们不是因为一些理论螺母告诉您您的编程做法会违反面向对象的原则。请记住如果您在一个行业工作始终是质量和盈利能力不理论纯度。
最后,什么是面向对象?面向对象和数据的归一化战略,以创建一种正交信息的视角。例如较早时期 IBM 手册是写是非常正交。就是如果一块信息这种想象写在什么地方内那些成千上万的手册页在他们避免重复的信息。这是坏的因为你会读书学习如何执行某项任务,经常会遇到的概念在其它手册中提到,您要熟悉的狩猎连接件的信息血栓性手册数据模型数以千计的手册。
出于同样的原因 OS/2 失败与微软竞争,因为 IBM 的概念正交的纯粹是机和基于数据和 IBM 如此自豪地宣布其真实对象意志与微软的虚假对象-新规迎合人类的角度来看。他们忘记了我们人类有我们自己各自不同正交观点的信息不符合数据和机器基于正交或甚至彼此。
要熟悉的树拓扑结构会意识到,您可以选择任何叶节点,并使其根。或甚至任何的节点,如果你不介意有 multi-trunk 的树。每个人都认为其节点为根时事实上任何可能是根。如果您认为您的面向对象的角度来看,佳能,再想一想。更重要的是尽量减少被认为是候选人根的节点的数目。
需要有效力和效率的折衷。没有在拥有高效的数据或对象模型,它同程序员可以很难有效地使用的点。
如果它不与此的对象,但实际上是类的属于的该类 (我会考虑将其移动到其它地方) 它应是类的静态的。
我一般不让他们静态,但可能应。它是方法的对象的作为告诉下一个编码器,此方法不能修改您的状态,这是方法的对象的宝贵时您修改访问您要更改性质的成员方法为您提供一条警告提示有价值。
编码是所有通信与下一个编码器 — — 别担心使代码运行,这是微不足道的。因此,最大限度地通信我会说是否你真的需要这样的帮助,使其静态是个好主意。使其私人至关重要的太除非您正在一个数学。像类。
有趣的问题。实际地,我不明白这一点使类 A's 私人的帮助器方法静态 (除非他们正在与有关的可公开访问的静态方法,在 A,当然)。你不取得任何东西 — — 定义,他们已经可能需要的任何方法有一个实例的 A 在其处理。因为他们是幕后的帮助器方法,没有什么可说您 (或另一个同事) 不会最终决定这些无国籍的佣工之一实际上可能受益于知道情况可能导致有点重构的滋扰。
我不认为它的 错误 使一大批内部的静态方法,但看不到你也从他们,哪些好处。除非您有一个好的理由,不,我说默认为非静态。
号永远不会。静态方法应该是一个例外。面向对象是所有关于有行为,围绕对象的状态的对象。imho,理想的情况下,不应该有任何 (或很少) 的静态方法由于一切无关的对象的状态能和以避免领导的一个对象广告大,概念应放置在平原的旧功能,在模块级别。可能的例外的工厂因为 Complex.fromCartesian (以维基百科示例) 读取这样好。
当然这 (编辑: 模块级别的功能) 不可能在一种单一模式的面向对象语言中 (编辑: 喜欢 Java)-这就是为什么我通过这种方式的混合语言设计中,这种专门的主张。但即使是在一种语言完全面向对象,大多数方法将围绕对象的状态,因此被非静态。也就除非您的设计与面向对象-无关但在这种情况下,您使用了错误的语言。
如果一个方法不不用实例数据然后它应是静态的。如果是公共的功能,这会给,您不需要创建一个多余的只是要调用函数的对象实例的重要效率大大提高。可能更重要的是简写优势: 通过在函数声明静态,你电报向读者此函数不使用实例数据。
我不懂的很多海报情绪有一点错有静态函数在 Java 程序中的这里。如果函数是逻辑上是静态的使静态。Java 库有很多的静态函数。Math 类非常充满了静态函数。
如果我需要说要计算一个平方根的函数将是最合理的方法:
public class MathUtils
{
public static float squareRoot(float x)
{
... calculate square root of parameter x ...
return root;
}
}
当然,您可以使一个看起来像这样的"更多 OOPy"版本:
public class MathUtils
{
private float x;
public MathUtils(float x)
{
this.x=x;
}
public float squareRoot()
{
... calculate square root of this.x ...
return root;
}
}
但除了满足使用尽可能的面向对象的一些抽象的目标,如何将这是任何更好呢?它需要更多行代码,不够灵活。
(和是的我现在有一个方形根标准的数学类中的函数。我只使用这作为一种方便的示例。
如果唯一的地方静态函数用于,是每个可能要使用的是从内某一类,然后是,使这类的成员。如果它没有道理叫它从类的外部,使私人。
如果静态函数是与一类可能但逻辑上相关联的合理地称为从外面,然后又使其公共静态。喜欢,因为它要用整数,所以这是一个合理的地方,把它放 Java 的 parseInt 函数是整班。
在另一方面它经常发生的您正在编写类,你意识到您需要一些静态的功能,但功能真的不依赖于此类。这是只是碰巧实现您所需要的第一次,但它可能相当合理使用由其他类,无事可做,你现在正在做什么。像,回到平方根示例,如果你有一种"地点"类,其中包括纬度和经度,和你想要一个函数来计算两个位置之间的距离和您需要进行的计算广场根 (并且假装有了标准库中没有可用的平方根的函数),它将使有很多创建一个单独的平方根函数,而不是在您较大的逻辑中嵌入这意义。但它不会真正属于您的地类。这将创建一个单独的类数学的实用程序"或一些这样的时间。
你问问"应富始终是静态的无论任何其它考虑因素的?"我会说"快,但不是完全。
我能想到的它使不静态的唯一原因是子类如果想要重写它。
我想不出任何其他原因,但我不会排除。我愿意说"不会在任何情况下",是因为有人通常能有一些特殊的情况。
在标题上回答在一般的 Java 方法,在 不 是静态的默认情况下。Java 是一种面向对象的语言。
但是,你说是有点不同的。你说具体的帮助器方法。
帮助器方法,只是采取值作为参数并返回一个的值,而不访问状态的情况下,他们 应是静态的。私人和静态。我要强调它:
不会访问状态的帮助器方法应是静态的。
使这些方法静态具有至少一个主要优势: 您明确它完全在代码中 的 方法不需要知道任何实例状态。
本身已说明的代码。事情更明显会读取您的代码的其他人,甚至您在某一时刻在将来成为。
如果您确保该方法不依赖于外部或全球的状态,则它是 纯函数,即,数学意识 中的函数: 对同一的输入您可以是某些始终获得相同的输出。
如果该方法是静态的是纯函数然后在某些情况下它可能是 memoized,获得一些性能收益 (使用更多内存的更改)。
字节码级如果您声明作为实例方法或静态的方法的帮助器方法您会获得两个完全不同的事情。
为了使这一节更容易了解,让我们用一个示例:
public class App {
public static void main(String[] args) {
WithoutStaticMethods without = new WithoutStaticMethods();
without.setValue(1);
without.calculate();
WithStaticMethods with = new WithStaticMethods();
with.setValue(1);
with.calculate();
}
}
class WithoutStaticMethods {
private int value;
private int helper(int a, int b) {
return a * b + 1;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public int calculate() {
return helper(value, 2 * value);
}
}
class WithStaticMethods {
private int value;
private static int helper(int a, int b) {
return a * b + 1;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public int calculate() {
return helper(value, 2 * value);
}
}
我们感兴趣的行是对调用 helper(...) 类 WithoutStaticMethods 和 WithStaticMethods。
在第一种情况下不静态的方法的情况下调用帮助器方法时 JVM 需要推送到转达,实例引用 invokespecial。看一看的代码,calculate() 方法:
0 aload_0
1 aload_0
2 getfield #2 <app/WithoutStaticMethods.value>
5 iconst_2
6 aload_0
7 getfield #2 <app/WithoutStaticMethods.value>
10 imul
11 invokespecial #3 <app/WithoutStaticMethods.helper>
14 ireturn
在 0 (或 1) 指令 aload_0 将加载到的堆栈上的实例的引用,它会消耗后的 invokespecial。此指令将该值作为第一个参数,helper(...) 功能,和它永远不会用作,在这里我们可以看到:
0 iload_1
1 iload_2
2 imul
3 iconst_1
4 iadd
5 ireturn
看看有没有 iload_0 吗?它已被不必要地加载。
现在您声明该方法是静态,则 calculate() 方法将看起来像:
0 aload_0
1 getfield #2 <app/WithStaticMethods.value>
4 iconst_2
5 aload_0
6 getfield #2 <app/WithStaticMethods.value>
9 imul
10 invokestatic #3 <app/WithStaticMethods.helper>
13 ireturn
区别是:
aload_0 指令invokestatic好,则 helper 函数的代码也是有点不同: 有没有 this 作为第一次的参数,参数其实位于位置 0 和 1,在这里我们可以看到:
0 iload_0
1 iload_1
2 imul
3 iconst_1
4 iadd
5 ireturn
代码设计角度更有意义多帮助器方法声明静态: 代码说明问题本身,它包含更多有用的信息。它说它不需要工作的实例状态。
字节码级别更清楚发生了什么事,没有无用的代码 (,虽然我相信 JIT 优化它,不能将不会带来显著的性能成本)。