Effectively? Because unlike methods, fields cannot be overridden. Fundamentally: It makes no sense.
When you override a method, it is not about just the name. Only if everything matches, does it count. Let's try this:
public class Example {
@Override public boolean equals(Example other) { return false; }
}
The above will not compile because that is not the same as Object's own equals. The parameter type doesn't match. As a language syntax sugar nicety to you, you may 'widen' your specs (you can specify a more specific return type, and a more general parameter type, and you can elect to declare fewer checked exceptions), but if you inspect a class file, you'll find the exact method signature of your parent class in your own.
Expanding that notion to fields, a field isn't just the name. It's the name and its type.
When you declare int x;
in class Parent
, that field exists in all instances of Parent, including any instances of a subclass of Parent. In other words, your class Child extends Parent
class already has an x field. There's nothing you can do to change its essence. That's in sharp contrast to methods, where you can redefine what it does by changing the code. This just doesn't apply to fields: Fields don't have code.
Because of all that, when you declare a method that has the same signature as a method declaration of a parent, that is an override, but:
When you declare a field that has the same signature (same name, same type) as a parent class's field, you are declaring a second, separate field whose name shadows the field of the parent.
The behaviour is just completely different. The simple solution is to simply not declare int x
, at all, in child. Write into parent's x
, if you must. The above explains why this behaviour is so very different.