Java:何时使用静态方法

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

例如

Obj x = new Obj();
x.someMethod

要么

Obj.someMethod

(这是静态方式吗?)

我很困惑!


#1楼

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


#2楼

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

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

  • 实用性 :使用静态导入调用Util.method(arg)method(arg)而不是调用new Util().method(arg) 。 更容易,更短。

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

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

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

现在,更重要的是, 为什么不想创建静态方法? 基本上, 多态性超出了人们的视野 。 您将无法覆盖该方法, 也无法在接口中 (Java 8之前的版本)对其进行声明 。 设计需要很大的灵活性。 另外,如果您需要state ,那么如果不小心的话,您将遇到许多并发错误和/或瓶颈。


#3楼

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.");
     }
  }

#4楼

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


#5楼

不,静态方法不与实例相关联; 他们属于阶级。 静态方法是您的第二个示例。 实例方法是第一个。


#6楼

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


#7楼

静态: Obj.someMethod

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


#8楼

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

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

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


#9楼

一个经验法则:问自己“即使尚未构建Obj,调用此方法是否有意义?” 如果是这样,那肯定是静态的。

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

(顺便说一句,情况并非总是如此:您有时可能有一个涉及两个Car对象的方法,但仍然希望它是静态的。例如Car theMoreEfficientOf( Car c1, Car c2 ) 。尽管可以将其转换为非-static版本,有些人会争辩说,由于没有哪个“汽车”更重要的“特权”选择,因此您不应该强迫调用者选择一个Car作为要在其上调用该方法的对象。不过,对于所有静态方法中的一小部分而言。)


#10楼

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

我如何确保我只有一件东西

只拥有一种东西问题“我如何确保自己只有一种东西”被很好地绕开了。 您只实例化了主实例中的单个ApplicationFactory,结果,您只实例化了所有单例的单个实例。

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

静态方法的基本问题是它们是过程代码。 我不知道如何对程序代码进行单元测试。 单元测试假设我可以孤立地实例化我的应用程序的一部分。 在实例化过程中,我将依赖关系与模拟/友好关系连接起来,以替换实际的依赖关系。 使用过程编程,由于没有对象,因此代码和数据是分开的,因此无需“连接”。


#11楼

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


#12楼

如果通过任何方法应用static关键字,则称为static方法。

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

运/输:111印度BBDIT 222美国BBDIT 333中国BBDIT


#13楼

如果可以使用静态方法

  • 一个不想对实例执行操作(实用程序方法)

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

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

#14楼

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

日食设置


#15楼

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

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


#16楼

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

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

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

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

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

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

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

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

#17楼

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

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

#18楼

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

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

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


#19楼

仅在以下情况下定义静态方法:

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

#20楼

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

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

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

什么时候静态方法不好?

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

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

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

最后的话

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


#21楼

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

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值