Java中的变量与变量的作用域

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

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

0. 变量的概念

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

1. Java的变量类型

Java中的变量与变量的作用域

Java中的变量与变量的作用域

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型取值范围,然而却报错

Java中的变量与变量的作用域

这是因为在表达式求值时,变量值被自动提升为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);
}
}
上一篇:关于正餐智能POS6.0.1.1改版后,订单模块无法进行部分退款的FAQ


下一篇:BZOJ 1620: [Usaco2008 Nov]Time Management 时间管理( 二分答案 )