Answers:
一个经验法则:问问自己“即使尚未构造任何对象,调用此方法是否有意义?” 如果是这样,它绝对应该是静态的。
因此,在一个类中,Car
您可能有一个方法:
double convertMpgToKpl(double mpg)
...这将是静态的,因为即使没有人构建过,也可能想知道35mpg会转换成什么Car
。但是这种方法(设置一个特定的效率Car
):
void setMileage(double mpg)
...不能是静态的,因为Car
在构造任何方法之前无法调用该方法。
(顺便说一句,情况并非总是如此:您有时可能有一个涉及两个Car
对象的方法,但仍然希望它是静态的。例如:
Car theMoreEfficientOf( Car c1, Car c2 )
尽管可以将其转换为非静态版本,但有人会认为,由于没有“特权”选择Car
更为重要,因此您不应强迫调用者选择一个Car
作为要调用的对象。方法。不过,这种情况仅占所有静态方法的一小部分。)
Car#isMoreEfficientThan(Car)
。它的优点是,您平局返回的那辆车不是随心所欲的。通过方法的标题可以明显看出,领带中返回的是什么。
仅在以下情况下定义静态方法:
有一些使用静态方法的正当理由:
性能:如果您要运行一些代码,并且不想实例化一个额外的对象来这样做,请将其推入静态方法中。JVM还可以优化很多静态方法(我想我曾经读过James Gosling声明您不需要在JVM中使用自定义指令,因为静态方法将同样快,但是找不到源-因此这可能是完全错误的)。是的,这是微优化,可能不需要。而且我们程序员永远不会仅仅因为它们很酷就做不需要的事情,对吗?
实用性:而不是调用new Util().method(arg)
,call Util.method(arg)
或method(arg)
使用静态导入。更容易,更短。
添加方法:您确实希望String类具有removeSpecialChars()
实例方法,但是它不存在(并且不应该这样做,因为您项目的特殊字符可能与其他项目的特殊字符不同),并且您不能添加它(因为Java)有点理智),因此您创建了一个实用程序类,然后调用removeSpecialChars(s)
而不是s.removeSpecialChars()
。甜。
纯度:采取一些预防措施,您的静态方法将是一个纯函数,也就是说,它唯一依赖的是参数。数据输入,数据输出。这使您更容易阅读和调试,因为您无需担心继承问题。您也可以使用实例方法来做到这一点,但是编译器将通过静态方法(通过不允许引用实例属性,覆盖方法等)为您提供更多帮助。
如果要创建一个单例,还必须创建一个静态方法,但是...不要。我的意思是,三思而后行。
现在,更重要的是,为什么不想创建静态方法?基本上,多态性超出了人们的视野。您将无法覆盖该方法,也无法在接口中 (Java 8之前的版本)对其进行声明。设计需要很大的灵活性。另外,如果您需要state,那么如果您不小心的话,将会遇到很多并发错误和/或瓶颈。
阅读Misko的文章后,我认为从测试的角度来看,静态方法是不好的。您应该改为使用工厂(也许使用像Guice这样的依赖注入工具)。
只拥有一种东西问题“我如何确保自己只有一种东西”被很好地绕开了。您只实例化了主实例中的单个ApplicationFactory,因此,您只实例化了所有单例的单个实例。
静态方法的基本问题是它们是过程代码。我不知道如何对程序代码进行单元测试。单元测试假设我可以孤立地实例化我的应用程序的一部分。在实例化过程中,我将依赖关系与模拟/友好关系连接起来,以替换实际的依赖关系。使用过程编程,由于没有对象,因此代码和数据是分开的,因此无需“连接”。
Math.abs()
或)时Arrays.sort()
,甚至可以将所有依赖项传递给的方法,我也看不到这会如何阻碍单元测试。我想说一个简单的经验法则是:如果您有任何理由要模仿过程逻辑,则不要将其放在静态方法中。我从来没有理由嘲笑Arrays.sort()
或Math.abs()
。
Java中的静态方法属于该类(而不是其实例)。它们不使用实例变量,通常将从参数中获取输入,对其执行操作,然后返回一些结果。实例方法与对象相关联,顾名思义,实例方法可以使用实例变量。
如果通过任何方法应用static关键字,则称为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();
} }
运/输:111印度BBDIT 222美国BBDIT 333中国BBDIT
实际上,我们在类中使用静态属性和方法,当我们要使用程序的某些部分时,应该在其中存在该部分,直到程序运行为止。而且我们知道,要操作静态属性,我们需要静态方法,因为它们不是实例变量的一部分。而且,如果没有静态方法,则操作静态属性将非常耗时。
静态方法不需要在对象上调用,也就是在使用它时。示例:您的Main()是静态的,并且您没有创建调用它的对象。
静态方法和变量是Java中“全局”函数和变量的受控版本。可以使用classname.methodName()
或来访问方法classInstanceName.methodName()
,即可以使用类名以及该类的实例来访问静态方法和变量。
不能将类声明为静态的(因为这没有意义。如果将一个类声明为公共的,则可以从任何地方访问它),可以将内部类声明为静态的。
如果可以使用静态方法
一个不想对实例执行操作(实用程序方法)
如本博文中上述解答中所提到的,将英里转换为公里,或计算温度从华氏温度到摄氏温度,反之亦然。通过使用静态方法的这些示例,无需实例化堆内存中的整个新对象。考虑以下
1. new ABCClass(double farenheit).convertFarenheitToCelcium()
2. ABCClass.convertFarenheitToCelcium(double farenheit)
前者为每个方法调用(性能,实用)创建了一个新的类足迹。示例包括下面的Math和Apache-Commons库的StringUtils类:
Math.random()
Math.sqrt(double)
Math.min(int, int)
StringUtils.isEmpty(String)
StringUtils.isBlank(String)
一个人想用做一个简单的功能。显式传递输入,并将结果数据作为返回值。继承,对象实例化没有体现出来。简洁,可读。
注意:很少有人反对静态方法的可测试性,但是也可以测试静态方法!使用jMockit,可以模拟静态方法。可测性。下面的例子:
new MockUp<ClassName>() {
@Mock
public int doSomething(Input input1, Input input2){
return returnValue;
}
};
我想知道何时使用静态方法?
static
方法的常见用法是访问static
字段。但是您可以拥有static
方法,而无需引用static
变量。static
可以在一些java类(例如java.lang.Math)中找到不引用变量的辅助方法。
public static int min(int a, int b) {
return (a <= b) ? a : b;
}
另一个用例,我可以想到将这些方法与方法结合使用synchronized
是在多线程环境中实现类级别的锁定。
假设我有一个带有几个getter和setter的类,一个或两个方法,并且我希望这些方法只能在该类的实例对象上调用。这是否意味着我应该使用静态方法?
如果需要访问该类的实例对象上的方法,则该方法应为非静态。
Oracle文档页面提供了更多详细信息。
并非允许实例和类变量以及方法的所有组合:
A common use for static methods is to access static fields.
不是一个论点。
每当您不想在代码中创建对象来调用方法时,只需将该方法声明为静态方法即可。由于静态方法不需要调用实例,但是这里要注意的是并不是所有静态方法都可以由JVM自动调用。此特权仅由Java中的main()“ public static void main [String ... args]”方法享有,因为在运行时,这是JVM寻求Signature public“ static” void main []作为入口的方法。开始执行代码。
例:
public class Demo
{
public static void main(String... args)
{
Demo d = new Demo();
System.out.println("This static method is executed by JVM");
//Now to call the static method Displ() you can use the below methods:
Displ(); //By method name itself
Demo.Displ(); //By using class name//Recommended
d.Displ(); //By using instance //Not recommended
}
public static void Displ()
{
System.out.println("This static method needs to be called explicitly");
}
}
输出:-此静态方法由JVM执行此静态方法需要显式调用此静态方法需要显式调用此静态方法需要显式调用