关于Java中的变量及变量的作用域

关于Java中的变量及变量的作用域

0. 变量的概念

在程序运行期间,系统可以为程序分配一块内存单元,用来存储各种类型的数据。系统分配的内存单元要使用一个标记符来标识,这种内存单元中的数据是可以更改的。所有叫变量。定义变量的标记符就是变量名,内存单元中所装载的数据就是变量值。用一个变量定义一块内存以后,程序就可以用变量名代表这块内存中的数据。根据所存储数据类型的不同,有各种不同类型的变量。

1. Java的变量类型



2. 注意变量的有效取值范围

系统为不同的变量类型分配不同的空间大小,如double型常量在内存中占8个字节,float的变量占4个字节,byte型占1个字节等。

byte b=129;//编译报错,129超出了byte类型的取值范围
float f=3.5;//编译报错,因为小数常量的默认类型为double型。double型在内存中占8个字节,而Java只为float的变量分配4个字节的空间,显然有问题
float f=3.5f;//编译通过

3. 基本数据类型之间的转换

①.自动类型转换(隐式类型转换)

要实现自动类型转换,需要同时满足两个条件:i.两种类型彼此兼容,ii.目标类型的取值范围要大于源类型。

byte b=3;
int x=b;//程序把b的结果自动转换成int型

②.强制类型转换(显式类型转换)

当两种类型彼此不兼容,或目标类型取值范围小于源类型时,自动转换无法进行,就需要强制类型转换。

byte a;
int b;
a=(byte)b;

将int型的变量b的取值强制转换成byte型,再将该值赋给变量a。此时,变量b本身的数据类型并没有改变。

例:

程序清单:Conversion.java

public class Conversion
{
public static void main(String[] args)
{
byte b;
int i=266;
b=(byte)i;
System.out.println("byte to int is"+" "+b);
}
}

程序输出如下:

byte to int is 10

十进制266→二进制100001010

byte类型取值范围为-128~127,所以只能取到010,省略0,所以输出10

也就是用目标内存块去套取源内存中的数据,能套多少算多少

4. 表达式的数据类型自动提升

下面来看一个错误程序:

程序清单:Test.java

class Test
{
public static void main(String[] args)
{
byte b=5;
b=(b-2);
System.out.println(b);
}
}

这段代码中,5-2的值并未超出byte型取值范围,然而却报错



这是因为在表达式求值时,变量值被自动提升为int型,表达式结果也就成了int型,这时想把它赋给byte型变量就必须强制转换了。

因此就应该改成:

b=(byte)(b-2);

关于类型的自动提升,Java定义了若干适用于表达式的类型提升规则

  • 所有byte型、short型和char型的值奖杯提升为int型
  • 如果一个操作数为long型,计算结果就是long型
  • 如果一个操作数为float型,计算结果就是float型
  • 如果一个操作数为double型,计算结果就是double型

    也就是byte、short、char→int→long→float→double

下面演示一些Java的类型自动提升规则:

程序清单:Promote.java

class Promote
{
public static void main(String[] args)
{
byte b=50;
char c='a';
short s=1024;
int i=50000;
float f=5.67f;
double d=.1234;
double result=(f*b)+(i/c)-(d*s);
System.out.println((f*b)+"+"+(i/c)+"-"+(d*s));
System.out.println("result="+result);
}
}

下面看看代码行的类型提升:

double result=(f*b)+(i/c)-(d*s);

在第一个子表达式f*b中,变量b被提升为float类型,该子表达式的结果也被提升为float类型。接下来,在子表达i/c中,变量c被提升为int类型。该子表达的结果提升为int类型。

然后子表达式d*s中的变量s被提升为double类型,该子表达式的结果提升为double类型。

最后这三个结果值类型分别为float、int、double。float类型加int类型的结果是float类型,然后float类型减去double类型,该表达式的最后结果就是double类型。

变量的作用域

大多数程序设计语言都提供了“变量作用域”(Scope)的概念。在C、C++、Java中,一对大括号中间部分就是一个代码块,代码块决定其中定义的变量的作用域。代码块由若干语句组成,必须用大括号括起来,形成一个复合语句,多个复合语句可以潜逃在另外的一对大括号中形成更复杂的复合语句。

{
int x=0;
{
int y=0;
y=y+1;
}
x=x+1;
}

代码块决定了变量的作用域,作用域决定了变量的“可见性”以及“存在时间”。

例如:

程序清单:TestScope.java

public class TestScope
{
public static void main(String[] args)
{
int x=12;
{
int q=96;//x和q都可用
System.out.println("x is "+x);
System.out.println("q is "+q);
}
q=x;/*错误的行,只有x可用,q超出作用域范围*/
System.out.println("x is "+x);
}
}

q作为在里层的代码块中定义的一个变量,只有在那个代码块中位于这个变量定义之后的语句,才可以使用这个变量,q=x语句已经超过了q的作用域,所以编译无法通过。

在定义变量的语句所属的那层大括号之间,就是这个变量的有效作用范围,但是不能违背变量先定义后使用的原则。

6. 局部变量的初始化

在一个函数或函数里面的代码块中定义的变量称为局部变量,局部变量在函数或代码块被执行时创建,在函数或代码块结束时被摧毁。局部变量在进行取值操作前必须被初始化或进行过赋值操作,否则会出现编译错误。例如:

程序清单:TestVar.java

public class TestVar
{
public static void main(String[] args)
{
int x;//应改为int x=0;
x=x+1;//这个x由于没有初始化,编译报错
System.out.println("x is "+x);
}
}

Java中的变量与变量的作用域的更多相关文章

  1. JAVA中局部变量 和 成员变量有哪些区别

    JAVA中局部变量 和 成员变量有哪些区别 1.定义的位置不一样<重点>***局部变量:在方法的内部成员变量:在方法的外部,直接写在类当中 2.作用范围不一样<重点>***局部 ...

  2. Java 中(静态)变量、(静态)代码块的执行顺序

    Java 中(静态)变量.(静态)代码块的执行顺序 非原创 本文讨论 Java 中(静态)变量.(静态)代码块的执行顺序 首先创建 3 个类 1.Foo 类 public class Foo { pu ...

  3. 在 Java 中不使用多余变量交换两个字符串

    在 Java 中不使用多余变量交换两个字符串 public class Test { public static void main(String[] args) { String a = " ...

  4. 关于java中jdk的环境变量配置

    关于java中jdk的环境变量配置 烦死人,在网上找了很长时间.最终找到了一个方法!现在将其总结帮助后来人. 方法/步骤   1 下载好jdk,并按照提示一步步安装,最后记下jdk所在的安装位置,这里 ...

  5. Java中private、protected和public作用域的异同

    Java中private.protected和public作用域的异同 说明:(1)private的作用范围为当前类,protected的作用范围哦不能超过其他包: (2)区别不同的作用域的不同作用范 ...

  6. 理解Java中的对象,变量和方法

    1.对象的创建和销毁 1.1 对象的创建 这里只介绍创建对象与构造方法的关系 (1).每实例化一个对象就会自动调用一次构造方法,实质上这个过程就是创建对象的过程,准确的说,在Java语言中使用new操 ...

  7. Java基础知识强化10:Java中的中间缓存变量机制

    1.对于自增运算++j与j++,由于加一的执行顺序不同,所以Java中有中间缓存变量来储存其单个表达式的值,而j的自增自减的结果依然保留在原来的变量储存区.因为本体是j的值,而单个表达式的值是中间产生 ...

  8. Java中实例方法,实例变量,静态方法,静态变量,final方法重写的问题,覆盖

    Java中只有非私有的实例方法能被重写,即实现多态,子类可以覆盖父类的方法,但是实例变量不能覆盖,若子类和父类均定义了同样名称的变量,则对于子类来说这是两个不同的变量,要想调用父类的变量必须显示去调用 ...

  9. Java入门以及Java中的常量与变量总结

    JDK与JRE的区别: JDK给开发人员使用(包含开发工具),JRE给客户使用(运行java程序的核心类库),JDK包含JRE关键字的含义: JAVA语言赋予特殊含义,具有专门用途的单词,关键字的单词 ...

  10. Java中final关键字修饰变量、方法、类的含义是什么

    Java中的关键字final修饰变量.方法.类分别表示什么含义? 先看一个简单的介绍 修饰对象 解释说明 备注 类 无子类,不可以被继承,更不可能被重写. final类中的方法默认是final的 方法 ...

随机推荐

  1. 在spring中进行基于Executor的任务调度

    Executor java.util.concurrent.Executor接口的主要目的是要将“任务提交”和“任务执行”两者分离解耦.该接口定义了任务提交的方法,实现者可以提供不同的任务运行机制,解 ...

  2. 灵光一闪-VS设计界面能访问到private修饰的各种控件

    大家都知道,用VS设计界面时,VS默认控件的访问修饰符为private,但是我就很奇怪,private修饰的字段不是只有类内部才能访问吗? 好神奇的VS,这到底是怎么实现的?难道就是类似文本编辑器的作 ...

  3. leetcode Combination Sum II python

    Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...

  4. Linux简介(好!)

    Linux操作系统介绍 来源:233网校论文中心[ 2009-12-02 14:23:00 ]阅读:1作者:王长青编辑:studa20 [摘 要]文章从Unix.Minix系统的产生引出了Linux操 ...

  5. 深度解析Linux通过日志反查入侵

    有一个朋友的服务器发现有入侵的痕迹后来处理解决但是由于对方把日志都清理了无疑给排查工作增加了许多难度.刚好手里有些资料我就整理整理贴出来分享一下.其实日志的作用是非常大的.学会使用通过日志来排查解决我 ...

  6. windbg命令学习4

    4.查看调用栈 k命令:显示的是一定数量的栈帧, 其中帧的数量是由.kframes命令来控制的, 默认值是256. 我们如何来判断函数的栈指针,参数地址和局部变量地址呢? 举一个简单的windbg的k ...

  7. 《转》JAVA中PriorityQueue优先级队列使用方法

    该文章转自:http://blog.csdn.net/hiphopmattshi/article/details/7334487 优先级队列是不同于先进先出队列的另一种队列.每次从队列中取出的是具有最 ...

  8. J2SE知识点摘记(二十三)

    我们简单介绍一下这个接口: 1.4.3        Comparable 接口 在 java.lang 包中,Comparable 接口适用于一个类有自然顺序的时候.假定对象集合是同一类型,该接口允 ...

  9. 提醒录入BOM更改原因

    应用 Oracle Bill Of   Materiel 层 Level Function 函数名 Funcgtion Name BOM_BOMFDBOM 表单名 Form Name BOMFDBOM ...

  10. 深入分析MFC文档视图结构(项目实践)

    k_eckel:http://www.mscenter.edu.cn/blog/k_eckel 文档视图结构(Document/View Architecture)是MFC的精髓,也是Observer ...