Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么是「;“非静态法”;错误和“怎么做?”;这";工作_Java_Oop_Compiler Errors_Instance Variables_Class Members - Fatal编程技术网

Java 什么是「;“非静态法”;错误和“怎么做?”;这";工作

Java 什么是「;“非静态法”;错误和“怎么做?”;这";工作,java,oop,compiler-errors,instance-variables,class-members,Java,Oop,Compiler Errors,Instance Variables,Class Members,我有几个非常基本的Java问题,我想最终一劳永逸地理解它们。我有以下简短的代码: public class VeryBasicJava{ public static void main(String[] args){ int x = 3; int y = 4; swapMe(x, y); } private void swapMe(int a, int b){ int a; int b;

我有几个非常基本的Java问题,我想最终一劳永逸地理解它们。我有以下简短的代码:

public class VeryBasicJava{
    public static void main(String[] args){
        int x = 3;
        int y = 4;
        swapMe(x, y);
    }
    private void swapMe(int a, int b){
        int a;
        int b;
        int tmp = a;
        this.a = b;
        this.b = a;
    }
}
当我编译时,我得到了可怕的“非静态方法swapMe(int,int)不能从静态上下文引用”错误。另外,我得到“a已经在swapMe(int,int)中定义”和“b已经在swapMe(int,int)中定义”

我需要的是“非静态方法”错误,它是如何(为什么)产生的,以及如何避免它

此外,我假设您可以使用“swapMe”方法中的“a”和“b”变量执行我试图执行的操作。我想我可以传入'a'和'b',但也可以创建新的变量'a'和'b',并用“this”关键字引用它们

我知道这是非常基本的,但这两个“问题”是我在Java中遇到的两个主要问题,并且由于某些原因,似乎无法正确地学习


感谢大家花时间阅读本文。祝您度过愉快的一天。

这意味着方法
swapMe()
是一个实例方法,您需要
VeryBasicJava
类的实例来调用它,如下所示:

VeryBasicJava instance = new VeryBasicJava();
int x = 3; int y = 4;
instance.swapMe(x, y);
    int a; //this is the first argument
    int b; //this is the second argument
    int a; //this is the first line of your function
    int b; //this is the second line of your function
 private void swapMe(int a, int b){
    int tmp = a;
    a = b;
    b = tmp;
 }
private void swapMe(VeryBasicJava this, int a, int b){
    //              ^^^^^^^^^^^^^^^^^^^^
    // ...
或者,您可以将
swapMe()
声明为
static
,这样您就不需要先创建实例:

private static void swapMe(int a, int b)

类是对象的模板。类的实例(即和对象)有自己的非静态变量和方法版本

静态方法和字段不绑定到类的任何特定实例


因此,如果没有要调用该方法的实例,那么从静态方法调用类实例方法是没有意义的。在您的示例中,
是对实例的引用,但您没有实例……

对于第二个问题,当您创建函数时,它会为其所有变量创建自己的小堆栈。它的参数包含在该堆栈中-因此,您的堆栈如下所示:

VeryBasicJava instance = new VeryBasicJava();
int x = 3; int y = 4;
instance.swapMe(x, y);
    int a; //this is the first argument
    int b; //this is the second argument
    int a; //this is the first line of your function
    int b; //this is the second line of your function
 private void swapMe(int a, int b){
    int tmp = a;
    a = b;
    b = tmp;
 }
private void swapMe(VeryBasicJava this, int a, int b){
    //              ^^^^^^^^^^^^^^^^^^^^
    // ...
这就是为什么你会遇到问题——你在你的论点之后声明的a和b与你的论点相冲突,而不是“this.a”和“this.b”


您的第一个问题已经得到回答。

swapMe需要一个VeryBasicJava实例来调用它。静态不需要

从该对象外部,您可以调用:VeryBasicJava.main(args)

从对象外部,您需要执行(new VeryBasicJava()).swapMe(a,b)来调用该方法

在swapMe中出现错误的原因是因为您定义了两次这些变量。签名行在该命名空间中为您声明了它们。在该方法中,您已经有一个int a。然后在第一行,再次声明int a

您希望在交换中执行的操作如下:

VeryBasicJava instance = new VeryBasicJava();
int x = 3; int y = 4;
instance.swapMe(x, y);
    int a; //this is the first argument
    int b; //this is the second argument
    int a; //this is the first line of your function
    int b; //this is the second line of your function
 private void swapMe(int a, int b){
    int tmp = a;
    a = b;
    b = tmp;
 }
private void swapMe(VeryBasicJava this, int a, int b){
    //              ^^^^^^^^^^^^^^^^^^^^
    // ...

当然,变量a和b只存在于该方法中,因此一旦该方法结束,您的工作就会丢失。如果您想保留它,请将变量设置为类变量,并为它们提供getter和setter。

由于提供了修复程序,我想添加:

静态方法只能调用其他静态方法,并且只能直接访问静态变量(在java中)


要调用非静态方法,您必须创建该类的实例,然后调用这些方法。

您只有几个小问题。你在评论中提到你对C有一些经验,所以我将尝试做一些基本的类比。
static
方法(例如
main
)的行为类似于普通的C函数。但是,非
静态
方法采用一个隐藏参数:
this
,该参数引用该方法要操作的对象。当您编写这样的方法时:

private void swapMe(int a, int b) {
    // ...
它的真正含义是:

VeryBasicJava instance = new VeryBasicJava();
int x = 3; int y = 4;
instance.swapMe(x, y);
    int a; //this is the first argument
    int b; //this is the second argument
    int a; //this is the first line of your function
    int b; //this is the second line of your function
 private void swapMe(int a, int b){
    int tmp = a;
    a = b;
    b = tmp;
 }
private void swapMe(VeryBasicJava this, int a, int b){
    //              ^^^^^^^^^^^^^^^^^^^^
    // ...
因为
这个
参数是经过特殊处理的,所以有一种特殊的语法用于在对象上调用非
静态
方法:

    myInstance.swapMe(someA, someB);
//  ^^^^^^^^^^        ^^^^^  ^^^^^
//     this             a      b
而且由于
swapMe
未声明为
static
,因此希望像上面那样调用它

main
VeryBasicJava
类中声明这一事实并不意味着您自动拥有一个
VeryBasicJava
对象。同样,由于
main
static
,因此它与普通的C函数类似:

void VeryBasicJava_main(...) {
    // ...
1: private void swapMe(int a, int b) {
2:     int a;
3:     int b;
4:     int tmp = a;
5:     this.a = b;
6:     this.b = a;
7: }
要创建对象的实例,请使用
new

VeryBasicJava vbj = new VeryBasicJava();
这类似于C中的
malloc

VeryBasicJava *vbj = malloc(sizeof(VeryBasicJava));
VeryBasicJava_construct(vbj);
通过实例,您可以调用一个方法:

vbj.swapMe(spam, eggs);
你的另一个问题有两个:一个是范围问题,另一个是成员问题。您可能知道,作用域是指变量存在的位置。采取以下措施:

void VeryBasicJava_main(...) {
    // ...
1: private void swapMe(int a, int b) {
2:     int a;
3:     int b;
4:     int tmp = a;
5:     this.a = b;
6:     this.b = a;
7: }
调用此方法时,会发生以下情况:

  • 根据调用
    swapMe
    中指定的值,将创建
    a
    b

  • 将创建一个新的
    A
    ,位于
    swapMe
    本地,默认值为
    0
    。此
    a
    隐藏参数
    a
    ,无法区分它们

  • 创建了一个新的
    b
    ,也是严格本地的。它也有默认的
    0
    值,并隐藏参数
    b

  • 创建
    tmp
    ,其值设置为新声明的
    a
    的值,因此它也是
    0

  • [见下文]

  • [见下文]

  • 局部变量
    a
    b
    不复存在,参数
    a
    b
    也不复存在

  • 在第5行和第6行中,尝试使用语法
    this.a
    来引用本地
    a
    ,而不是参数。尽管这种语法存在于Java中,但它并不符合您的意思。参数被视为与局部变量完全相同,因此与其区分这两个类别,不如将这两个类别区分开来