Java初步使用

java 目前属于甲骨文, 长期支持版本为 java8 和 java11, 主要学习JavaEE (Java Enterprise Edition) 企业版
java特性:

  1. 强类型 静态类型的语言
  2. 跨平台 --> 不同平台的JVM保证
  3. 解释性 --> 使用JVM解释字节码

JVM是一台虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器

JDK(Java Development Kit)是什么?
JDK 是 Java 语言的软件开发工具包,关于JDK与JRE:

  1. JDK = JRE + java开发工具
  2. JRE = JVM + 核心类库

如果只需要运行开发好的.class文件, 只需要JRE即可

JDK的国内下载源,见:JDK下载

第一个程序

创建一个Hello.java文件,写入如下内容:

public class Hello {
    public static void main(String[] args){
        System.out.println("hello world");
    }
}
  1. 文件名要与类名相同

  2. 定义方式public classpublic static void main(){xxx}

  3. 要以 ; 结尾

  4. 使用javac Hello.java编译java文件成Hello.class(字节码)

    假如报错: 错误: 编码 GBK 的不可映射字符,那是因为编码问题,只需要添加-encoding utf8即可

  5. 使用java Hello运行程序(将字节码放到JVM中解释)

开发注意事项

  1. java源文件以.java为扩展名,源文件的基本组成部分为

  2. java应用程序的执行入口为main, 它有固定的写法:

    public static void main(String[] args){....}
    
  3. java区分大小写

  4. 语句要以 ; 结尾

  5. 一个源文件中最多只能有一个public类, 其他类不限

    public class Hello{
       public static void main(String[] args){
          System.out.println("hello 1");
       }
    
    }
    // 其他的类
    
    class Dog{
       public static void main(String[] args){
          System.out.println("hello dog");
       }
    }
    
    class Cat{
       public static void main(String[] args){
          System.out.println("hello Cat");
       }
    }
    

    编译后会生成对应类的字节码如: Dog.class Cat.class

  6. 编写风格
    有两种:行尾风格和次行风格
    行尾风格
    次行风格

  7. 包名
    多单词组成时,都小写且使用.链接,如:aaa.bbb.ccc

  8. 类名 接口名
    多单词组成时,使用大驼峰, 比如ShotGame

  9. 变量名 方法名 使用小驼峰, 比如shotGame

  10. 常量名 全大写使用_连接,比如MAX_NUM

转义符号

一般使用如下:

public class Test{
    public static void main(String[] args){
        System.out.println("张三\t李四\t王五");  // 制表符
        System.out.println("你好\n世界"); // 回车
        System.out.println("c:\\d");  // \
        System.out.println("aaa\rbb");  // 换行会替换掉
        System.out.println("aaa\r\bbb");  // 换行+回车会在下一行
    }
}

注释

java的注释分

  1. 单行注释
    public class Comment{
       public static void main(String[] args){
          // 单行注释
          /*
          多行注释
          */
          System.out.println("查看代码");
       }
    }
    
  2. 多行注释
    public class Comment{
       public static void main(String[] args){
          /*
          多行注释
          */
          System.out.println("查看代码");
       }
    }
    
  3. 文档注释
    比较重要,文档注释可以被javadoc解析成网页,其写法有固定的格式。
    /**
    * 这个类演示了文档注释
    * @author lczmx
    * @version 1.2
    */
    
    public class Comment{
       public static void main(String[] args){
          System.out.println("查看代码");
       }
    }
    
    使用命令: javadoc Comment.java -d ./docs -encoding utf8 -author -version即可解析成网页
    上面使用的是authorversion这两个标签,更多的标签见:Java 文档注释
    打开./docs/index.html即可查看文档
    看文档时需要注意java类的组织形式:
    java类组织形式

变量定义

有两种方式:

public class Var{
    public static void main(String[] args){

        // 声明再赋值
        int a;
        a = 1;
        // 声明并赋值
        int b = 3;
        System.out.println("a=" + a + "b=" + b);
    }

}

+号的使用

使用+时遵循如下规则:

  1. 两边为数值,加法运算
  2. 一边为字符串,拼接
public class Plus{
    public static void main(String[] args){
        System.out.println(100 + 98);
        System.out.println("100" + 98);
        System.out.println(100 + 3 + "hello");
        System.out.println("hello" + 100 + 3);
        /*
        198
        10098    
        103hello 
        hello1003
         */
   
    }
}

基本数据类型

基本数据类型

注意, java的字符串不是基本数据类型,它是一个对象

使用例子:

public class Type{
    public static void main(String[] args) {
        // 整形
        byte a = 1;  // -128 127 2^7
        short b = 22;  // -32768 32767
        int c = 123455; // -2147483648 2147483647
        long d = 123232323L; // -9223372036854775808 9223372036854775807
		// 形如1234 默认为int,可以手动指明为long类型
		// 不指明时会自动转换
		
        // 浮点型
        float f1 = 1.1234F;  
        // Java中的浮点字面值默认为双精度。要指定浮点字面值,必须在该常量后面附加一个 F 或 f 。
        double f2 = 1.231;
        // 字符
        char e = '六';  // !!!! 注意为单引号,内部就是一个数字, 所以可以 char e = 97 这样定义
        boolean f = true;  // or false
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        System.out.println(d);
        System.out.println(f1);
        System.out.println(f2);
        System.out.println(e);
        System.out.println(f);

    }
}

关于浮点数的运算与比较,有点特殊:

public class Float{
    public static void main (String[] args) {
        // 默认1.1为双精度浮点型, 需要指定F
        float f1 = 1.23456789F;
        double f2 = 1.23456789;
        System.out.println(f1); // 精度缺失
        System.out.println(f2); // 精度可以保存

        // 科学计数法
        double f3 = 1.23E2; // 1.23 * 10^2
        double f4 = 1.23E-2;  // 1.23 * 10^-2
        System.out.println(f3);  // 123.0
        System.out.println(f4);  // 0.0123

        // 比较浮点数
        // 由于计算后的浮点数在内存中为一个近似值,所以不能直接比较
        // 应该相减,小于一个固定范围视为相等(范围根据业务来)
        double money1 = 1.2;
        double money2 = 1.2;
        // 可以执行
        if ( money1 == money2 ) {
            System.out.println("money1与money2 金额相等!");
        }
        double money3;
        money3 = 0.4 * 3;  // 实质上可能是1.200000000001
        // 计算相差绝对值,是否小于固定范围
        if ( Math.abs(money1 - money3) <= 0.001 ) {
            System.out.printlnk("money1与money3 金额相等!");
        }

    }
}

这是因为浮点数不直接存放数字,而是存放:符号位 + 指数位 + 尾数位
而尾数部分可能丢失,造成精度损失(所以浮点数都是近似值)

关于字符类型,也要补充一下, 主要是编码方式的区别:

public class CharDetail{
    public static void main(String[] args){
        // 一般使用
        char c1 = 'a';
        char c2 = 98;
        char c3 = 'a' + 2;
        // 输出
        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        // =====> 输出数字
        System.out.println((int)c1);    

        // 1. Char两个字符表示, 对应的编码方式为unicode
        // 2. Char在内部以数字存储:
        //            a -(通过编码方式)-> 97 -> 内存
        // 3. 读取的时候会,自动将数字装换成编码方式中对应的字符
        //            内存 -> 97 -(通过编码方式)-> a
        // 补充一下字符编码
        // ASCII 8bit表示,128个字符(0~127)
        // unicode  中英文都为2字节
        // UTF-8  (1~6个字节) 大小可动态变化,英文1字节 中文3字节
        // ----------- 一个字符(即'a'或'中')可以有多个字节
    }
}

字符集中只规定了 字符的代码值 并未规定具体如何存储,编码方式解决了字符在计算机中 如何存储 的问题。

类型转换

即不同数据类型如何转换

自动类型转换

低精度可以自动向高精度转换
有两条路线:

// char -> int -> long -> float -> double
//   2      4      8        4        8
// byte -> short -> int -> long -> float -> double
//  1        2       4      8        4        8

这里有一个问题: float 4个字节可以存放 long 8个字节?
主要原因是float/double不是直接存储数值: 浮点数的32位不是简单的直接表示大小,而是按照一定的标准分配的。其中

  1. 第1位,符号位。
  2. 接下来的8位,指数域。
  3. 剩下的23位,小数域,M的取值范围为[1,2)或[0,1)
    也就是说,浮点数在内存中的二进制值不是直接转换为十进制数值的,而是按照上述公式计算而来, 通过这个公式,虽然只用到了4个字节,但是浮点数却比长整型的最大值要大。

一般使用的规则:

  1. 低精度可以转换成高精度, 反之不行
  2. 多种类型运算时,先转化成最大的
  3. ( byte, short ) 不可以与 char 之间相互转化
  4. byte short 和 char 之间 虽然不能转化,但是这三者之间可以进行运算,结果提升为int,自身运算也会提升
  5. boolean 不转化 为数字
// 类型转换
public class AutoConvert{
    public static void main(String[] args) {
        // 1. ======= 低精度可以转换成高精度
        // char -> int -> long -> float -> double
        //  2       4      8       4         8
        // byte -> short -> int -> long -> float -> double
        //  1        2       4      8       4         8
        int a = 'a';
        double b = 80;
        System.out.println(a);  // 97
        System.out.println(b);  // 80.0

        // 2. =========== 多种类型运算时,先转化成最大的
        int a2 = 10;
        // float b2 = a2 + 1.1;  // 不可以,因为1.1为double
        double b2 = a2 + 1.1;
        System.out.println(b2);

        // 3. =========== ( byte, short ) 不可以与 char 之间相互转化
        // 按照我的理解,byte 和 short 虽然有1字节和2字节大小,但是为有符号的数字
        // 所以不能让byte short 和 char之间进行转化

        /*
        byte c3 = 1;
        short s3 = 2;
        char char3 = c3; 

        */
        // 4. =========== 低精度往高精度转化,不行
        // int a4 = 1.1;
        // !! 但是 byte short 会先判断数值大小,才赋值,所以可以直接使用 1 2 3........
        byte b4 = 1;
        // !! 如果用int的话不行, 它先判断类型
        int ab4 = 2;
        // byte b44 = ab4;
        short s4 = 1;

        // 5. byte short 和 char 之间 虽然不能转化,但是这三者之间可以进行运算,结果提升为int
        byte b5 = 2;
        short s5 = 1;
        char c5 = 11;

        int result5 = b5 + s5;  // byte + short
        System.out.println(result5);  // 3
        int result6 = b5 + c5; // byte + char;
        System.out.println(result6);  // 13
        int result7 = s5 + c5; // short + char;
        System.out.println(result7);  // 12

        // !!! 与自身运算也是int
        int result8 = b5 + b5;  // byte + byte => int
        // short char 也是这样
        System.out.println(result8);  // 4

        byte num1 = 1;
        short num2 = 2;
        int num3 = 123;
        float num4 = 1.234F;
        double num5 = num1 + num2 + num3 + num4;  // => float 转化成 double

        System.out.println(num5);

        // 6. ========= boolean 不转化 为数字
        // !! 就行强制转化也不行
        /*
        boolean boo6 = true;
        int i6 = (int)boo5;
        int i6 = boo5;
        */

    }
}

强制类型转换

我们可以对数值进行强制转化,不过强制类型转化 会丢失精度 或 数据溢出, 取舍权衡需要考虑好
一般的使用形式: (type)xx

// 高精度 -> 低精度:需要强制类型转化

public class ForceConvert{
    public static void main(String[] args){
        int a = (int)2201.2;  // 精度丢失
        byte b = (byte)a;  // 数据溢出

        System.out.println(a);  // 2201
        System.out.println(b);  // -103 数据溢出了
        System.out.println( (byte)127 );  //  不超出范围则不会溢出 (byte 1个字节 -127 ~ 127)
    }

}

与字符串的相互转换

即如何将其他类型转换成字符串和将字符串转化成其他类型
前者需要只需要+空字符串即可
后者需要 通过基本类型的 包装类 调用 parseXxx方法即可

需要注意的是,字符串转字符类型,使用的是charAt(index)方法

public class ToString{

    public static void main(String[] args){
        // 其他类型 => String
        char c1 = 97;
        int i1 = 2;
        float f1 = 3.14F;
        boolean b1 = true;
        String s1 = c1 + "";
        String s2 = i1 + "";
        String s3 = f1 + "";
        String s4 = b1 + "";
        //                      a 2 3.14 true
        System.out.println(  " " + s1 + " " + s2 + " " + s3 + " " + s4 );

    }
}

class ToOther{

    public static void main( String[] args ){
        // String => 其他类型
        // !! 通过基本类型的 包装类 调用 parseXxx方法即可
        // !! 属于面向对象内容

        // 注意Integer的写法
        String s1 = "123";
        
        int num1 = Integer.parseInt(s1);
        float num2 = Float.parseFloat(s1);
        short num3 = Short.parseShort(s1);
        // 其他的类推
        boolean b = Boolean.parseBoolean("true");
        System.out.println(num1);
        System.out.println(num2);
        System.out.println(num3);
        System.out.println(b);

        // !! 取字符
        System.out.println(s1.charAt(0));

        // !! 注意:可能不一定装换成功, 需要异常处理
    }
}

运算符

运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。

算术运算符

算术运算符 是对数值类型的变量进行运算的运算符

运算符 运算 例子 结果
+ 正号 +7 7
- 负号 b=11; -b -11
+ 9 + 9 18
- 10 - 8 2
* 7 * 8 56
/ 9 / 9 1
% 取模(余数) 11%9 2
++ 自增 a=2;b=++a; a = 3;b=3
-- 自减 a=2;b=--a a=1;b=1;
+ 字符串相加 "lcz" + "mx" “lczmx”

需要特别注意 ++--, 它们在给其他变量赋值时,在原变量的前后的结果是不一样的,看下面的例子

使用例子:

public class ArithmeticOperator{
    public static void main(String[] args){
        // 注意混合运算后的结果类型
        // +
        int a = 2;
        int b = 1;
        System.out.println(a + b);  // 3

        // -
        System.out.println(a - b);  // 1

        // *
        System.out.println(a * b);  // 2
        // /
        System.out.println(a / b); // 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

        // 总结一下:
        /*
        1. 正 % 正 = 正
        2. 负 % 正 = 负
        3. 正 % 负 = 正
        4. 负 % 负 = 负

        即 第一个数为负数时,结果为负数
        !! 假如a为double时会:
        a % b = a - (int)a / b * b
        */

        // ++ 和 --
        // i = j++   i = j-- : 先赋值再操作
        // i = ++j   i = --j : 先操作再赋值
        // 总结,看变量在前面还是运算符在前面
        // 变量在前,则先取变量的值,则运算
        // 运算符在前,则先运算,再取值

        int i = 10;
        int j = i++;
        System.out.println("i++: i = " + i + " j = " + j);

        i = 10;
        j = ++i;
        System.out.println("++i: i = " + i + " j = " + j);

        // !! 自己使用++ -- 赋值时的规则
        // 会引用一个临时变量,保存数据
        int count = 1;
        count = count++;
        // 1. 返回count使用临时变量保存,即 temp = count
        // 2. 运算++, 即 count = count + 1
        // 3. 赋值给count, 用的是temp的数据: count = temp
        System.out.println(count);  // 1

        count = ++count;
        // 1. 返回++使用临时变量保存
        //    count = count + 1
        //    temp = count
        // 2. 赋值给count,即 count = temp
        System.out.println(count);  // 2
    }

}

关系运算符

关系运算符的结果都是boolean型,即true或者false
使用例子如下:

public class RelationalOperator{
    public static void main(String[] args){
        System.out.println(1 == 1);
        System.out.println(1 != 1);
        System.out.println(1 < 2);
        System.out.println(1 > 2);
        System.out.println(1 <= 2);
        System.out.println(1 >= 2);
        boolean isInstance = "lczmx" instanceof String;
        System.out.println("\"lczmx\"为String子类: " + isInstance);
    }
}

逻辑运算符

逻辑运算符有以下几种:

  • & && 逻辑与 短路与
  • | || 逻辑或 短路或
  • ! 取反
  • ^ 逻辑异或

解释一下:

  1. 与指的是两边同时为true时, 才为true
  2. 或指的是有一边为true时, 则为true
  3. 短路指的是不满足条件的立即返回 如(false && true), 看到false就跳出了,不看true,而逻辑则会全部看完
  4. 取反即trueflasefalsetrue
  5. 逻辑异或指的是两边布尔值不同时为true, 否则为false, 如(false^ true=> true

重点关注: 逻辑与 短路与 逻辑或 短路或,举个例子:

public class LogicOperator{
    public static void main(String[] args){
    int a = 3;
	// 短路
    if (a < 2 && a++ > 10){}
    // 结果: a = 3
    System.out.println(a);
	
	// 逻辑
    if (a < 2 & a++ > 10){}
    // 结果: a = 4  
    System.out.println(a);
    }
}

赋值运算符

比较简单:= += -= *= /= %=
使用例子:

public class AssignOperator{
    public static void main(String[] args) {
	    int n1 = 10;
		n1 += 4;  // n1 = n1 + 4;
		System.out.println(n1); // 14
		
		n1 /= 3; // n1 = n1 /3; 
		System.out.println(n1); // 4
		
		byte b = 3;
		b += 2; // 等价于 b = (byte)(b + 2);
	}
}

三元运算符

相当于if-else的简写版, 格式:

int a = 10;
int b = 99;
int result = a > b ? a++ : b--;

表达式成立时, 返回的第一个a++, 否返回第二个b--

需要主要返回类型是否为接收结果的类型

位运算符

7个位运算符

  • & 按位与
  • | 按位或
  • ^ 按位异或
  • ~ 按位取反
  • >> 算术右移 低位溢出, 符号位不变 并用符号位补充溢出的高位
  • << 算术左移 符号位不变 低位补0
  • >>> 无符号右移 低位溢出 到位补0

注意: 没有<<<

运算时注意转成补码, 取结果时注意转成原码
使用例子:

public class BitOperator{

    public static void main(String[] args){

        // 2 & 3
        /*
        2的原码 00000000 00000000 00000000 00000010
        3的原码 00000000 00000000 00000000 00000011
        补码相同
            &   00000000 00000000 00000000 00000010
        补码为正,原码相同
                                                2
        */
        System.out.println(2 & 3);
        // ~-2

        /*
        -2的原码 10000000 00000000 00000000 00000010
            反码 11111111 11111111 11111111 11111101
            补码 11111111 11111111 11111111 11111110
             ~   00000000 00000000 00000000 00000001
            补码为正,原码相同
                                                1
        */
        System.out.println(~-2);

        // ~2
        /*
        2的原码 00000000 00000000 00000000 00000010
        补码相同
            ~   11111111 11111111 11111111 11111101
        结果反码
                11111111 11111111 11111111 11111100
        结果原码 10000000 00000000 00000000 00000011
                                                -3
        */
       System.out.println(~2);

        // 2|3
        /*
        2的原码 00000000 00000000 00000000 00000010
        3的原码 00000000 00000000 00000000 00000011
        都为正数 补码相同
            |  00000000 00000000 00000000 00000011
        结果为正数
                                                3
        */
        System.out.println(2|3);

        // 2^3
        /*
        2的原码 00000000 00000000 00000000 00000010
        3的原码 00000000 00000000 00000000 00000011
        都为正数 补码相同
            |  00000000 00000000 00000000 00000001
        结果为正数
                                                1
        */
        System.out.println(2^3);

        // 1 >> 2
         System.out.println(1 >> 2);
        /*
        00000001 => 000000000 => 1/2/2 = 0
        */

        // 1 << 2
        /*
        00000001 => 000000100 => 1*2*2 = 4
        */
        System.out.println(1 << 2);

        // 4 << 3
        /*
        00000100
        00100000
        => 32
        => 4 * 2 * 2 * 2 = 32
        !! 即我们无需写出位,可以直接*2或/2, 取整即可
        */
        System.out.println(4 << 3);
    

    }
}

运算符优先级

如下图
优先级

输入输出

输入使用Scanner类, 输出使用System.out.printlnSystem.out.print
使用例子:

// 1. 导入, 简单的文本扫描器
import java.util.Scanner;

public class ScannerIn{
    public static void main(String[] args) {
        // 2. 创建一个对象实例
        // 注意类型
        Scanner s = new Scanner(System.in);
        // 3. 打印提示
        System.out.println("请输入名字");
        // 4. 使用next等方法,接收用户输入
        String name = s.next();  // 字符串
        System.out.println("请输入年龄");
        int age = s.nextInt();  // int 
        System.out.println("请输入工资");
        double salary = s.nextDouble(); // double
        // !! 输入类型不对时,会报错
        System.out.println("用户信息如下:");
        System.out.println("name=" + name + "; age=" + age + "; salary=" + salary);
        // 5. 这些方法,可以看文档:https://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Scanner.html
    }
}

System.out.print不会自动换行

进制

定义方式

通过数字前面的标记,确定进制,默认十进制

public class BinaryTest{
    public static void main(String[] args) {

        // 二进制
        int num1 = 0B10; // or 0b1234
        // 八进制
        int num2 = 010; // 0开头
        // 十进制
        int num3 = 10;
        // 十六进制
        int num4 = 0X10; // or 0xa
        System.out.println(num1);  // 2
        System.out.println(num2);  // 8
        System.out.println(num3);  // 10
        System.out.println(num4);  // 16
    }
}

十进制转其他进制

要点:

  1. 将该数不断除以进制数, 直到商为0
  2. 将每一步的余数倒过来
public class DecimalToOther{
    public static void main(String[] args){
        int num1 = 123;  // -> 2
        /*
        123 / 2 = 61 余 1
        61 / 2 = 30  余 1
        30 / 2 = 15 余 0
        15 / 2 = 7 余 1
        7  / 2 = 3  余 1
        3  / 2  = 1 余 1
                 1        
         */
        // => 0b01111011
        // 记得补全八位

        int num2 = 679;  // -> 8
        /*
        679 / 8 = 84 余 7
        84 / 8 = 10 余 4
        10 / 8 = 1 余 2
                1 
        */
        // => 01247

        int num3 = 8912; // ->16
        /*
        8912 / 16 = 557 余 0
        557 / 16 = 34 余 d (13)
        34 / 16 = 2 余 2
                2
        */
        // => 0X22E0
    }
}

其他进制转十进制

规则:从最低为开始(右边),将每位上的数据提取出来,乘以进制的(位数-1)次方

public class OtherToDecimal{
    int num1 = 0b110001100;
    // 0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 1 * 2^3 + 0 * 2^4 + 0 * 2^5 + 0 * 2^6 + 1*2^7 + 1*2^8
    // = 0 + 0 + 4 + 8 + 0 + 0 + 0 + 128 + 256
    // =  396

    int num2 = 02456;
    // 6 * 8^0 + 5 * 8^1 + 4 * 8^2 + 2 * 8^3
    // = 6 + 40 + 256 + 1024
    // = 1326

    int num3 = 0xa45;
    // 5 * 16^0 + 4 * 16^1 + 10 * 16^2
    // = 5 + 64 + 2560
    // = 2629

}

二进制转八/十六进制

要点:

  1. 分组(3 位 或 4 位一组)转换成10进制
  2. 合并即可
    注意二进制与十进制的对应关系:
 1  1 1 1 1 1
32 16 8 4 2 1

这样就可以很快得出答案了,如:111 => 1 + 2 + 4 = 7
使用例子:

public class BinaryToOther{

    public static void main(String[] args){
        int num1 = 0b11100101;  // -> 8
        /*
        11 100 101
        3   4   5
        =>0345
        */
        int num2 = 0b1110010110; // -> 16
        /*
        11 1001 0110
        3   9    6
        =>0x396
        */
    }
}

八/十六进制转二进制

要点:

  1. 将一位数 转换为(3 位 或 4 位一组二进制)
  2. 合并即可

注意补全

使用例子:

public class OtherToBinary{

    public static void main(String[] args){
        int num1 = 01230;
        /*
        1230
        1(001) 2(010) 3(011) 0(000)
        => 0b0000001010011000
        */
        int num2 = 0xAB29
        /*
        AB29
        A(1010) B(1011) 2(0010) 9(1001)

        数值太大时 只需要让8-当前值,等到小的值即可
        => 0b1010101100101001
        */
    }
}

原码反码补码

这个问题比较重要

主要遵循如下规则:

  1. 二进制的最高位是符号位:0表示正数,1表示负数 (将1倒过来不就是-了吗)
  2. 正数的原码,反码,补码都一样(三码合一)
  3. 负数的反码=它的原码符号位不变,其它位取反 (0->1,1->0)
  4. 负数的补码=它的反码 + 1,即 负数的反码=负数的补码 - 1
  5. 0的反码,补码都是0
  6. java没有无符号数,换言之,java中的数都是有符号的
  7. 在计算机运算的时候,都是以补码的方式来运算的 (所以需要先转成补码)
  8. 当我们看运算结果的时候,要看他的原码(结果是补码,需要转成原码)

流程控制

一般来说,流程控制用三种:

  1. 顺序控制 一般的代码流程,从上到下执行
  2. 分支控制 一个或多个分支执行
  3. 循环控制 可以让代码重复执行

分支控制

if分支

举个例子:
做个出票系统:根据淡旺季的月份和年龄,打印票价

  • 4-10月旺季:
    1. 成人(18-60):60
    2. 儿童(<18):半价
    3. 老人(>60):1/3
  • 淡季:
    1. 成人(18-60):40
    2. 其他:20
import java.util.Scanner;
public class TicketingSytem{
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        System.out.println("月份");
        int month = s.nextInt();
        System.out.println("年龄");
        byte yearOld = s.nextByte();

        if (month >= 4 && month <= 10){
            int price = 60;
            if (yearOld < 18){
                System.out.println(price / 2);
            }else if(yearOld > 60){
                 System.out.println(price / 3);
            }else{
                 System.out.println(price);
            }
        }else{
            if (yearOld > 18 && yearOld < 60){
                 System.out.println(40);
            }else{
                System.out.println(20);
            }

        }

    }
}

赋值作为条件时,看赋值后的变量,如boolen a= false if(a=true)=> 这样是可以执行的

switch分支

格式:

switch (c){
            case 'a':
                System.out.println("星期一");
                break;
             default :
                System.out.println("未知");
                break;
            
	}

注意事项:

  1. 表达式数据类型,应和case后的常量类型一致,或者是可以自动转成可以相互比较的类型,比如输入的是字符 而常量是int
  2. switch(表达式)中表达式的返回值必须是:(byte,short,int,char,enum,String)
  3. case子句中的值必须是常量,而不能是变量
  4. default子句是可选的,当没有匹配的case时,执行default
  5. break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有写break,程序会顺序执行到switch结尾(即不会判断case)

使用例子:

/*
1.
使用switch把小写类型的char型转为大写(键盘输入)。只转换a,b,c,d,e.
其它的输出"other"。
2.
对学生成绩大于60分的,输出"合格”。低于60分的,输出"不合格”。(注:输入
的成绩不能大于100),提示成绩/60
3.
根据用于指定月份,打印该月份所属的季节。3,4,5春季6,7,8夏季9,10,11
秋季12,1,2冬季[课堂练习,提示使用穿透]
*/
import java.util.Scanner;

public class SwitchExercise{
    public static void main(String[] args){

        // 1 
        System.out.println("char>>>");
        Scanner scanner = new Scanner(System.in);
        char c = scanner.next().charAt(0);
        switch (c){
            case 'a':
                System.out.println('A');
                break;
            case 'b':
                System.out.println('B');
                break;
            case 'c':
                System.out.println('C');
                break;
            case 'd':
                System.out.println('D');
                break;
            case 'e':
                System.out.println('E');
                break;
            default:
                System.out.println("other");
                break;
        }
        // 2
        System.out.println("成绩>>>");
        double score = scanner.nextDouble();
        // [60, 100] => /60 = 1;
        // [0, 60)  => /60 = 0;
        switch ( (int)score / 60 ){
            case 1:
                System.out.println("合格");
                break;
            case 0:
                System.out.println("不合格");
                break;
            default:
                System.out.println("异常数据");
                break;
        }

        // 3
        System.out.println("月份>>>");
        int month = scanner.nextInt();
        switch (month){
            case 3:
            case 4:
            case 5:
                 System.out.println("春季");
                 break;

            case 6:
            case 7:
            case 8:
                 System.out.println("夏季");
                 break;

            case 9:
            case 10:
            case 11:
                 System.out.println("秋季");
                 break;
            case 12:
            case 1:
            case 2:
                 System.out.println("冬季");
                 break;

            

        }


    }
}

循环控制

for循环

一般使用例子:

public class For {
    public static void main(String[] args){
        // 1.打印1~100之间所有是9的倍数的整数,统计个数及总和
        int sum = 0, count = 0;
        int start = 1, end = 100;
        int t = 9; // 倍数
        for (int i = start; i <= end; i++){
            if (i % t == 0){
                sum += i;
                count++;
                // 81 90 99 
                // 9  10  11
            }
        }
        System.out.println("sum: " + sum + " count: " + count);

        //打印
        /*
        0 + 5 = 5
        1 + 4 = 5
        2 + 3 = 5
        3 + 2 = 5
        4 + 1 = 5
        5 + 0 = 5
        */
        int total = 5;
        for (int i=0; i<= total; i++){
            int temp = total - i;
            System.out.println(i + " + " + temp + " = " +  total);
        }

    }
}

注意:

  1. 循环内部语句只有一天是,可以省略{}, 但不建议使用
  2. 多个条件可以使用,隔开,如if(int i=0,j=0; i<count; i++, j+=2)
  3. 我们可以省略初始化条件和变量迭代, 灵活使用,如for( ; i<= 10 ; )
  4. 还可以全部省略,变成死循环,如for(;;)

关于增强for, 是一种简化迭代器书写方式
使用例子:


public class Demo{
	public static void main(String[] args){
	    int arr[] = {1,2,3};
	    /**
	    *增强for
	    */
	    for(int num : arr){
	     System.out.println(num);
	    }
	}
}

只适合取数据,不能更改数据
只用于数组,或实现Iterable接口的集合类上;set,list

while循环

使用格式:

while (循环条件) {
    循环体(语句);
	循环变量迭代;
}

使用例子:

public class While{
    public static void main(String[] args){
        /*
        1.打印1一100之间所有能被3整除的数
        2.打印40一200之间所有的偶数
        */
        int end1 = 100, end2 = 200;
        int start1 = 1, start2 = 40;

        int t1 = 3;
        int t2 = 2;
        while (start1 <= end1){
            if (start1 % t1 == 0){
                System.out.println(start1);
            }
            start1++;
        }

        while (start2 <= end2){
            if (start2 % t2 == 0){
                System.out.println(start2);
            }
            start2++;
        }


    }
}

doWhile循环

基本使用:

do{
	循环体(语句);
	循环变量迭代;
}while(循环条件);
  1. 先执行在判断,即至少执行一次
  2. while后面有;

流程图:
流程

使用例子:

import java.util.Scanner;

public class DoWhile{
    public static void main(String[] args){

        // 一般使用
        // !! 至少会执行一次
        // ! 不要忘记while后面的 ';' 了
        int c = 0;
        do {
            System.out.println("lczmx " + c);
            c++;
        }while(c > 10);

        // 统计1 - 200之间能被5整除但不能被3整除的个数
        byte num1 = 5;
        byte num2 = 3;
        int i = 1;
        int count = 0;
        do {
            if(i % num1 == 0 && i % num2 != 0){
                count++;
            }
              i++;
        }while(i<=200);
        System.out.println("count " + count);

        // 如果李三不还钱,打到张三说还钱为止
        Scanner scanner = new Scanner(System.in);
        char input;
        do{
            System.out.println("打!!\n还钱? y or n >>>");
            input = scanner.next().charAt(0);
        }while(input != 'y');

    }
}

break和continue

  • break跳出当前循环
  • continue跳过本次循环

它们都可以指定Label,跳到对应的俄循环中

默认是当前的循环

使用例子:

lable1:
for (int j = 0; j < 4; j++) {
lable2:
        for (int i = 0; i<10;i++) {
		    if(i == 2){
			    break lable1
			}
		 }
}

同理,continue也可以像上面那样操作

本文根据韩顺平 零基础30天学会Java视频整理而来

posted @ 2022-03-20 11:44  403·Forbidden  阅读(212)  评论(0编辑  收藏  举报