1.静态方法
除了静态变量,类也可以有静态方法。
常规方法绑定到类的对象(实例),可以引用类的普通(非静态)变量(以及静态变量和方法)。静态方法绑定到类的静态对象,只能访问类的静态变量和/或其他静态方法。
要在类上调用普通(非静态)方法,必须首先创建该类的对象,然后在该对象上调用该方法。您不能在类而不是对象上调用普通方法。
例子:
您不能在类上调用非静态方法! |
---|
|
但是要调用静态方法,类的静态对象只要简单存在就足够了(而且在类加载到内存后一直存在)。这就是为什么 main() 方法是静态的。它绑定到类的静态对象,所以你不需要创建任何对象来调用它。
声明一个方法为static,需要在方法头之前写上static关键字。该构造的一般外观如下:
static Type name(parameters)
{
method code
}
例子:
代码 | 笔记 |
---|---|
|
Java 机器 main 使用如下命令调用该方法Solution.main() : 在静态方法 test() 中调用静态方法main() 。 |
要从另一个类调用静态方法,需要在静态方法名前指定类名。该构造的一般外观如下:
Type name = ClassName.methodName(arguments)
例子:
代码 | 静态方法 |
---|---|
|
|
|
|
|
|
2.静态与普通(非静态)方法
静态方法和普通方法有什么区别?
普通方法绑定到普通对象(类的实例),而静态方法则不是。普通方法可以访问其实例中的变量,但静态方法不能:它只是没有关联的实例。
两种方法的区别如下表所示:
能力/财产 | 普通方法 | 静态方法 |
---|---|---|
绑定到类的实例 | 是的 | 不 |
可以调用类的普通方法 | 是的 | 不 |
可以调用类的静态方法 | 是的 | 是的 |
可以访问类的普通变量 | 是的 | 不 |
可以访问类的静态变量 | 是的 | 是的 |
可以在对象上调用 | 是的 | 是的 |
可以在课堂上被调用 | 不 | 是的 |
如果这些方法受到如此严重的限制,为什么还需要这些方法?答案是这种方式也有它的优势。
首先,您不需要传递任何对象引用来访问静态方法和变量。
其次,有时您只需要一个变量实例。例如,System.out
(System 类的静态输出变量)。
第三,有时您甚至需要在创建对象之前调用方法。例如,Java 机器甚至在创建类的实例之前就调用 main() 方法开始执行程序。
绑定到类的实例
当一个普通方法被调用时,一个参数——调用该方法的对象——被隐式地传递给它。这个参数称为this
. 这个隐式参数(对调用方法的对象的引用)将普通方法与静态方法区分开来。
静态方法没有这个隐式参数,所以不能this
在静态方法内部使用关键字,也不能在静态方法内部调用非静态方法。根本没有地方可以获得对类实例的引用。
可以调用类的普通方法
一个普通的方法总是有隐式this
参数,所以你总是有一个对调用该方法的对象的引用。每当您在另一个普通方法中调用一个普通方法时,this
都会使用隐式参数进行该调用。例子
代码 | 怎么运行的 |
---|---|
|
|
这就是为什么不能从静态方法调用普通方法的原因。this
静态方法中根本没有命名的隐式变量。
或者想象另一种情况:在我们的程序中还没有创建我们类的任何一个对象。我们可以调用我们类的静态方法吗?是的。而这个静态方法是否可以调用一个普通的(非静态)方法呢?
好吧,我们会在什么对象上调用它?毕竟,我们类的一个实例还不存在!
可以调用类的静态方法
静态方法可以从任何地方调用——从程序中的任何地方。这意味着它们可以从静态方法和普通方法中调用。这里没有限制。
可以访问类的普通变量
您可以从普通方法访问类的普通变量,因为它可以通过隐式参数轻松获得对类实例的引用this
。
静态方法不知道它应该使用类的哪个实例来获取普通变量的值。更一般地,我们很容易遇到调用静态方法但尚未在程序中创建该类的单个实例的情况。
因此,静态方法不能访问类的普通变量。
假设一个静态方法调用了一个普通方法。该普通方法应该调用什么对象?
没人知道!这就是为什么你不能在不传递对对象的引用的情况下从静态方法调用普通方法的原因!
可以访问类的静态变量
调用静态变量的情况与调用静态方法的情况相同。可以从程序中的任何地方访问静态变量。这意味着您可以从静态方法和普通方法访问它们。
可以在对象上调用
静态方法和普通方法都可以在对象上调用。可能的普通方法调用——实际上,这是调用普通方法的唯一方法。也可以在对象上调用静态方法:在这种情况下,编译器自己确定变量的类型并根据其类型调用静态方法:
代码 | 编译器如何看待它 |
---|---|
|
|
|
|
|
|
可以在课堂上被调用
您只能调用类的静态方法。要调用普通方法,您需要引用该类的实例。因此,您不能使用此构造调用普通方法:ClassName.methodName(arguments)
GO TO FULL VERSION