java-1.基础入门
Lin
xiaominglin789java 特点
- 面向对象(封装,继承,多态)
- 高性能、分布式、多线程
- 安全性、健壮性
- 半解释半编译语言(编译与解释并存)
- JAVA在线中文文档
1 - JDK、JRE、JVM 关系
- JDK: Java Development Kit (Java开发工具包)
- JRE: Java Runtime Environment (运行时环境)
- JVM: Java Virtual Machine (虚拟机)
JVM是可运行Java代码的假想计算机.包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收,堆和一个存储方法域。
.java文件 —-> 编译器(javac) —->字节码文件(.class) —-> JVM(java) —->机器码
JDK = JRE + java的开发工具(java/javac/javadoc/javap等)
JRE = JVM + Java的核心类库(类)
- 如果只是想运行一个开发好的Java程序,只需要安装JRE即可
2 - 变量
- 1.变量的声明
- 2.+号的使用
- 3.数据类型
- 4.数据类型转换
- 5.自增和自减
2.1 - 变量声明赋值
- 变量是内存中的一个数据存储空间的表示, 可以通过变量名找到变量的值
- [数据类型] 变量名 = 赋值;
- exp:
- int a; // 变量的声明
- a = 60; // 变量的赋值,60赋给a
2.2 - 加号的使用
- 当左右两边都是数值型, 则作加法运算 -当左右两边有一方为字符串, 则为拼接运算
System.out.println(10 + "90"); // 1090
System.out.println("age:" + 18); // age:18
System.out.println(11 + 68 + "" + 1); // 791
3 - 数据类型
每一种数据都定义了明确的数据类型,在内存种分配了不同大小的内存空间(字节)
- 基本数据类型(8种)
- 6种数字类型: byte、short、int、long、float、double
- 1种字符类型: char
- 1种布尔类型: boolean
- 引用数据类型
- 类(class)
- 接口(interface)
- 数组(ArrayList)
4 - 8大基本数据类型的占位表
基本类型 | 位数(bit) | 字节大小 | 默认值 | 取值范围 |
---|---|---|---|---|
byte(字节) | 8 | 1 | 0 | -(2^7)~(2^7 -1) |
short(短整型) | 16 | 2 | 0 | -(2^15)~(2^15 -1) |
int(整型) | 32 | 4 | 0 | -(2^31)~(2^31 -1) |
long(长整型) | 64 | 8 | 0L | -(2^63)~(2^63 -1) |
float(单精度) | 32 | 4 | 0f | |
double(双精度) | 64 | 8 | 0d | |
char(字符型) | 8 | 2 | 'u0000' | |
boolean(布尔型) | 1(jvm) | false |
4.1 - 注意点:
bit
是计算机中最小的存储单位,byte字节
是计算机中基本存储单元.- 8bit = 1byte
- 使用 Long 类型的数据一定要在数值后加上
L
, 否则将作为整型解析. - tybe,short,char本质上都是整型变量。char不能直接=int型,int型可以=char型。
char a = 'c';
char: 单引号,一个字符位String s = "cry";
String: 双引号, 字符串是多个字符拼接得来的.
4.2 - 浮点数(内存): 浮点数 = 符号位 + 指数位 + 位数位
- 尾数部分可能丢失,造成精度丢失(小数都是近似值)
- Java的浮点数默认是
double
类型 - Double类型后缀加
D
或d
- Float类型后缀加
F
或f
- 通常表示小数,都用 double, 保证精度
- 避免小数的运算
4.3 - 字符类型(char):
- char 可以表示
单个字符
, 占2byte
,可以存放汉字。使用单引号
括住. - 多个字符则需要用
字符串String
来表示 - 字符型 在计算机的存储/读取过程:
- 存储: 'a' ==> 码值:97 ==> 97转成二进制 ==>存储
- 读取: 二进制 ==> 转成码值:97 ==> 转成char: 'a'
- char:char的本质是一个整数,输出时,是unicode码对应的字符
- char c1 = 'a';
- char c2 = 97;
- char c3 = '大';
- char c4 = '\t';
- c1 == c2 ? true
- c1 + c2 = 194;
- (int)c1 = 97;
- System.out.println('a' + 3); // 100
4.4 - 布尔类型
- boolean: 只允许取值: true 或 false, 默认 false. 无null
- boolean类型适用于逻辑判断:
- if / while / do...while / for
- 不可以用
0
或非0
的整数来代替false
或true
- boolean isOk = 1; // 这是错误的。。。
- boolean 逻辑上理解是占用 1bit,但是实际中会考虑计算机高效存储因素
- java规范中,没有明确指出boolean的大小.
- 计算机处理数据的最小单位是1byte,
- 实际存储的空间是:用1个字节的最低位存储,其他7位用0填补,
- true -> 二进制(0000 0001)
- false -> 二进制(0000 0000)
- boolean类型占了单独使用是4个字节,在数组中又是1个字节
5 - 基础数据类型的转换
- 自动类型转换: 进行赋值运算时: 低容量类型 => 自动转成 => 高容量类型
# 低 ----------------------------------> 高
char -> int -> long -> float -> double
# 低 ----------------------------------> 高
byte -> short -> int -> long -> float -> double
- 注意细节
- 1.多种类型的数据混合运算时, 系统会先
自动
将所有数据转换
成容量最大的类型
,再计算,得到容量最大的类型
的结果。- 小可以变大
- 2.容量大的数据类型 赋值给 容量小的数据类型时,会报错。
- 大不能变小(精度缺失)
- 3.(byte、short) 和 char 之间不会互相自动转换
- 4.byte、short、char 三者可以计算(单种或混合),在计算时首先转成 int 类型、
- 5.自动提升原则: 表达式结果的类型自动提升为 操作数中最大的类型
- 1.多种类型的数据混合运算时, 系统会先
6 - 强制类型转换
- 自动类型转换的逆过程,强制将容量大的数据类型转换成容量小的数据类型,使用时加上强制转换符:(类型), 但可能造成数据的精度降低或溢出.
- 强制类型转换的细节:
- 1.当进行数据的大小
从 大 --> 小
, 就需要使用强制类型转换. - 2.强转符号
只针对最近的操作数
, 往往会使用小括号来提升优先级. - 3.
char
类型可以保存int的常量值
,但不能保存int的变量值
,需要强转. - 4.
byte
和short
类型进行运算时,当作int类型
处理.
- 1.当进行数据的大小
int n1 = (int)10 * 3.5 + 5 * 1.5; // // compilation failed, (int)10 => 10, 10 * 3.5 is double, 5 * 1.5 is double, double + double is double. so double cannot be assigned to int
System.out.println(n1);
int n2 = (int)(10 * 3.5 + 5 * 1.5); // proximity principle, parentheses to enhance priority
System.out.println(n2); // 42
char c1 = 100; // compilation passed
int m = 100; // compilation passed
// char c2 = m; // compilation failed
char c3 = (char)(m); // compilation passed, Forced conversion before assignment
System.out.println(c3); // d
7 - 基本数据类型 和 String类型的转换
程序开发中,常常需要将基本数据类型
转成 String类型
, 或 将 String类型
转成基本数据类型
- 1.基本数据类型 转 String类型:基本数据类型 + ""
String s1 = (byte)(2) + ""; // "2"
String s2 = (short)(3) + ""; // "3"
String s3 = 5 + ""; // "5"
String s4 = 3L + ""; // "3"
String s5 = 4.5F + ""; // "4.5"
String s6 = 6.6 + ""; // "6.6"
String s7 = (char)97 + ""; // "a"
String s8 = true + ""; // "true"
- 2.基本数据类型都有自己的包装类,其中大部分有
parseXxxx(String s)
的方法将字符串转成其对应的基本类型。char
类型则有所不同。如下:
String s = "97";
byte b = Byte.parseByte(s); // 97
short t = Short.parseShort(s); // 97
int i = Integer.parseInt(s); // 97
long l = Long.parseLong(s); // 97
float f = Float.parseFloat(s); // 97.0
double d = Double.parseDouble(s); // 97.0
boolean bool = Boolean.parseBoolean("true"); // true
char c = s.charAt(0); // '9'
- 注意事项:
- String 转 基本数据类型时, 要确保 String类型能够转成有效的数据,否则会报错.
exp: "hello" =转=> int, 抛出异常,程序中止
8 - 编码规范(无关语言)
- ASCII编码表
- ASCII码编码表中,每一个
字符
都是用一个字节表示,一共有128个字符.- 此处的
字符
可不是 java中的char。
- 此处的
- ASCII码编码表最多能表示256个字符, 但是只用了128个字符: 数字 + 大小写字母 + 普通符号 + 特殊符号 + 转义字符
- 用一个字节的低 7 位表示,0~31 是控制字符如换行回车删除等;32~126 是打印字符(可以通过键盘输入并且能够显示出来的)
- 一个字节 = 8个bit,所以能表示的字符范围是 0~255 个
- ASCII码编码表中,每一个
- Unicode编码表:固定大小的编码, 数字、字母和汉字等都统一 占2个字节.
- utf-8编码表: 大小可变,一个字母占 1个字节, 一个汉字占 3个字节.
- 转义字符(转义符号+字母) 占 2字节:换行符、制表符...
9 - java类的组织形式
|---> 接口 |-> 字段
|---> 枚举 |-> 类1 ->|-> 构造
|->包1 ->|---> 类(...) ->| |-> 方法
| | |-> 类2
JDK->| |---> 异常
|
|-> 包2
|-> 包...
10 - 运算符
- 算术运算符:+ , - , * , / , % , ++ , --
- 赋值运算符:=, += , -= , *= , /=
- 关系运算符:> , < , >= , <= , == , != , instanceof
- 逻辑运算符:&& , || , ! , & , | , ^ ,
- 位运算符: ~ , >> , << , >>>
- 条件运算符:? :
10.1 - 算术运算符
加、减、乘、除、取余、++、--
- 1.乘法、除法运算
- 元素都会先转成最高精度再进行运算
System.out.println(10 / 4); // 2
System.out.println(10.0 / 4); // 2.5
double d = 10 / 4;
System.out.println(d); // 2.0
- 2.取余
- 模计算: a % b = a - (a / b) * b
System.out.println(10 % 3); // 1
System.out.println(-10 % 3); // -1
System.out.println(10 % -3); // 1
System.out.println(-10 % -3); // -1
3.
++
、--
- 独立语句使用:
int a = 1;a++; // a = a + 1 => 2a--; // a = a - 1 => 1- 作为表达式使用:
- 后
i = i++
: 规则使用临时变量的过程- (1) temp = i;
- (2) i = i + 1;
- (3) i = temp;
- 前
i = ++i
: 规则使用临时变量的过程- (1) i = i + 1;
- (2) temp = i;
- (3) i = temp;
--
同理
- 后
++
、--
默认会进行类型转换
byte gg = 1;gg++; // gg = byte(gg + 1)System.out.println(gg); // 2int a = 1;a = a++;System.out.println("a=" + a); // 1int b = 1;b = ++b;System.out.println("b=" + b); // 2int a5 = 10;int a6 = 20;int a7 = a5++; // 1.temp=a5=10; 2.a5=a5+1=11; 3.a7=temp=10;System.out.println("a7 = " + a7); // 10System.out.println("a6 = " + a6); // 20a7 = --a6; // 1.a6=a6-1=19; 2.temp=a6=19; 3.a7=temp=19System.out.println("a7 = " + a7); // 19System.out.println("a6 = " + a6); // 19
算术运算符-练习题:
// 1.假如还有59天放假, 问 合多少个星期零多少天?
// y = 7 * a + d = 59
int days = 59;
int week = days/ 7; // = 8;
int less = days % 7; // 59 - (59 / 7) * 7 = 59 - 8 * 7 = 59 - 56 = 3;
System.out.println("合"+ week +"个星期零"+ less +"天");
System.out.println();
// 2.定义一个变量保存华氏温度, 华氏温度转成摄氏温度的公式是:5/9 * (华氏温度 - 100), 当前的华氏温度是: 234.5, 请求出华氏温度对应的摄氏温度。
// y = 5/9 * (x-100)
// 注意: java中 5/9 = 整型/整型 => 整型 = 0
double x = 234.5;
double y = (5.0 / 9) * (x - 100); // 5.0/9 * 134.5 = 74.xxxxxx
System.out.println(x + "华氏温度 = " + y + "摄氏温度");
10.2 - 赋值运算符
-基本赋值运算符
+ `=`
- 复合运算符:复合赋值运算会进行类型转换
+=
加等-=
减等*=
乘等(注意:小数)/=
除等(注意: 小数 / 分母=0 的情况)
算术运算符-练习题
// 复合赋值运算会进行类型转换
byte b = 12;
b += 12; // 按道理 b = b + 12 是编译失败的。由于是 复合运算, 所有 b += 12 => b = byte(b + 2)=>byte=24
b++; // b = byte(b + 1) = 25
10.3 - 关系运算符
>
大于<=
小于等于>=
大于等于==
用于比较等号左右两边的值(基本数据类型)是否相等
!=
用于比较等号左右两边的值(基本数据类型)是否不相等
instanceof
判断它左边的对象是否是它右边的类的实例,返回布尔值
// 关系运算符: 结果 布尔值
int g1 = 10;
int g2 = 20;
System.out.println(g1 > g2); // false
System.out.println(g1 >= g2); // false
System.out.println(g1 < g2); // true
System.out.println(g1 <= g2); // true
System.out.println(g1 != g2); // true
System.out.println(g1 == g2); // false
10.4 - 条件运算符(三元运算符)
条件判断,非A即B
- 条件 ? true : false
// 三元运算: 条件 ? 真-表达式 : 假-表达式
int a = 60;
byte b = 70;
int r = a > b ? a-- : --b; // a > b 转成int比较, r 至少为int类型, a > b ? false=> --b;
System.out.println("a = " + a); // 60
System.out.println("b = " + b); // 69 int r=--b => b=(int)(b-1)=69;r=b=69
System.out.println("r = " + r); // 69
10.5 - 逻辑运算符(重点)
逻辑运算符: 用于连接多个条件多个关系表达式, 最终的结果是boolean类型
&&
:短路与
- 规则: 2个条件都为:true, 结果为:true. 否则结果为:false
- 只要
第一个条件为false
,第二个条件不会再去判断
,最终结果:false
; 全部条件都为true
,最终结果才为true
. - 一般开发中都是使用:
&&
, 判断效率高
&
:逻辑与
- 规则: 2个条件都为:true, 结果为:true. 否则结果为:false
- 不同点: 即使
第一个条件为false
,第二个条件仍然会去判断,最终结果:false
; 全部条件都为true
,最终结果才为true
.
||
:短路或
- 规则: 只要有一个条件为:true, 结果为:true. 全部为: false,结果才为为:false
- 只要有一个条件为
true
, 所有条件都会去判断,则结果为true
。当所有条件都为false
,最终结果才为false
.
|
:逻辑或
- 规则: 只要有一个条件为:true, 结果为:true. 全部为: false,结果才为为:false
- 不同点: 不管第一个条件是否为:true, 第二个条件都要判断。执行效率低
!
:取反(非)
- !true => false !false => true
^
:逻辑异或
(a^b
,a
和b
不同,返回true
; a 和 b 相同, 则返回false
)- a ^ b 不同时, 则结果为 true. 否则为 false
逻辑运算符-练习题:
// 1.与 ->规则: 2个条件都为:true, 结果为:true. 否则结果为:false
// &&(短路与) 第一个条件为false, 后面的条件不再判断,最终结果为:false。效率高
// &(逻辑与) 第一个条件为false, 后面的条件仍然要去判断。效率低
int a = 4;
int b = 9;
if (a < 4 && ++b < 11) {
System.out.println("a > 4 & ++b < 11 条件满足"); // 不执行
}
System.out.println("a=" + a + " b=" + b); // a=4 b=9
if (a < 4 & ++b < 11) {
System.out.println("a > 4 & ++b < 11 条件满足"); // 不执行
}
System.out.println("a=" + a + " b=" + b); // a=4 b=10
System.out.println();
// 2.或 ->规则: 只要有一个条件为:true, 结果为:true. 全部为: false,结果才为为:false
// ||(短路或) 第一个条件为:true, 第二个条件不在判断,最终结果为: true。效率高
// |(逻辑或) 不管第一个条件是否为:true, 第二个条件都要判断。执行效率低
int c = 3;
int d = 7;
if (c > 1 || ++d < 5) {
System.out.println("c > 1 || ++d < 5 条件满足");
}
System.out.println("c=" + c + " d=" + d); // c=3 d=7
if (c > 1 | ++d < 5) {
System.out.println("c > 1 | ++d < 5 条件满足");
}
System.out.println("c=" + c + " d=" + d); // c=3 d=8
System.out.println();
// 3. `!`: 取反
System.out.println(60 > 20); // true
System.out.println(!(60 > 20)); // false
System.out.println();
// 4. `^`: 逻辑异或
// 当 a ^ b 不同时, 结果为true. 否则为 false
boolean res = (10 > 1) ^ (3 > 5); // true ^ false => true
System.out.println("res = " + res); // true
System.out.println();
// 异或运算符的巧用:在不使用第三个变量的情况下, 交换2个变量的值
int num = 1;
int count = 2;
System.out.println("交换前: num=" + num + " count=" + count);
num = num ^ count; // num = 0001 ^ 0011 = 0010
count = num ^ count; // count = 0010 ^ 0011 = 0001
num = num ^ count; // num = 0010 ^ 0001 = 0011
System.out.println("交换后: num=" + num + " count=" + count);
位运算符(重点: 需要补码、反码的知识基础)
10.6 -位运算是基于二进制的,所以 请先看: 二进制基础
&
: 按位与, 同位全为:1
,结果为1
; 否则为0
|
:按位或, 同位只要有一个为1
,结果就为1
; 否则为0
^
: 按位异或, 同位一个为0
、一个为1
,结果才为1
; 否则为0
~
:按位取反, (二进制补码) 0变成1, 1变成0.<<
:左移, 值放大2的n次方倍。(二进制补码) 左移n位,符号位不变,低位补0
.>>
:右移, 值缩小2的n次方倍。(二进制补码) 右移n位,位符号位不变。用补符号位
来补高位。>>>
:无符号右移, 缩小2的n次方倍。不论正数还是负数,移位过程中高位均补0
。
位运算练习:
// 1. 2 & 3 = ?
// 2.int a = 2; ~a = ?
// 3.int c = -2; ~c = ?
// 4.2 | 3 = ?
// 5.3 ^ 2 = ?
// 6.int e1 = 1; int e2 = e1 << 2; e2 = ?
// 1. 2 & 3 = ?
// 分析:
// `&`:同位都为`1`才得`1`
// 2的补码: 0b00000000000000000000000000000010
// 3的补码: 0b00000000000000000000000000000011
// 得补: 0b00000000000000000000000000000010
// 得原: 0b00000000000000000000000000000010 => 2
// 正数三码合一: 补码 = 原码
System.out.println(2 & 3); // 2
// 2.int a = 2; ~a = ?
// 分析:
// 2原码: 0b00000000000000000000000000000010
// 2补码: 0b00000000000000000000000000000010
// ~2= ? 2按位取反:0->1,1->0
// 补: 0b11111111111111111111111111111101
// 反: 0b11111111111111111111111111111100
// 得原: 0b10000000000000000000000000000011
// 所以: ~2 = -3
int a = 2;
System.out.println(~a); // -3
// 3.int c = -2; ~c = ?
// `~` : 按位取反, 0->1, 1->1
// -2 原: 0b10000000000000000000000000000010
// -2 反: 0b11111111111111111111111111111101
// -2 补: 0b11111111111111111111111111111110
// ~-2 补: 0b00000000000000000000000000000001
// ~-2 原: 0b00000000000000000000000000000001 => 1
// `~-2`为正数,那么三码合一
int c = -2;
System.out.println(~c); // 1
// 4.2 | 3 = ?
// 分析:
// `|` : 按位或, 同位只有一个为`1`,结果为`1`;否则为`0`
// 2 补: 0b00000000000000000000000000000010
// 3 补: 0b00000000000000000000000000000011
// 2|3 补: 0b00000000000000000000000000000011
// 2|3 原: 0b00000000000000000000000000000011 => 3
System.out.println(2|3); // 3
// 5.3^2 = ?
// 分析:
// `^` : 按位异或, 同位不同,结果为`1`;否则为`0`
// 3 补: 0b00000000000000000000000000000011
// 2 补: 0b00000000000000000000000000000010
// 3^2 补: 0b00000000000000000000000000000001
// 3^2 原: 0b00000000000000000000000000000001 => 1
System.out.println(3^2); // 1
// 6.int e1 = 1; int e2 = e1 << 2; e2 = ?
// 1 补: 0b00000000000000000000000000000001
// 1<<2 = 4 : 0b00000000000000000000000000000100
// >>: 右移 缩小`2^n`倍。(二进制补码) 右移`n`位
int pp = -11;
int ppt = pp >> 2; // -11 / (2*2) = -3
System.out.println(ppt);
// -11 补: 0b11111111111111111111111111110101
// -11>>2 右移补,高位`1` 补: 0b11111111111111111111111111111101
System.out.println(0b11111111111111111111111111111101);
System.out.println("=====================================");
// >>>:无符号右移, 数据缩小。不论正数还是负数,移位过程中高位均补`零
`。
int u1 = -11;
int u2 = u1 >>> 30; // 3
System.out.println(u2);
// -11 补: 0b11111111111111111111111111110101
// -11>>>30 右移30,高位补'0':
// 补: 0b00000000000000000000000000000011
10.7 - 运算符的优先级
运算符的优先级,如下:
- ()、 {}
- 单目运算 ++ --
- 算数运算符
- 位移运算符
- 比较运算符
- 逻辑运算符
- 三元运算符
- 赋值运算符
11 - Java命名规范
- 严格区分大小写
- 不可以使用
关键字
和保留字
- 包名:xxx.yyy.zzz, exp: com.apem163.shop
- 类:大写字母开头 + 驼峰, exp: PlusChar
- 类成员变量:小写字母开发 + 驼峰, exp: appName
- 类方法:小写 + 驼峰, exp: startApplication
- 类常量:全大写 或 大写+下划线连接, exp: MENU_CATES
11.1 - 控制台输入:Scanner 类(文本扫描器?)
- Scanner.nextLine() => 换行前的输入内容
- Scanner.nextByte() => 输入的byte
- Scanner.nextChar() => 输入的char
- Scanner.nextInt() => 输入的整数
- Scanner.nextDouble() => 输入的小数
// 实例Scanner对象
Scanner scanner = new Scanner(System.in);
// 接收输入
String inputValue = scanner.nextLine();
if (inputValue != null) {
System.out.println("你输入的是: " + inputValue);
}
12 - 四种进制和相互转换
- 二进制: 0,1 满2进1, 以
0b
或0B
开头 - 八进制: 0-7 满8进1, 以 数字
0
开头, 后面全跟数字的 - 十进制: 0-9 满10进1
- 十六进制: 0-9及A(10)~F(15) 满16进1, 以
0x
或0X
开头的(字母不区分大小写)
int n1 = 0b0011; // 3
int n2 = 0101; // 1 * 8 + 7 * 8 + 1 = 65
int n3 = 217; // 217
int n4 = 0x001a; // 1 * 16 + 10 = 26
12.1 - 二进制、八进制、十六进制 转 十进制
- 1.二进制 转 十进制
转换规则: 从最低位(右边)开始, 每个位上的数提取出来, 乘以
2^(位数-1)
(次方),然后 求和、二进制转十进制-快速对位法
位数(值:0), 则该位的十进制的值为
0
位数(1): 8 7 6 5 4 3 2 1 \t\t值: 128 64 32 16 8 4 2 1
# 将`0b1011` 转成 十进制
第1位: 1 x 2^(1-1) = 1
第2位: 1 x 2^(2-1) = 2
第3位: 0 x 2^(3-1) = 0
第4位: 1 x 2^(4-1) = 8
最终: 8 + 0 + 2 + 1 = 11
二进制 十进制
0b1011 => 11
8+0+2+1 = 11
- 2.八进制 转 十进制
转换规则: 从最低位(右边)开始, 每个位上的数提取出来, 乘以
8^(位数-1)
(次方),然后 求和、
# 将 `0232` 转成 十进制
第1位: 2 x 8^(1-1) = 2 x 1 = 2
第2位: 3 x 8^(2-1) = 3 x 8 = 24
第3位: 2 x 8^(3-1) = 2 x 64 = 128
第4位: 0 x 8^(4-1) = 0
最终: 0 + 128 + 24 + 2 = 154
八进制 十进制
0232 154
- 3.十六进制 转 十进制
转换规则: 从最低位(右边)开始, 每个位上的数提取出来, 乘以
16^(位数-1)
(次方),然后 求和、
# 将`0x23A` 转成 十进制
第1位: A x 16^(1-1) = 10 x 1 = 10
第2位: 3 x 16^(2-1) = 3 x 16 = 48
第3位: 2 x 16^(3-1) = 2 x 16 x 16 = 512
最终: 512 + 48 + 10 = 570
十六进制 十进制
0x23A 122
12.2 - 十进制 转 二进制/八进制/十六进制
规则: 将该数
不断 除以 进制数
, 直到商为0
。每步得到的余数倒过来的, 组成对应的进制数.
十进制 转 二进制
31 => 0b11111
步骤:
31 / 2 = 15...1
15 / 2 = 7....1
7 / 2 = 3....1
3 / 2 = 1....1
1 / 2 = 0....1
十进制 转 八进制
241 => 0361
步骤:
241 / 8 = 30...1
30 / 8 = 3....6
3 / 8 = 0....3
十进制 转 十六进制
514 => 0x202
步骤:
514 / 16 = 32...2
32 / 16 = 2....0
2 / 16 = 0....2
12.3 - 二进制 转 八进制、十六进制
- 1.二进制转八进制
规则: 从地位开始,将二进制数每三位一组,组成对应的八进制数即可(不够三位前面补
0
)
# 请将二进制 0b11010101 转 八进制
0b11010101 => 0b011_010_101
倒数第1位: 101 = 5
倒数第2位: 010 = 2
倒数第3位: 11 => 011 = 3
最终:0325
- 2.二进制转十六进制
规则: 从地位开始,将二进制数每四位一组,组成对应的十六进制数即可(不够四位前面补
0
)
# 请将 0b11010101 转成 十六进制
0b11010101 => 0b1101_0101
倒数第1位: 0101 = 0+4+0+1 = 5
倒数第2位: 1101 = 8+4+0+1 = 13 = D
最终:0xD5
12.4 - 八进制、十六进制 转 二进制
- 1.八进制 转 二进制
规则:将八进制的每位,转成一个对应的
3位一组的二进制
即可
# 请将 0237 转 二进制
倒数第1位:7 = 111
倒数第2位:3 = 011
倒数第3位:2 = 010
最终: 0b010_011_111 => 0b10011111
- 2.十六进制 转 二进制
规则:将十六进制的每位,转成一个对应的
4位一组的二进制
即可
# 将 0x23B 转 二进制
倒数第1位:B = 11 =8+0+2+1 = 1011
倒数第2位:3 = 0011
倒数第3位:2 = 0010
最终: 0b0010_0011_1011 => 0b1000111011
二进制基础(重点)
13 -计算机内以 二进制
的进位制来存储数据
。
- 二进制是
逢2进位
的进位制
,0
、1
是基本符号 - 原码 反码 补码 都是
二进制
的一种表示方式
- 以
补码的形式
来存储数据
和二进制数运算
- 补码: 给计算机使用的(存储/运算)
- 以
原码的形式
来展示数据- 原码: 给人理解、给人看的
- 以
反码
来解决补码
和原码
之间的转换问题
- 以
13.1 - 原码、补码、反码
- 1.二进制的最高位表示
符号位
(最左边的位):0
开头代表正数
- 00000111 = 7
1
开头代表负数
- 10000111 = -7
- 2.正数
原码
=反码
=补码
- 正数三码合一
- 3.负数
- 反码 = 原码`符号位`不变,其他位取反
- 补码 = 反码 + 1
- 反码 = 补码 - 1
- 4.
0
的反码,补码都是0
- 5.java的数都是有符号的
- 6.计算机运算时,都是以
补码
的方式类运算的 - 7.当我们看运算结果的时候, 要看结果的
原码
位运算符
13.214 - 前面1-13章内容知识点回顾练习
// 1. 求下列的结果:
// 10/3=? 10/5=? 10%2=? -10.5%3=?
// => 10/3=3 10/5=2 10%2=0
// => -10.5%3=? (有小数参与的运算,得到的结果是近似值)
// => a % b, 当 a 为小数时: 公式= a - ((int)a / b) * b = -10.5 - ((-10) /3) * 3 = -10.5 - (-3)*3 = -10.5 - (-9) = -10.5 + 9 = -1.5
System.out.println(-10.5 % 3);
// 2. 下面的结果是:
// int i = 66;
// ++i + i= ?
// => i=i+1; i + i = 134;
System.out.println(++i + i + " 计算结果是? = 134");
// 3.在java中, 以下赋值语句正确的是:
// A.int num1 = (int)"18";
// B.int num2 = 18.0;
// C.double num3 = 3d; // 正确
// D.double num4 = 8; // 正确
// E.int i = 48; char ch = i + 1;
// F.byte b = 19; short s = b+1;
// A => 错误, Integer.parseInt(String)
// B => 错误, 18.0 是double类型, 低容量无法主动强塞高容量的数据类型
// D => 错误, 低容量被强塞高容量的类型
// F => 错误
// => 1.byte b = 19; 可以通过, 应该 19 在 byte的值范围内:[-128~127)
// => 2.short s = b+1 => 错误,b+1 => byte + int => int, short 装不下 int
15 - 流程控制
- 顺序控制
- 分支控制(if、else、switch)
- 循环控制(for、while、dowhile、多重循环)
- break
- continue
- return
15.1 - 顺序控制
- 程序从上到下逐行执行, 中间没有任何判断和跳转
- java中定义变量时,采用合法的前向引用。
public class Test {
int num1 = 12; //
int num2 = num1 + 2; // 使用num1需要在前面现有定义
}
public class Test2 {
int num2 = num1 + 2; // 编译报错...
int num1 = 12;
}
15.2 分支控制(if...else)
- 单分支:if (
条件表达式
) {逻辑代码
}
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
System.out.println("输入数字:")
// 接收输入
Scanner scanner = new Scanner(System.in);
int inputValue = scanner.nextInt();
// 分支判断
if (inputValue >= 18) {
System.out.println("防沉迷认证通过");
}
}
}
- 双分支: if (
条件表达式
) {满足条件的逻辑
} else {不满足条件的逻辑
} => 三元运算
boolean isPass = false;
if (isPass) {
// true
System.out.println('true')
} else {
// false
System.out.println('false')
}
- 多分支: if...[else if]{n}...else... 多次分支嵌套:最多不要超过3层
/**
* 题目:
* 参加歌手比赛,如果初赛成绩大于8.0则进入决赛,否则提示淘汰。
* 并且根据性别提示进入男子组或女子组。输入成绩和性别,
* 进行判断和输出信息
* tip:double scope、char gender
*/
Scanner sc = new Scanner(System.in);
System.out.print(" 成绩:");
double scope = sc.nextDouble();
if (scope > 8.0) {
System.out.print("选手性别:");
char gender = sc.next().charAt(0);
if (gender == '男') {
System.out.println("成功进入男子决赛组");
} else if (gender == '女') {
System.out.println("成功进入女子决赛组");
} else {
System.out.println("输入的性别有误.");
}
} else {
System.out.println("淘汰");
}
- switch 分支结构
- 1.swith(表达式) 使用场景: 变量
有且只有
几个固定
的值. - 2.switch-case 对应一个固定值
- 3.case穿透: 有
break
遇到则结束switch;没有break
的分支会造成 case穿透,直到遇到breack
或执行到switch结尾 - 4.
default
: 是可选的,当没有匹配到case
时,执行default
- 5.注意事项
- switch 表达式数据类型,应和
case
后的常量类型一致
,或者是可以自动转成可以互相比较的类型
- swtch(表达式)中表达式的返回值必须是: (byte、short、int、char、enum、String)的某一种
- case 后必须跟
常量
- case 穿透(无breack)
- switch 表达式数据类型,应和
- 1.swith(表达式) 使用场景: 变量
/**
* 题目:
* 输入
* 月份,打印对应的季节。
* 穿透
*/
Scanner scanner4 = new Scanner(System.in);
System.out.print("请输入月份:");
int mouth = scanner4.nextInt();
String seasonText = "";
switch(mouth) {
case 3:
case 4:
case 5:
seasonText = "春季";
break;
case 6:
case 7:
case 8:
seasonText = "夏季";
break;
case 9:
case 10:
case 11:
seasonText = "秋季";
break;
case 12:
case 1:
case 2:
seasonText = "冬季";
break;
default:
seasonText = "不是正常的月份数";
break;
}
System.out.println(mouth + "月 " + seasonText);
- swith 和 if 的使用场景:
对于 区间、范围 的判断, 对结果为
boolean
类型判断,使用if
. 如果判断的具体数字不多,而且符合 {"byte", "short", "int", "char", "enum", "String"} 这6中类型, 用switch
.
15.3 for循环控制
限定了次数的循环
- for(int i=0; i < length; i++) {} 常用于遍历数组、列表
- for(T t : Object) {...} 常用于遍历对象的属性
/**
* 题目:
* 打印 1~100 之间所有是9的倍数的整数,统计个数 及 总和
*/
// 解法二:
int MAX = 100;
int MIN = 1;
int BASE = 9;
int size = 0;
int total = 0;
for(int i=MIN,sum2=0; sum2 <= MAX; i++) {
sum2 = i * BASE;
if (sum2 <= 100) {
System.out.print(sum2 + " ");
size++;
total += sum2;
}
}
System.out.println("\n个数: " + size);
System.out.println("总和: " + total);
/**
* 输出 一个整数和的加法组合
* 1 + 4 = 5
* 2 + 3 = 5
* 3 + 2 = 5
* 4 + 1 = 5
*/
int endSum = 13;
int start = 3;
for (int i = start; i <= endSum; i++) {
for (int j = start; j <= endSum ; j++) {
if (i + j == endSum) {
System.out.println(i+ " + " + j + " = " + endSum);
}
}
}
15.4 while循环
- 细节说明:
- 1.循环条件是返回一个布尔值的表达式
- 2.while循环是先判断再执行语句
/**
* 练习:
* 1.打印 1-100 所有3的倍数的数
* 2.打印 40-200 所有偶数的数
*/
int MAX = 100;
int MIN = 1;
int MULTIPLE = 3;
int remainder = 0;
System.out.print("打印 1-100 所有3的倍数的数: ");
while(MAX-- > MIN) {
remainder = MAX % MULTIPLE;
if (remainder != 0) { continue; }
System.out.print(MAX + " ");
}
System.out.println();
MAX = 200;
MIN = 40;
MULTIPLE = 2;
System.out.print("打印 40-200 所有偶数的数: ");
while(MAX-- > MIN) {
remainder = MAX % MULTIPLE;
if (remainder != 0) { continue; }
System.out.print(MAX + " ");
}
System.out.println();
15.5 do...while 循环
- do...while 先执行,再判断.
- while 和 do..while 的区别: do..while 至少执行一次
- 细节:
- 循环条件是返回一个布尔值的表达式
- 先执行,再判断。 至少执行一次
do {
循环体
} while(循环条件);
- 练习:
/**
* do..while
* 题目:
* 统计 1-200 之间能被`5`整除但是不能被`3`整除的数的个数(do..while)
* 思路:
* 1.化繁为简: 使用do..while输出 1-200
* 2.过滤: 能被5整除但不能被3整除的数
* 3.统计 满足条件的个数
* 4.先死后活
*/
int i =1;
int count = 0;
int maxLimit = 200;
int first = 5;
int second = 3;
do {
if (i % first == 0 && i % second !=0) {
// System.out.println("i = " + i);
count++;
}
i++;
} while(i <= maxLimit);
System.out.println("1-200 之间能被`5`整除但是不能被`3`整除的数的个数: " + count);
15.6 多重循环
- 嵌套循环: 最多3层循环极限了。否则拆分业务
- 外层循环次数为
m
, 内层循环次数为n
, 则内层循环体实际上需要执行m x n
次。
/**
* 练习二:
* 打印九九乘法表
* 思路:
*
*/
int firstChar = 1;
int endChar = 9;
System.out.println("九九乘法表:");
for (; firstChar <= endChar; firstChar++) {
int secondChar = 1;
for (; secondChar <= firstChar; secondChar++) {
System.out.print(secondChar + " x " + firstChar + " = " + (firstChar * secondChar) + " ");
}
System.out.println();
}
/**
* 打印空心金字塔
*/
static void practice_hollow_pyramid_5() {
int rowLevel = 9; // 层数
System.out.println("思路6-先死后活: 层数变量 = " + rowLevel);
for (int i = 1; i <= rowLevel; i++) {
for (int j=1; j <= rowLevel - i; j++) {
System.out.print(" ");
}
for (int j=1; j <= 2 * i - 1; j++) {
if (i == rowLevel || j == 1 || j == (2*i-1)) {
System.out.print("*");
} else {
// 其他位置 空心
System.out.print(" ");
}
}
System.out.println();
}
}
15.7 跳转流程控制的语句: break
break: 跳出当前流程控制
- 细节:
- break 语句出现在多层嵌套的中, 默认 退出最近的循环体
- 一般不会使用的
break labelName;
直到退出指定的label的循环体
/**
* 思考题:
* 随机生成 1-100的一个数,直到生成了 96 这个数, 看看一共用了几次?
* tip:Math.random() => [0.0, 1.0)
*/
int randomNumber = 0;
int count = 0;
int CONST_NUM = 96;
while(true) {
randomNumber = (int)(Math.random() * 100) +1;
count++;
if (randomNumber == CONST_NUM) { break; }
}
System.out.println("一共执行了 " + count + " 次,才生成 " + randomNumber);
/**
* 练习题一:
* 1-100以内的数求和, 求出当 和 第一次大于 20 的当前数是:?
*/
int current = 0;
int sum = 0;
int CONST_TOTAL = 20;
int MIN = 1, MAX = 100;
for (int i = MIN; i <= MAX; i++) {
sum += i;
if (sum >= CONST_TOTAL) {
current = i;
break;
}
}
System.out.println("1-100以内的数求和, 求出当 和 第一次大于 20 的当前数是: " + current);
15.8 跳转本次循环的语句: continue
- 跳转本次循环的语句,继续执行下一次循环: continue
/**
* 练习题:
* 实现登录验证, 有3次机会, 如果用户名为 'root', 密码为 '1234' 提示登录成功、
* 否则提示还有几次机会。
* 思路:
* 1.最多循环3次, 满足条件就提前 break 跳出循环
* 2.输入错误, 提示还有几次机会. continue 跳过本次循环
* tip:
* 字符串的比较: stringA.equals(stringB). equals:比较的是值
*/
int MIN = 1;
int MAX_COUNT = 3;
int less = CONST_COUNT;
boolean isPass = false;
Scanner scanner = new Scanner(System.in);
String inputVal = "";
String realUsename = "root", realPassword = "1234";
for (int i=MIN; i <= MAX_COUNT; i++) {
less--;
System.out.print("登录验证,请输入用户名: ");
inputVal = scanner.next();
if (!realUsename.equals(inputVal)) {
System.out.println("账号或密码错误, 还可以再试 " + less + " 次。");
continue;
}
System.out.print("请输入密码: ");
inputVal = scanner.next();
if (!realPassword.equals(inputVal)) {
System.out.println("账号或密码错误, 还可以再试 " + less + " 次。");
continue;
}
isPass = true;
if (isPass) {
System.out.println("登录成功");
break;
}
}
System.out.println("登录验证校验是否通过: " + isPass + " 剩余验证次数: " + less);
15.9 退出/跳出方法: return
- return 如果用在方法时, 代表跳出方法
- 如果用在main中, 代表退出程序。
int[] cls = {1,2,3,4};
for(int i=0;i < cls.length; i++) {
if (i == 2) {
return; // 满足条件则退出该方法,"3"、"4"、"程序运行结束" 都不会输出
}
System.out.println(cls[i]);
}
System.out.println("程序运行结束");
16 - 编程思路: 化繁为简、先死后活
- 化繁为简
- 将复杂的需求, 拆解成简单的需求, 逐步完成.
- 先死后活
- 先考虑固定的值, 然后转出可以灵活变化的值.