Java 从超类调用方法的超关键字和类名之间的差异
请原谅我的问题,因为我试图搜索使用super关键字和类名从super类调用方法之间的差异,但找不到答案。 我的问题是,我试图将Java作为一门学习课程来学习,并使用链接中的一个示例:使用示例#3,下面是我编写的代码: 我创建了一个名为Vehicle的超级类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
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
$
因此,这是有意义的,因为在您的示例中,非静态变量可以访问非静态方法速度()