繁体   English   中英

何时使用 static 方法

[英]When to use static methods

我想知道什么时候使用 static 方法? 假设我有一个 class,带有一些 getter 和 setter,一个或两个方法,我希望这些方法只能在 class 的实例 object 上调用。这是否意味着我应该使用 static 方法?

例子:

Obj x = new Obj();
x.someMethod();

...要么:

Obj.someMethod(); // Is this the static way?

我比较糊涂!

一条经验法则:问问自己“调用此方法是否有意义,即使尚未构造任何对象?” 如果是这样,它肯定应该是静态的。

因此,在Car类中,您可能有一个方法:

double convertMpgToKpl(double mpg)

...这将是静态的,因为人们可能想知道 35mpg 转换为什么,即使没有人制造过Car 但是这种方法(它设置了一个特定Car的效率):

void setMileage(double mpg)

...不能是静态的,因为在构造任何Car之前调用该方法是不可想象的。

(顺便说一句,反过来并不总是正确的:你有时可能有一个涉及两个Car对象的方法,并且仍然希望它是静态的。例如:

Car theMoreEfficientOf(Car c1, Car c2)

尽管这可以转换为非静态版本,但有些人会争辩说,由于没有“特权”选择哪个Car更重要,因此您不应该强迫调用者选择一个Car作为您将调用方法。 不过,这种情况只占所有静态方法的一小部分。

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

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

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

  • 性能:如果你想运行一些代码,并且不想实例化一个额外的对象来这样做,把它塞进一个静态方法中。 JVM 还可以优化静态方法很多(我想我曾经读过 James Gosling 声明你不需要 JVM 中的自定义指令,因为静态方法会一样快,但找不到源 - 因此这可能是完全错误的)。 是的,它是微优化,可能不需要。 而且我们程序员永远不会仅仅因为它们很酷而做不必要的事情,对吧?

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

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

  • 纯度:采取一些预防措施,你的静态方法将是一个纯函数,也就是说,它唯一依赖的就是它的参数。 数据输入,数据输出。 这更易于阅读和调试,因为您无需担心继承问题。 您也可以使用实例方法来做到这一点,但编译器会在静态方法方面为您提供更多帮助(通过不允许引用实例属性、覆盖方法等)。

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

现在,更重要的是,为什么您不想创建静态方法? 基本上,多态性消失了 您将无法覆盖该方法, 也无法在接口中声明它 (Java 8 之前) 您的设计需要很大的灵活性。 此外,如果您需要state ,如果您不小心,最终会遇到很多并发错误和/或瓶颈。

在阅读了 Misko 的文章后,我认为从测试的角度来看, 静态方法是不好的。 你应该有工厂(也许使用像Guice这样的依赖注入工具)。

我如何确保我只有其中之一

只有一件东西“我如何确保我只拥有一件东西”的问题被很好地回避了。 您只在 main 中实例化了一个 ApplicationFactory,因此,您只实例化了所有单例的一个实例。

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

静态方法的基本问题是它们是过程代码。 我不知道如何对程序代码进行单元测试。 单元测试假设我可以单独实例化我的应用程序的一部分。 在实例化期间,我将依赖项与替换真正依赖项的模拟/友好连接。 对于过程式编程,没有什么可以“连接”的,因为没有对象,代码和数据是分开的。

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

考虑以下示例:

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

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

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

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

如果您将静态关键字应用于任何方法,则称为静态方法。

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

//改变所有对象的公共属性(静态字段)的程序。

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

静态方法不与实例关联,因此它们不能访问类中的任何非静态字段。

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

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

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

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

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

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

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

静态: Obj.someMethod

当您想要提供对方法的类级别访问时使用static ,即在没有类实例的情况下该方法应该是可调用的。

不需要在对象上调用静态方法,即在您使用它时。 示例:您的 Main() 是静态的,并且您没有创建对象来调用它。

可以使用静态方法,如果

  • 不想对实例执行操作(实用方法)

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

    1. new ABCClass(double farenheit).convertFarenheitToCelcium() 2. ABCClass.convertFarenheitToCelcium(double farenheit)

    前者为每个方法调用、 Performance、Practical创建一个新的类足迹。 示例如下: 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;
    }
};

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

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

静态方法是Java中无需创建类对象即可调用的方法。 它属于类。

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

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

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

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

没有硬性规定,编写良好的规则来决定何时使方法成为静态方法,但很少有基于经验的观察,这不仅有助于使方法成为静态方法,而且还教会了何时在 Java 中使用静态方法. 您应该考虑在 Java 中将方法设为静态:

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

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

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

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

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

来源在这里

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

日食设置

我想知道什么时候使用静态方法?

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

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

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

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

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

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

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

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

仅在两种情况下使用静态方法或变量,而不是可憎的。

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

什么时候静态方法不好?

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

  2. 静态方法的另一个主要问题是可测试性。 在构建软件时,可测试性很重要。 众所周知,静态方法很难测试,特别是当它们创建具体类的新实例时。 如果您曾经使用过遗留代码,并试图为静态方法编写单元测试,那么您就知道我的痛苦。

  3. 静态方法也不是多态的。 如果在类上创建静态方法,则不会覆盖该行为。 您会受到对该实现的硬编码引用的困扰。

最后的话

因此,请记住创建静态方法时要仔细考虑它。 我不是在提倡永远不要使用它们。 我主张有充分的理由,并首先检查静态方法是否确实属于可以使用状态信息的其他类。

每当您不想创建对象来调用代码中的方法时,只需将该方法声明为静态。 由于静态方法不需要调用实例,但这里的问题并不是所有静态方法都由 JVM 自动调用。 此特权仅由 java 中的 main() "public static void main[String...args]" 方法享有,因为在运行时这是 JVM 寻求的签名 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 执行此静态方法需要显式调用此静态方法需要显式调用此静态方法需要显式调用

无论何时,您都应该使用静态方法,

  1. 该方法中的代码不依赖于实例创建,也不使用任何实例变量。
  2. 一段特定的代码将由所有实例方法共享。
  3. 不应更改或覆盖方法的定义。
  4. 您正在编写不应更改的实用程序类。

https://www.tutorialspoint.com/When-to-use-static-methods-in-Java

绝不。

永远不要使用静态方法。 它们与全局函数没有什么不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM