静态方法和实例方法的区别

104

我刚刚在我的教科书中看到了这段文字,但我不太确定它的意思。它的基本意思是静态方法或类方法包括“修饰符”关键字静态。但我不知道这是什么意思?

请有人用简单易懂的语言解释一下静态或类方法是什么吗?

还有,我能不能得到一个简单的解释关于实例方法是什么?

这是他们在教科书中给我的内容:

存在或不存在静态修饰符的重要实际影响。公共类方法可以在Java处理其所属的类的定义时立即调用和执行。实例方法则不是这种情况。在可以调用和执行公共实例方法之前,必须创建该类的一个实例。要使用公共类方法,只需要该类即可。另一方面,在使用公共实例方法之前,必须先有该类的实例。

在另一个方法的定义中调用静态方法的方式取决于这两个方法是否属于同一个类。在上面的示例中,阶乘(factorial)和main都是MainClass类的方法。因此,在main的定义中调用factorial时,只需引用方法名“factorial”即可。

11个回答

188

在Java中的基本编程模式是编写类,实例化这些类。被实例化的对象(即类的一个实例)具有与之相关联的属性(成员变量),这些属性会影响它们的行为;当该实例执行方法时,它将引用这些变量。

然而,某些特定类型的所有对象可能都具有与成员变量完全无关的行为;这些方法最好定义为静态方法。通过声明为静态方法,不需要创建类的实例就能运行该方法。

您可以按照以下方式执行静态方法:

MyClass.staticMethod();  // Simply refers to the class's static code

但是要执行一个非静态方法,你必须这样做:

MyClass obj = new MyClass();  //Create an instance
obj.nonstaticMethod();  // Refer to the instance's class's code

编译器在组合一个类时,会深入地收集该类的方法指针并将其附加到类中。当这些方法被执行时,编译器会遵循指针并在远端执行代码。如果一个类被实例化,所创建的对象包含指向“虚函数表”的指针,该表指向继承层次结构中特定类要调用的方法。然而,如果该方法是静态的,则不需要“虚函数表”:所有对该方法的调用都到达内存中的同一位置以执行完全相同的代码。因此,在高性能系统中,如果您不依赖于实例变量,最好使用静态方法。


2
非常感谢您提供的代码示例,它们看起来很熟悉,所以我现在明白了。 - Panthy
6
另一个看待这个问题的好方法是,任何“静态”的东西(类、方法或字段)实际上并不属于任何对象,它只是为组织目的而存在于类中。 - gobernador
2
此外,静态字段被用作数据对象(它持有数据,因此不能更改,但可以在其中操作数据)。静态方法只能调用静态字段,因此具有保持恒定或不变或不实例化的相同概念! - user2416728
3
@user2416728,您的评论非常混乱。静态字段可以被更改,但它们的作用域是全局的,适用于它们的执行环境。因此,任何可以访问该字段的代码都可以访问相同的数据。这并不等同于该数据保持不变(除非使用“final”修饰符)。 - Nathaniel Ford
2
对不起,我想表达的是无法实例化! - user2416728

19

没有被声明为静态的方法和变量被称为实例方法和实例变量。要引用实例方法和变量,您必须首先实例化该类,也就是创建该类的一个对象。对于静态的方法和变量,您不需要实例化类,可以使用类名和点号(.)来访问它们。

例如:

Person.staticMethod();           //accessing static method.

对于非静态方法,您必须实例化该类。

Person person1 = new Person();   //instantiating
person1.nonStaticMethod();       //accessing non-static method.

13

静态方法与实例方法的区别

  1. 实例方法是需要创建类对象后才能调用的方法。而静态方法是Java中可以在不创建类对象的情况下调用的方法。

  2. 静态方法使用static关键字声明,而实例方法则没有static关键字。

  3. 静态方法作为类的单个副本存在,而实例方法则根据创建该类的实例数存在多个副本。

  4. 可以通过类引用来调用静态方法,而只能通过对象引用来调用实例或非静态方法。

  5. 静态方法不能直接访问实例方法和实例变量。但是实例方法可以直接访问静态变量和静态方法。

参考资料:geeksforgeeks


8

静态方法和变量属于整个类,而不仅仅是对象实例。静态方法和变量与整个类相关联,而不是与类的特定实例相关联。每个对象将共享静态方法和变量的公共副本。无论从该类创建多少个对象,每个类只有一个副本。


4
实例方法 => 在特定类的特定实例上调用。方法想要知道它被调用的类是哪个。它发生的方式是有一个名为“this”的不可见参数。在“this”内部,我们已经设置了实例类成员的值。'This' 不是变量。它是一个值,你不能改变它,这个值是调用接收者的引用。 例如:你打电话给修理工(实例方法)来修理电视(实际程序)。他带着工具('this' 参数)来了。他携带了修理电视所需的特定工具,他也可以修理其他东西。
在静态方法中 => 没有“this”这样的东西。 例如:同样的修理工(静态方法)。当你呼叫他时,你必须指定要呼叫哪个修理工(比如电工)。他会来修理你的电视。但是,他没有修理其他东西的工具(没有“this”参数)。
静态方法通常对于不需要从类的实例(从'this')获取任何数据并且可以仅使用其参数执行其预期目的的操作非常有用。

3
简而言之,静态方法和静态变量是类级别的,而实例方法和实例变量是实例或对象级别的。
这意味着每当创建一个实例或对象(使用 new ClassName())时,该对象将保留其自己的实例变量副本。如果您有同一类的五个不同对象,则将有五个不同的实例变量副本。但静态变量和方法将对这五个对象保持相同。如果您需要每个创建的对象都使用共同的内容,请将其设置为静态。如果您需要一个不需要对象特定数据即可工作的方法,请将其设置为静态。静态方法仅与静态变量一起工作,或者将根据传递的参数返回数据。
class A {
    int a;
    int b;

    public void setParameters(int a, int b){
        this.a = a;
        this.b = b;
    }
    public int add(){
        return this.a + this.b;
   }

    public static returnSum(int s1, int s2){
        return (s1 + s2);
    }
}

在上面的例子中,当你调用add()函数时:
A objA = new A();
objA.setParameters(1,2); //since it is instance method, call it using object
objA.add(); // returns 3 

B objB = new B();
objB.setParameters(3,2);
objB.add(); // returns 5

//calling static method
// since it is a class level method, you can call it using class itself
A.returnSum(4,6); //returns 10

class B{
    int s=8;
    int t = 8;
    public addition(int s,int t){
       A.returnSum(s,t);//returns 16
    }
}

在第一类中,add()方法将返回由特定对象传递的数据总和。但是,静态方法可以用于从任何类中获取总和,而不独立于任何特定实例或对象。因此,对于只需要参数即可工作的通用方法,可以将其设置为静态以保持DRY原则。


2

一个对象的行为取决于该类的变量和方法。当我们创建一个类时,我们为它创建了一个对象。对于静态方法,我们不需要它们,因为静态方法意味着所有对象都将拥有相同的副本,因此不需要对象。 例如:

Myclass.get();

在实例方法中,每个对象都会有不同的行为,因此它们必须使用对象实例调用该方法。

例如:
Myclass x = new Myclass();
x.get();

2

如果一个方法的状态不应该被改变,或者它不会使用任何实例变量。

你希望在没有实例的情况下调用方法。

如果它只对提供给它的参数起作用。

实用函数是静态方法的好例子。例如math.pow(),这个函数不会为不同的值更改状态。因此它是静态的。


1
很多答案已经在这里存在,但没有人指出在Java中静态方法无法被重写,因此它们不允许多态性,而多态性与继承一起构成了面向对象编程的核心。

0

静态方法和实例方法

构造函数:

const Person = function (birthYear) {
  this.birthYear = birthYear;
}

实例方法 -> 可用

Person.prototype.calcAge = function () {
  2037 - this.birthYear);
} 

静态方法 -> 不可用

Person.hey = function(){
  console.log('Hey')
}

类:

class PersonCl {
    constructor(birthYear) {
      this.birthYear = birthYear;
    } 

    /**
     * Instance Method -> Available to instances
     */
    calcAge() {  
        console.log(2037 - this.birthYear);
    }
    
    /**
     * Static method -> Not available to instances
     */
    static hey() { 
        console.log('Static HEY ! ');
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接