1. Overview
1.概述
When we work with Java, we often run into problems that demand a deeper understanding of the language’s intricacies. One common puzzle is the error message: “Non-static method … cannot be referenced from a static context.” This error may seem daunting to beginners and can even confuse experienced programmers.
在使用 Java 时,我们经常会遇到一些问题,需要对该语言的复杂性有更深入的了解。其中一个常见的难题就是错误信息:”不能从静态上下文引用非静态方法……”。这个错误可能让初学者望而生畏,甚至会让经验丰富的程序员感到困惑。
In this tutorial, we’ll delve into the reasons behind this error and explore ways to resolve it.
在本教程中,我们将深入研究这一错误背后的原因,并探索解决方法。
2. Introduction to the Problem
2.问题介绍
As usual, let’s understand the problem quickly through an example. Let’s say we have the ToolBox class:
像往常一样,让我们通过一个例子来快速理解这个问题。假设我们有一个 ToolBox 类:
class ToolBox {
private String concat(String str1, String str2) {
return str1 + str2;
}
static String joinTwoStrings(String str1, String str2) {
return concat(str1, str2); //<-- compilation error
}
}
The ToolBox class has the concat() method. We didn’t want everybody to call it, so we declared it a private method. Also, we have a static method joinTwoStrings(), which invokes the concat() method internally.
ToolBox 类中有 concat() 方法。我们不希望每个人都调用它,因此将其声明为 private 方法。此外,我们还有一个 静态方法 joinTwoStrings(),它在内部调用 concat() 方法。
However, if we compile it, a compilation error occurs:
但是,如果我们对其进行编译,就会出现编译错误:
java: non-static method concat(java.lang.String,java.lang.String) cannot be referenced from a static context
Next, let’s understand what this error message means and see how to solve it.
接下来,让我们了解一下这条错误信息的含义,并看看如何解决它。
3. What Does the Error Mean?
3.错误意味着什么?
Before we tackle the non-static method issue, let’s understand the concept of a static context in Java.
在解决非静态方法问题之前,让我们先了解一下 Java 中静态上下文的概念。
In Java, the keyword “static” is used to declare elements that belong to the class rather than instances. Static members are shared among all instances of a class and can be accessed without creating an object of the class.
在 Java 中,关键字”static“用于声明属于类而非实例的元素。静态成员在类的所有实例中共享,无需创建该类的对象即可访问。
However, on the other hand, non-static methods are associated with instances of a class and cannot be invoked without creating an object. They can rely on the specific state of an object, and their behavior may vary depending on the values of instance variables.
然而,另一方面,非静态方法与类的实例相关联,在不创建对象的情况下无法调用。它们可能依赖于对象的特定状态,其行为可能会根据实例变量的值而变化。
The compilation error “Non-static method … cannot be referenced from a static context” occurs when an attempt is made to call a non-static method from a static context. This static context could be a static method, a static block, or the main() method, which is always static.
当尝试从静态上下文调用非静态方法时,会出现编译错误 “Non-static method … cannot be referenced from a static context”(非静态方法…不能从静态上下文引用)。
Now that we understand why the problem happens, let’s see how to fix it.
既然了解了问题发生的原因,我们就来看看如何解决它。
4. Resolving the Problem
4.解决问题
We’ve learned that non-static members cannot be invoked without creating an instance. Then, depending on the requirement, we have a couple of ways to fix the problem.
我们已经知道,如果不创建实例,就无法调用非静态成员。那么,根据不同的需求,我们有几种方法来解决这个问题。
Next, let’s take a closer look at them.
接下来,让我们仔细看看它们。
4.1. Calling Static Method From a Static Context
4.1.从静态上下文调用静态方法
The first solution is turning the instance method into a static method. If we’ve done that transition, there won’t be any problem if we call it from a static context:
第一种解决方案是将实例方法转化为静态方法。如果我们完成了这一转变,那么在静态上下文中调用它就不会有任何问题:
class ToolBox {
private static String concatStatic(String str1, String str2) {
return str1 + str2;
}
static String joinTwoStrings(String str1, String str2) {
return concatStatic(str1, str2);
}
}
As we can see in the code above, to make it easier to spot the changes we made, we used the new method name concatStatic. Further, we made it a static method by adding the static keyword.
正如我们在上面的代码中所看到的,为了更容易发现我们所做的更改,我们使用了新的方法名称 concatStatic。此外,我们还添加了 static 关键字,使其成为一个静态方法。
Now, if we call the static joinTwoStrings() method, we get the expected result:
现在,如果我们调用静态 joinTwoStrings() 方法,就会得到预期的结果:
assertEquals("ab", ToolBox.joinTwoStrings("a", "b"));
4.2. Creating an Instance and Calling the Instance Method
4.2.创建实例和调用实例方法
Sometimes, the requirement doesn’t allow us to change the instance method to a static one. In this case, we can refactor the static method, first creating an instance and then calling the instance method:
有时,需求不允许我们将实例方法更改为静态方法。在这种情况下,我们可以重构静态方法,首先创建一个实例,然后调用实例方法:
class ToolBox {
private String concat(String str1, String str2) {
return str1 + str2;
}
static String creatingInstanceJoinTwoStrings(String str1, String str2) {
ToolBox toolBox = new ToolBox();
return toolBox.concat(str1, str2);
}
}
Now, if we call the static creatingInstanceJoinTwoStrings() method, it works properly:
现在,如果我们调用静态 creatingInstanceJoinTwoStrings() 方法,它就会正常工作:
assertEquals("ab", ToolBox.creatingInstanceJoinTwoStrings("a", "b"));
Alternatively, we can consider whether the creatingInstanceJoinTwoStrings() method in this class must be static. If not, we can also convert the static method into a regular instance method:
另外,我们还可以考虑 该类中的 CreatingInstanceJoinTwoStrings() 方法是否必须是静态方法。如果不是,我们还可以 将静态方法转换为常规实例方法:
class ToolBox {
private String concat(String str1, String str2) {
return str1 + str2;
}
String instanceJoinTwoStrings(String str1, String str2) {
return concat(str1, str2);
}
}
With this fix, the instanceJoinTwoStrings() method is no longer static. So, it can invoke the private concrete() instance method directly.
通过此修复,instanceJoinTwoStrings() 方法不再是静态的。因此,它可以直接调用私有 concrete() 实例方法。
Of course, when we utilize instanceJoinTwoStrings(), we must first create a ToolBox object:
当然,在使用 instanceJoinTwoStrings() 时,我们必须首先创建一个 ToolBox 对象:
ToolBox toolBox = new ToolBox();
assertEquals("ab", toolBox.instanceJoinTwoStrings("a", "b"));
5. Can a Static Method Be Called by an Instance?
5.静态方法可以被实例调用吗?
We’ve learned we cannot reference non-static members from a static context. Some might ask, can we call a static method in an instance method?
我们已经知道,在静态上下文中不能引用非静态成员。有人可能会问,我们可以在实例方法中调用静态方法吗?
Next, let’s give it a test:
接下来,让我们来测试一下:
class ToolBox {
private static String concatStatic(String str1, String str2) {
return str1 + str2;
}
String instanceCallStaticJoinTwoStrings(String str1, String str2) {
return concatStatic(str1, str2);
}
}
As we can see in the code above, the instance method instanceCallStaticJoinTwoStrings() calls the private static method concatStatic().
从上面的代码中我们可以看到,实例方法 instanceCallStaticJoinTwoStrings() 调用了私有静态方法 concatStatic() 。
The code compiles. Further, if we test it, it works properly:
代码可以编译。此外,如果我们对其进行测试,它也能正常运行:
ToolBox toolBox = new ToolBox();
assertEquals("ab", toolBox.instanceCallStaticJoinTwoStrings("a", "b"));
So, the answer to the question is yes.
所以,问题的答案是肯定的。
In Java, calling a static method from an instance method is allowed. This is because static members aren’t tied to a specific instance. Instead, they’re associated with the class itself and can be invoked using the class name. In our code, we called concatStatic(str1, str2) without the class name “ToolBox.concatStatic(str1, str2)” since we’re already in the ToolBox class.
在 Java 中,允许从实例方法调用静态方法。这是因为静态成员并不与特定实例绑定。相反,它们与类本身相关联,可以使用类名调用。在我们的代码中,我们调用了 concatStatic(str1, str2),但没有使用类名”ToolBox.concatStatic(str1, str2)”,因为我们已经在 ToolBox 类中。
6. Conclusion
6.结论
In this article, we explored the compilation error “Non-static method cannot be referenced from a static context,” delving into its causes and examining various resolutions to address and fix this issue.
在本文中,我们探讨了编译错误 “无法从静态上下文引用非静态方法”,深入分析了其原因,并研究了解决和修复此问题的各种方法。
As always, the complete source code for the examples is available over on GitHub.
与往常一样,这些示例的完整源代码可在 GitHub 上获取。