方法覆盖返回 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
中声明了单独 name
和 price
变量,并且从未为它们赋值 - 它们与 name
和 @987654325 不同@在Transport
中声明(和初始化)的变量。所以你基本上看到了String
和double
的默认值。去掉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的主要内容,如果未能解决你的问题,请参考以下文章