Java变量的声明和初始化
Java 语言是强类型(strongly typed)语言,强类型包含以下两方面的含义:
-
所有的变量必须先声明、后使用。
-
指定类型的变量只能接受类型与之匹配的值。
这意味着每个变量和每个表达式都有一个在编译时就确定的类型。类型限制了一个变量能被赋的值,限制了一个表达式可以产生的值,限制了在这些值上可以进行的操作,并确定了这些操作的含义。
常量和变量是 Java 程序中最基础的两个元素。常量的值是不能被修改的,而变量的值在程序运行期间可以被修改。本文详细介绍 Java 中变量的声明和赋值方法。
声明变量
对开发人员来说,变量是用来描述一条信息的别名,可以在程序代码中使用一个或多个变量。变量中可以存储各种类型的信息,如登录信息、版本名称、文件的大小、某个英文单词以及飞机票价格等。
在 java 中用户可以通过指定数据类型和标识符来声明变量,其基本语法如下所示:
DataType identifier;
或者
DataType identifier=value;
上述语法代码中涉及 3 个内容:DataType、 identifier 和 value,其具体说明如下:
-
DataType:变量类型,如 int、string、 char 和 double 等。
-
identifier:标识符,也叫变量名称。
-
value:声明变量时的值。
变量标识符的命名规范如下:
-
首字符必须是字母、下划线(―)、美元符号($)或者人民币符号(¥)。
-
标识符由数字(0~9)、大写字母(A~Z)、小写字母(a~z)、下划线(―)、美元符号($)、人民币符号(¥)以及所有在十六进制 0xc0 前的 ASCII 码组成。
-
不能把关键字、保留字作为标识符。
-
标识符的长度没有限制。
-
标识符区分大小写。
如下代码分别声明了 String、boolean 和 int 类型的变量。
String employee; // String 类型的变量
boolean isSave; // boolean 类型的变量
int create_at; // int 类型的变量
变量赋值
初始化变量是指为变量指定一个明确的初始值。初始化变量有两种方式:一种是声明时直接赋值,一种是先声明、后赋值。如下代码分别使用两种方式对变量进行了初始化。
char usersex='女'; // 直接赋值
或者
String username; // 先声明
username ="琪琪"; // 后赋值
另外,多个同类型的变量可以同时定义或者初始化,但是多个变量中间要使用逗号分隔,声明结束时用分号分隔。
String username,address,phone,tel; // 声明多个变量
int num1=12,num2=23,result=35; // 声明并初始化多个变量
Java 中初始化变量时需要注意以下事项:
-
变量是类或者结构中的字段,如果没有显式地初始化,默认状态下创建变量并默认初始值为 0。
-
方法中的变量必须显式地初始化,否则在使用该变量时就会出错。
变量的初始化问题
我们先来看一个例子
public class TestDemo {
int a; //类的成员变量
public static void main(String[] args) {
TestDemo td =new TestDemo(); //默认的构造方法
System.out.println(td.a);
}
}
// 第二种类型
public class TestDemo {
public static void main(String[] args) {
int a;
System.out.println(a);
}
}
我先验证了一下结果给大家说,上面部分代码运行结果为 0 . 下面部分代码编译执行报错(变量可能未初始化)。
成员变量和局部变量的区别
上面两部分代码的区别是上面代码,变量 a 是作为类的成员变量,主方法中创建了对象,我们发现此时的 a 结果是 0,如果我们换成字符串就是 null ,boolean型变量默认就是 false ,所以我们发现当变量作为类的成员变量的时候类在创建对象的时候会默认给它们赋初值。
而下面部分代码则是方法中的变量,也就是局部变量。我们直接打印它或者用到它的时候直接会报错。
如何解释这一现象?局部变量必须赋初始值?下面我们多方面分析一下。
首先,Java语言是这么明文规定的。局部变量使用前必须赋值。为什么Java 语言要这么规定呢。我们知道Java 是一门面向对象的语言,它将重点放在 数据 和对象的接口上。就好比一个木匠,一个“面向对象”的木匠始终关注的是所制作的椅子,第二位才是所使用的工具和打造的过程;而一个“非面向对象的”木匠首先考虑的是所用的工具。
最上面部分代码,将 a 变量作为类的成员变量,当我们创建对象的时候,Java 虚拟机会在系统的堆 (heap)区域申请一块内存区域来存放类的数据,在这里成员变量就是类的数据,这个时候JVM为加载的类要分配内存啦!成员变量作为类的数据是会随着类的加载在堆中分配内存,注意了,JVM 在申请内存时自动给它们赋了初值。这里附上下面一个堆栈简单示意图,
至于默认给类的成员变量赋初值有什么机理吗?我们可以想到类都有一个默认的构造方法的。(因为我们没有给出显式的构造方法)我们创建对象的时候实际上是调用了默认的构造方法的,会给成员变量赋一个默认的初始值,这样在打印输出的时候才会有值输出而不报错。
成员变量的初始化一般放在构造方法中
无参构造:默认初始值
If you have multiple constructors, you might want to initialize a field to different values.
When you initialize the field in the constructor, there can be no confusion over when exactly it is initialized in regard to the rest of the constructor. This may seem trivial with a single class, but not so much when you have an inheritance hierarchy with constructor code running at each level and accessing superclass fields.
有参构造:变量初始化
声明时为成员变量赋值,那么你一创建对象,这个赋值就进行,而且先于构造器执行。而且你每次创建这个类的对象,都是同一个值。构造方法初始化可以单独为每一个对象赋不同的值。
这时我们看一下第二段代码,并没有涉及到任何实例化对象的操作,在主函数里面 a 是没有任何东西对其初始化的,所以直接对其输出会直接报错。 现在我们想一想如果Java 设计的时候也给方法里的局部变量赋初始值会怎样? 一个方法里面可能会有很多个局部变量,类里面也会有很多个方法,而且生命周期短。如果我们都给它们赋初值,一定是一笔很大的开销,而且安全性也达不到要求,所以换成我是虚拟机也不想干这等活儿…但程序员们最好有给局部变量初始化的习惯。我们不妨看下下面这个例子。
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
int a;
if (i % 2 == 0) {
a = 1;
} else {
a = 2;
}
}
}
如果我们每次都对 a 进行初始化,那真的是丝毫没有必要的。
我们还可以换个角度来想这个问题,假如你是开发 Java 这门伟大语言的开发者,你在设计的时候,类的成员变量是要在堆中分配内存的,方法中的局部变量是在栈中的。其实,不管是局部变量还是成员变量,都是必须要初始化的,那为什么成员变量会自动初始化?其实正是因为成员变量属于对象,而对象是保存在堆中的,随着类的加载在为对象开辟空间的时候自动为成员变量赋初值,如果我们还要给局部变量都赋初值,那性能影响太大了吧,开发者想到这里的时候可能就直接将给局部变量初始化的想法抹杀掉了吧。同时在一般情况下成员变量也不会有初始值,你可以联想一下,有一个class 比如说是人类,里面的身高体重如果定义时候给了初始值,是不是觉得一点都不抽象了,所以成员变量不初始化可能更符合需求,创建类的对象的时候它们也会有初始值。(ps: static 修饰的成员变量不用创建对象也可以哦)
最后套用《Thinking in Java》作者的话:
编译器当然可以为局部变量附一个默认值,但是未初始化的局部变量更有可能是程序员的疏忽,所以采用默认值范围会掩盖这种失误。因此强制程序员提供一个初始值,往往能够帮助找出程序里的缺陷。
果然是大佬,说出来的话就是让人无可反驳。
上一篇: php关于位运算符