我想知道何时使用静态方法?比如说,如果我有一个类,里面有几个getter和setter,还有一两个方法,并且我希望这些方法只能在该类的实例对象上调用。这是否意味着我应该使用静态方法?
例如:
Obj x = new Obj();
x.someMethod();
...或者:
Obj.someMethod(); // Is this the static way?
我很困惑!
我想知道何时使用静态方法?比如说,如果我有一个类,里面有几个getter和setter,还有一两个方法,并且我希望这些方法只能在该类的实例对象上调用。这是否意味着我应该使用静态方法?
例如:
Obj x = new Obj();
x.someMethod();
...或者:
Obj.someMethod(); // Is this the static way?
我很困惑!
Car
的类中,你可能会有一个方法:double convertMpgToKpl(double mpg)
...这将是静态的,因为即使没有人制造过Car
,某些人可能仍想知道35mpg相当于多少。但是这个方法(设置一个特定Car
的效率):
void setMileage(double mpg)
由于在构造任何“汽车”之前调用该方法是不可想象的,因此它不能是静态的。
(顺便说一下,反过来并不总是成立:有时您可能会有涉及两个“汽车”对象的方法,但仍希望它是静态的。例如:
Car theMoreEfficientOf(Car c1, Car c2)
Car
更重要,你不应该强迫调用者选择一个Car
作为将调用方法的对象。尽管如此,这种情况只占所有静态方法的相当小的比例。Car#isMoreEfficientThan(Car)
这种方法。它的优点在于当出现平局时,你返回哪辆车不是随意的。从该方法的标题就可以明显看出在平局情况下会返回哪辆车。 - Cruncher只有在以下情况下定义静态方法:
使用静态方法有一些有效的原因:
性能:如果你想运行某些代码,而不想实例化额外的对象来执行此操作,则将其放入静态方法中。JVM也可以对静态方法进行优化(我认为我曾经读过James Gosling宣称你不需要在JVM中使用自定义指令,因为静态方法将像这样快,但我找不到来源 - 所以可能完全是错误的)。是的,这是微优化,可能不需要。我们程序员永远不会做不必要的事情,只是因为它们很酷,对吧?
实用性:不要调用new Util().method(arg)
,而是调用Util.method(arg)
或带有静态导入的method(arg)
。更容易,更短。
添加方法:你真的希望类String有一个removeSpecialChars()
实例方法,但它不存在(而且不应该存在,因为你的项目的特殊字符可能与其他项目的不同),并且你无法添加它(因为Java有点明智),所以你创建一个实用程序类,并调用removeSpecialChars(s)
而不是s.removeSpecialChars()
。Sweet。
纯度:采取一些预防措施,您的静态方法将是纯函数,也就是说,它所依赖的唯一事物是其参数。数据进去,数据出来。这更容易阅读和调试,因为你不必担心继承怪癖。你也可以使用实例方法来实现,但编译器会在静态方法上帮你一点忙(不允许引用实例属性,重写方法等)。
如果你想创建单例,也必须创建静态方法,但是……别这么做。我的意思是,考虑清楚。
现在,更重要的是,为什么你不想创建静态方法?基本上,多态性将不复存在。您将无法覆盖该方法,也不能在接口中声明它(Java 8之前)。它会从设计中带走很多灵活性。此外,如果您需要状态,如果不小心,您将遇到大量并发错误和/或瓶颈。
阅读Misko的文章后,我认为从测试的角度看,静态方法不好。你应该使用工厂模式(也许使用像Guice这样的依赖注入工具)。
确保“我只有一个实例”这个问题得到了很好的解决。您仅在主函数中实例化一个ApplicationFactory,因此您仅实例化所有单例的单个实例。
静态方法的基本问题在于它们是过程性代码。我不知道如何对过程性代码进行单元测试。单元测试假定我可以将应用程序的一部分隔离出来进行实例化。在实例化期间,我使用mocks/friendlies替换真实的依赖项来连接依赖项。由于过程性编程没有对象,所以没有任何东西可“连接”,代码和数据是分离的。
Math.abs()
或Arrays.sort()
等,即使是您可以将所有依赖项传递进去的方法,我也不认为这会妨碍单元测试。 我会说一个简单的经验法则是:如果您有任何原因模拟过程逻辑,则不要将其放在静态方法中。我从未有过模拟Arrays.sort()
或Math.abs()
的原因。 - Andystatic
方法是一种不需要初始化对象即可调用的方法类型。你是否注意到在Java中static
被用于main
函数中?程序从那里开始执行,不需要创建对象。
考虑以下示例:
class Languages
{
public static void main(String[] args)
{
display();
}
static void display()
{
System.out.println("Java is my favorite programming language.");
}
}
Java中的静态方法属于类(而不是其实例)。它们不使用实例变量,通常从参数中获取输入,对其执行操作,然后返回一些结果。实例方法与对象相关联,顾名思义可以使用实例变量。
如果您在任何方法中使用static关键字,它就被称为静态方法。
//更改所有对象(静态字段)的公共属性的程序。
class Student9{
int rollno;
String name;
static String college = "ITS";
static void change(){
college = "BBDIT";
}
Student9(int r, String n){
rollno = r;
name = n;
}
void display (){System.out.println(rollno+" "+name+" "+college);}
public static void main(String args[]){
Student9.change();
Student9 s1 = new Student9 (111,"Indian");
Student9 s2 = new Student9 (222,"American");
Student9 s3 = new Student9 (333,"China");
s1.display();
s2.display();
s3.display();
} }
O/P: 111 印度 BBDIT 222 美国 BBDIT 333 中国 BBDIT
不,静态方法与实例无关;它们属于类。 静态方法是您的第二个示例;实例方法是第一个示例。
静态方法与实例无关,因此不能访问类中的任何非静态字段。
如果该方法不使用类的任何字段(或仅使用静态字段),则应使用静态方法。
如果使用了类的任何非静态字段,则必须使用非静态方法。