CodeGym /课程 /JAVA 25 SELF /访问修饰符与变量作用域

访问修饰符与变量作用域

JAVA 25 SELF
第 8 级 , 课程 5
可用

1. 引言

Java 中,就像在现实生活里,并非一切都应该对所有人随时开放。想象一下你的公寓:你肯定不希望邻居随便进你的卧室,对吧?在程序中我们也常常希望“关上某些门”,让外部无法访问某些变量或方法。

为此,Java 提供了访问修饰符——一些特殊的关键字,用来指明某个变量或方法可以被使用的范围:例如 publicprivate

主要访问修饰符

修饰符 可见范围
public
在类可见的任何地方(包括其他包、其他文件)
private
仅在同一个类内部
(无修饰符)
仅在同一个包内(即同一目录下的类中)

还有其他修饰符,但等我们讲到继承时再详细讨论。

实践示例

public class User 
{
    public String name;           // 对所有人可见
    private int age;              // 仅在 User 类内部可见

    public void sayHello() 
    {
        System.out.println("你好,我叫 " + name);
    }

    private void secretMethod() 
    {
        System.out.println("这是一个秘密方法!");
    }
}

说明:

  • name — 在任何可以使用 User 类的地方都可见。
  • age — 仅在 User 类内部可见。
  • sayHello() — 公有方法,可从任何其他类调用。
  • secretMethod() — 私有方法,无法从外部调用。

在真实任务中如何工作?
假设我们有一个表示银行账户的类。我们显然不希望任何人都能直接修改余额!因此余额变量应为 private,并提供专门的方法来操作它。

为什么不应该把一切都设为 public?

你可能会想:“干脆把一切都设为 public,省心!”但这会走向混乱。想象一下,任何人都能修改你的余额、用户名,甚至调用本应仅供内部使用的方法。在大型程序中,这会导致错误和“魔法”般的 bug。

Java 开发者的黄金法则:
先把一切设为 private,然后只对外暴露真正需要的部分。

2. 变量的作用域

作用域是变量“存在”并且可以被使用的代码区域。一旦离开这个区域,变量就“消失”了——仿佛它从未存在过。

Java 中,按作用域可以将变量分为:

  • 局部变量 — 在方法或代码块 { ... } 中声明。
  • 方法参数 — 在方法的圆括号中声明。
  • 类字段 — 在类中、但在方法之外声明。

如果变量在 {  } 内声明,
它只在该内可见,
在块外不可访问。
局部变量的作用域

局部变量

局部变量只在其声明的方法或代码块内存活。

void printSum(int a, int b) 
{
    int sum = a + b; // 局部变量
    System.out.println(sum);
}
// 此处 sum 已不存在!

在方法之外访问 sum 会导致编译错误:“无法找到变量 sum”。

方法参数

参数也是变量,但它们只在方法内部存活。

void greet(String name) 
{
    System.out.println("你好," + name);
}
// 此处 name 已不存在!

类字段(成员变量)

类字段在类内但在方法之外声明。它们在该类的所有方法中可见。

public class Counter 
{
    private int count = 0; // 类字段

    public void increment() 
    {
        count++; // 可以使用该字段
    }

    public int getCount() 
    {
        return count; // 同样可以使用该字段
    }
}

3. 变量遮蔽(Shadowing)

遮蔽(shadowing)是指在某个作用域内声明了一个与外部作用域同名的变量(或参数)。在这个内层作用域中,“新”的名字会遮蔽外层的名字,无法直接访问外层的值。

遮蔽示例:

class ShadowDemo 
{
    int value = 10; // 类字段

    void printValue() 
    {
        System.out.println(value);  // 10 — 输出类字段
        int value = 5; // 局部变量遮蔽了类字段
        System.out.println(value); // 输出 5,而不是 10
    }
}

在这个示例中,当我们写下 int value = 5; 时,声明了一个新的局部变量,它优先于同名的类字段。在 printValue() 方法内部访问 value 时,将使用局部变量而不是类字段。

如果确实需要访问类的静态字段,请使用类名作为前缀:

class ShadowDemo 
{
    static int value = 10; // 静态类字段 

    void printValue() 
    {
        System.out.println(value);      // 10 — 类字段
        int value = 5;
        System.out.println(value);      // 5 — 局部变量
        System.out.println(ShadowDemo.value); // 10 — 静态类字段,通过 'ShadowDemo'
    }
}

如果需要访问非静态类字段,请使用关键字 this。它指向当前对象实例。

class ShadowDemo 
{
    int value = 10;

    void printValue() 
    {
        System.out.println(value);      // 10 — 类字段
        int value = 5;
        System.out.println(value);      // 5 — 局部变量
        System.out.println(this.value); // 10 — 类字段,通过 'this'
    }
}

4. 实践:访问修饰符与作用域

让我们继续开发教学应用:一个简单的学生管理系统。我们将为字段和方法设置不同的访问修饰符。

示例:Student 类

public class Student 
{
    public String name;        // 学生姓名(对所有人可见)
    private int age;           // 年龄(仅在类内部可见)

    public Student(String name, int age) 
    {
        this.name = name;
        this.age = age;
    }

    public void sayHello() 
    {
        System.out.println("你好,我叫 " + name);
    }

    private void printSecret() 
    {
        System.out.println("我的年龄: " + age);
    }

    public void revealSecret() 
    {
        printSecret(); // 在类内部可以调用私有方法
    }
}

使用 Student 类

public class Main 
{
    public static void main(String[] args) 
    {
        Student s = new Student("Jimmy", 20);
        s.sayHello();       // OK:公有方法
        s.revealSecret();   // OK:公有方法,它在内部调用私有方法

        s.age = 30;      // 错误!字段 age 是私有的

        s.printSecret(); // 错误!方法 printSecret 是私有的
    }
}

5. 使用访问修饰符与作用域时的常见错误

错误 1:全部设为 public —— 混乱从此开始!
如果把所有字段和方法都设为公有,你就会失去对数据被谁、以何种方式修改的控制。请将字段设为 private,只对外暴露必要内容。

错误 2:尝试在变量作用域之外使用它。
例如,在方法内声明了变量,却试图在外部访问——会得到编译错误。局部变量只在自己的 { ... } 块中存活。

错误 3:命名冲突(变量遮蔽)。
如果在方法中声明了与类字段同名的变量,很容易混淆你实际在使用哪个变量。使用 this 来明确指向类字段:this.value

错误 4:从其他类访问 private 方法或字段。
如果方法或字段被标记为 private,它们只在同一个类内可访问。从外部访问会导致编译错误。

错误 5:忽略了循环或代码块中的作用域。
在循环或任何 { } 块内声明的变量只在该块内存活。块外它不存在。

1
调查/小测验
方法第 8 级,课程 5
不可用
方法
方法的声明和调用
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION