Java 从超类调用方法的超关键字和类名之间的差异

Java 从超类调用方法的超关键字和类名之间的差异,java,methods,constructor,super,Java,Methods,Constructor,Super,请原谅我的问题,因为我试图搜索使用super关键字和类名从super类调用方法之间的差异,但找不到答案。 我的问题是,我试图将Java作为一门学习课程来学习,并使用链接中的一个示例:使用示例#3,下面是我编写的代码: 我创建了一个名为Vehicle的超级类 public class Vehicle { Vehicle() { System.out.println("Vehicle constructor created"); } public void

请原谅我的问题,因为我试图搜索使用super关键字和类名从super类调用方法之间的差异,但找不到答案。 我的问题是,我试图将Java作为一门学习课程来学习,并使用链接中的一个示例:使用示例#3,下面是我编写的代码:

我创建了一个名为Vehicle的超级类

public class Vehicle {
    Vehicle() {
        System.out.println("Vehicle constructor created");
    }

    public void speed() {
        int a = 20;
        System.out.println(a);
    }

}
然后创建了一个名为Bike的子类,其代码如下:

public class Bike extends Vehicle {
    int speed;

    Bike(int speed1) {
        this.speed = speed1;
        System.out.println(speed1);
        super.speed();

    }

    public static void main(String args[]) {
        Bike b = new Bike(10);

    }

}
在Bike构造函数下的子类中,我使用super.speed()从super(Vehicle)类调用speed方法。现在,如果我将这一行更改为Vehicle.speed(),我会得到一个错误,指出我需要将speed方法设置为static

我不想让我的方法成为静态的,我想知道它们之间的区别


干杯,

非静态方法只能在对象的特定实例上调用。这就是为什么调用
Vehicle.speed()
只能在
speed
方法是静态的情况下工作。之所以可以调用
super.speed()
,是因为在构造函数中,您已经构造了vehicle对象,并且基本上正在对正在构造的对象调用方法

对于上面的例子,我认为调用
super.speed()
是最好的方法


另外,由于没有重写
speed
方法的超级实现,因此可以轻松调用
this.speed()
speed()
。这种方法意味着,如果您曾经决定
Bike
speed
方法中需要不同的功能,那么您的特定实现将被调用,而不是默认实现

这两种结构并不等同

调用
Vehicle.speed()
时,编译器正在名为
Vehicle
的类中查找名为
speed()
的静态方法。静态方法不属于该类的任何实例。不能在静态方法内使用任何实例变量。您尚未在
Vehicle
类中定义名为
speed()
的静态方法,因此不存在
Vehicle.speed()
。因此,会出现编译错误


调用
super.speed()
时,您不会像前一种情况那样寻找静态方法:使用
super
语法时要调用的实际方法是在当前对象的超类中定义的实例方法(在您的情况下称为
speed()
)。也就是说,
super.speed()
是在当前对象的超类中定义的实例方法(与
this.speed()
不同,后者是在当前对象的实际类中定义的名为
speed()
的实例方法)。换句话说,它将调用类
车辆
中定义的方法
speed()
,但
参数将是当前对象
b
引用的参数。

如果要将方法直接与类名一起使用,则必须将方法指定为静态

public static void speed() {
    int a = 20;
    System.out.println(a);
}

您可以在子类中创建类Vehicle和access speed方法的对象,如下所示

Bike(int speed1) {
    this.speed = speed1;
    System.out.println(speed1);
    Vehicle vehicle = new Vehicle();
    vehicle.speed();
}

直接使用类名调用方法意味着您要调用一个静态方法,该方法与类的任何对象无关,而是与它自身的类相关。 这就是为什么编译器告诉您该方法必须是静态的

至于您的问题,当您创建子类(本例中为自行车类)的对象时,始终会创建其父类的对象,并在此基础上创建特定的子对象

类似于,当您创建
自行车
时,始终会创建一辆倒车
车辆
,并以此为基础创建
自行车
。否则,
自行车
就不会是
车辆

因此,通过
super
调用一个方法意味着,你告诉编译器在类上调用这个方法,这个类被用作生成这个
Bike
类的基(父),我从中调用这个方法


当您按类名调用方法时,您告诉编译器调用
Vehicle
类的此方法,该方法与任何
Vehicle
对象/实例(显然与任何子对象(例如
Bike
对象或实例)无关

hi super是一个关键字,用于访问子类中的超类方法。 此超级关键字主要在重写方法时使用

范例

class A    
{       
    method m()        
}

class B extends A     
{       
   method m()        

   method m1()   
   {        
       super.m()          
   }        
}

class C
{
   public static void main(String args[])   
   {   
        B b = new B(); 

        b.m()  // calls method m() in class B
        b.m1()  // calls method m() in class A because method m is pointing to  super class method 
     }   
}

您需要实例来调用实例(非静态)方法

super是父类的实例。简单地说,类名不是实例(它是整个类的静态上下文)

[超级是父类的实例?]

Jon skeet没有“父实例”这类东西,但我怀疑“实例”这个术语

super的变量首先被初始化,然后轮到child来决定是共享同一个变量/方法(即
返回this.i;
在这种方法中,当child调用时将返回super.i,而不是this.i)还是重写它

import java.util.Random;
class Love {

    int i = 1;
    int hole() {
        return this.i;
    }
}

class Main extends Love {

    void wrapper() {
        System.out.println(super.i); //1
        System.out.println(this.i); //2
        super.i = new Random().nextInt(50) + 2; //to avoid compiler pre-optimizing hard coded return value in hole(), so we set again.
        System.out.println(super.i); //23
        i = 3; //2nd attempt override
        this.i = 3; //3rd attempt override
        System.out.println(hole()); //23, super "instance" keep its own version of this.i
    }

    int i = 2; //1st attempt oveeride
    public static void main(String[] args) {
        new Main().wrapper();
    }

}
因此,很明显,当子级重写时,super仍保留其自己的版本,因此IMHO super可以大致将其视为父实例,只是与普通实例的区别在于它是一个具有一定使用限制的关键字(例如super.super.i不允许,direct print super不允许)。另一个区别是,变量值将在每个实例中同步,因为子实例可能如上所述共享该变量值

您可以尝试在静态方法内打印super.variable\u name,它将输出super是一个非静态变量

$ javac Bike.java 
Bike.java:132: error: non-static variable super cannot be referenced from a static context
        System.out.println(super.dummy); 
                           ^
Bike.java:132: error: cannot find symbol
        System.out.println(super.dummy); 
                                ^
  symbol: variable dummy
2 errors
$ 
因此,这是有意义的,因为在您的示例中,非静态变量可以访问非静态方法速度()