Java 方法重写返回null

Java 方法重写返回null,java,overriding,Java,Overriding,我是Java的新手。所以这个问题听起来可能很简单,但我被卡住了,无法理解为什么这段代码返回null和0.0 文件:Transport.java public class Transport { private String name; private double price; public Transport(String name, double price) { this.name = name; this.pri

我是Java的新手。所以这个问题听起来可能很简单,但我被卡住了,无法理解为什么这段代码返回null和0.0

文件:Transport.java

public class Transport { private String name; private double price; public Transport(String name, double price) { this.name = name; this.price = price; } public String carName() { return name; } public double carPrice(){ return price; } } 公共交通{ 私有字符串名称; 私人双价; 公共交通(字符串名称,双倍价格){ this.name=名称; 这个价格=价格; } 公共字符串carName(){ 返回名称; } 公共双卡普里斯(){ 退货价格; } } 文件:Car.java

public class Car extends Transport{ protected String name; protected double price; public Car(String name, double price) { super(name, price); } @Override public String carName(){ return name; } @Override public double carPrice(){ return price * 1.5; } } 公车扩展交通{ 受保护的字符串名称; 保护双重价格; 公共汽车(字符串名称,双倍价格){ 超级(名称、价格); } @凌驾 公共字符串carName(){ 返回名称; } @凌驾 公共双卡普里斯(){ 退货价格*1.5; } } 文件:Main.java

public class Main { public static void main(String[] args) { Car c = new Car("CarBrand", 1000); System.out.println("Name: " + c.carName()); System.out.println("Price: " + c.carPrice()); } } 公共班机{ 公共静态void main(字符串[]args){ c车=新车(“卡伯兰”,1000); System.out.println(“名称:+c.carName()); System.out.println(“价格:+c.carPrice()); } } 输出

Name: null Price: 0.0 名称:空 Price:0.0您在
Car
中声明了单独的
name
Price
变量,并且从未给它们赋值-它们与
Transport
中声明(并初始化)的
name
Price
变量不同。基本上,您可以看到
String
double
的默认值。去掉
汽车中的那些额外变量
,并使用
super.carPrice()
运输
获取原始价格:

public class Car extends Transport {    
    public Car(String name, double price) {
        super(name, price);
    }

    @Override
    public double carPrice(){
        return super.carPrice() * 1.5;
    }
}
请注意,根本不需要重写
carName()
,除非您确实希望它改变行为


我还建议将
carName()
carPrice()
更改为
getName()
getPrice()
,使其更为地道。

问题是
name
有两个不同的变量,一个在车内,一个在运输中
c.carName()
返回未初始化的
Car.name

如果你的汽车等级是下面的那一级,它就可以工作了

public class Car extends Transport {
    public Car(String name, double price) {
        super(name, price);
    }

    @Override
    public double carPrice(){
       return price * 1.5;
    }        
}

变量
price

也是如此,派生类
Car
隐藏了类
Transport
的实例变量。因此,尽管您从
Transport
类继承了正确初始化的数据成员,但是初始化为默认值的
Car
类实例变量将从
Car
类方法返回您正在通过super()将这两个值传递给父类传输。所以

终将定局

传输类属性名称和价格


您不需要在Car类中声明这两个属性。Car将通过继承隐式地具有这两个属性。这里您正在为Car创建单独的属性。

当您创建Car类型的“c”对象时,您只为类Transport的“name”和“price”变量赋值(因为在构造函数中您调用super(name,price),它将从父类调用构造函数)

这里:c.carName()从Car类调用该方法(因为它被标记为@Override),这个方法从Car类返回'name'变量的值。在你的例子中,这个变量是空的,因为你还没有给它赋值。 您为Transport类型的'name'变量指定了值“CarBrand”。
“price”变量也是如此。

使用super将通过调用构造函数super(名称、价格)返回已存储在父类中的值,使用super后跟点表示法将访问父类方法。因此super.carPrice()将返回存储在父类中的值

此外,@Override注释只应用于更改父类中的现有方法,在子类中使用新功能,而不更改名称。因此,对于@Overide for carname(),您需要调用super.carname(),因为您正在从父类返回值

简言之,之所以会得到null和0.0,是因为在应该访问父类值时,您正在访问子类值

    public class Car extends Transport{
        
        protected String name;
        protected double price;
    
        public Car(String name, double price) {
            super(name, price);
        }
    
        @Override
        public String carName(){
            return name;
        }
    
        @Override
        public double carPrice(){
            return price * 1.5;
        }
    }

Your class should be 

       public class Car extends Transport{
        
         
        
            public Car(String name, double price) {
                super(name, price);
            }
        
            
            public String getName(){
                return super.carName();
            }
        
            @Override
            public double carPrice(){
                return super.carPrice()* 1.5;
            }
        }
你的主课现在应该是

public class Main {
  public static void main(String[] args) {

    Car c = new Car("CarBrand", 1000);
    System.out.println("Name: " + c.getName());
    System.out.println("Price: " + c.carPrice());

  }
}

好的,明白了。但是,从
Car
类调用方法
carPrice()
的正确方法是什么呢?@Gerardas:我不知道你的意思。我在回答中向您展示了如何从
Car
调用
Transport
实现来调用原始方法,该方法只返回
price
变量。。。使用我答案中的代码替换你的类,这就是你所需要做的。当你写评论时,上面没有代码。。。谢谢你的帮助!:)@Gerardas调用继承的方法的正确方法是:c.carPrice()-如果它在您的上下文中可见(取决于它是公共的、包私有的、受保护的),它就会像您在Car中声明的一样出现。此更正会导致错误:
线程“main”中出现异常java.lang.Error:未解决的编译问题:Transport.price字段不可见
如果您的类名为“Car”,通常不需要在属性名称中添加“Car”。您可能还希望尽早习惯重要的bean模式,并通过“get”和“set”前缀属性访问器。考虑这样的名字:Car MyCar=新车(…)、MyCar、GETNAME()
public class Main {
  public static void main(String[] args) {

    Car c = new Car("CarBrand", 1000);
    System.out.println("Name: " + c.getName());
    System.out.println("Price: " + c.carPrice());

  }
}