专栏首页技术从心Java 中变量的作用域

Java 中变量的作用域

一、开头

变量的作用域是一个程序的重要组成部分。因为它决定了某个时候每个地方某个变量是否可访问。与 C/C++ 一样。静态语言的作用域在编译期就是确定的。而且独立于函数调用堆栈。

类 ( class ) 是 Java 程序的基本组成单元。而类又通过 包 ( package ) 来组织。因此 Java 中的作用域可以分为以下几个部分。

二、成员变量 ( 类级作用域 )

成员变量 就是 Java 中的变量 中所提到的 实例变量 。也就是说,成员变量 是定义在类中的,而又在任何方法之外的变量。

成员变量 在类的任何位置都可以直接访问。

比如下面这个类 JavaTester.java

public class JavaTester
{
    // 所有在类中定义的非静态变量都是成员变量
    int a;
    private String b
    void method1() {....}
    int method2() {....}
    char c;
}

成员变量 可以在类的任何位置声明和定义,但必须位于方法之外。

成员变量 前的 访问修饰符 规则并不适用于在类的内部访问。

而在类的外部,成员变量的可见性( 可访问性 )则由访问修饰符决定。并且遵循以下规则

访问修饰符          包   子类  全局
public             是    是    是
protected          是    是    否private            否    否     否
默认(无修饰符)      是    否    否

三、局部变量 ( 方法级别作用域 )

在方法内部声明的变量,嗯,就是局部变量,只限于方法级别的作用域。也就是说,局部变量在方法外部是无法访问的。

JavaTester.java
public class JavaTester
{
    void run() 
    {
       // 局部变量 ( 方法级别作用域 )
       int x;
    }
}

注意:当方法执行结束,局部变量也会随之销毁。也就是说在方法外部,局部变量就不存在了。

下面是方法作用域的另一个范例,在这个实例中,变量 x 是方法的一个参数。

public class JavaTester
{
    private int x;
    public void setX(int x)
    {
        this.x = x;
    }
}

上面这段代码中,我们使用 this 关键字来区分局部变量和实例变量。

作为一个练习,你能说出下面程序的执行结果吗?

JavaTester.java
public class JavaTester 
{ 
    static int x = 11; 
    private int y = 33; 
    public void run(int x) 
    { 
        JavaTester t = new JavaTester(); 
        this.x = 22; 
        y = 44; 

        System.out.println("Test.x: " + JavaTester.x); 
        System.out.println("t.x: " + t.x); 
        System.out.println("t.y: " + t.y); 
        System.out.println("y: " + y); 
    } 

    public static void main(String args[]) 
    { 
        JavaTester t = new JavaTester(); 
        t.run(5); 
    } 
}

我们运行下上面的代码,看看输出结果如何

[yufei@www.twle.cn java]$ javac JavaTester.java && java JavaTester
Test.x: 22
t.x: 22
t.y: 33
y: 44

四、循环变量 ( 块级作用域 )

大括号 { 和 } 内声明的变量的作用域仅限于该大括号 {} 内部。

例如下面的代码,变量 x 的作用域仅限于离它最近的大括号 {}

JavaTester.java
public class JavaTester 
{ 
    public static void main(String args[]) 
    { 
        { 
            // 变量 x 的作用域仅限于离它最近的大括号
            int x = 10; 
            System.out.println(x); 
        } 

        // 如果你把下一行代码的注释去掉,会抛出一个异常

        // System.out.println(x);  
    } 
}

编译运行以上代码,输出结果如下

[yufei@www.twle.cn java]$ javac JavaTester.java && java JavaTester
10

如果把最后一行的注释去掉,则会发生编译错误

[yufei@www.twle.cn java]$ javac JavaTester.java && java JavaTester
JavaTester.java:13: 错误: 找不到符号
        System.out.println(x);  
                           ^
  符号:   变量 x
  位置: 类 JavaTester
1 个错误

五、循环中的作用域

循环中声明的变量的作用域范围仅限于该循环的大括号 {}。

例如下面的代码,变量 x 的作用域仅限于 for 循环中的大括号。

JavaTester.java
public class JavaTester 
{ 
    public static void main(String args[]) 
    { 
        for (int x = 0; x < 4; x++) 
        { 
            System.out.println(x); 
        } 

        // 抛出错误 
        // System.out.println(x); 
    } 
}

运行结果如下

[yufei@www.twle.cn java]$ javac JavaTester.java && java JavaTester
0
1
2
3

如果把注释去掉,编译时会产生一个错误

[yufei@www.twle.cn java]$ javac JavaTester.java && java JavaTester
JavaTester.java:11: 错误: 找不到符号
        System.out.println(x); 
                           ^
  符号:   变量 x
  位置: 类 JavaTester
1 个错误

如何修复这个错误 ?

最佳的办法时把变量 x 的声明移到 for 循环之外,就像下面这样

public class JavaTester 
{ 
    public static void main(String args[]) 
    { 
        int x = 0;
        for (; x < 4; x++) 
        { 
            System.out.println(x); 
        } 

        // 抛出错误 
        System.out.println(x); 
    } 
}

编译运行上面这段代码,输出结果如下

[yufei@www.twle.cn java]$ javac JavaTester.java && java JavaTester
0
1
2
3
4

但是,Java 中的 for 循环有一个诡异的地方,看看下面的代码,你知道输出结果是什么吗?

public class JavaTester 
{ 
    public static void main(String args[]) 
    { 
        int x = 0;
        for (int x = 0; x < 4; x++) 
        { 
            System.out.println(x); 
        } 

        // 抛出错误 
        System.out.println(x); 
    } 
}

如果你熟悉 C/C++ ,你一定会感到非常诧异,因为编译的时候报错了

[yufei@www.twle.cn java]$ javac JavaTester.java && java JavaTester
JavaTester.java:6: 错误: 已在方法 main(String[])中定义了变量 x
        for (int x = 0; x < 4; x++) 
                 ^
1 个错误

同样的,你能猜出下面的代码输出结果是什么吗?

public class JavaTester 
{ 
    public static void main(String args[]) 
    { 
        { 
            int x = 5; 
            { 
                int x = 10; 
                System.out.println(x); 
            } 
        } 
    } 
}

运行结果如下

[yufei@www.twle.cn java]$ javac JavaTester.java && java JavaTester
JavaTester.java:8: 错误: 已在方法 main(String[])中定义了变量 x
                int x = 10; 
                    ^
1 个错误

六、总结

是不是很郁闷。我们总结下 Java 中的作用域的知识点: 通常来说,Java 中的作用域由花括号 {} 来界定。 在同一个花括号范围之内,只要定义了一个变量,就可以在该定义之后访问该变量。而且,一个变量可以在定义之后的任何子花括号作用域内访问。 在类中定义的且在方法之外定义的变量,俗称实例变量,可以在类中的任何方法中访问。 当一个访问内部定义的局部变量和类的实例变量同名时,局部变量会覆盖实例变量,如果要引用实例变量,可以使用 this 关键字。 如果要在循环之后再访问一个变量,则必须在循环之前就定义该变量。

原文链接:https://www.twle.cn/t/441

END

好看、转发和辣条会提升颜值哦~

关注我

每天进步一点点

本文分享自微信公众号 - 技术从心(gh_d845efe513db),作者:LYJ

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-03-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JAVAAPI中SortedMap解释

    A Map进一步提供其键上的总排序 。地图根据其键的natural ordering或通过在分类地图创建时提供的Comparator进行排序。当迭代排序的地图的...

    技术从心
  • java中IO流详细解释?

    BufferedReader的readLine()&BufferedWriter的newLine()方法

    技术从心
  • 小工具|计算两个日期之间的天数?

    在开发中我们常要使用到日期格式的转换或者是计算两个时间的间距,因此很有必要自己封装一个通用的工具类方便自己以后调用使用,方便自己的开发,也可使项目更简洁。

    技术从心
  • Spark踩坑记:共享变量

    如果我们想在节点之间共享一份变量,比如一份公共的配置项,该怎么办呢?Spark为我们提供了两种特定的共享变量,来完成节点间变量的共享。 本文首先简单的介绍spa...

    肖力涛
  • 如何通过Fiori后台调试的方式找到gateway系统的ID

    如果只知道后台系统的ID,需要知道到底是哪个gateway系统发起的RFC调用,可在debugger里查看如下变量:

    Jerry Wang
  • CSS3 border-image 彻底明白

    距离图片上部30%的地方,距离右边35%,距离底部40%,左边30%的地方各剪裁一下。也就是对图片进行了“四刀切”,形成了九个分离的区域,这就是九宫格,这是下面...

    前端博客 : alili.tech
  • 【可视化】数学告诉你宇宙中还有外星文明

    大数据文摘
  • PE知识复习之PE的各种头属性解析

    DOS头是在16位程序下使用的.所以不用全部关心.只需要关心第一个跟最后一个成员记住即可.

    IBinary
  • 译文 | 与TensorFlow的第一次接触 第五章:多层神经网络

    本章中,我们继续使用之前章节中的MNIST数字识别问题,与读者一起编码实现一个简单的深度学习神经网络。 如我们所了解的,一个深度学习神经网络由相互叠加的多层组成...

    用户1332428
  • 编程小白 | 每日一练(162)

    这道理放在编程上也一并受用。在编程方面有着天赋异禀的人毕竟是少数,我们大多数人想要从编程小白进阶到高手,需要经历的是日积月累的学习,那么如何学习呢?当然是每天都...

    闫小林

扫码关注云+社区

领取腾讯云代金券