Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的继承和转换_Java_Inheritance_Casting - Fatal编程技术网

Java中的继承和转换

Java中的继承和转换,java,inheritance,casting,Java,Inheritance,Casting,我有一个关于Java中的继承和转换的问题。我有以下两个示例类和一个测试类,我在课后陈述我的问题: public class Automobile { public int var; public Automobile () { var = 1; } public String toString () { return "AUTOMOBILE: " + var; } } public class Porsche ext

我有一个关于Java中的继承和转换的问题。我有以下两个示例类和一个测试类,我在课后陈述我的问题:

public class Automobile {
    public int var;

    public Automobile () {
        var = 1;
    }

    public String toString () {
        return "AUTOMOBILE: " + var;
    }
}


public class Porsche extends Automobile {
    public int var;

    public Porsche () {
        var = 2;
    }

    public String toString () {
        return "PORSCHE: " + var;
    }
}

public class Test {
    public static void main (String [] args) {
        Porsche p = new Porsche();
        Automobile a = new Automobile();

        System.out.println ("(Automobile) p = " + (Automobile)p);

        System.out.println ("(Automobile) p.var = " + ((Automobile)p).var); 
    }
}
输出为:

(Automobile) p = PORSCHE: 2
(Automobile) p.var = 1
我不明白为什么在第二个声明中我们有1。不是应该是2点吗?因为在我在第一句话中将p转换为Automobile之后,我仍然将
PORSCHE:2
作为
p
的表示形式-我以以下方式理解这一点:

尽管如此,我还是将
p
铸造到了汽车
p
保持了它的“原始性质”-
p
是保时捷的一个等级对象,但是因为保时捷扩展了汽车,我们可以说p也是一辆汽车。因此,当我们显式地将其转换为Automobile时,它将继续使用其方法-in 我们的案例使用Porsche中定义的方法
toString()

另一方面,如果我写的是正确的,那么第二个print语句应该给出2而不是1


现在,这对我来说似乎是一个矛盾,但由于它在Java中工作,我似乎不理解在转换和继承过程中发生了什么

我相信在Java中实际上无法重写变量。子类实际上“隐藏”了变量
var

当您强制转换到
Automobile
时,您将获得
var
变量的超类版本。但是,
toString()
方法仍在查看实例版本的
var
变量

如果您从Porsche子类中删除了
public int var
,它应该可以正常工作


应该注意的是,使用公共实例变量不是一种好的做法,您应该始终创建getter/setter以具有适当的属性。

变量的阴影
var

您的
Porche.var
Automobile.var
是不同的变量


Porsche.toString()
方法使用
Porsche.var
,而cast告诉编译器使用
Automobile
版本。

对字段的访问不是多态的-它只取决于表达式的编译时类型

表达式((Automobile)p)具有编译时类型Automobile,因此使用它的字段。

在两个类中声明变量“var”,实际上会在内存中创建两个字段

“Porsche”的实例在内存中有两个“var”字段,一个是“Porsche”类,另一个是超级类“Automobile”。当您从已知的“Porsche”实例中引用“var”时,超级类的“var”字段将隐藏。如果将此实例强制转换为“Automobile”并引用“var”字段,则引用“Automobile”的var字段

字段中没有重写。同名的新字段盖过了超类的字段

要获得预期结果,您根本不应该在“Porsche”类中声明“var”字段。

但是:

如果您有一个返回父类对象的方法,它可以返回任何对象类型或扩展它的类(例如factory)。现在,如果这个方法返回一个子类B对象,而您没有将它转换为B,那么它的所有属性都将是父属性。如果将其强制转换为B,则其属性将是A和B属性

class A {
int a1,a2;
public A(){}


  public static A getInstance () {
  return new B() ;
  }
}
class B {
int b1,b2;
  public B() {}

}
 class Test{

 public static void main (String [] args) {

  A theA = A.getInstance() ; //here theA has only a1,a2 as attributes
  B theB = (B)theA    // here theB has b1,a2 and a1,a2 as attributes 
  }


}