java-1.基础入门

Lin

Lin

xiaominglin789

java 特点

  • 面向对象(封装,继承,多态)
  • 高性能、分布式、多线程
  • 安全性、健壮性
  • 半解释半编译语言(编译与解释并存)
  • 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(字节)810-(2^7)~(2^7 -1)
short(短整型)1620-(2^15)~(2^15 -1)
int(整型)3240-(2^31)~(2^31 -1)
long(长整型)6480L-(2^63)~(2^63 -1)
float(单精度)3240f
double(双精度)6480d
char(字符型)82'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类型后缀加 Dd
  • Float类型后缀加 Ff
  • 通常表示小数,都用 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 的整数来代替falsetrue
    • 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.自动提升原则: 表达式结果的类型自动提升为 操作数中最大的类型

6 - 强制类型转换

  • 自动类型转换的逆过程,强制将容量大的数据类型转换成容量小的数据类型,使用时加上强制转换符:(类型), 但可能造成数据的精度降低或溢出.
  • 强制类型转换的细节:
    • 1.当进行数据的大小从 大 --> 小, 就需要使用强制类型转换.
    • 2.强转符号只针对最近的操作数, 往往会使用小括号来提升优先级.
    • 3.char类型可以保存 int的常量值,但不能保存int的变量值,需要强转.
    • 4.byteshort类型进行运算时,当作int类型处理.
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'
    1. 注意事项:
    • String 转 基本数据类型时, 要确保 String类型能够转成有效的数据,否则会报错. exp: "hello" =转=> int, 抛出异常,程序中止

8 - 编码规范(无关语言)

ASCII编码表

  • ASCII编码表
    • ASCII码编码表中,每一个字符都是用一个字节表示,一共有128个字符.
      • 此处的 字符 可不是 java中的char。
    • ASCII码编码表最多能表示256个字符, 但是只用了128个字符: 数字 + 大小写字母 + 普通符号 + 特殊符号 + 转义字符
    • 用一个字节的低 7 位表示,0~31 是控制字符如换行回车删除等;32~126 是打印字符(可以通过键盘输入并且能够显示出来的)
      • 一个字节 = 8个bit,所以能表示的字符范围是 0~255 个
  • 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 => 2
    a--; // 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); // 2
    int a = 1;
    a = a++;
    System.out.println("a=" + a); // 1
    int b = 1;
    b = ++b;
    System.out.println("b=" + b); // 2
    int 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); // 10
    System.out.println("a6 = " + a6); // 20
    a7 = --a6; // 1.a6=a6-1=19; 2.temp=a6=19; 3.a7=temp=19
    System.out.println("a7 = " + a7); // 19
    System.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, ab 不同,返回 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 - 运算符的优先级

运算符的优先级,如下:

    1. ()、 {}
    1. 单目运算 ++ --
    1. 算数运算符
    1. 位移运算符
    1. 比较运算符
    1. 逻辑运算符
    1. 三元运算符
    1. 赋值运算符

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, 以 0b0B 开头
  • 八进制: 0-7 满8进1, 以 数字0 开头, 后面全跟数字的
  • 十进制: 0-9 满10进1
  • 十六进制: 0-9及A(10)~F(15) 满16进1, 以 0x0X 开头的(字母不区分大小写)
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进位进位制, 01是基本符号
  • 原码 反码 补码 都是二进制的一种 表示方式
    • 补码的形式存储数据二进制数运算
      • 补码: 给计算机使用的(存储/运算)
    • 原码的形式来展示数据
      • 原码: 给人理解、给人看的
    • 反码来解决补码原码之间的转换问题

13.1 - 原码、补码、反码

  • 1.二进制的最高位表示符号位(最左边的位):
    • 0 开头代表 正数
      • 00000111 = 7
    • 1 开头代表 负数
      • 10000111 = -7
  • 2.正数
    • 原码 = 反码 = 补码
    • 正数三码合一
  • 3.负数
    • 反码 = 原码`符号位`不变,其他位取反
    • 补码 = 反码 + 1
    • 反码 = 补码 - 1
  • 4.0的反码,补码都是0
  • 5.java的数都是有符号的
  • 6.计算机运算时,都是以 补码 的方式类运算的
  • 7.当我们看运算结果的时候, 要看结果的 原码

13.2 位运算符

14 - 前面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)
/**
* 题目:
* 输入
* 月份,打印对应的季节。
* 穿透
*/
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 - 编程思路: 化繁为简、先死后活

  • 化繁为简
    • 将复杂的需求, 拆解成简单的需求, 逐步完成.
  • 先死后活
    • 先考虑固定的值, 然后转出可以灵活变化的值.

17 -