为什么其他方法可以“静态”但构造函数不能?

时间:2011-10-15 20:22:58

标签: java static constructor

我不明白为什么main方法必须是静态的。我理解静态变量,但我很难掌握静态方法。是否存在静态方法,以便可以在两个不会相互冲突的类中创建两个具有相同名称的方法?

另外,我不明白为什么我不能创建静态构造函数。

有人可以帮助解释这个概念吗?

16 个答案:

答案 0 :(得分:80)

Java有 [静态构造函数] static initialization blocks,可以将其视为“静态构造函数”:

class Foo {
  static String Bar;
  static {
     // "static constructor"
     Bar = "Hello world!";
  }
}

在任何情况下,必须静态的主类中唯一的方法是main方法。这是因为在没有的情况下调用首先创建“主类”的实例。一种常见的技术,也是我喜欢的技术,是快速走出的静态背景:

class Main {
   int argCount;

   // constructor
   public Main (String[] args) {
     // and back to boring ol' non-static Java
     argCount = args.length;       
   }

   void runIt () {
      System.out.println("arg count: " + argCount);
   }

   // must be static -- no Main instance created yet
   public static void main (String[] args) {
      Main me = new Main(args);
      me.runIt();
   }
}

另外,静态与“名字冲突”无关。静态方法(或变量)只是与类型的特定实例相关联的方法(或变量)。我建议您阅读Classes and Objects Java TutorialUnderstanding Instance and Class Variables部分。

快乐的编码。

答案 1 :(得分:24)

我正在分享“为什么java构造函数不是静态的”。

简单地说,“java构造函数总是非静态的”,因为,

构造函数的目的只是初始化/构造对象,并使继承成为可能。要做到这些,我们需要使用两个有用的java关键字(兼非静态变量),例如this和super。   我们将使用'this'来初始化对象。   我们/ Java将使用super(ofcourse super())来调用超类构造函数,以便首先创建超级对象(或Object类),然后创建子对象(因此继承)   如果构造函数是静态的,那么我们不能在构造函数中使用这两个关键字(非静态变量)(因为我们知道非静态的东西不能从静态上下文中引用)

所以java构造函数不应该是静态的。

答案 2 :(得分:7)

静态方法属于类,而不是对象。 main方法必须是静态的,因为在执行任何其他代码实例化任何对象之前,首先调用它。它提供了该程序的入口点。从对象的容器外部调用静态方法。静态类变量也是如此。整个类只存在一个副本,而不是成员变量,该变量为从类创建的每个对象创建一次。它们用于存储类的数据,例如已创建但未销毁的对象实例数。此数据属于该类。静态方法的一个很好的例子是单例模式,其中构造函数是私有的,只能由静态成员函数访问。类外的函数将无法复制此功能。此方法作用于类数据和对象,因此逻辑上属于同一个类。这一切都归结为封装。一个班级只对自己负责,只知道自己。

另一方面,对象方法意味着对与类的一个实例(对象)相关联的数据进行操作。构造函数是用于初始化对象并将其数据设置为初始状态的代码。在分配内存以存储新对象后立即(并自动)执行它们。即使您没有明确定义构造函数,也会执行一种“默认构造函数”,以便将对象的成员变量和对象的方法代码映射到新对象。

希望这有帮助。

答案 3 :(得分:7)

构造函数用于创建对象。

静态通常对所有对象都相同。

因此,如果我们有静态构造函数,则创建一个对象会影响所有其他现有对象。

静态方法仅引用静态变量。因此,您为创建对象提供的所有初始参数都将针对所有对象进行更改。没有必要创建类似的对象。

希望这有助于.... :)

答案 4 :(得分:1)

构造函数是对象的属性,而静态与对象无关。这就是静态构造函数之类的原因。但是我们有静态块来执行与构造函数类似的任务,即字段的初始化等。

答案 5 :(得分:1)

Bruce Eckel撰写的《 Thinking in Java,第4版》第272页上说:

²即使static关键字不是显式的,构造方法也是一个静态方法。准确地说,是在访问类的任何静态成员时首先加载该类。

更多上下文。

...每个类的已编译代码位于其自己的单独文件中。在需要代码之前,不会加载该文件。通常,您可以说“在首次使用时就加载了类代码”。通常是在构造该类的第一个对象时,但在访问静态字段或静态方法时也会发生加载。²

如果您考虑说静态方法不能使用同一类的非静态方法的规则,这很有道理。几个星期前,当我不明白如何使用Singleton模式时,如何在用于创建该类的新实例的静态方法中访问构造函数,使我产生了疑问。今天,我翻阅了这本书,偶然发现了这个解释。

从某种意义上讲,如果构造函数不是静态的,则首先需要该类的实例才能访问它,但是我想这可能会引发关于鸡肉的古老讨论。或鸡蛋。

希望有帮助!

答案 6 :(得分:0)

我写了一个简单的例子作为昨天相关问题的答案,可能有助于使事情更容易理解:what's the point of java constructor?

静态方法的要点是可以在不创建类实例的情况下调用它们,而“普通”实例方法与实例相关,并且不能在没有实例的情况下调用它们。

由于Main类的Main方法是程序的入口点,因此无法创建任何实例,因此您无法通过实例访问它。因此,它是静态的,因此它可以作为程序的开始运行。

答案 7 :(得分:0)

只需看一下这个链接,它肯定会帮助您理解: Why can't make a constructor static?

在创建对象时,在运行时调用构造函数。 所有对象的静态都相同,但所有对象都有自己的状态和属性。 因此,如果我们有静态构造函数,则创建一个对象会影响所有其他现有对象。 注意:static是类级别,而构造函数与对象相关。

e.g。

  public class Foo
    {
       String name;
       int id;
        // define constructors
           Foo (String name, int id)
        {
            this.name = name;
            this.id = id;
        }

          p s v m(String[] arg)
      {
          Foo f1 = new Foo("Amit",001);
          Foo f2 = new Foo("Rahul",002);
      }
    }

如果我们创建静态构造函数,那么两个对象(f1也)将包含有关name和id的最后更新值Rahul和002。

答案 8 :(得分:0)

构造函数不能是静态的,因为在OO语言中,创建对象的过程如下:

  • 分配对象
  • 调用构造函数初始化新分配的对象

构造函数不会在其他任何地方使用(并且类型安全的语言应该强制执行此操作),因此遵循构造函数将始终在非静态上下文中调用。

如果构造函数是静态的,它将不会接收对新分配的对象的引用,因此无法初始化它。

因此,构造函数总是非静态的(因为它总是从非静态上下文调用)并且必须始终是非静态的(否则它将无法执行其任务)。

答案 9 :(得分:0)

main(String[])方法有一个特定的原型,由Java运行时环境的工作方式决定。从命令行调用java MyApplication时,Java VM将查找该类中包含的静态main(String[])方法,以便执行该应用程序。如果找不到该方法,则Java VM无法将该类作为应用程序运行。这就是语言的定义方式。这也意味着Java VM 不会创建应用程序类的实例以便运行它。

现在,如果您希望您的类既可以作为独立应用程序使用,也可以作为由其他东西创建的实例,那么您可以让您的类实现Runnable接口,并提供{{1在新实例上执行main方法的方法。

run

现在任何类都可能创建public class MyRunnableThing implements Runnable { // Define whatever variables your runnable thing needs here as // private instance fields. /** Fulfills requirements of Runnable interface. */ public void run() { System.out.println( "I'm running..." ) ; } /** Also makes the class runnable from the console. */ public static void main( String[] args ) { MyRunnableThing runMeNow = new MyRunnableThing() ; runMeNow.run() ; } } 的实例,并使用其MyRunnableThing方法生成相同的行为执行run()

另见:Working with Static Constructor in Java。 Q& A中的一些亮点:

  • 构造函数用于创建类的实例,因此它是实例方法,而不是静态方法。
  • 您可以使用构造函数创建一个静态方法来创建类的实例。这就是时髦的新“建设者”课程的工作方式。
  • 您可以创建一个静态方法,返回持久的,唯一的单例实例。
  • 如果您的班级有静态成员,那么您可以创建一个静态初始值设定项来初始化这些成员的值。

答案 10 :(得分:0)

构造函数的目的是构造一个Object,即将类的实例变量初始化为默认值或初始化值。静态方法无法访问非静态实例变量。所以构造函数不是静态的。

答案 11 :(得分:0)

声明为static的方法不需要创建对象。由于我们没有为main方法创建对象,因此它被声明为static。

隐式调用

构造函数来初始化一个对象,因此没有静态构造函数的目的。

答案 12 :(得分:0)

Java不允许将构造函数声明为静态。以下是原因。

  1. 静态表示相同的类。即无法继承静态方法。

  2. 对于静态,不能使用“ this”引用(关键字)。 “ this”始终链接到对象。构造函数始终属于某个对象。

  3. 如果构造函数是静态的,则子类的对象无法访问。如果构造函数允许使用static,则可以在类中但不能通过子类访问它。

答案 13 :(得分:0)

静态属于类,构造函数属于对象

我们知道静态方法,块或变量属于该类。而构造函数属于该对象,并在使用new运算符创建实例时调用。由于构造函数不是类属性,因此有理由认为它不能是静态的。

答案 14 :(得分:0)

构造函数既不是完全静态的(类级别)也不是完全静态的(实例级)。

  • 与实例方法不同,构造函数不会被继承。
  • 与静态方法不同,构造函数可以引用this

那么,为什么不能声明构造函数static

好吧,我的看法是,(冗余)static关键字会造成混乱,并且没有任何作用。因此,他们决定不允许它。


关于静态初始化块可以视为构造函数的解释(IMO)在概念上是错误的。 (这类似于说实例初始化块是常规构造函数。这同样是错误的。)

静态初始化和构造 1 之间的主要区别是:

  • 静态初始化发生在不确定的时间 2 ;没有与new等效的类初始化功能,
  • 没有直接方法(构造函数)将参数传递给初始化代码
  • 没有从静态初始化期间发生的错误中恢复的实用方法。

1-假设,如果显式的类初始化 ,则具有静态构造函数是有意义的。但是缩小规模是因为应用程序需要显式“构造”他们使用的所有类……这太可怕了。

2-如果可以动态加载类,则可以控制一定程度,但是即使在当前类加载器中已经加载了该类并对其进行了初始化,尝试控制初始化也会失败。


我不明白为什么主要方法必须是静态的。

必须要让main方法充当应用程序的入口点。

问题是,如果main是一个实例方法,则需要在您的入口点类的顶部创建一个实例来调用main方法。但是,如何创建它呢?您会选择哪个构造函数?如果没有公共构造函数怎么办?

最重要的是,这就是Java的设计方式……早在1990年代……到目前为止,他们还没有看到改变这一需求的必要条件。


答案 15 :(得分:0)

第一,关键字static意味着所有标记为static的东西都必须是类级别的东西,只属于类。而构造函数属于对象,通常在我们使用时可能会调用它们new 运算符。所以我们现在知道构造函数甚至不是类属性,我们怎么可能将其标记为静态?

第二,静态构造函数违背了java中继承的全部目的。每次在我们创建子类对象之前,JVM都会自动调用超类构造函数来为要创建的子类对象做好准备.但是如果我们将构造函数标记为静态,子类将无法访问其超类的构造函数,因为它被标记为静态因此只属于类。