JAVA 第二章
目标
Java中的变量和数据类型Java中变量的作用域规则数据类型转换Java中的输出语句Java中的运算符和表达式程序控制结构Java中的数组new关键字Java中的垃圾回收机制命令行参数
变量
变量是内存(堆栈)中的一块存储区域,是存储数据的基本单元;声明变量的语法:数据类型 标识符 [= 值];
如:int num;
float money = 123.45f;
char ch1, ch2 = ‘A’;
数据类型
数据类型用来确定要存储在内存单元中的数据的类型;在Java中,数据类型被区分成两个种类:原始数据类型 引用数据类型
原始数据类型
原始数据类型是最简单的数据形式,与C的基本数据类型很相似
数据类型
大小
(位)
取值范围
说 明
boolean 布尔型
1
true/false
用于存储真值/假值
byte 字节型
8
-128~127
数据存储在内存中的最原始形态
char 字符型
16
‘\u0000’~‘\uFFFF’ 0-65535
用于存储字符,以Unicode编码方式
short 短整型
16
-32768~32767
略
int 整 型
32
-231~231-1
略
long 长整型
64
-263~263-1
略
float 浮点型
32
-3.4e+038~3.4e+038
略
double 双精度
64
-1.7e+308~1.7e+308
略
引用数据类型
在Java中,除了上述8种原始数据类型的变量以外,其余的全都属于引用数据类型,其中包括:–数组–对象存储在引用类型变量中的值是该变量表示的值的地址;可以借用C语言中指针的概念来理解引用数据类型。
C语言中的内存分配
C语言中内存分配的两种形式:栈内存:–特点:和作用域同生命周期,自动申请,自动释放。–申请方式:局部变量,形式参数。–栈内存中的空间一般都有名称,通过变量名访问其存储的数据。堆内存(即动态内存分配):–特点:手工申请,手工释放,生命周期由程序员决定。–申请方式:由malloc函数或calloc函数申请,realloc函数进行调整,free函数负责释放。–堆内存中的空间一般没有名称,只能通过指针访问。
JAVA中的内存分配
Java中的原始数据类型与C语言中的基本数据类型一样,其变量都是在栈中分配空间;而除了8种原始数据类型以外,其它的任何数据都不可以在栈中分配,只能到堆中开辟空间,而在堆中分配的空间又只能通过指针访问;通过指针访问堆内存的方式,在Java中被称作引用数据类型;可以认为,Java中的引用就类似于C语言中的指针,只是对指针进行了一定程度上的包装,避免了因直接操作指针而造成的数据意外损坏,从而导致程序错误的情况。
标识符命名规则变量的作用域和生命周期
变量、函数、数组、对象、类和接口等等都需要命名,这些名称统称为标识符;Java中对于标识符的命名规则作了如下限制:–只能由英文字母、数字、下划线“_”和“$”符号组成;–必须以英文字母、“_”或“$”开头,即不能以数字开头;–除“_”和“$”以外,不能包含其它任何特殊字符;–不能与关键字冲突;严格区分大小写
变量 的作用域指变量起作用的范围,说明变量在什么部分可以被访问;变量的生命周期是指变量在内存中存在的周期,即什么时候分配空间,什么时候销毁;
C
Java
变量
声明
程序中所有使用到的变量应该在程
序开始部分预先进行声明。
可以在程序的任何部分声明,即:何处 使用,何处声明。
作用域
规则
变量的作用域属于声明它的函数范围之内,变量的最小作用域是函数。
变量的作用域属于声明它的代码块,变量的最小作用域是包含它的一对{}之间。
数据类型转换
程序中经常会遇到要将数据类型进行转换的情况(如:在一个表达式中存在不同类型的操作数时),Java的数据类型转换比C控制得更为严格;数据类型转换有两种情况:自动类型转换强制类型转换
自动类型转换
自动类型转换也称作隐式类型转换;将一种类型的变量赋值给另一种类型的变量时,只要满足以下条件,就会发生自动类型转换:–两种类型之间相互兼容;–目标类型大于源类型(即类型提升);如:char ch = 'A';
int num = ch;
float f = num;
double d = f;
//类型转换自动发生,无需显式说明
强制类型转换
强制类型转换也称作显式类型转换;如果被转换的值的数据类型大于其目标类型,将会丢失部分信息;如:int x = 65;
char ch = x;
这样的语句将报错,因为char类型小于int类型,编译器无法将其自动转换,只能进行强制转换:int x = 65;
char ch = (char)x;
类型提升规则
不难看出,在有类型提升的情况下,编译器将自动进行类型转换,否则就要进行强制类型转换;类型提升应遵循如下规则:两种类型必须兼容,且目标类型大于源类型,例如:byte、char和short类型都可以提升为int型。
对于表达式而言,其最终结果将会与表达式中最高的数据类型相同。
使用转义字符控制输出格式如果要将某些信息打印到屏幕上,就必须使用输出语句;使用System.out.println()实现换行输出效果;使用System.out.print()实现输出但不换行效果;无论输出什么类型的数据,只需将数据作为参数传递给它们即可,而无需像C语言中那样,使用%s、%d之类的控制字符,如:int a = 10;
float f = 3.14f;
System.out.println(a);
System.out.print(f);
System.out.println("X");
有些时候,我们可能会需要对输出格式进行控制,这就使用到了转义字符;以下是一些常用的转义字符:
转义字符
说 明
\n
换行符,将光标移到下一行
\r
回车符,将光标移到当前行的开头
\t
制表符,将光标移到下一制表位
\\
输出反斜线
\'
输出单引号
\"
输出双引号
运算符和表达式
运算符是通过一定的运算规则操作一个或多个操作数,并生成结果的特定符号;运算符和操作数的有效组合称为表达式;Java提供了一系列丰富的运算符,包括:–算术运算符–关系运算符–逻辑运算符–条件运算符–赋值运算符
算术运算符主要用于数学计算,一般使用数值作为操作数:
运算符
说 明
一元
-
一元减,即取负
++
自增,如:++a等价于a = a
+
1
--
自减,如:--a等价于a = a – 1
二元
+
加法,返回两个操作数的和
-
减法,返回两个操作数的差
*
乘法,返回两个操作数的积
/
除法,返回两个操作数的商
%
取模,返回两个操作数整除后的余数
关系运算符可以测试两个操作数之间的关系(但不会改变操作数的值),关系表达式的结果为boolean型true/false:
运算符
说 明
==
等于,检查两个操作数是否相等
!=
不等于,检查两个操作数是否不相等
>
大于,检查左操作数是否大于右操作数
>=
大于等于,检查左操作数是否大于或等于右操作数
<
小于,检查左操作数是否小于右操作数
<=
小于等于,检查左操作数是否小于或等于右操作数
逻辑运算符
逻辑运算符与boolean型操作数一起使用:
运算符
说 明
Java
C
一元
!
逻辑非(NOT)
逻辑取非(NOT)
二元
&
逻辑与(AND)
与C语言中的&&相同
按位与
|
逻辑或(OR)
与C语言中的||相同
按位或
&&
短路与
如左操作数为false,则不运算右操作数
逻辑与(AND)
||
短路或
如左操作数为ture,则不运算右操作数
逻辑或(OR)
短路"与"和短路"或"
赋值运算符Java提供了两个在其它计算机语言中没有的逻辑运算符,这就是逻辑与和逻辑或的短路版本;对于短路与(&&),如果其左侧为false,则不再计算其右侧,整个表达式的结果为false,只有左侧为true时才计算右侧;对于短路或(||),如果其左侧为true,则不再计算其右侧,整个表达式的结果为true,只有左侧为false时,才计算右侧。
短路与示例
int a = 10; int b = 20; if (++a == 12 & ++b == 22) { …… } System.out.println(a); // 11 System.out.println(b); // 21 /*这里使用的是逻辑与, 试分析最后的输出结果*/
int a = 10; int b = 20; if (++a == 12 && ++b == 22) { …… } System.out.println(a); //11 System.out.println(b); //20 /*这里使用的是短路与, 试分析最后的输出结果*/
条件运算符赋值运算符的运算顺序是 从右至左的:
运算符
说 明
=
赋值,将右侧的值赋给左侧的变量
+=
相加并赋值,如:a += b等价于a = a + b
-=
相减并赋值,如:a -= b等价于a = a – b
*=
相乘并赋值,如:a *= b等价于a = a * b
/=
相除并赋值,如:a /= b等价于a = a / b
%=
取模并赋值,如:a %= b等价于a = a % b
运算符的优先级
条件运算符是三元运算符;它的一般形式是:表达式1 ? 表达式2 : 表达式3
根据表达式1的结果来判断执行表达式2还是表达式3,如果表达式1的结果为true,则执行表达式2,否则执行表达式3;条件运算符在某些情况下能够替代小型的if…else语句。
很多情况下,一个表达式由多个运算符组成,优先级决定运算符的计算顺序:
优先级
运 算 符
1
括号: ()和[]
2
一元运算符:-、++(前置)、--(前置)、!
3
算术运算符:*、/、%、+和-
4
关系运算符:>、>=、<、<=、==和!=
5
逻辑运算符:&、|、&&和||
6
条件运算符:? :
7
赋值运算符:=、*=、/=、%=、+=和-=
控制流语句
判断语句一般情况下,程序是从上往下依次顺序执行的;但很多时候,我们需要改变程序执行的流程,这就使用到了控制流语句;控制流语句包括:–判断语句–循环语句–跳转语句
循环语句判断语句也称作条件语句或分支语句;判断语句主要用来控制程序在何种情况下执行某一部分;判断语句包括:–if语句–if…else语句–if…else if语句–switch…case语句
循环语句也称作迭代语句;循环语句可用于重复执行相同的操作;循环语句包括:–while语句–do…while语句–for语句
跳转语句
跳转语句允许以非线性的方式执行程序,可以将控制权转到程序的其它部分;跳转语句包括:–break语句–continue语句Java抛弃了C语言中的goto语句。
数组
数组用于将相同类型的数据存储在连续的存储单元中;可以通过指定数组的名称和长度来声明数组;一旦声明数组的大小,就不能再修改;数组元素通过数组名和索引来访问,索引从0开始;数组可以是一维,也可以是多维。
在Java中,不允许将数组分配在栈内存中,只能分配在堆内存中;new是Java中内置的操作符;new操作符用来从堆中分配指定类型的内存空间,并返回相应类型的引用.
Java中声明数组的几种方式
声明数组示例public class ArrayDemo { public static void main(String[] args) { //声明整型数组的引用,类似于C中的 int *p; int[] ary; //为数组引用在堆内存中分配实际的内存空间 //类似于C中的 p = (int*)malloc(10 * sizeof(int)); ary = new int[10]; //使用循环为数组元素赋值 for (int i = 0; i < ary.length; i++) { ary[i] = i; } //使用循环将数组元素逐个输出到控制台 for (int i = 0; i < ary.length; i++) { System.out.println(ary[i]); } } }
//仅声明数组的引用,但没有分配内存空间
float[] fAry;
//声明数组的同时,根据指定的长度分配内存,但数组中没有值
char[] chAry = new char[10];
//声明数组并分配内存,同时将其初始化
int[] ary1 = new int[]{1,2, 3, 4, 5};
//与前一种方式相同,仅仅只是语法相对简略
int[] ary2 = {1, 2, 3, 4, 5};
数组之间赋值
在C语言中,不可以将数组直接赋值给另一个数组;在Java中,语法上允许这样做,但实际得到的效果是两个数组引用指向同一块内存。int[] ary1 = {2, 4, 6, 8, 10};
int[] ary2;
ary2= ary1; //允许这样赋值
数组赋值示例
public class ArrayDemo { public static void main(String[] args) { int[] ary1 = {2, 4, 6, 8, 10}; //声明并初始化数组1 int[] ary2; //声明数组2 ary2 = ary1; //将数组1赋值给数组2 ary2[3] = 1024; //通过数组2修改其中一个元素的值 //打印出数组1中的元素 System.out.println("数组1中的元素:"); for (int i = 0; i < ary1.length; i++) { System.out.println(ary1[i]); } //打印出数组2中的元素 System.out.println("数组2中的元素:"); for (int i = 0; i < ary2.length; i++) { System.out.println(ary2[i]); } } } //两组输出值是相同的
关于数组长度
在Java中,程序员可以不再关注数组的长度,数组自带的length属性将负责保管数组的长度;C语言不检查数组的边界,数组索引完全由程序员掌握;Java对数组下标越界情况强加约束;如果试图访问不在有效索引以内的元素,将会引发运行错误。(异常:数组下标越界)
在C语言中,被malloc或calloc函数分配的堆内存在使用完毕以后,必须使用free函数进行释放,否则将会造成内存泄漏;同样的,在Java中由new分配的内存也将存在内存泄漏的可能;但释放内存的任务是由Java虚拟机来完成的,程序员可以不再关心此项工作;如果某块内存空间没有任何引用指向它,那么虚拟机就将其认定为垃圾;虚拟机并不是随时随地地立即回收垃圾,而是在系统比较空闲的时候,才会执行回收任务。
命令行参数
在命令行使用java命令执行程序时,可以将一些参数传递给main函数;main函数携带的String[](字符串数组)类型的形参args正是为了接收这些来自命令行的参数;可以从命令行传递任意多个字符串给main函数,其间使用空格隔开,也可以不传递任何参数;这些传递进来的多个字符串最后以字符串数组的形式,供main函数中加以使用。
示例:
public class ArgumentDemo { public static void main(String[] args) { int len = args.length; //获得命令行参数的个数 if (len > 0) //判断是否有命令行参数 { //如果有,将其逐一打印到控制台 System.out.println(len + "个命令行参数,具体如下:"); for (int i = 0; i < args.length; i++) { System.out.println(args[i]); } } else { //否则给出提示信息 System.out.println("您没有传递任何命令行参数。"); } } }
Java中的数据类型大体上分为两种:原始数据类型和引用数据类型;变量是存储数据的基本单位;运算符和流程控制基本上与C相似;Java中数组是引用数据类型,只能存放在堆内存中;数组必须由new关键字为其分配内存;释放内存的工作由Java虚拟机的垃圾回收机制来完成;可以利用命令行参数接收来自用户的输入。
资料
Java垃圾回收机制 : http://download.csdn.net/detail/nisior/3646034
深入Java对象及元素的存储区域 :http://download.csdn.net/detail/nisior/3646303
深入Java内存分配 :http://download.csdn.net/detail/nisior/3646313
详解Java中的char型数据 :http://download.csdn.net/detail/nisior/3646320
作业
利用命令行参数输入一个整数,并判断该数字是否为奇数,如果是奇数,则用其作行数打印空心菱形–PS:将字符串转换为数字的方法•intnum=Integer.parseInt(String number);利用命令行参数输入三个整数,并对三个数字进行降序排列。–PS:将字符串转换为数字的方法•intnum=Integer.parseInt(String number);利用命令行参数输入多个参数,并赋值给一数组,同时判断该数组是否为回文数组–PS:例如数组{“123”,”222”,”333”,”222”,”123”}就是回文数组,即元素倒置过后与原元素一样利用命令行参数输入一个整数,并判断该数字是否为奇数,如果是奇数,则用其作行数打印空心菱形–PS:将字符串转换为数字的方法•intnum=Integer.parseInt(String number);利用命令行参数输入三个整数,并对三个数字进行降序排列。–PS:将字符串转换为数字的方法•intnum=Integer.parseInt(String number);利用命令行参数输入多个参数,并赋值给一数组,同时判断该数组是否为回文数组–PS:例如数组{“123”,”222”,”333”,”222”,”123”}就是回文数组,即元素倒置过后与原元素一样