Java:何时使用静态方法

时间:2010-04-19 23:05:33

标签: java static-methods

我想知道何时使用静态方法?假设我有一个带有几个getter和setter的类,一个或两个方法,我希望这些方法只能在类的实例对象上调用。这是否意味着我应该使用静态方法?

e.g

Obj x = new Obj();
x.someMethod

Obj.someMethod

(这是静态方式吗?)

我很困惑!

23 个答案:

答案 0 :(得分:1336)

一个经验法则:问问自己“即使没有构建Obj,这个方法也有意义吗?”如果是这样,那肯定是静态的。

因此,在类Car中,您可能有一个静态的方法double convertMpgToKpl(double mpg),因为有人可能想知道35mpg转换为什么,即使没有人构建过汽车。但是void setMileage(double mpg)(设置一个特定Car的效率)不能是静态的,因为在构造任何Car之前调用该方法是不可思议的。

(顺便说一下,反过来并不总是这样:你有时会有一个涉及两个Car个对象的方法,但仍然希望它是静态的。例如Car theMoreEfficientOf( Car c1, Car c2 )。虽然这可以被转换对于非静态版本,有人会争辩说,由于没有“特权”选择哪个Car更重要,所以不应强制调用者选择一个Car作为您将调用该方法的对象。但是,这种情况只占所有静态方法的一小部分。)

答案 1 :(得分:495)

仅在以下方案中定义静态方法:

  1. 如果您正在编写实用程序类,则不应更改它们。
  2. 如果方法未使用任何实例变量。
  3. 如果任何操作不依赖于实例创建。
  4. 如果有一些代码可以被所有实例方法轻松共享,请将该代码提取到静态方法中。
  5. 如果您确定永远不会更改或覆盖方法的定义。由于无法覆盖静态方法。

答案 2 :(得分:159)

使用静态方法有一些正当理由:

  • 性能:如果您希望运行某些代码,并且不想实例化额外的对象,请将其推送到静态方法中。 JVM也可以大量优化静态方法(我想我曾经读过James Gosling声明你不需要JVM中的自定义指令,因为静态方法会同样快,但找不到源 - 因此它可能是完全错误的)。是的,它是微优化,可能不需要。我们程序员从不做不需要的事情只是因为它们很酷,对吗?

  • 实用性:不要拨打new Util().method(arg),而是使用静态导入调用Util.method(arg)method(arg)。更简单,更短。

  • 添加方法:你真的希望类String有一个removeSpecialChars()实例方法,但它不存在(它不应该,因为你的项目的特殊字符可能与其他项目不同),你不能添加它(因为Java有点理智),所以你创建了一个实用程序类,并调用removeSpecialChars(s)而不是s.removeSpecialChars()。甜。

  • 纯度:采取一些预防措施,您的静态方法将是pure function,也就是说,它唯一依赖的是它的参数。数据输入,数据输出。这更容易阅读和调试,因为您没有担心继承怪癖。您也可以使用实例方法来完成它,但编译器将使用静态方法帮助您(通过不允许引用实例属性,重写方法等)。

如果你想制作单身,你还必须创建一个静态方法,但是......不要。我的意思是,三思而后行。

现在,更重要的是,为什么你不希望创建静态方法?基本上,多态性不在窗口。您将无法覆盖方法,也无法在接口 (Java 8之前版本)中声明它。它从您的设计中获得了很大的灵活性。此外,如果您需要状态,如果您不小心,最终会出现大量并发错误和/或瓶颈。

答案 3 :(得分:39)

在阅读Misko的文章后,我认为static methods从测试的角度来看是不好的。您应该使用factories(可能使用依赖注入工具,如Guice)。

我如何确保我只有一个

  

只有一个东西   “如何确保我的问题”   只有一个“很好的东西   回避。您只实例化一个   您的单个ApplicationFactory   主要的,因此,你只   实例化所有的单个实例   你的单身人士。

静态方法的基本问题是它们是程序代码

  

静态方法的基本问题是   它们是程序代码。我没有   想法如何对程序代码进行单元测试。   单元测试假设我可以   实例化我的一个应用程序   处于隔离状态。在实例化期间   我用依赖关系连接   嘲笑/友谊取代了   真正的依赖。随着程序   编程没有“连线”   因为没有对象,代码   和数据是分开的。

答案 4 :(得分:31)

static方法是一种方法,它不需要初始化任何对象来调用它。您是否注意到Java中的static函数中使用了main?程序执行从那里开始,没有创建对象。

考虑以下示例:

 class Languages 
 {
     public static void main(String[] args) 
     {
         display();
     }

     static void display() 
     {
         System.out.println("Java is my favorite programming language.");
     }
  }

答案 5 :(得分:18)

java中的静态方法属于该类(不是它的实例)。它们不使用实例变量,通常从参数中获取输入,对其执行操作,然后返回一些结果。 Instances方法与对象相关联,顾名思义,它可以使用实例变量。

答案 6 :(得分:11)

不,静态方法与实例无关;他们属于这个班级。静态方法是你的第二个例子;实例方法是第一个。

答案 7 :(得分:11)

如果使用任何方法应用static关键字,则称为静态方法。

  1. 静态方法属于类而不是类的对象。
  2. 调用静态方法而无需创建类的实例。
  3. 静态方法可以访问静态数据成员,并可以更改它的值。
  4. 只需使用类点静态名称的名称即可访问静态方法。 。 。示例:Student9.change();
  5. 如果要使用类的非静态字段,则必须使用非静态方法。
  6. //更改所有对象的公共属性的程序(静态字段)。

    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

答案 8 :(得分:8)

静态方法与实例无关,因此无法访问类中的任何非静态字段。

如果方法不使用类的任何字段(或仅静态字段),则可以使用静态方法。

如果使用类的任何非静态字段,则必须使用非静态方法。

答案 9 :(得分:6)

实际上,我们在类中使用静态属性和方法,当我们想要使用我们程序的某些部分应该存在时,直到我们的程序运行。我们知道,要操纵静态属性,我们需要静态方法,因为它们不是实例变量的一部分。如果没有静态方法,操作静态属性非常耗时。

答案 10 :(得分:6)

应该在Class上调用静态方法,应该在Class的Instances上调用Instance方法。但这在现实中意味着什么呢?这是一个有用的例子:

汽车类可能有一个名为Accelerate()的实例方法。如果汽车实际存在(已经构建),你只能加速汽车,因此这将是一个实例方法。

汽车类也可能有一个名为GetCarCount()的计数方法。这将返回创建(或构建)的汽车总数。如果没有构建汽车,这个方法将返回0,但它仍然可以被调用,因此它必须是静态方法。

答案 11 :(得分:5)

如果希望能够在没有类实例的情况下访问该方法,请使用静态方法。

答案 12 :(得分:4)

不需要在对象上调用静态方法,也就是在使用它时。示例:您的Main()是静态的,您不会创建一个对象来调用它。

答案 13 :(得分:4)

静态方法和变量是Java中“全局”函数和变量的受控版本。可以使用classname.methodName()classInstanceName.methodName()访问哪些方法,即可以使用类名以及类的实例访问静态方法和变量。

Class不能声明为static(因为它没有意义。如果一个类被声明为public,它可以从任何地方访问),内部类可以声明为static。

答案 14 :(得分:3)

静态: Obj.someMethod

如果要为方法提供类级别访问权限,请使用static,即在没有类实例的情况下应该可以调用该方法。

答案 15 :(得分:3)

如果

,可以使用静态方法
  • 您不希望对实例执行操作(实用程序方法)

      

    正如本文上面的几个答案所提到的,将里程转换为公里,或计算从华氏温度到摄氏温度的温度,反之亦然。使用静态方法的这些示例,它不需要在堆内存中实例化整个新对象。请考虑以下

    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;
    }
};

答案 16 :(得分:3)

静态方法是Java中可以在不创建类对象的情况下调用的方法。它属于班级。

当我们不需要使用实例调用方法时,我们使用静态方法。

答案 17 :(得分:2)

  

我想知道何时使用静态方法?

  1. static方法的一个常见用途是访问static字段。
  2. 但您可以使用static方法,而无需引用static个变量。没有引用static变量的Helper方法可以在某些java类中找到,例如java.lang.Math

    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }
    
  3. 另一个用例,我可以想到这些方法结合synchronized方法是在多线程环境中实现类级别锁定。

  4.   

    假设我有一个带有一些getter和setter的类,一个或两个方法,我希望这些方法只能在类的实例对象上调用。这是否意味着我应该使用静态方法?

    如果需要访问类的实例对象的方法,那么您的方法应该是非静态的。

    Oracle文档page提供了更多详细信息。

    并非所有实例和类变量和方法的组合都是允许的:

    1. 实例方法可以直接访问实例变量和实例方法。
    2. 实例方法可以直接访问类变量和类方法。
    3. 类方法可以直接访问类变量和类方法。
    4. 类方法不能直接访问实例变量或实例方法 - 它们必须使用对象引用。此外,类方法不能使用this关键字,因为没有要引用的实例。

答案 18 :(得分:2)

静态方法有两个主要目的:

  1. 对于不需要任何对象状态的实用程序或辅助方法。 由于不需要访问实例变量,因此具有静态 方法消除了调用者实例化对象的需要 只是为了调用方法。
  2. 对于所有人共享的州 类的实例,就像一个计数器。所有实例都必须共享 同州。仅使用该状态的方法应该是静态的 好。

答案 19 :(得分:1)

在eclipse中,您可以启用警告,帮助您检测潜在的静态方法。 (在突出显示的行上方是另一个我忘了突出显示的行)

eclipse setting

答案 20 :(得分:1)

我找到了一个很好的描述,什么时候使用静态方法:

没有硬性规定,写得很好的规则来决定何时使方法静态,但很少有基于经验的观察,这不仅有助于使方法静态化,而且还教导何时使用静态Java中的方法。您应该考虑在 Java 中使用静态方法:

  1. 如果一个方法没有修改对象的状态,或者没有使用任何实例变量。

  2. 您想在不创建该类的实例的情况下调用方法。

  3. 一个方法是静态的很好的候选者,如果它只适用于提供给它的参数,例如public int factorial(int number){},这个方法只对作为参数提供的数字进行操作。

  4. 实用方法也是静态的良好候选者,例如StringUtils.isEmpty(String text),这是一个检查字符串是否为空的实用方法。

  5. 如果方法的函数在类层次结构中保持静态,例如equals() 方法不是静态化的好选择,因为每个类都可以重新定义相等性。

来源是 here

答案 21 :(得分:0)

什么时候可以使用静态方法好?

只有两种情况下使用静态方法或变量,这不是可憎的。

  1. 声明一个真正的全局常量,而不是全局变量。全球 不变。示例:Math.PI。这对于 说宇宙只有一个实例,那个宇宙 单例包含数学概念单例,其中 是不变的属性PI。这个概念似乎很奇怪 对我们来说,因为我们习惯于在以下情况下不考虑PI 面向对象的责任。如果我们 在设计一些奇怪的游戏,其中有不同的替代宇宙 数学概念和常数。
  2. 对象创建。静态方法是一种有价值且有效的方法 对象创建。重载的构造函数需要不同的 论点不是很清楚,通常通过替换来变得更清晰 它们带有静态构造函数。

静态方法不好吗?

  1. 考虑静态方法的一种方法是全局过程。 本质上,可以在任何地方任何地方调用静态方法。 它只是假装是班级的一部分,而实际上 仅用作“标签”,通过某种逻辑将方法组织起来 师。我用这些术语看待静态方法,因为创建 全局过程与面向对象设计完全相反。

  2. 静态方法的另一个主要问题是可测试性。 在构建软件时,可测试性很重要。静态方法 非常难以测试,尤其是当它们创建新的 具体类的实例。如果您曾经从事过传统工作 代码并尝试为静态方法编写单元测试,您知道我的 痛苦。

  3. 静态方法也不是多态的。如果您创建静态 类上的方法,没有覆盖该行为。你是 卡住了对该实现的硬编码引用。

最后一句话

  

因此,请记住当您创建静态方法进行思考时   小心。我不是在提倡永远不要使用它们。我提倡   有一个很好的理由,首先检查一下静态   方法确实属于另一个可以使用状态的类   信息。

答案 22 :(得分:0)

每当不想在代码中创建对象来调用方法时,只需将该方法声明为静态方法即可。由于静态方法不需要调用实例,但是这里要注意的是并不是所有静态方法都可以由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执行 该静态方法需要显式调用 该静态方法需要显式调用 该静态方法需要显式调用