如你所知,Java是一种类型严格的语言.除了用于基本类型的标准转换和自动升级,类型兼容也是被严格执行的.因此,一个类类型的引用变量通常不能引用一个其他类型的对象.例如,考虑下面的程序:
public class test2
{
// @param args
public static void main(String args[])
{
X x = new X(10);
X x2;
Y y = new Y(5);
x2 = x;//ok, both of same type
x2 = y;//error not of same type
}
}
class X
{
int a;
X(int i){ a = i;}
}
class Y
{
int a;
Y(int i){ a = i;}
}
- public class test2
- {
- // @param args
- public static void main(String args[])
- {
- X x = new X(10);
- X x2;
- Y y = new Y(5);
-
- x2 = x;//ok, both of same type
- x2 = y;//error not of same type
- }
- }
- class X
- {
- int a;
- X(int i){ a = i;}
- }
- class Y
- {
- int a;
- Y(int i){ a = i;}
- }
public class test2
{
// @param args
public static void main(String args[])
{
X x = new X(10);
X x2;
Y y = new Y(5);
x2 = x;//ok, both of same type
x2 = y;//error not of same type
}
}
class X
{
int a;
X(int i){ a = i;}
}
class Y
{
int a;
Y(int i){ a = i;}
}
这里,尽管X类和Y类本质上是一样的,但是不能把一个Y对象赋值给一个X引用,因为他们的类型不同.总之,对象引用变量只能引用自己类型的对象.
然而,Java的严格类型却有一个例外,即可以把对超类派生子类对象的引用赋给一个超类的引用变量.换句话说,超类引用可以引用子类对象,如下所示:
public class test2
{
// @param args
public static void main(String args[])
{
X x = new X(10);
X x2;
Y y = new Y(5);
x2 = x;//ok, both of same type
x2 = y;//still ok,because y is derived form x
// x2.b = 1; // error x doesn't have a b member
}
}
class X
{
int a;
X(int i){ a = i;}
}
class Y extends X
{
int b;
Y(int i)
{
super(i);
b = i;
}
}
- public class test2
- {
- // @param args
- public static void main(String args[])
- {
- X x = new X(10);
- X x2;
- Y y = new Y(5);
-
- x2 = x;//ok, both of same type
- x2 = y;//still ok,because y is derived form x
- // x2.b = 1; // error x doesn't have a b member
- }
- }
- class X
- {
- int a;
- X(int i){ a = i;}
- }
- class Y extends X
- {
- int b;
- Y(int i)
- {
- super(i);
- b = i;
- }
- }
public class test2
{
// @param args
public static void main(String args[])
{
X x = new X(10);
X x2;
Y y = new Y(5);
x2 = x;//ok, both of same type
x2 = y;//still ok,because y is derived form x
// x2.b = 1; // error x doesn't have a b member
}
}
class X
{
int a;
X(int i){ a = i;}
}
class Y extends X
{
int b;
Y(int i)
{
super(i);
b = i;
}
}
这里,X派生了Y,所以允许赋给x2一个对Y对象的引用.
哪些成员可以访问是由引用变量的类型(而不是他引用的对象类型)决定的,理解这一点十分重要.也就是说,当一个子类对象的引用被赋给一个超类引用变量时,只有权访问对象的那些超类定义的部分.这就是为什么即使x2引用了一个Y对象后,还不能访问b的原因.考虑一下就会发现这是合理的,因为超类不知道子类增加了什么,这也就是程序中代码的最后一行被注释调的原因.
尽管前面的讨论看似深奥,但却有一些重要的实际用途.我们这里就其中一点进行介绍,其他的将在后面设计方法重写时讨论.
把子类引用赋给超类变量常用于在类层次结构中调用构造函数时.如你所知,对于类而言,定义一个把类的对象作为形参的构造函数是很常见的.这就允许类构造对象的副本.这种类的子类就可以利用这一功能,例如,考虑下面的X和Y.这两个类都添加了把对象作为形参的构造函数.
public class test2
{
// @param args
public static void main(String args[])
{
Y one = new Y(10);
Y two = new Y(one);
System.out.println("one.a="+one.a+" one.b="+one.b);
System.out.println("two.a="+two.a+" two.b="+two.b);
}
}
class X
{
int a;
X(int i){ a = i;}
X(X obj)
{
a = obj.a;
}
}
class Y extends X
{
int b;
Y(int i)
{
super(i);
b = i;
}
Y(Y obj)
{
super(obj.a);
b = obj.b;
}
}
- public class test2
- {
- // @param args
- public static void main(String args[])
- {
- Y one = new Y(10);
- Y two = new Y(one);
-
- System.out.println("one.a="+one.a+" one.b="+one.b);
- System.out.println("two.a="+two.a+" two.b="+two.b);
-
- }
- }
- class X
- {
- int a;
- X(int i){ a = i;}
- X(X obj)
- {
- a = obj.a;
- }
- }
- class Y extends X
- {
- int b;
- Y(int i)
- {
- super(i);
- b = i;
- }
-
- Y(Y obj)
- {
- super(obj.a);
- b = obj.b;
- }
- }
public class test2
{
// @param args
public static void main(String args[])
{
Y one = new Y(10);
Y two = new Y(one);
System.out.println("one.a="+one.a+" one.b="+one.b);
System.out.println("two.a="+two.a+" two.b="+two.b);
}
}
class X
{
int a;
X(int i){ a = i;}
X(X obj)
{
a = obj.a;
}
}
class Y extends X
{
int b;
Y(int i)
{
super(i);
b = i;
}
Y(Y obj)
{
super(obj.a);
b = obj.b;
}
}
输出:
one.a=10 one.b=10
two.a=10 two.b=10
- one.a=10 one.b=10
- two.a=10 two.b=10
one.a=10 one.b=10
two.a=10 two.b=10
该程序中,通过one构造了two,因此他们是一样的.