为什么静态方法被认为是一种方法?

Car*_*ate 135 java methods static static-methods terminology

我正在为一门课程的一些代码写一个解释,并且不小心使用了这些单词method并且function可以互换.我决定回过头来修改措辞,但在我的理解中遇到了一个漏洞.

根据我的理解,子程序是一个function如果它不作用于一个类的实例(它的效果仅限于它的显式输入/输出),并且是一个method如果它在一个类的实例上运行(它可能携带)对实例造成不纯的副作用).

这里有关于这个主题的很好的讨论.请注意,根据接受的答案的定义,静态method实际上应该是一个函数,因为实例永远不会被隐式传递,并且它不能访问任何实例的成员.

虽然这是心灵,但是静态methods实际上不应该是函数吗?

根据他们的定义,他们不会对某一类的特定情况采取行动; 由于关系,他们只与班级"捆绑".我已经看到一些好看的网站将静态子程序称为"方法"(Oracle,Fredosaurus,ProgrammingSimplified),所以要么它们都忽略了术语,要么我错过了一些东西(我的猜测是后者) .

我想确保我使用正确的措辞.
任何人都能清楚这一点吗?

Rad*_*def 122

8.4.3.2的引用可能有所帮助:

声明的static方法称为类方法.

未声明的static方法称为实例方法 [...].

  • 类方法:与类相关联.
  • 实例方法:与实例关联.

Java只是希望你"思考面向对象".此外,静态方法可以访问可能包括状态的周围范围.在某种程度上,这个类就像一个对象本身.

  • 我很尴尬.我来自Scala并且仍然错过了这个类本身就像对象一样的事实.谢谢. (4认同)

小智 80

简单的答案是,当Java决定将所有东西称为"方法"时,他们并不关心理论计算机科学中的函数和方法之间的区别.

  • 尽管我喜欢这个答案的简单性,但我认为Radiodef的答案更加正确,因为它提到了类本身作为对象的关键点.谢谢你. (4认同)
  • 这个答案得到了如此多的赞成,我感到非常惊讶.首先,这个答案假装不存在类方法.其次,这几乎不是Java中引入的概念.例如,Smalltalk中已经存在类方法,这种方法在Java成为事物之前就存在了几十年. (4认同)
  • 那就对了.在包含Java 7之前,您甚至不会在[语言规范]中找到"功能"一词(https://docs.oracle.com/javase/specs/jls/se7/html/index.html) (3认同)
  • 有趣的是,这与早期语言不区分功能和子程序的决定是平行的. (2认同)

Tho*_* S. 26

静态方法并不完全是函数,区别是微妙的,但很重要.

只使用给定的输入参数的静态方法本质上的功能.

但静态方法可以访问静态变量和其它静态函数(也使用静态变量)以便静态方法可以具有状态这是其可通过定义一个函数根本不同的无状态.(附录:虽然程序员通常不太习惯使用"功能"作为定义,但计算机科学中的严格功能只能访问输入参数).因此,定义访问静态字段的这种情况,说静态方法总是函数是无效的.

证明使用"静态方法"的另一个不同之处在于,您可以在C派生中定义全局函数和可在任何地方访问的全局变量.如果您无法访问包含静态方法的类,则这些方法也是不可访问的.因此,与全局函数相比,"静态方法"的设计范围受到限制.

  • 我有点喜欢这个答案,但想更好地了解一些事情.这不是一个"纯粹"与"副作用"功能,而不是功能与方法吗?或者因为副作用是一种方法吗?我只是在这里集思广益. (2认同)
  • 这个答案是对的.但是,有人可能会争辩说,许多(大多数?)语言中的函数可以访问全局变量,因此它们通常不是严格无状态的(相同的输入,相同的输出).在Java静态方法的情况下,访问类变量可以被认为等同于访问"全局"(即不是函数/方法的本地)变量 - 类实例是一种命名空间. (2认同)
  • @leonbloy 像 Haskell 这样的 Pure [函数式编程语言](https://en.wikipedia.org/wiki/Functional_programming) 是完全无状态的;没有什么可以称为全局变量。 (2认同)

Mik*_*ark 17

在Java中,用户定义的类实际上是java.lang.Class的子类的实例.

在这个意义上说,静态方法安装到一个概念类的一个实例:它们连接到java.lang.Class的一个子类的实例.

考虑到这一点,术语"类方法"(Java的静态方法的替代名称)开始有意义.术语"类方法"可以在很多地方找到:Objective C,Smalltalk和JLS - 仅举几例.

  • @ Random832 - 有点.只要每个实例都有自己独立的类加载器,您就可以在同一个JVM中拥有同一Class子类的两个(或更多)实例.每个类加载器不能多次实例化同一个Class子类.它有点令人困惑,与经典OO概念的类比在这一点上开始变得有点薄. (2认同)

Joo*_*gen 11

在计算机科学中,功能明确映射到静态方法.但是类的"方法"有点通用,比如"成员"(字段成员,方法成员).有像这样的措辞

数据成员和方法成员有两个单独的名称空间:.x和.x()可以共存.

所以原因是,正如哲学Ludwig Wittgenstein所说,语言是一种具有不同语境的工具."方法"是上面引用的一个很好的绰号,用于对"成员"进行分类.


Ely*_*Ely 9

你的想法是正确的,这是有道理的.它只是Java社区中没有建立的术语.让我解释一些内部结构,可以帮助理解术语存在的原因.

Java是一种基于类的面向对象语言.方法始终是类或实例的成员(这也是对其他编程语言有效的一般语句).我们认为类和实例都是对象.

实例方法(动态)

您无法直接从类中调用此方法,您必须创建一个实例.每个实例都引用该方法.您可以使用完全相同的方法签名覆盖方法定义(在子类化时),即引用指向不同的方法(具有相同的签名,但可以具有不同的方法体).该方法是动态的.

类方法(静态)

您只能直接从类中调用此方法,即您不需要创建该类的实例.整个程序中只有一种全局定义.当方法声明为static时,您不能覆盖完全相同的方法签名,因为只有一个定义对整个程序有效.请注意,该方法是类对象本身的成员,实例具有对该方法的所有相同的唯一(和修复)引用.


muc*_*aho 7

这是对术语的另一种看法,使用Scala作为助记符:
在Scala中你有objects,它是隐式定义的类的单例实例1.

根据您的定义,我们可以调用这些属于这些object 方法的子例程,因为它们在类的单个实例上运行.
此外,该对象还将定义类A,并将对象A中的所有方法创建为类A上的静态方法(用于与Java连接) [2].

因此,我们可以说Java类A的静态方法访问与Scala单例实例相同的成员,根据您的定义,它们应该被称为A类的(静态)方法.