# 变量遮盖

> 原文： [https://javabeginnerstutorial.com/core-java-tutorial/variable-shadowing/](https://javabeginnerstutorial.com/core-java-tutorial/variable-shadowing/)

今天，我们将探讨 Java 的一项罕见功能：**变量遮盖**

首先，让我们定义什么是遮盖字段或方法：

当**被遮盖**时，该字段被视为

*   其声明类的子类声明一个具有**同名**的字段
*   在本地范围内声明具有相同名称和类型的变量
*   用相同名称和类型声明方法参数/参数

## 局部变量遮盖

```java
public class MyClass
{
	private int count = 10;

	private void localVariable()
	{
		int count = 5;

		System.out.println("count = "+ count);
	}

	public static void main(String[] args)
	{
		MyClass test = new MyClass();
		test.localVariable();
	}
}
```

上面的代码将输出

> `count=5`

因为在**第 7 行**中声明的`count`**局部变量**遮盖了在类级别声明的变量*计数*。 如果要访问实例变量，则需要添加`this`关键字。

```java
private void localVariable()
{
	int count = 5;

	System.out.println("count = "+ this.count);
}
```

## 方法参数遮盖

即使我们对此不太关注，这种情况也很常见。 下面是一个简单的获取器定义

```java
private int count;

public void setCount(int count)
{
	this.count = count;
}
```

`this`关键字是解决歧义所必需的。 如果没有`this`，编译器将无法知道我们是否要为其自身分配*计数*方法参数值。 如果删除`this`关键字，则仍然会收到编译警告。

## 超类字段遮盖

让我们考虑以下类：

```java
public class SuperClass
{
	protected String val = "SUPER_VAL";

	protected void display()
	{
		System.out.println("val = "+this.val);
	}
}

public class ChildClass extends SuperClass
{
	private String val;

	public ChildClass(String value) {
		this.val = value;
	}

	public static void main(String[] args)
	{
		ChildClass child = new ChildClass("CHILD_VAL");
		child.display();
	}

}
```

执行给出：

> `value = SUPER_VAL`

在`SuperClass`中声明了`val`字段，但在`ChildClass`中被遮盖了，因为后者声明了另一个具有相同**名称和类型**的字段。 尽管已使用`CHILD_VAL`实例化了`ChildClass`，但执行`child.display()`却给您`SUPER_VAL`。

原因很简单。 创建子实例时，有 2 个变量`val`。 通过构造器，来自`SuperClass`的一个具有值`SUPER_VAL`，来自`ChildClass`的一个具有注入值`CHILD_VAL`。

调用`display()`方法时，由于它是在**超类**中定义的，因此它是超类的**上下文**中的`val`字段。输出显示`SUPER_VAL`也就不足为奇了。

```java
public class ChildClass extends SuperClass
{
	private String val;

	public ChildClass(String value) {
		this.val = value;
		super.val = value;
	}

	public static void main(String[] args)
	{
		ChildClass child = new ChildClass("CHILD_VAL");
		child.display();
	}

}
```

在上面修改的代码中，我们将`SuperClass`中隐藏的`val`字段的值强制为`super.val = value`，输出给出：

> `value = CHILD_VAL`

现在让我们在层次结构中添加另一个类

```java
public class AncestorClass
{
	protected String val = "ANCESTOR_VAL";
}

public class SuperClass extends AncestorClass
{
	protected String val = "SUPER_VAL";
}

public class ChildClass extends SuperClass
{
	private String val = "CHILD_VAL";

	public void displayVal()
	{
		System.out.println("val = " + super.val);
	}

	public static void main(String[] args)
	{
		ChildClass child = new ChildClass();
		child.displayVal();
	}
}
```

显然，输出将显示

> `val = SUPER_VAL`

现在的问题是：如果要显示祖先类的`val`值，该怎么办？ 显然，仅`super`关键字引用了类层次结构中的第一个父类。

救援人员来了。 实际上，我们可以将代表当前类实例的**关键字强制**应用于类层次结构中的特定类型！

```java
public class ChildClass extends SuperClass
{
	private String val = "CHILD_VAL";

	public void displayVal()
	{
		System.out.println("val = " + ((AncestorClass) this).val);
	}

	public static void main(String[] args)
	{
		ChildClass child = new ChildClass();
		child.displayVal();
	}
}
```

这次，我们确实有

> val = ANCESTOR_VAL

