第2章 程序,数据,变量和计算
2.1 数据和变量
变量是一段有名字的内存, 存储程序中的信息, 描述事物的数据项;
每段定义了名字的内存只能存储一种特定类型的数据. Type; 编译器会检测错误的类型使用;
程序中出现的显式数据值叫做字面量, 有特定类型;
2.1.1 变量的命名
标识符-选择的名称; 可以是任意长度, 必须以字母, 下划线或美元符号$开始; 标识符的其他部分最好使用字母数字或下划线, 不能使用运算符(+ - * /);
大小写敏感, 不能在一个名字中包含空格或制表符; 不能数字开头; 不能使用关键字, 不能是常量;
Note Java通常约定变量名小写字母开始, 词的首字母大写;
2.1.2 变量名与Unicode
Java源码使用Unicode, 不管原始代码的编码, 在编译之前会在内部转换为Unicode字符;
编译器假设源代码在工作过程中使用默认字符编码. 使用-encode选项告诉编译器源代码使用的字符编码; e.g. javac.exe -encoding unicode JavaTest.java
2.1.3 变量与类型
类型+名字: int nubmerOfCats;
基本数据类型: 数值数据, 整型或浮点; 单个Unicode字符; 逻辑值true/false;
Java中的基本变量类型名都是关键字;
2.2 整数数据类型
4种变量, 都是带符号的;
byte: −128 到+127; 占1字节(8 比特);
short: −32768 到32767; 占2 字节(16 比特);
int: −2147483648 到2147483647; 占4 字节(32 比特);
long: −9223372036854775808 到9223372036854775807; 占8 字节(64 比特);
Java中存储值的范围不会变, 与计算机类型无关;
最大值和最小值:
>最左边的是符号位, 0代表正, 1代表负; 负二进制数用补码形式来表示;
整数字面量
设定为十进制数字序列的整数字面量都默认为int类型: 1, -999, 123; long类型的整数字面量需要加L: 1L, -999L, 123L;(可以用小写l, 但是容易和数字1混淆)
数字字面量可以使用(一个或多个)下划线字符划分表示: 1,234,567,890->1234567890L->1_234_567_890L.
4种方式写整数字面量:
十进制, 十六进制, 二进制, 八进制;
1) 十六进制
0x或0X开头, 字母A-F(a-f)表示数字10-15; e.g. 0x100 = 1*16^2 + 0X16^0 + 0*16^0 = 256;
默认为int, 需要设定long类型时在后面添加L; 0xFL -> 15;
下划线字符可以将十六进制数字每4个分为一组, 每组对应内存中的2个字节; 下划线只能在数字间出现, 0x_3A和0x3A_都不对;
2) 二进制
0b或0B开头, 数字为1或0; 0b1100_1010_1011和0xCAB一样->3234; 每组4个二进制对于一个十六进制数;
3) 八进制
0开头, e.g. 0777_777L, 只能使用数字0-7; 每个八进制数为3比特;
2.2.1 声明整型变量
声明变量需要初始化;
单条语句定义多个变量, 使用逗号分隔: long bigOne = 999_999L, largeOne = 100_100L;
一般使用int和long足够, 使用byte和short增加复杂度, 在必须对应数据类型的情况下才使用,e.g. 从硬盘读取数据;
2.3 浮点数数据类型
有准确的固定位数, 广泛的取值空间; float和double的定义遵循IEEE 754标准;
float: −3.4E38(−3.4×10^38)到+3.4E38(+3.4×10^38), 4个字节, 小数点后7位. 最小值~1.4*10^-45;
double: −1.7E308(−1.7×10^308)到+1.7E308(+1.7×10^308); 8字节, 小数点后17位, 最小值~4.9*10^-324;
表示浮点值的数字位数称为精度precision;
2.3.1 浮点数字面量
默认为double类型; e.g. 1.0, 345.678; 设定float类型需要在后面加上f或F, e.g. 1.0f. 345.678F; double类型需要的话在后面附加d或D;
7.123456 == 7.123_456; 149,600,000 == 1.496E8, 添加E或e代表10的指数次方;
2.3.2 声明浮点型变量
double sunDistance = 1.496E8; flat electronMass = 9E-28F;
Note 不在数字末尾添加F/f的话默认为double类型;
2.4 固定变量的值
final int FEET_PER_YARD = 3; //constant vlaue;
final关键字设定变量的值不能修改, 使用大写字母是Java中约定的常量写法; 必须有初始值;
2.5 算术运算
赋值语句: 变量名; 运算符=; 算术表达式' numFruit = numApple + numOrange;
单条语句赋值: a = b = c = 777; (编译器会在编译时优化赋值语句)
short value = 10; 类型转换int ->short;
2.5.1 整数计算
加减乘除, 二元运算符;
Note 使用括号()来控制运算顺序/优先级;
一元运算符: count(-10)->-count == 10;
e.g. 读取键盘输入, Enter退出
1
2
3
4
5
6
7
8
9
|
public static void main(String[] System.out.print( "press ); try { System.in.read(); } catch (IOException return ; } } |
>args提供运行时访问从命令行传数据的方法;
>通常将main()设为public static, 返回值void: 共有, 静态(不必创建对象), 没有返回值;
2.5.2 整数除法和余数
整数不能整除时, 会舍弃余数, e.g. 3/2->1; 11/3->3; 正负符号不影响绝对值, e.g. 7/(-3)->-2; (-5)/(-3)->1;
Note 特例 -2_147_483_648是int的最大负值, 除以-1等于2_147_483_648超过了int的最大值2_147_483_647, 结果无法表示, 会变回为最初的被除数-2_147_483_648;
被0除会导致程序终止->ArithmeticException;
余数%, 8%(−3)->+2; (-8)%3->-2; (-8)%(-3)->-2; 与乘除法有同样优先级;
2.5.3 增量与减量运算符
++和--; 前缀式prefix(先自操作, 后计算), 后缀式postfix(先计算, 后自操作);
e.g. int a = 1; int b = ++a; int c = a++; >b和c都为2;
2.5.4 短整数类型的计算
Note Java中的二元整数运算只允许int或long, byte和short类型会转换为int, 使用32位计算, 结果是int类型(32位整数);
int->short需要显式转换: int a =100; short b = (short)a;
Note Java二进制数位都是从右向左增加, 保留低位是可以转换值的, 但是如果超出位数, 转换就会截断;
这里只能把b转换到最接近a的内容, 应该避免意料之外的数据的显式转换;
long类型值的整数运算总是使用64位, 编译器会把其他操作数转换为long类型;
2.5.5 整数算术中的错误
除以0和对0取余都会抛出异常;
如果整数表达式产生的值在取值范围之外, 结果会缩减至相应类型的位数, 这个情况不会报错, 需要程序员来确保结果不出错;
Note 注意中间结果也可能出错, e.g. (1000000*2000000)/500000 乘法得到的结果是有问题的, 最后值没有溢出但是结果不是预期的;(可以先做出发避免溢出)
2.5.6 浮点计算
+ - * /
2.5.7 其他浮点算术运算符
++, --, 每次位移1.0;
取模 %; floatOperand1 % floatOperand2->将floatO1用floatO2分割整数次之后得到的浮点余数;
e.g. 12.6%5.1 == 2.4; 结果的符号一般和被除数的符号一致;
2.5.8 浮点算术中的错误
1) 计算产生的值在浮点型取值范围外; "Infinity"-表示正的有效无限大的结果; (10 / 0)
2) 数学上的: 计算除以零的值; "NaN"-非数字Not a Number, 表示一个不确定值; (0 / 0)
Note Infinity与有限数做加,减或乘运算时, 值不会改变; 但是如果除以任何有限数, 结果为0;
2.5.9 混合算术表达式
类型检查: 如果一个操作数是double/float/long, 运算前将另一个转换为double/float/long;
Note 先后次序是double, float, long; (有double变double)
2.5.10 显式转换
e.g. three(3), two(2)
result = 1.5 + three/two; //2.5
result = 1.5 + (double)three/two; //3, 在运算前three被转换成了double型的3.0;
Note 注意类型转换时的精度丢失, e.g. double --> float, 如果double的值比float的最大值大, 会产生一个Infinity;
2.5.11 赋值中的自动类型转换
当赋值运算符右边的算术表达式结果的类型与左边不同, 信息不丢失的情况下会自动转换;
byte->short->int->long-float->double;
相反方向需要进行显式转换;
2.6 op=运算符
op=操作符可以是任何算术运算符 +, -, *, /, %;
lhs op = rhs; --> lhs = lhs op (rhs);
rhs会首先执行, 然后进行运算; e.g. result /= a % b/(a + b); --> result = result/(a % b/(a + b));
如果rhs和lhs类型不同, 编译器会自动插入转换, 将rhs的值转换成lhs的类型; lhs = (type_of_lhs)(lhs op (rhs));
+=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, |=, ^=;
2.7 数学函数和常量
数学函数作为标准库的一部分存储在java.lang中; 数学函数的方法都在Math类中, 作为static方法;
sin(arg)正弦; cos(arg)余弦; tan(arg)正切; asin(arg)反正弦; acos(arg)反余弦; atan(arg)反正切; atan2(arg1, arg2) arg1/arg2的反正切; toRadians()将角度转换为弧度, 反之toDegrees(); Math.E和Math.PI; abs(arg)绝对值; max(arg1, arg2)较大值,
min(arg1, arg2); ceil(arg) 返回等同于参数或比参数大的最小整数值; floor(arg) 返回等同于参数或比参数小的最大整数值; round(arg)离参数值最近的整数, rint(arg); random() 返回比0.0 大但比1.0 小的伪随机数; ...
导入Math类的方法
import static java.lang.Math.*; //导入静态的类成员, 可以在使用时省略类名;
Math.floor(radius) --> floor(radius);
import static java.lang.Math.floor; //导入特定的方法或者变量;
2.8 存储字符
char-单个字符代码, Unicode, 占16bit/2字节, 初始化: char myCharacter = 'X'; 单引号代表字符, 双引号代表字符串;
2.8.1 字符转义序列
通过转义序列(escape sequence)设定十六进制表示的字符编码来定义Unicode字符;
转义序列通常通过代码设定字符, 反斜线开始- \n;
在表示字符编码的4个16进制数字前加上\u, 可以为一个Unicode字符创建一个转义序列: X - 0x0058; e.g. char myCharacter = '\u0058';//对应 'X';
www.unicode.org 反斜线的转义序列: \\, 引号 \', \"; \b 退格; \f 换页符; \n 新行; \r
回车换行; \t 制表符;
2.8.2 字符算术
myCharacter += 1; //当myCharacter为字符时,'X'+1 --> 'Y' (same as ++myCharacter)
char类型在算术表达式中被转换为int类型进行计算;