使用 Java 中的两个 类 关于继承的基本查询
A Fundamental Query about Inheritance using two classes in Java
请考虑Java中的以下代码:
class a
{
int i = 10;
int j = 20;
}
class b extends a
{
int i = 100;
int j = 200;
}
public class Test
{
public static void main(String args[])
{
a a1 = new a();
b b1 = new b();
a1 = b1;
System.out.println("a1.i is " + a1.i);
System.out.println("a1.j is " + a1.j);
System.out.println("b1.i is " + b1.i);
System.out.println("b1.j is " + b1.j);
}
}
我得到的输出是
a1.i is 10
a1.j is 20
b1.i is 100
b1.j is 200
我的问题是:为什么语句a1=b1没有把a1.i变成100,a1.j变成200?语句 a1 = b1 没有任何改变吗?
您正在将 class B
的实例向上转换为 class A
.
的实例
执行后
a1 = b1
那么从技术上讲,您无法通过变量 a1
访问 b1
的字段。那是因为 a1
,无论它是否来自 b1
的赋值 "comes",实际上都是 之后的 class A
的一个实例向上转换它。
考虑一下:您在 class A
和 class [=13] 中定义了字段 i
和 j
的一个实例这一事实=] 并不意味着它们完全相关。
我认为您打算执行以下操作(概念上):
class A {
int i;
int j;
public A() {
i = 10;
j = 20;
}
}
class B extends A {
public B() {
i = 100;
j = 200;
}
}
那就试试这个
A a1 = new A();
B b1 = new B();
a1 = b1;
System.out.println("a1.i is " + a1.i); // 100
System.out.println("a1.j is " + a1.j); // 200
System.out.println("b1.i is " + b1.i); // 100
System.out.println("b1.j is " + b1.j); // 200
如果您这样做,那么 class B
正在设置从 class A
继承的字段。届时,您将获得预期的行为。这是因为即使你将 B
的实例向下转换为 A
的实例,你总是在改变从 A
继承的字段,而不是 B
你现在的例子。
a
的实例具有字段 i
(10) 和 j
(20)。
b
的实例具有 a
具有的那些字段,以及另外两个字段,也容易混淆地称为 i
和 j
,其值为 100 和 200。
所以 b1
有 { a::i=10, a::j=20, b::i=100, b::j=200 }
.
如果您访问 b1.i
,您会从对象 b1
中获得 b::i
字段(如您所料)。
您的 a1
变量是 a
类型(即使它包含 b
的实例),因此您只能使用它访问 a
的字段。因此,如果您访问 a1.i
,您会从对象(即 10)中获取 a::i
字段,而不是 b::i
字段(即 100)。
准备好,因为你问的问题需要一个复杂的答案。
Java 在 Jave Virtual Machine.In 中是 运行 你问题的上下文,关于 java 和 JVM,你需要记住两件事。
- Java 方法是 运行 时间绑定
- Java 类型转换(和装箱、拆箱)是 运行时间绑定
- Java class 参数是编译时绑定
- Java 转换会给你错误 当且仅当 .铸造在逻辑上是不正确的。
现在让我们分析您的代码。
a a1 = new a();
b b1 = new b();
//This type cast happens a Runtime and not compile time although the check is done at compile time and your code passes the check!
a1 = b1;
//These variables are binded at compile.And hence possess the value
that they possesed during compie time.This means that they have
the original values which they were defined with
System.out.println("a1.i is " + a1.i);
System.out.println("a1.j is " + a1.j);
System.out.println("b1.i is " + b1.i);
System.out.println("b1.j is " + b1.j);
现在说明这个的影响和修改,将这个添加到你的代码中并测试它。
class Test{
public static void main(String args[])
{
a a1 = new a();
b b1 = new b();
a1 = b1;
System.out.println("a1.i is " + a1.i);
System.out.println("a1.j is " + a1.j);
System.out.println("b1.i is " + b1.i);
System.out.println("b1.j is " + b1.j);
a1.print();
//shall print b
b1.print();
//shall print b
}
}
}
class a
{
int i = 10;
int j = 20;
public void print(){
System.out.println("a");
}
}
class b extends a
{
int i = 100;
int j = 200;
public void print(){
System.out.println("b");
}
}
编辑:努力寻找一个写得很好的 SO 答案来解决差异,但没有遇到 any.So this tutorial 很好地解释了这个概念。
请考虑Java中的以下代码:
class a
{
int i = 10;
int j = 20;
}
class b extends a
{
int i = 100;
int j = 200;
}
public class Test
{
public static void main(String args[])
{
a a1 = new a();
b b1 = new b();
a1 = b1;
System.out.println("a1.i is " + a1.i);
System.out.println("a1.j is " + a1.j);
System.out.println("b1.i is " + b1.i);
System.out.println("b1.j is " + b1.j);
}
}
我得到的输出是
a1.i is 10
a1.j is 20
b1.i is 100
b1.j is 200
我的问题是:为什么语句a1=b1没有把a1.i变成100,a1.j变成200?语句 a1 = b1 没有任何改变吗?
您正在将 class B
的实例向上转换为 class A
.
执行后
a1 = b1
那么从技术上讲,您无法通过变量 a1
访问 b1
的字段。那是因为 a1
,无论它是否来自 b1
的赋值 "comes",实际上都是 之后的 class A
的一个实例向上转换它。
考虑一下:您在 class A
和 class [=13] 中定义了字段 i
和 j
的一个实例这一事实=] 并不意味着它们完全相关。
我认为您打算执行以下操作(概念上):
class A {
int i;
int j;
public A() {
i = 10;
j = 20;
}
}
class B extends A {
public B() {
i = 100;
j = 200;
}
}
那就试试这个
A a1 = new A();
B b1 = new B();
a1 = b1;
System.out.println("a1.i is " + a1.i); // 100
System.out.println("a1.j is " + a1.j); // 200
System.out.println("b1.i is " + b1.i); // 100
System.out.println("b1.j is " + b1.j); // 200
如果您这样做,那么 class B
正在设置从 class A
继承的字段。届时,您将获得预期的行为。这是因为即使你将 B
的实例向下转换为 A
的实例,你总是在改变从 A
继承的字段,而不是 B
你现在的例子。
a
的实例具有字段 i
(10) 和 j
(20)。
b
的实例具有 a
具有的那些字段,以及另外两个字段,也容易混淆地称为 i
和 j
,其值为 100 和 200。
所以 b1
有 { a::i=10, a::j=20, b::i=100, b::j=200 }
.
如果您访问 b1.i
,您会从对象 b1
中获得 b::i
字段(如您所料)。
您的 a1
变量是 a
类型(即使它包含 b
的实例),因此您只能使用它访问 a
的字段。因此,如果您访问 a1.i
,您会从对象(即 10)中获取 a::i
字段,而不是 b::i
字段(即 100)。
准备好,因为你问的问题需要一个复杂的答案。
Java 在 Jave Virtual Machine.In 中是 运行 你问题的上下文,关于 java 和 JVM,你需要记住两件事。
- Java 方法是 运行 时间绑定
- Java 类型转换(和装箱、拆箱)是 运行时间绑定
- Java class 参数是编译时绑定
- Java 转换会给你错误 当且仅当 .铸造在逻辑上是不正确的。
现在让我们分析您的代码。
a a1 = new a();
b b1 = new b();
//This type cast happens a Runtime and not compile time although the check is done at compile time and your code passes the check!
a1 = b1;
//These variables are binded at compile.And hence possess the value
that they possesed during compie time.This means that they have
the original values which they were defined with
System.out.println("a1.i is " + a1.i);
System.out.println("a1.j is " + a1.j);
System.out.println("b1.i is " + b1.i);
System.out.println("b1.j is " + b1.j);
现在说明这个的影响和修改,将这个添加到你的代码中并测试它。
class Test{
public static void main(String args[])
{
a a1 = new a();
b b1 = new b();
a1 = b1;
System.out.println("a1.i is " + a1.i);
System.out.println("a1.j is " + a1.j);
System.out.println("b1.i is " + b1.i);
System.out.println("b1.j is " + b1.j);
a1.print();
//shall print b
b1.print();
//shall print b
}
}
}
class a
{
int i = 10;
int j = 20;
public void print(){
System.out.println("a");
}
}
class b extends a
{
int i = 100;
int j = 200;
public void print(){
System.out.println("b");
}
}
编辑:努力寻找一个写得很好的 SO 答案来解决差异,但没有遇到 any.So this tutorial 很好地解释了这个概念。