Si un champ de la classe parente est à nouveau défini, avec le même nom, mais pas nécessairement avec le même type, dans la classe dérivée, le champ hérité de la classe parente est masqué.
Le masquage d'un champ est plus une maladresse de programmation qu'une caractéristique utile : il vaut mieux s'abstenir d'utiliser cette possibilité. Par exemple, si l'on a
class A { int p=1; } class B extends A { int p=2; // À ÉVITER }
le champ p de A est masqué par la définition d'un autre champ de même nom par B (il en serait de même si p était déclaré d'un autre type dans B). Si b est une variable (ou une expression) de type B, l'expression b.p accède au champ p défini dans B, de valeur 2 (figure 1.11). Cependant, les champs de A peuvent être obtenus au moyen d'un transtypage : (A)b est une expression de type A, donc l'expression ((A)b).p accède au champ de A, qui a pour valeur 1.
Le mécanisme de la liaison tardive ne concerne ni les champs ni les méthodes de classe : seul le type de l'expression détermine le champ accédé, et non le type de la valeur. Ainsi, si l'on déclare
A a = new B();
l'expression a.p accède au champ p défini dans A, pas à celui de B, bien que la valeur affectée à a soit une référence à une instance de B. Contrairement aux méthodes d'instance, qui peuvent être redéfinies, les méthodes de classe peuvent être masquées, de façon analogue aux champs, mais il n'est pas recommandé de le faire :
class A { static int f() { return 1; } } class B extends A { static int f() { // À ÉVITER return 2; } }