第二章Java的基础语法
2.1Java的注释
1、注释是干什么的?
给程序员(人)看的,辅助程序员理解代码的解释性的文字。
2、注释的形式有3种
(1)、单行注释
//注释内容
(2)、多行注释
/*
注释内容1
注释内容2
注释内容3
*/
(3)、文档注释
/**
文档注释内容
*/
文档注释可以被javadoc.exe工具读取,生成API帮助文档
javadoc -d ./doc 源文件名.java
例如:
/**
这是注释的演示代码
@author panghu
@since Java8
@version V1.0
*/
public class Comment{
//这是Java主方法
/**
这是Java程序的入口。
@param args String[]可以通过它给main方法传参数
*/
public static void main(String[] args){
System.out.println("hello");
}
/**
这是求两个整数相除的方法
@param a int 被除数
@param b int 除数
@return int a/b的商
*/
public int divide(int a, int b){
return a/b;
}
}
2.2Java的关键字
Java8版本一共有50关键字,例如:class、public、static、void等。
关键字:全部都是小写的字母组成
关键字中有2个单词比较特殊,它们在Java中没有定义它的作用,在C语言中它有特殊的含义。
- goto:跳转
- const:常量声明关键字
它们称为保留字。
还有3个单词,经常被误认为是关键字,但是从技术角度来说,它们不属于关键字,它们属于特殊值。
- true:真、条件成立,底层是1
- false:假、条件不成立,底层是0
- null:空、没有对象,底层也是0、无
2.3Java的标识符
标识符:凡是程序中需要程序员自己“命名”的地方都是标识符。例如:类名(class后面)、变量名、包名、方法名等。
标识符有命名规则:(不尊重,会发生编译或运行错误)
- 使用26个英文字母(大小写字母都可以用来作为标识符)、数字0-9、下划线_、美元符号$组成。
- 严格区分大小写
- 不能直接使用关键字、保留字、特殊值作为标识符
- 标识符中不能包含空格
- 数字不能开头
标识符有命名规范:(至少5条)(不遵守,会被鄙视和排挤)
- 见名知意
- 类名等:每一个单词首字母大写,例如:HelloWorld,形式:XxxYyyZzz
- 变量名等:从第二个单词开始首字母大写,例如:age,maxValue,形式:xxxYyyZzz
- 常量名等:每一个字母都大写,单词之间使用下划线分割,例如:PI,MAX_VALUE,形式:XXX_YYY_ZZZ
- 包名等:每一个字母都小写,单词之间使用.分割,例如:java.lang包,java.util包,com.alibaba.druid包
2.4初始Java的数据类型
byte:整数类型,字节类型(**)
short:整数类型,短整型(*)
int:整数类型,整型(***)
long:整数类型,长整型(**)
float:小数类型,单精度浮点型(*)
double:小数类型,双精度浮点型(***)
char:单字符类型(**)
boolean:布尔型(**)
String:字符串类型(***)
Java的数据类型分为两大类:
(1)基本数据类型:8种
整数:byte,short,int,long
小数:float,double
字符:char
布尔:boolean
(2)引用数据类型:类、接口、数组、枚举、注解等
类:String
2.5常量
整数类型:
byte,short,int,就正常表示就可以
long,需要加L 或 l(小写L),不推荐用小写,推荐使用大写L,因为小写l和数字1容易混淆
小数类型:
带小数点的数字,默认是double类型,可以在数字后面加D或d
float,需要在数字后面加F或f
单字符:
使用单引号,单引号里面只能是1个字符
字符串:
使用双引号,双引号里面可以是0~n个字符
布尔类型:
true或false
2.6变量
什么是变量?在程序运行期间,值可能改变。
变量的本质:代表内存中一块存储区域。便于程序中对内存中的数据的访问、使用、修改等。
变量有三要素:
- 数据类型:决定了变量内存区域的大小。
- 变量名:程序中就是通过变量名来访问、修改、使用数据。
- 变量值:这块内存区域中存储的数据值。
变量使用有一些要求:
- 必须先声明后使用
数据类型 变量名;
错误案例:
class TestVariable{
public static void main(String[] args){
age = 18;
System.out.println(age);
}
}
这种的未声明变量类型,会报错
2、使用之前必须初始化
变量名 = 值;
错误案例:
class TestVariable{
public static void main(String[] args){
int age;
System.out.println(age);
}
}
正确代码:
class TestVariable{
public static void main(String[] args){
//int age;//声明
//age = 18;//赋值
int age = 18;
System.out.println(age);
age = 19;//可以反复赋值
System.out.println(age);
age = 21;
System.out.println(age);
}
}
3、变量可以反复赋值,但是同一个作用域中不能重复声明
错误案例:
class TestVariable{
public static void main(String[] args){
int age;//声明
age = 18;//赋值
int age = 16;//重复声明age
}
}
4、变量有作用域,不同的作用域可以重名,该变量最近的{}为一个作用域
5、给变量赋的值类型必须<=变量声明的类型
byte<short<int<long<float<double
char<
boolean不参与,只能是true和false
错误案例:
class TestVariable{
public static void main(String[] args){
int age = 18L;
System.out.println(age);
}
}
2.7最终变量
什么是最终变量?
它由final修饰的变量称为最终变量,也叫做常量。因为它的值一旦初始化就不能修改了。
声明最终变量的好处:
- 可读性好:PI比直接使用3.14更容易理解
- 便于维护:如果要修改3.14为3.1415926,只要修改一个地方
- final double PI = 3.1415926;
class TestFinal{
public static void main(String[] args){
//下面3个是圆半径值
double r1 = 1.5;
double r2 = 2.5;
double r3 = 2.0;
//求它们的面积值
//圆面积 = 圆周率π * 半径 * 半径;
//Java中*表示乘法
/*
double area1 = 3.14 * r1 * r1;
double area2 = 3.14 * r2 * r2;
double area3 = 3.14 * r3 * r3;
*/
//代码已经完成了,客户说,圆周率统一使用3.1415926,而不是3.14
//需要修改代码,如果按照上面的写法,需要修改3个地方
//工作量大,还容易出错,漏了,误改等问题
//final double PI = 3.14;
final double PI = 3.1415926;
double area1 = PI * r1 * r1;
double area2 = PI * r2 * r2;
//PI = 3.15;
double area3 = PI * r3 * r3;
System.out.println("第1个圆的半径:" + area1);
System.out.println("第2个圆的半径:" + area2);
System.out.println("第3个圆的半径:" + area3);
}
}
2.8计算机数据的表示和存储
2.8.1进制
1、进制(了解):
十进制:(生活中,人比较熟悉)
数字组成:0-9
进位规则:逢十进一
二进制:(计算机中,只有0和1)
数字组成:0-1
进位规则:逢二进一
八进制:
数字组成:0-7
进位规则:逢八进一
十六进制:
数字组成:0-9,A-F或a-f
进位规则:逢十六进一
2、如何换算?
十进制 二进制 八进制 十六进制
0 0 0 0
1 1 1 1
2 10 2 2
3 11 3 3
4 100 4 4
5 101 5 5
6 110 6 6
7 111 7 7
8 1000 10 8
9 1001 11 9
10 1010 12 a或A
11 1011 13 b或B
12 1100 14 c或C
13 1101 15 d或D
14 1110 16 e或E
15 1111 17 f或F
16 10000 20 10
整数:
二进制->八进制:从右往左数,每3位2进制一组,换算成8进制的数字。
二进制->十六进制:从右往左数,每4位2进制一组,换算成16进制的数字。
目的是在程序中尽量缩短二进制的表示方式,又接近于二进制。
十进制->二进制:除以2倒取余
平时:用计算器的程序员模式
3、程序中如何表示不同的进制呢?
十进制:正常表示
二进制:0B或0b
八进制:0
十六进制:0X或0x
代码:
class ScaleTest{
public static void main(String[] args){
System.out.println("十进制:" + 11);
System.out.println("二进制:" + 0B11);
System.out.println("八进制:" + 011);
System.out.println("十六进制:" + 0X11);
//System.out.println("二进制:" + 0B25);
//二进制只有0和1,在0B后面不能出现0和1以外的数字
}
}
2.8.2计算机存储单位
- 字节(Byte):是计算机信息技术用于计量存储容量的一种计量单位,一字节等于八位。
- 位(bit):是数据存储的最小单位。也就是二进制。二进制数系统中,每个0或1就是一个位,叫做bit(比特),其中8 bit 就称为一个字节(Byte)。
- 转换关系:
- 8 bit = 1 Byte
- 1024 Byte = 1 KB
- 1024 KB = 1 MB
- 1024 MB = 1 GB
- 1024 GB = 1 TB
2.8.3 Java的基本数据类型的存储范围
float:单精度浮点型,占内存:4个字节,精度:科学记数法的小数点后6~7位
double:双精度浮点型,占内存:8个字节,精度:科学记数法的小数点后15~16位
2.8.4计算机如何表示数据
1、如何表示boolean类型的值
true底层使用1表示
false底层使用0表示
2、如何表示整数
原码、反码、补码与符号位概念:
计算机数据的存储使用二进制补码形式存储,并且最高位是符号位,最高位1是负数,最高位0是正数。
规定:正数的补码与反码、原码一样,称为三码合一;
负数的补码与反码、原码不一样:
负数的原码:把十进制转为二进制,然后最高位设置为1
负数的反码:在原码的基础上,最高位不变,其余位取反(0变1,1变0)
负数的补码:反码+1
例如:byte类型(1个字节,8位)
25 ==> 原码 0001 1001 ==> 反码 0001 1001 -->补码 0001 1001
-25 ==>原码 1001 1001 ==> 反码1110 0110 ==>补码 1110 0111
整数:
正数:25 00000000 00000000 000000000 00011001(原码)
正数:25 00000000 00000000 000000000 00011001(反码)
正数:25 00000000 00000000 000000000 00011001(补码)
负数:-25 10000000 00000000 000000000 00011001(原码)
负数:-25 11111111 11111111 111111111 11100110(反码)
负数:-25 11111111 11111111 111111111 11100111(补码)
一个字节可以存储的整数范围?
以byte为例:
最大的正数:01111111 ->127(十进制)
最小的正数:00000001 ->1(十进制)
最大的负数:11111111 ->-1(十进制)
11111111(补码)->11111110(反码)->10000001(原码)
最小的负数:10000001 ->-127(十进制)
10000001(补码)->10000000(反码)->11111111(原码)
零:
00000000 ->+0(十进制)
10000000 ->-0(十进制)(有点浪费)
10000000 ->-128(十进制)
因为:
-127的二进制补码:10000001
1 的二进制补码:00000001
-127-1的二进制补码:10000000(-128的补码)
结论:1个byte的存储范围是 -128 ~ 127
3、如何表示小数?
小数类型如何存储?
(1)十进制->二进制
整数部分:除2倒取余
小数部分:乘2取整数
例如:25.6
11001.10011001******
(2)宽度:
float:4个字节
double:8个字节
(3)符号位
最高位是符号位,0是正,1是负的
(4)把二进制处理成科学计数法
科学计数法:整数部分留1位非0的数字,其余都在小数点后面
小数点往左移动了,就乘以2的n次方
小数点往右移动了,就乘以2的-n次方
例如:25.6
11001.10011001******
1.100110011001****** 小数点往左移了4位,2的4次方
(5)把科学计数法的3个部分存储
A:符号位:正或负
B:小数点右边的数字,称为尾数位
小数点左边的1和小数点不存了,因为所有小数二进制用科学计数法
表示之后,左边都是1.开头。
C:指数位,存储移动了几次
float:1位符号位 + 8位指数位 + 23位尾数位
double:1位符号位 + 11位指数位 + 52位尾数位
因为小数中会用科学计数法表示数字,并且存储指数位,
那么8位的指数位可以表示的指数范围:-128~127,
那么这个数字是很大的。
==> 4个字节的float类型能表示的数字范围比8个字节的long类型大
因为double类型的尾数位(52位)远远超过float类型尾数位(23位)的位数
==> double类型的精度大于float的精度范围。
float:大约小数点后7-8位(十进制科学计数法)
double:大约小数点后15-16位(十进制科学计数法)
==>float和double只能是浮点类型,不是精确定点类型。
4、如何表示char?
char类型如何存储和表示?
(1)字符->整数
计算机最早用128个整数来表示128个字符,ASCII码表。
最早的ASCII码表编码值范围:0-127
'A'->65
'B'->66
...
'a'->97
'b'->98
...
'0'->48
'1'->49
...
目前Java中使用Unicode字符集来表示所有字符。
Unicode字符集的编码范围是:0-65535
(2)把整数用二进制表示,不考虑符号位,称为无符号表示形式。
(3)char:2个字节
(4)程序中如何表示?
A:单引号,里面包含1个字符
B:十进制编码值
C:十六进制编码值
D:只适用于特殊的几个字符,转义字符
\'
\"
\b:退格键,Backspace
\t:制表位,相当于按了Tab键
\r:回车键,结束本行,光标回到行首
\n:换行,光标到下一行行首
\\
2.9基本数据类型的转换
1、自动类型转换
/*
程序中数据(常量/变量)的类型有很多种,
它们需要互相赋值、混合运算、比较等,
如果类型不一致,就需要统一类型再处理。
基本数据类型的转换:
(1)自动类型转换
A:当把数据范围小的类型的值赋值给数据范围大的类型的变量时,
会自动发生类型提升
byte->short->int->long->float->double
char->
B:当byte与byte,short与short,char与char,或者它们3个的混合运算,
都会自动升级为int。
C:如果存在多种数据类型一起混合运算,最后结果会升级为它们中最大的
D:boolean类型不参与它们的换算
(2)强制类型转换
*/
class DataTypeChange{
public static void main(String[] args){
char c = 'a';
int num = c;
double d = c;
System.out.println("c=" + c);
System.out.println("num=" + num);
System.out.println("d=" + d);
short s = 15;
//char code = s;
System.out.println("------------------");
byte b1 = 3;
byte b2 = 5;
//byte b3 = b1 + b2;//报错
char c1 = '0';
char c2 = '1';
//char c3 = c1 + c2;//报错
System.out.println("------------------");
System.out.println(c + s + num + d + b1);//最终结果是double
System.out.println("------------------");
/*
int i = true;
boolean flag = 0;*/
}
}
2、强制类型转换
/*
(2)强制类型转换
A:当把存储范围大的数据类型的值(常量、变量、计算表达式结果)
赋值给存储范围小的变量时,都需要强制类型转换才可以
(强制后的数据类型)值
这种情况可能发生溢出或损失精度。
B:故意“提升”某些值的类型,也可以使用强制类型转换
这种情况不会发生溢出或损失精度。
C:boolean类型不参与它们的换算
*/
class DataTypeChange2{
public static void main(String[] args){
int num = (int)1.5; //把double类型的1.5常量值,强制转为int类型
System.out.println(num);
byte b1 = 127;
byte b2 = 3;
byte b3 = (byte)(b1 + b2);
//把b1+b2的结果int类型强制转换为byte类型
System.out.println(b3);//-126
/*
b1的二进制:01111111
b2的二进制:00000011
+--------------------
00000000 00000000 00000000 10000010(int类型)
高位截断,只留下低位的1个字节
10000010(byte类型) 补码
10000001(反码)
11111110(原码) -126
*/
System.out.println(b1+b2);//130
byte b4 = 1;
byte b5 = 2;
byte b6 = (byte)(b4 + b5);
System.out.println(b6);
System.out.println("------------------");
int x = 1;
int y = 2;
System.out.println(x/y);//0
System.out.println((double)x/y);//0.5 升级x的类型为double
System.out.println((double)(x/y));//0.0 升级x/y的结果为double
}
}
3、和字符串拼接+问题
/*
字符串和基本数据类型的计算?
如果没有字符串参与,那么“+”就表示求和。
如果有字符串参与,那么“+”就表示拼接,拼接的结果也是字符串。
换句话说,任意基本数据类型与字符串进行了“+”操作,都是按照字符串处理的。
*/
class DataTypeChange3{
public static void main(String[] args){
System.out.println("a" + 'b' + 97);
System.out.println('a' + 'b' + 97);
System.out.println('a' + 'b' + "" + 97);
String s = "a";
System.out.println(s + 'b' + 97);
/*
ab97 "a"是字符串,后面+都是拼接,都是按照字符串处理
"a" + "b" + "97"拼接起来
292 97+98+97 求和
19597 当'a' + 'b'是两个char计算,按照求和处理的
97+98得到195
后面遇到了"",""是字符串,后面都按照字符串拼接了
"195" + "" + "97" 拼接起来
ab97
*/
}
}
2.10运算符
2.10.1算术运算符
/*
算术运算符:
加:+
当+左右两边的操作数(加数)没有字符串时,它是求和
当+左右两边的操作数出现了字符串,它就是拼接
减:-
当-左右两边的操作数(加数)没有字符串时,它是求差
当-左右两边的操作数出现了字符串,编译报错(字符串只支持拼接+,其他运算都不支持)
乘:*
除:/
当被除数和除数都是整数类型,那么结果也是整数类型。
当被除数和除数都是整数类型,除数不能为0。
当被除数和除数都是小数类型,那么结果也是小数类型。
当被除数和除数都是小数类型,除数为0,结果是Infinity。
模(取余):%
结果的正负号只看被除数(被模数)。
结果一定是<除数,[0, 除数-1]范围。
当被除数和除数都是整数类型,除数不能为0。
当被除数和除数都是小数类型,除数为0,结果是NaN(not a number)。
正号:+
负号:-
一元运算符:操作数只有1个。
二元运算符:操作数有2个。
System.out.println(+5);//操作数只有1个5,它是一元运算符
System.out.println(1+5);//操作数就有2个了,它是1和5,它是二元运算符
自增:++,自增变量自增1
自减:--,自增变量自减1
以自增为例:
(1)当自增表达式是独立的一个语句时,++在前在后没有任何区别。
i++;
++i;
完全等价的。
(2)当自增表达式不是独立的语句时,即自增表达式和
输出、赋值、其他各种运算一起时,
++在前,表示先自增1,再取自增变量的值做其他操作,
++在后,表示先取自增变量的值,自增变量在自增1,做其他运算是用自增之前的值。
System.out.println(i++);
System.out.println(++i);
*/
class TestArithmetic{
public static void main(String[] args){
System.out.println(8+9);//求和 17
System.out.println('a' + 'b');//求和 195
System.out.println('a' + "b");//拼接 ab
System.out.println("-------------");
int x = 1;
int y = 2;
System.out.println("x+y=" + x + y);//x+y=12 拼接
//System.out.println("x-y=" + x - y);//错误
//因为"x-y=" + x,是字符串拼接,结果也是字符串
//字符串 - y是错误的,字符串不支持减法
System.out.println("x+y=" + (x + y));//x+y=3
System.out.println("x*y=" + x*y);//x*y=2
System.out.println("x/y=" + x/y);//x/y=0
System.out.println("x/y=" + (double)x/y);//x/y=0.5
System.out.println("-------------");
//System.out.println(8/0);//除数不能为0
//运行时发生异常:java.lang.ArithmeticException: / by zero
double a = 1;
double b = 0;
double c = 2;
System.out.println(a/c);//0.5
System.out.println(a/b);//Infinity 无穷大
System.out.println("-------------");
System.out.println(5 % 2);//1
System.out.println(2 % 5);//2
System.out.println("-------------");
System.out.println(5 % 2);//1
System.out.println(5 % -2);//1
System.out.println(-5 % 2);//-1
System.out.println(-5 % -2);//-1
System.out.println("-------------");
System.out.println(5 / 2);//2
System.out.println(5 / -2);//-2
System.out.println(-5 / 2);//-2
System.out.println(-5 / -2);//2
/*
被除数 ÷ 除数 = 商 ...... 余数
余数一定是<除数,余数的范围[0, 除数-1]
余数是被除数中不够除数整数倍,剩下来的,它的正负号只看被除数
*/
System.out.println("-------------");
//System.out.println(5 % 0);
//java.lang.ArithmeticException: / by zero
System.out.println(5.0 % 0.0);//NaN
System.out.println("-------------");
int m = -5;
int n = +m;
int p = -m;
System.out.println("m = " + m);//-5
System.out.println("n = " + n);//-5
System.out.println("p = " + p);//5
System.out.println("-------------");
int i = 1;
System.out.println("i=" + i);
i++;//i自增1
System.out.println("i=" + i);
++i;//i自增1
System.out.println("i=" + i);
i--;//i自减1
System.out.println("i=" + i);
--i;//i自减1
System.out.println("i=" + i);
--i;//i自减1
System.out.println("i=" + i);//i=0
System.out.println("-------------");
System.out.println(i++);//0
/*
先取i的值0,然后i自增1,i=1,但是输出的是i自增之前的0。
这个0被取出来放到了操作数栈中。
*/
System.out.println(++i);//2
/*
先对i自增1,i=2,然后取出i变量的值2输出。
这个2被取出来也放到了操作数栈中。
*/
System.out.println("-------------");
i = ++i;
System.out.println("i = " + i);//i=3
i = i++;
System.out.println("i = " + i);//i=3
System.out.println("-------------");
int j = i++ + ++i * i++;
/*
Java的表达式是从左往右进行解析。
(1)i++
先取i的值3放入操作数栈,然后i自增为4
(2)+运算符入栈
(3)++i
先对i进行自增,i=5,然后取i的值5放入操作数栈
(4)*运算符入栈
(5)i++
先取i的值5放入操作数栈,然后i自增为6
(6)算乘法5*5=25,结果在入栈
(7)算加法3+25=28,结果在入栈
(8)赋值,把28赋值给j
*/
System.out.println("i=" + i);//6
System.out.println("j=" + j);
}
}
2.10.2赋值运算符
/*
赋值运算符:
(1)=的作用:把=右边的值“赋值”左边的变量。
注意:
=左边一定是一个变量,不能是常量、表达式。
=的优先级最低,最后算赋值
=右边值的类型<=左边变量声明的类型
(2) +=,-=,*=,/=,%=等等
这些运算符的作用:先用 +=等左边的变量 与 右边的表达式做计算,
最后把结果赋值给左边的变量。
注意:=左边一定是一个变量,不能是常量、表达式。
赋值的优先级最低,最后算赋值
+=,-=,*=,/=,%=等计算的结果类型 超过左边变量的类型了,
会“自动”发生强制类型转换,可能结果会溢出或损失精度。
*/
class TestAssign{
public static void main(String[] args){
int x;
x = 1;
System.out.println(x);
//1 = x;// 需要: 变量,=一定是变量
x += 3; //x = x + 3;
System.out.println(x);
x *= x + 2;//x = x * (x+2);
System.out.println(x);
byte b1 = 120;
byte b2 = 8;
//byte b3 = b1 + b2;//编译报错
byte b3 = (byte)(b1 + b2);
System.out.println(b3);//-128
b1 += b2;// b1 = b1 + b2;
System.out.println(b3);//-128
}
}
2.10.3关系运算符
/*
比较运算符:
作用:比较两个操作数的大小、相等的关系。
所以又称为关系运算符。
大于:>
小于:<
大于等于:>=
小于等于:<=
等于:==
注意和=的区别
=:赋值
==:比较
不等于:!=
注意:比较运算符(关系运算符)计算结果只有true或false。
关系表达式通常用来作为条件使用。
后面学习if条件,循环条件等。
*/
class TestCompare{
public static void main(String[] args){
int age = 16;
System.out.println(age >= 18);
System.out.println(age == 18);
System.out.println(age);//16
System.out.println(age = 18);//18
//把18赋值给age,然后取age的值输出
System.out.println(age);//18
}
}
2.10.4逻辑运算符
/*
逻辑运算符:
作用:判断两个逻辑值的关系,或者判断两个条件的关系。
要求:逻辑运算符的操作数必须是boolean值
结果:也是boolean值
与:且,两个条件同时成立
逻辑与:&
true & true 结果true
true & false 结果false
false & true 结果false
false & false 结果false
TT才为T。
只有两边都是true,结果才为true。
当&左边为false时,右边继续看。
短路与:&&
true && true 结果true
true && false 结果false
false && true 结果false
false && false 结果false
TT才为T。
只有两边都是true,与的结果才为true。
但是,当&&左边为false时,右边就不看了。
&和&&的区别:
&&会发生短路,&永远不会。
&&当左边是false时短路。
或:两个条件成立1个就可以。
逻辑或:|
true | true 结果是true
true | false 结果是true
false | true 结果是true
false | false 结果是false
FF才为F。
只有两边都是false,或的结果才为false。
短路或:||
true || true 结果是true
true || false 结果是true
false || true 结果是true
false || false 结果是false
当||的左边为true时,右边就不看了。
逻辑异或:两个条件不能同时成立
true ^ true 结果是false
true ^ false 结果是true
false ^ true 结果是true
false ^ false 结果是false
TF或FT才为T。
只有两边不同,一边是true,一边是false,异或结果才为true.
逻辑非:
!true 为false
!false 为true
*/
class TestLogic{
public static void main(String[] args){
int age = 16;
//判断:年龄是否满足[18,35]之间
//两个条件同时满足:age>=18 和 age<=35
//System.out.println(18 <= age <= 35);//错误
//因为 18 <= age 计算完的结果是true/false
// false <= 35无法比较
System.out.println(18 <= age & age <= 35);
System.out.println(age>=18 & age<= 35);
System.out.println(age>=18 && age<= 35);
int i = 3;
System.out.println(i<2 && ++i>0);//false
System.out.println(i);//3
int j=3;
System.out.println(j<2 & ++j>0);//false
System.out.println(j);//j=4
System.out.println("-------------------");
//年龄满足<18 或 满足>35,都不符合尚硅谷学员标准
System.out.println(age<18 | age>35);
System.out.println(age<18 || age>35);
int m = 1;
System.out.println(m>=0 || ++m<=5);
System.out.println(m);
System.out.println("----------------");
int a = 3;
int b = 4;
int c = 5;
System.out.println((a > b) ^ (a > c));//false ^ false false
System.out.println((a > b) ^ (a < c)); //false ^ true true
System.out.println((a < b) ^ (a > c)); //true ^ false true
System.out.println((a < b) ^ (a < c)); //true ^ true false
}
}
2.10.5条件运算符
/*
条件运算符:
Java中唯一的三元运算符。
条件表达式 ? 结果表达式1 : 结果表达式2
条件表达式必须是true或false的结果。
*/
class TestCondition{
public static void main(String[] args){
int x = 6;
int y = 6;
//输出两个整数中的最大值
System.out.println(x>y ? x : y);
boolean marry = false;
System.out.println(marry ? "已婚" : "未婚");
//marry ? "已婚" : "未婚";//marry ? "已婚" : "未婚"
System.out.println("=================");
int z = 15;
int max = x > y ? x : y;
max = max > z ? max : z;
System.out.println("max = " + max);
}
}
2.10.6位运算符
/*
位运算符:(最难,因为它最不直观)
按位与:&
其实本质上(底层)逻辑与就是按位与。
因为逻辑值只有true和false,就是1和0.
1 & 1 结果是1
1 & 0 结果是0
0 & 1 结果是0
0 & 0 结果是0
只是按位与更宽泛一点,是针对所有的二进制位,
两个操作数的所有对应二进制位都做&运算。
按位或:|
其实本质上(底层)逻辑或就是按位或。
因为逻辑值只有true和false,就是1和0.
1 | 1 结果是1
1 | 0 结果是1
0 | 1 结果是1
0 | 0 结果是0
只是按位或更宽泛一点,是针对所有的二进制位,
两个操作数的所有对应二进制位都做|运算。
按位异或:^
其实本质上(底层)逻辑异或就是按位异或。
因为逻辑值只有true和false,就是1和0.
1 ^ 1 结果是0
1 ^ 0 结果是1
0 ^ 1 结果是1
0 ^ 0 结果是0
只是按位异或更宽泛一点,是针对所有的二进制位,
两个操作数的所有对应二进制位都做^运算。
按位取反:~
原来的逻辑非就是按位取反,
因为逻辑值只有true和false,就是1和0.
1变0
0变1
~时不看符号位,所有位都取反。
但是看结果时,二进制补码要算回十进制,要看符号位。
如果符号位是0,说明是正数,原码、反码、补码一样,直接算十进制。
如果符号位是1,说明是负数,从补码要一步一步算回原码再算十进制。
左移:<<
所有二进制位整体左移n位,右边补0,左边移出去了。
大部分情况:左移n位就相当于乘以2的n次方。
有时候特殊:移位后符号位变了,结果就不能按照乘以2的n次方来算。
当移的位数n超过当前类型的最大位数,实际移动位数 = n-当前类型的最大位数。
例如:int类型,n-32
右移:>>
所有二进制位整体右移n位,左边补什么要看最高位是什么就补什么。
大部分情况:右移n位,相当于除以2的n次方。
当移的位数n超过当前类型的最大位数,实际移动位数 = n-当前类型的最大位数。
例如:int类型,n-32
右移不会出现正变负,负变正的情况。
无符号右移:>>>
所有二进制位整体右移n位,左边补0,不看符号位。
如果原来是正数,无符号右移和普通右移是一样的。
如果原来是负数,无符号右移会让负数变为正数,因为最高位补0。
总结:
只有负数的普通右移(>>),左边补1,其余所有移位都补0。
只有普通右移不会改变正负号,其余移位都可能改变正负号。
*/
class TestBit{
public static void main(String[] args){
System.out.println(5 & 3);//1
/*
5的二进制:00000000 00000000 00000000 00000101
3的二进制:00000000 00000000 00000000 00000011
&----------------------------------------------
00000000 00000000 00000000 00000001
*/
System.out.println(5 | 3);//7
/*
5的二进制:00000000 00000000 00000000 00000101
3的二进制:00000000 00000000 00000000 00000011
|----------------------------------------------
00000000 00000000 00000000 00000111
*/
System.out.println(5 ^ 3);//6
/*
5的二进制:00000000 00000000 00000000 00000101
3的二进制:00000000 00000000 00000000 00000011
^----------------------------------------------
00000000 00000000 00000000 00000110
*/
System.out.println(~5);//-6
/*
5的二进制:00000000 00000000 00000000 00000101
~----------------------------------------------
11111111 11111111 11111111 11111010
~运算不考虑符号位的特殊,所有位都取反。
再看结果的十进制值时,要看符号位的。
11111111 11111111 11111111 11111010的符号位是1,说明是负数。
11111111 11111111 11111111 11111010(补码)
11111111 11111111 11111111 11111001(反码)
10000000 00000000 00000000 00000110(原码)
*/
System.out.println(~-6);//5
/*
-6的二进制:10000000 00000000 00000000 00000110(原码)
11111111 11111111 11111111 11111001(反码)
11111111 11111111 11111111 11111010(补码)
~---------------------------------------------------------
00000000 00000000 00000000 00000101(结果)
~运算不考虑符号位的特殊,所有位都取反。
再看结果的十进制值时,要看符号位的。
00000000 00000000 00000000 00000101最高位是0,说明是正数。
正数的原码、反码、补码是一样的。
*/
System.out.println(5 << 3);//40
/*
5的二进制:00000000 00000000 00000000 00000101
5 << 3--------------------------------------------
00000 00000000 00000000 00000101000
00000000 00000000 00000000 00101000
简单看:左移n位相当于乘以2的n次方
5<<3相当于 5 * 2的3次 = 5*8 = 40
*/
System.out.println(5 << 29);//-1610612736
/*
5的二进制:00000000 00000000 00000000 00000101
5 << 29-------------------------------------------
10100000 00000000 00000000 00000000
结果的最高位是1,是负数
10100000 00000000 00000000 00000000(补码)
10011111 11111111 11111111 11111111(反码)
11100000 00000000 00000000 00000000(原码)
*/
System.out.println(5 << 35);//40
/*
5 << 35,当前5是int类型,总共是32位,左移35位,等价于 左移(35-32)位。
有点类似于循环回来的意思。
*/
System.out.println(5 >> 1);//2
/*
5的二进制:00000000 00000000 00000000 00000101
5 >> 1------------------------------------------
00000000 00000000 00000000 00000010
(左边原来最高位是0,左边补0)
结果还是正的。
简单看:右移n位,相当于除以2的n次方。
5 >> 1相当于 5 / 2的1次 = 5/2 = 2(int/int还是int)
*/
System.out.println(-6>>>1);//2147483645
/*
-6的二进制:10000000 00000000 00000000 00000110(原码)
11111111 11111111 11111111 11111001(反码)
11111111 11111111 11111111 11111010(补码)
-6>>>1----------------------------------------------------
011111111 11111111 11111111 1111101(结果)
最高位是0,表示正数
*/
}
}
2.10.7运算符分类
在Java8中,一共有38个运算符
运算符的分类:
- 按照功能分:算术运算符、赋值运算符、比较运算符、逻辑运算、条件运算符、Lambda运算符
分类 | 运算符 |
算术运算符(7个) | +、-、*、/、%、++、-- |
赋值运算符(12个) | =、+=、-=、*=、/=、%=、>>=、<<=、>>>=、&=、|=、^=等 |
关系运算符(6个) | >、>=、<、<=、==、!= |
逻辑运算符(6个) | &、|、^、!、&&、|| |
条件运算符(2个) | 条件表达式?结果1:结果2 |
位运算符(7个) | &、|、^、~、<<、>>、>>> |
Lambda运算符(1个) | ->(后面学) |
- 按照操作数个数分:一元运算符(单目运算符)、二元运算符(双目运算符)、三元运算符 (三目运算符)
分类 | 运算符 |
一元运算符(单目运算符) | 正号(+)、负号(-)、++、--、!、~ |
二元运算符(双目运算符) | 除了一元和三元运算符剩下的都是二元运算符 |
三元运算符 (三目运算符) | (条件表达式)?结果1:结果2 |
2.10.8运算符优先级
提示说明:
(1)表达式不要太复杂
(2)先算的使用()
口诀:
单目运算排第一;
乘除余二加减三;
移位四,关系五;
等和不等排第六;
位与、异或和位或;
短路与和短路或;
依次从七到十一;
条件排在第十二;
赋值一定是最后;
2.11标点符号
在Java中一共有12个标点符号。(从一开始就需要开始留意代码中不同位置使用的不同标点符号,训练眼力)
- 小括号()用于强制类型转换、表示优先运算表达式、方法参数列表
- 大括号{}用于数组元素列表、类体、方法体、复合语句代码块边界符
- 中括号[]用于数组
- 分号;用于结束语句
- 逗号,用于多个赋值表达式的分隔符和方法参数列表分隔符
- 英文句号.用于成员访问和包目录结构分隔符
- 英文省略号...用于可变参数
- @用于注解
- 双冒号::用于方法引用
class Sign{
public static void main(String[] args){
int x,y,z;//声明了3个int类型的变量
int a = 1, b = 2, c = 1;//声明了3个int类型的变量,并且初始化
//int m = n = 1;//n没有声明
}
}
标签:运算符,Java,00000000,System,笔记,学习,println,true,out
From: https://blog.51cto.com/u_16213911/6957643