Java:何时使方法成为静态与实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1618969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: When to make methods static v. instance
提问by Nick Heiner
I have a Geneclass that keeps track of genes. Genehas a method for calculating the distance between two genes. Are there any reasons to make it static?
我有一个Gene跟踪基因的课程。Gene有一种计算两个基因之间距离的方法。有什么理由让它静态吗?
Which is better?
哪个更好?
public static int geneDistance(Gene g0, Gene g1)
public static int geneDistance(Gene g0, Gene g1)
or
或者
public int geneDistance(Gene other)
public int geneDistance(Gene other)
Arguments for/against making it static? I understand what it means for a member to be static, I'm just interested in its implications for maximum cleanliness/efficiency/etc.
支持/反对使其静态化的论据?我理解成员保持静态意味着什么,我只是对它对最大清洁度/效率/等的影响感兴趣。
I repeat the same pattern for returning trimmed versions of two genes, finding matches between genes, finding matches between animals (which contain collections of genes), etc.
我重复相同的模式来返回两个基因的修剪版本,寻找基因之间的匹配,寻找动物(包含基因集合)之间的匹配,等等。
采纳答案by DigitalRoss
Instance, not static
实例,不是静态的
For this case I think the second choice is clearly better. If you think about it, any method could be implemented as static if you are willing to pass the object to it, this only seemsto be a special case because the other parameter is also an instance.
对于这种情况,我认为第二个选择显然更好。如果您考虑一下,如果您愿意将对象传递给它,任何方法都可以实现为静态方法,这似乎只是一个特例,因为另一个参数也是一个实例。
Therefore, our search for symmetry and abstraction is slightly offended by having to choose between the two instance objects for the dot operator. But if you look at .methodas .then operator, it isn't really a problem.
因此,必须在点运算符的两个实例对象之间进行选择,这有点冒犯了我们对对称性和抽象性的搜索。但是,如果你看.method的.那么运营商,这是不是一个真正的问题。
Plus, the only way to do functional-style chaining is with an attribute, i.e., instance method. You probably want thing.up.down.parent.next.distance(x)to work.
另外,进行函数式链接的唯一方法是使用属性,即实例方法。你可能想thing.up.down.parent.next.distance(x)工作。
回答by Charles Salvia
When you make a method static, it means that the method can be called without an instance of the class. It also means that the method cannot access instance variables unless it is passed a reference to an object.
当您将方法设为静态时,这意味着可以在没有类的实例的情况下调用该方法。这也意味着该方法不能访问实例变量,除非它传递了对对象的引用。
Sometimes, it makes sense to make a method static, because the method is associated with the class, but not a particular instance of the class. For example, all the parseX methods, such as Integer.parseInt(String s). This converts a Stringto an int, but does not have anything to do with a particular instance of an Integerobject.
有时,将方法设为静态是有意义的,因为该方法与类相关联,而不是与类的特定实例相关联。例如所有的 parseX 方法,例如Integer.parseInt(String s)。这将 a 转换String为 an int,但与Integer对象的特定实例没有任何关系。
If, on the other hand, a method must return some data which is unique to a particular instance of an object, (like most getter and setter methods), then it can't be static.
另一方面,如果一个方法必须返回某些对象的特定实例所独有的数据(如大多数 getter 和 setter 方法),那么它就不能是静态的。
回答by Erich Kitzmueller
IMO there is no absolute "better", but public int geneDistance(Gene other)is stylistically more similar to other methods in Java (e.g. Object.equals, Comparable.compareTo), so I'd go that way.
IMO 没有绝对的“更好”,但public int geneDistance(Gene other)在风格上更类似于 Java 中的其他方法(例如 Object.equals、Comparable.compareTo),所以我会那样做。
回答by Pascal Thivent
I prefer the second form, i.e. instance method for the following reasons:
我更喜欢第二种形式,即实例方法,原因如下:
- static methods make testing hard because they can't be replaced,
- static methods are more procedural oriented (and thus less object oriented).
- 静态方法使测试变得困难,因为它们无法被替换,
- 静态方法更面向过程(因此更少面向对象)。
IMO, static methods are ok for utility classes (like StringUtils) but I prefer to not abuse using them.
IMO,静态方法适用于实用程序类(如 StringUtils),但我不想滥用它们。
回答by divesh premdeep
My rewording of Charle's answer :
我对查理的回答的改写:
If the method in question intends to use the state of the underlying objectin any way, make it an instance method. Else, make it static.
如果有问题的方法打算以任何方式使用底层对象的状态,请将其设为实例方法。否则,将其设为静态。
Which depends on the way the object's class is designed.
这取决于对象类的设计方式。
In your case, alphazero, probably the int geneDistance(Gene g0, Gene g1)does notreally depend on the state of the Geneinstance it is called on. I would make this method static. And put it in a utility class like GeneUtils.
在你的情况下,alphazero,可能int geneDistance(Gene g0, Gene g1)并不真正依赖于它被调用的Gene实例的状态。我会让这个方法是静态的。并将其放在一个实用程序类中,例如GeneUtils。
Of course, there might be other aspects of your problem that I am not aware of, but this is the general thumb of rule that I use.
当然,您的问题可能还有我不知道的其他方面,但这是我使用的一般规则。
P.S. -> The reason I would not put the method in the Geneclass itself is because a Gene should not be responsible for computing it's distance from another Gene. ;-)
PS -> 我不会把这个方法放在Gene类本身中的原因是因为一个 Gene 不应该负责计算它与另一个 Gene 的距离。;-)
回答by non sequitor
public static int geneDistance(Gene g0, Gene g1)would be part of a separate utility class like Collectionsand Arraysin Java whereas public int geneDistance(Gene other)will be part of the Geneclass. Considering you have other operations like "trimmed versions of two genes, finding matches between genes, finding matches between animals (which contain collections of genes), etc" I would create a separate static utility class for them as these operations aren't semantically meaningful to what a Geneis.
public static int geneDistance(Gene g0, Gene g1)将是一个单独的实用程序类的一部分,如Java 中的Collections和Arrays,而public int geneDistance(Gene other)将是Gene该类的一部分 。考虑到您还有其他操作,例如“两个基因的修剪版本、查找基因之间的匹配项、查找动物之间的匹配项(包含基因集合)等”,我将为它们创建一个单独的静态实用程序类,因为这些操作在语义上没有意义aGene是什么。
If the the semantics of "gene distance" can be wrapped up into your equals(Object o)method then you could consume it there or else include it in your static utility.
如果“基因距离”的语义可以包含在您的equals(Object o)方法中,那么您可以在那里使用它,或者将它包含在您的静态实用程序中。
回答by Cicero
I would like to start answering on your question with the new one: What your class Gene is responsible for? May be you have heard about the 'Single-Responsibility Principle': A class should have only one reason to change. So, I believe if you answer this question you will be able to decide how your application should be designed. In this particular case, I would not use neither the first approach nor the second one. In my opinion it is much better to define new responsibility and encapsulate it in a separate class or may be a function.
我想用新的问题开始回答你的问题:你的班级 Gene 负责什么?您可能听说过“单一职责原则”:一个类应该只有一个改变的理由。因此,我相信如果您回答了这个问题,您将能够决定您的应用程序应该如何设计。在这种特殊情况下,我既不会使用第一种方法,也不会使用第二种方法。在我看来,定义新的职责并将其封装在一个单独的类中或者可能是一个函数要好得多。
回答by qnoid
I'll try to sum up some of the points already given here to which I agree.
我将尝试总结这里已经给出的一些我同意的观点。
Personally I don't think there is a "feels better" answer. Valid reasons do existon why you don't wan't a utility class filled with static methods.
我个人认为没有“感觉更好”的答案。关于为什么您不想使用充满静态方法的实用程序类的正当理由确实存在。
The short answer is that in an object oriented world you should use objects and all the good "stuff" that comes with them (encapsulation, polymorphism)
简短的回答是,在面向对象的世界中,您应该使用对象以及它们附带的所有好“东西”(封装、多态)
Polymorphism
多态性
If the method for calculating the distance between the genes varies, you should roughly(more likely a Strategy) have a Gene class per variation. Encapsulate what varies. Else you will end up with multiple ifs.
如果计算基因之间距离的方法不同,您应该粗略地(更可能是Strategy)每个变异都有一个 Gene 类。封装不同的内容。否则你最终会得到多个 if。
Open For Extension, Closed for Modification
对扩展开放,对修改关闭
That means that if a new method for calculating the distance between genes comes up down the line, you shouldn't modify existing code, but rather add new one. Else you risk breaking what's already there.
这意味着,如果一种计算基因之间距离的新方法出现了,您不应修改现有代码,而应添加新代码。否则你可能会破坏已经存在的东西。
In this case you should add a new Gene class, not modify the code written in the #geneDistance
在这种情况下,您应该添加一个新的 Gene 类,而不是修改#geneDistance 中编写的代码
Tell Don't Ask
告诉不要问
You should tell your objects what to do, not ask them for their state and make decisions for them. Suddenly you break the single responsibility principle since that's polymorphism.
你应该告诉你的对象做什么,而不是询问他们的状态并为他们做决定。突然间你打破了单一职责原则,因为那是多态性。
Testability
可测试性
Static methods may well be easy to test in isolation, but down the road you will make use of this static method in other classes. When it comes to testing that classes on isolation, you will have hard time doing it. Or rather not.
静态方法很可能很容易单独测试,但以后您将在其他类中使用此静态方法。当涉及到隔离测试这些类时,您将很难做到。或者更确切地说不是。
I'll let Miskohave his saying which is more likely better than what I can come up with.
我会让米斯科说出他的说法,这可能比我想出的要好。
import junit.framework.Assert;
import org.junit.Test;
public class GeneTest
{
public static abstract class Gene
{
public abstract int geneDistance(Gene other);
}
public static class GeneUtils
{
public static int geneDistance(Gene g0, Gene g1)
{
if( g0.equals(polymorphicGene) )
return g0.geneDistance(g1);
else if( g0.equals(oneDistanceGene) )
return 1;
else if( g0.equals(dummyGene) )
return -1;
else
return 0;
}
}
private static Gene polymorphicGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return other.geneDistance(other);
}
};
private static Gene zeroDistanceGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return 0;
}
};
private static Gene oneDistanceGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return 1;
}
};
private static Gene hardToTestOnIsolationGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return GeneUtils.geneDistance(this, other);
}
};
private static Gene dummyGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return -1;
}
};
@Test
public void testPolymorphism()
{
Assert.assertEquals(0, polymorphicGene.geneDistance(zeroDistanceGene));
Assert.assertEquals(1, polymorphicGene.geneDistance(oneDistanceGene));
Assert.assertEquals(-1, polymorphicGene.geneDistance(dummyGene));
}
@Test
public void testTestability()
{
Assert.assertEquals(0, hardToTestOnIsolationGene.geneDistance(dummyGene));
Assert.assertEquals(-1, polymorphicGene.geneDistance(dummyGene));
}
@Test
public void testOpenForExtensionClosedForModification()
{
Assert.assertEquals(0, GeneUtils.geneDistance(polymorphicGene, zeroDistanceGene));
Assert.assertEquals(1, GeneUtils.geneDistance(oneDistanceGene, null));
Assert.assertEquals(-1, GeneUtils.geneDistance(dummyGene, null));
}
}
回答by p3t0r
I would make this an instance method. But that might be due to the fact that I have no clue of genes ;)
我会把它作为一个实例方法。但这可能是因为我对基因一无所知;)
Instance methods can be overridden by subclasses which greatly reduces the complexity of your code (less need for if-statements). In the static method example, what will happen I you get a specific type of gene for which the distance is calculated differently? Ad another static method? If you'd have to process a polymorphic list of genes you'd have to look a the type of gene to select the correct distance method... which increases coupling and complexity.
实例方法可以被子类覆盖,这大大降低了代码的复杂性(更少需要 if 语句)。在静态方法示例中,如果您得到距离计算方式不同的特定类型基因,会发生什么?广告另一个静态方法?如果您必须处理基因的多态性列表,则必须查看基因类型以选择正确的距离方法……这会增加耦合和复杂性。
回答by NawaMan
In this particular case, I will make it an intance method. BUT if you have a logical answer when g0 is null then use BOTH (this happen more often than you think).
在这种特殊情况下,我将使它成为一个实例方法。但是,如果您在 g0 为空时有一个合乎逻辑的答案,那么请同时使用 BOTH(这种情况发生的频率比您想象的要高)。
For example, aString.startsWith(), if the aString is null, you may think it is LOGICAL to return null (in case you think the function can be NULL-TOLERATE). This allows me to simplify my program a bit as there is no need to have aString check null in the client code.
例如,aString.startsWith()如果 aString 为 null,您可能认为返回 null 是符合逻辑的(以防您认为该函数可以是 NULL-TOLERATE)。这允许我稍微简化我的程序,因为不需要在客户端代码中检查空字符串。
final Stirng aPrefix = "-";
final Vector aStrings = new Vector();
for(final String aString : aStrings) {
if (MyString.startsWith(aString, aPrefix))
aStrings.aStringadd();
}
instead of
代替
final Stirng aPrefix = "-";
final Vector aStrings = new Vector();
for(final String aString : aStrings) {
if ((aString != null) && aString.startsWith(aPrefix))
aStrings.aStringadd();
}
NOTE: This is an overly simplified example.
注意:这是一个过于简化的示例。
Just a thought.
只是一个想法。

