[Java]重学Java-变量与运算符
变量与常量
如何定义变量
比如说你想用Java表示一个数字:100.那么你就需要赋值给一个变量,并且给它定义好数据类型和名字,类似于这样:
- 定义变量
int number = 100;
你也可以暂时不进行初始化,在某些需要合并计算的时候再对该变量进行赋值:
- 声明变量不初始化值
int sum;
sum = 1+1;
System.out.println(sum);
但是,局部声明的变量如果未进行赋值,是不可以直接进行使用的
- 错误示范
int uninitializedData;
// 无法通过编译
System.out.println(uninitializedData);
Java可以将变量赋值到任何地方,随意在你需要这个变量的时候再进行定义即可,这样也可以让你的代码变得更易读.
- 早早声明了变量,却很久才进行赋值
int sum;
int a = 1+1;
int b = 2+2;
int c = a+b;
sum = a+b+c;
- 推荐的做法
int a = 1+1;
int b = 2+2;
int c = a+b;
int sum = a+b+c;
变量命名有讲究嘛?
- 变量名必须以字母或者字符开头.但是不可以出现
+
、空格、等比较特殊的字符. - 命名不可以与Java本身的保留字进行冲突.例如:
int int;
int class;
int long;
int public;
- 推荐使用
驼峰命名法
来命名Java变量,并且变量命名有意义(不要使用简单的一个字母来声明变量),比如学生名称,你可以这么写:
private String studentName;
- $符号在一些框架下有特殊意义,尽量不要使用它来命名变量.
常量怎么定义-final
Java中的常量其实没有所谓的const
修饰符,你只需要使用final
关键字来修饰你的变量即可,通常按照规范,常量名都是需要大写,并且使用_
进行分隔,下面我们来看一个示例:
- 声明常量
private final String COUNTRY_CH = "Chinese";
final被final修饰的变量是不可变的,这意味着一经初始化,你将无法再次更改值了。
运算符
运算符可以操作数据.
算术运算符
+
、-
、*
、/
是我们经常使用的算数运算符,表示加、减、乘、除.
除此之外,我们还可以能用到取余:%
下面来简单运用一下运算符:
System.out.println(1 + 2);
System.out.println(2 - 1);
System.out.println(1 * 2);
System.out.println(1 / 2);
System.out.println(1 % 2);
Result:
3
1
2
0
1
- 除运算的特殊性
在上面的实践中,我们发现,除法并没有输出我们期望的1/2=0.5
,这是为什么呢?
因为1和2都是整型,而我们期望的结果是一个浮点型0.5
,Java执行了整数除法.
下面我们声明其中一个参数为浮点型,让编译器自动地进行类型转换.
// 打印->0.5
System.out.println(1 / 2.0);
组合运算符
可以将+
、-
、*
、/
与等号=
进行结合来使用.
int x = 0;
// 等价于 x = x + 1;
x += 1;
System.out.println(x);
i++
和++i
问题
Java提供自增与自减运算符的支持,如果你不想写i = i + 1
,你可以使用i++
或者++i
。但是这两者放在复杂的语句中会产生不一样的效果.
i++
与++i
int i = 0;
System.out.println(i++);
System.out.println(++i);
Result:
0
2
为什么会产生这样的结果?
原理比较复杂,但是记住一个原则,你就可以避开许多麻烦:
i++是先使用i原来的值再做自增,++i是先自增再使用值
同样的原则对于i--和--i也是一样的
如果你感觉很麻烦,那么大可不必在表达式中使用++
或者--
位运算
学过计算机组成原理的会很熟悉位运算,这给我们提供了操作二进制数据的机会.
- 异或:^
若两个输入位的某一个是 1,另一个不是 1,那么 "^" 运算后结果才是 1
// 3: 0011
// 5: 0101
// ^的规则是:若两个输入位的某一个是 1,另一个不是 1,那么 "^" 运算后结果才是 1
// ---0110->6
System.out.println("3^5运算的结果是 :" + (3 ^ 5));
3^5运算的结果是 :6
- 与:&
若两个输入位都是 1,则"&" 运算后结果是 1,否则结果是 0
// 3: 0011
// 5: 0101
// &的规则是:若两个输入位都是 1,则"&" 运算后结果是 1,否则结果是 0
// ---0001->1
System.out.println("3&5运算的结果是 :" + (3 & 5));
3&5运算的结果是 :1
- 或:|
若两个输入位里至少有一个是 1,则"|" 运算后结果是 1,都是0的情况下结果是 0
// 3: 0011
// 5: 0101
// |的规则是:若两个输入位里至少有一个是 1,则"|" 运算后结果是 1,都是0的情况下结果是 0
// ---0111->7
System.out.println("3|5运算的结果是 :" + (3 | 5));
3|5运算的结果是 :7
- 非:~
非的逻辑比较简单,0->1,1->0
// 3: 0011
// ~3: 1100-> -4
// 其中,第一位表示正负值
System.out.println("~3运算的结果是:" + ~3);
~3运算的结果是:-4,这里我们看到,
~
只对一个数做运算,它是一元运算符.
- 左移:<<
<< 在低位补 0
int i = 3 << 1;
// 3: 0011
// 左移: 0110->6
System.out.println("3左移一位运算结果是:" + i);
3左移一位运算结果是:6
- 右移:>>
>>
有“正”、“负”值:若值为正,则在高位插入 0;若值为负,则在高位插入 1
int j = 3 >> 1;
// 3: 0011
// 右移: 0001->1
System.out.println("3右移一位运算结果是:" + j);
3右移一位运算结果是:1
- 不区分正负的右移运算符:>>>
>>>
无论正负,都在高位插入 0.
// 15: 1111
// >>>: 0111->7
System.out.println("15>>>后的结果是:" + (15 >>> 1));
15>>>后的结果是:7
逻辑运算符与短路规则
我们主要来看&&
与||
这两个逻辑运算符.
- &&
int sum = 1;
if (sum > 0 && sum < 2) {
System.out.println("我是1");
}
这段代码表示: 当sum满足大于0且小于2,输出"我是1"
- ||
int number = 1;
if (sum > 0 || sum < 0) {
System.out.println("bingo!");
}
这段代码表示: 当number大于0或者小于0,即可输出"bingo!"
短路规则
表达式A && 表达式B
对于&&
来说,A不成立,就没必要执行B的逻辑了,所以A不成立会直接短路.
对于||
来说,只要A成立,也没必要执行B的逻辑了,所以A成立会直接短路.
三目运算符
可以通过三目运算符来简写if else.
int sum = 1;
if (sum > 0) {
sum = 1;
}else{
sum = -1;
}
// 等价于
sum = sum > 0 ? 1 : -1;
==和equals
==
和equals是经常容易犯错的问题,首先要清楚:
==
往往比较的是两个变量之间的存放位置,而不是值本身.
equlas
比较的是两个变量的值本身而不是变量的存放位置.
下面我们通过代码来看看这个现象:
比较String请使用equals
String a = new String("a");
String a1 = new String("a");
System.out.println(a == a1);
答案输出了: false.
为什么呢?我们来看一下
new关键字代表你向JVM申请了内存空间来赋值给你的引用.所以使用==
来比较字符串是不对的,应该使用equals
.
比较基础类型用==,比较对象值推荐equals或者compareTo
首先,Java中的数据都是存放在JVM中的,其中基础类型的数据则存放在JVM的局部变量表中,也可以理解成所谓的"栈"。
也就是说,还是可以通过==
来比较int这种类型的值是否相等,但是注意,int与Integer是截然不同的,一个是基础类型,一个是对象,这个在后面我们会细说。
- 比较基础类型值
int i = 11111111;
int j = 11111111;
System.out.println(i == j);
OK,这不会产生什么问题,现在我们换成Integer来比较.
- 比较对象值
Integer i = 11111111;
Integer j = 11111111;
// 错误的用法
System.out.println(i == j);
// 正确的用法
System.out.println(i.equals(j));
// 正确的用法
System.out.println(i.compareTo(j) == 0);
这个是个坑,所以要特意强调.
这里思考一个问题: equals一定是正确的嘛?
答案是不一定的,最好先确认所用的类是否重写了equals.这里我们用到的Integer便是重写了equals.