我对Java中类型检查和方法查找的功能感到困惑。
据我了解,类型检查是在编译时完成的,方法查找是在运行时完成的。
类型检查基于引用对象的声明类型,而方法查找则基于引用的实际类型。
因此,假设MyInt类是GaussianInt类的超类,如下所示:
class MyInt
{
private int n;
public myInt(int n)
{
this.n = n;
}
public int getval()
{
return n;
}
public void increment(int n)
{
this.n += n;
}
public myInt add(myInt N)
{
return new myInt(this.n + N.getval());
}
public void show()
{
System.out.println(n);
}
}
class GaussInt extends MyInt
{
private int m; //represents the imaginary part
public GaussInt(int x, int y)
{
super(x);
this.m = y;
}
public void show()
{
System.out.println( "realpart is: " + this.getval() +" imagpart is: " + m);
}
public int realpart()
{
return getval();
}
public int imagpart()
{
return m;
}
public GaussInt add(GaussInt z)
{
return new GaussInt(z.realpart() + realpart(), z.imagpart() + imagpart());
}
并假设在main方法中我们具有以下内容:
GaussInt z = new GaussInt(3,4);
MyInt b = z;
MyInt d = b.add(b)
System.out.println("the value of d is:"+ d.show());
最后,在print语句内的show语句中将使用哪种add方法?
据我了解,b被声明为MyInt,但实际上它是GuaussInt。类型检查器仅看到b为MyInt类型,并且具有add(MyInt),因此代码有意义并可以编译。
但是随后在运行时,方法查找发现b为GaussInt类型,并且它具有两个add()方法,因此它将通过查看方法签名使用add(GaussInt)方法,并生成一个GaussInt。但是d是MyInt类型,方法查找会认为它不起作用,然后返回add(Myint)吗?
程序的编译和运行背后的机制如何工作?
答案 0 :(得分:1)
据我了解,b被声明为MyInt,但实际上, 高斯诠释
您正确。 b
的引用类型为MyInt
,但它指向GaussInt
类型的对象。
但是在运行时,方法查找发现b是类型 GaussInt,它有两个add()方法,因此它将使用add(GaussInt) 通过查看方法签名获得方法GaussInt。但 d是GaussInt类型,方法查找将认为它不起作用,然后 它会返回添加(Myint)吗?
由于GaussInt
中的add方法采用的是GaussInt
类型的引用,而不是MyInt
类型的引用。因此b.add(b)
将调用MyInt
类型的add方法。由于gaussInt有两种添加方法,一种采用类型为MyInt
的参数,另一种采用类型为GaussInt
的参数。因此它将调用add
的{{1}}方法。
您要实现的目标是方法替代。为了使它起作用,方法签名应该相同。也就是说,父类和子类方法在各个方面都应该匹配,除了子类方法的返回类型可以是父类方法的返回类型的myInt(superclass)
为了达到您提到的目的,即subtype
应该调用b.add(b)
的{{1}}方法,使两个类中add方法的参数类型相同。
您还应该了解动态多态性(运行时检查)和静态多态性(编译时类型检查)。