方法覆盖返回 null

Posted

技术标签:

【中文标题】方法覆盖返回 null【英文标题】:Method override returns null 【发布时间】:2014-11-21 22:52:26 【问题描述】:

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

文件:Transport.java

公共类运输

        私有字符串名称;
        私人双倍价格;

    公共交通(字符串名称,双倍价格)
        this.name = 名称;
        this.price = 价格;
    

    公共字符串车名()
        返回名称;
    

    公共双车价格()
        退货价格;
    

文件:Car.java

公共类汽车扩展运输

    受保护的字符串名称;
    受保护的双倍价格;

    公共汽车(字符串名称,双倍价格)
        超级(名称,价格);
    

    @覆盖
    公共字符串车名()
        返回名称;
    

    @覆盖
    公共双车价格()
        返回价格 * 1.5;
    

文件:Main.java

公共类主要
    公共静态无效主要(字符串[]参数)

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

        System.out.println("名称:" + c.carName());
        System.out.println("价格:" + c.carPrice());
    

输出

名称:空
价格:0.0

【问题讨论】:

如果你的类名为“Car”,通常不需要将“car”放在属性名称中。您可能还想尽早习惯重要的 bean 模式,并通过“get”和“set”为属性访问器添加前缀。考虑这样的名称: Car myCar = new Car(...), myCar.getname() 【参考方案1】:

您已经在Car 中声明了单独 nameprice 变量,并且从未为它们赋值 - 它们与 name 和 @987654325 不同@在Transport 中声明(和初始化)的变量。所以你基本上看到了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() 以更加地道。

【讨论】:

好的,知道了。但是从Car类调用方法carPrice()的正确方法是什么? @Gerardas:我不确定你的意思。我在答案中向您展示了如何从Car 调用Transport 实现以调用原始方法,该方法仅返回price 变量...使用我的答案中的代码替换您的类,那就是所有你需要做的。 写评论的时候上面没有代码...谢谢你的帮助! :) @Gerardas 调用继承方法的正确方法是:c.carPrice() - 如果它在您的上下文中可见(取决于它是否是公共的、包私有的、受保护的),它只会就像你在 Car 中声明一样。【参考方案2】:

问题是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也是如此

【讨论】:

这个更正给出了错误:Exception in thread "main" java.lang.Error: Unresolved compilation problem: The field Transport.price is not visible【参考方案3】:

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

【讨论】:

【参考方案4】:

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

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

最终会设置

运输类属性名称和价格。

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

【参考方案6】:

使用 super 将通过调用构造函数 super(name, price) 返回您已经存储在父类中的值,使用 super 后跟点符号将访问父类方法。所以 super.carPrice() 会返回父类中存储的值。

另外,@Override 注释应该只用于更改父类中的现有方法,并在子类中使用新功能而不更改名称。因此,对于 carname() 的 @Overide,您需要调用 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());

  

【讨论】:

以上是关于方法覆盖返回 null的主要内容,如果未能解决你的问题,请参考以下文章

覆盖equals时总要覆盖hashCode

2.对于所有对象都通用的方法_EJ

无法使用自定义类返回类型覆盖方法

Java方法覆盖重写

在Java中,如果返回类型分别是原始类型及其包装类,是不是可以覆盖方法?

被覆盖的 Web API 方法返回“方法不允许”