方法覆盖返回null

时间:2014-09-26 20:30:39

标签: java override late-binding

我是Java的新手。所以问题可能听起来很简单,但我陷入困境,无法弄清楚为什么这段代码会返回null和0.0?

file: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;
    }
}

文件: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;
    }
}

file: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());
    }
}

输出

Name: null
Price: 0.0

6 个答案:

答案 0 :(得分:8)

您已在name中声明了单独的 priceCar个变量,并且从未为它们分配过值 - 它们与name中声明(并初始化)priceTransport个变量。因此,您基本上会看到Stringdouble的默认值。在Car中删除这些额外变量,并使用super.carPrice()Transport获取原始价格:

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()更加惯用。

答案 1 :(得分:1)

您正在通过super()将这两个值传递给父类Transport。所以

Car c = new Car("CarBrand", 1000);

最终将设置

  

传输类属性名称&价。

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

答案 2 :(得分:0)

问题是name有两个不同的变量,一个在Car中,一个在Transport中。 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

也是如此

答案 3 :(得分:0)

派生类Car隐藏了类Transport的实例变量。虽然您从Transport类继承了正确初始化的数据成员,但是Car类初始化为默认值的实例变量将从Car类方法返回

答案 4 :(得分:0)

在创建Car类型的'c'对象时,仅为Transport类的'name'和'price'变量分配值(因为在构造函数中,您调用super(name,price)会从中调用构造函数)您的家长班)。

在这里:c.carName()从Car类中调用该方法(因为标记为@Override),并且此方法从Car类返回'name'变量的值。在您的情况下,此变量为null,因为您尚未为其分配任何值。 您为“运输”类型的“名称”变量分配了“ CarBrand”值。 对于“ price”变量也是如此。

答案 5 :(得分:0)

使用super将通过调用构造函数super(name,price)返回您已经存储在父类中的值,使用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());

  }
}