Java基础超详细整理( 2024动力节点老杜第一、二章)

本篇文章重点对于Java的环境搭建以及Java的基础语法进行了知识点整理,对于一些琐碎的知识点进行了系统化总结,并且加入了我个人在学习过程中的一些理解。希望对大家的Java学习有所帮助。

(今天是2024年高考,祝高三学子们旗开得胜,高考加油!)


文章目录


一.Java开发环境搭建

常用的Windows组合键

  • win+D 回到桌面

  • win+E 打开资源管理器

  • win+R

  • win+L 锁屏

  • alt+tab 应用切换

常用的dos命令

  • dir 列出当前目录和文件
  • cls 清屏
  • exit 退出dos
  • 切换盘符 D: / C:
  • 删除一个或者多个文件 del [文件名]

​ del *.txt

  • ipconfig 网卡信息

    • ipconfig /all 更全
  • ping 网络连通

    • ping [ip] -t 一直ping
    • CTRL + C 强行终止
  • 上下方向键翻出历史记录

  • mkdir 创建目录

  • rd 删除目录

    • rd abc
  • ren 重命名

    • ren abc xyz 将abc目录修改为xyz
  • cd 切换目录change directory

    • cd [路径](包括相对路径和绝对路径)
    • 绝对路径:在Windows当中以盘符开始的都是绝对路径
    • 相对路径:以当前所在的位置为基准,从当前所在的位置开始找
    • cd … 回到上级目录(在Windows里面两个点代表上级目录。一个点代表当前路径)
    • cd / 回到根目录(正反斜杠都可以)
    • 注意:tab 能够自动补全,切换可以一直按tab
  • 在路径上方框子里面输入cmd能够直接进入该路径

  • 新建并编辑文件 copy con [文件名],CTRL+Z保存

  • type [文件名] 查看文件内容

  • shutdown 关机

    • shutdown -s -t 3600 一小时后自动关机(3600是秒)

批处理文件(多数为.bat)

c: //要先切换盘符
cd C:\root
del *.java

通用文本编辑快捷键

ctrl+c 复制

ctrl+v 粘贴

ctrl+x 剪切

ctrl+s 保存

ctrl+z 撤销

ctrl+y 重做

ctrl+a 全选

home 光标回到行首

end 光标回到行尾

ctrl + home 光标回到文章开始

ctrl + end 光标回到文章末尾

shift + home 或 end 选中一行

鼠标双击 (选中一个单词)

ctrl + shift + 右箭头或左箭头 (选中一个单词)

ctrl + f 查找

editplus配置(p5)

jdk安装

  • bin目录:存放命令

    • java命令:负责运行

    • javac:负责编译

  • lib:存放类库

    • srczip:jdk源码

Java的加载与运行

  • 编译阶段

    • 源代码:.java

    • javac命令检查语法规则

    • 字节码文件:.class

      A.class:A是一个类,A是类名

  • 运行阶段

    • java命令运行: java A (java后面跟的是A,不是A.class)

      运行后jvm开始运行类加载器(classloader),找A.class字节码文件,装载进去,解释为二进制文件,进行底层交互

      [外链图片转存中…(img-cPhugW45-1717761894783)]在这里插入图片描述

  • 注意点

在这里插入图片描述

jdk:Java工具箱(自带jre和jvm)

jre:Java运行环境

jvm:Java虚拟机

path环境变量

  • path环境变量不是java的,隶属于windows操作系统
  • path环境变量的作用是什么?
    • 在path中有很多路径,路径和路径之间采用 分号 隔开
    • 在DOS命令窗口中输入一个DOS命令之后,windows会先从当前路径下找这个命令,如果找不到,则会去环境变量PATH的路径中查找该命令,找到则执行,找不到,则报错。
    • PATH环境变量实际上就是给windows操作系统指路的。

编写第一个Java程序

//class表示定义一个类
//helloworld是给这个类起个名
public class helloword{
    //类体
    //1.这是main方法,也叫做主方法
    //2.main方法是jvm规定的固定写法,照抄就行了。这是程序的入口
    //3.对于mian方法来说,能修改的就是args这个变量名
    //4.public表示公开的
    //5.static表示静态的
    //6.void表示mian方法执行结束后不返回任何数据
    //7.除定义变量之外,类体当中不能编写Java语句
    public static void main(String[] args){
        
        //方法体
        //1.方法体当中由一行一行的Java语句组成
        //2.任何一条Java语句必须以";"结尾
        //3.方法体当中的代码是有执行顺序的,遵循自上而下的顺序依次逐行执行
        System.out.println("Hello World!");
        //这行代码的作用是将字符串"Hello World!"打印输出到控制台,并且println会换行(print不换行)
        //\t是制表符(tab键)
    }
    //类体
}

编译第一个Java程序

  • 使用javac命令来编译。首先确保javac命令能用。
  • javac命令怎么用,语法是什么?
    • javac java源文件的路径
    • javac java源文件的相对路径
    • javac java源文件的绝对路径
    • javac *.java

运行第一个Java程序

  • 使用java命令来运行程序,首先确保java命令可以用。

  • java命令怎么用?语法格式是什么?

    • java 类名
    • 切记切记切记~!!!!!!!!! java命令后面跟的不是文件路径。java命令后面跟的是类名
  • 什么是类名?

    • A.class,类名是A
    • HelloWorld.class,类名是HelloWorld
    • Test.class,类名是:Test
  • 这里先死记硬背,后面就明白了。要使用java命令,首先DOS命令窗口中的当前路径必须切换到class文件所在的位置。

掌握环境变量CLASSPATH

  • classpath环境变量是隶属于Java语言的。不是windows操作系统的。和PATH环境变量完全不同。

  • classpath环境变量是给classloader(类加载器)指路的。

  • java A。执行后。先启动JVM,JVM启动classloader,classloader去硬盘上通过classpath找A.class文件。找到则执行,找不到则报错。

  • 如果classpath没有配置的话,默认从当前路径下找class字节码文件。

  • 如果classpath配置了,例如配置到桌面上了:C:\Users\Administrator\Desktop,那么classloader以后就只会去桌面上找字节码文件了,不再从当前路径下找了。

  • 注意,如果classpath配置为:classpath=.;C:\Users\Administrator\Desktop 是什么意思呢?

    • 先让类加载器从当前路径下找,如果找不到的话,去C:\Users\Administrator\Desktop找。
  • 但是对于目前来说,我们还没有必要这样配置。所以目前classpath大家是可以不配置的。
    在这里插入图片描述

关于编译时的乱码问题

  • 当java源文件中有中文时,采用老杜给的editplus工具写代码,最后会出现中文乱码问题,为什么?

    • editplus默认是简体中文GBK。
    • java21的javac编译器采用的是UTF-8的编码方式进行编译。
    • 编码不一致,所以乱码了。
  • 怎么解决?

    • 第一种方案:
      • javac -encoding GBK HelloWorld2.java
    • 第二种方案:
      • 将editplus的字符集修改为UTF-8
        在这里插入图片描述
  • 不管哪一种解决方案,都是让两边的字符编码方式一致。

java中的三种注释

// 单行注释
// 单行注释
// 单行注释
// 单行注释
/*
	多行注释
	多行注释
*/
/**
* javadoc注释,可以给javadoc命令解析提取并生成帮助文档
* @author dujubin
* @version 1.0
* @since 1.0
*/

使用以下命令可以提取生成帮助文档:

javadoc -d docs -author -version -encoding utf-8 HelloWorld.java

public class与class的区别

  1. 一个Java源文件中可以定义多个class
  2. 编译之后,一个class就会对应生成一个class字节码文件
  3. 如果一个类是public的,类名必须和源文件名保持一致。
  4. public的类可以没有。如果有的话,也只能有一个。
  5. 每个类中都可以编写入口main方法。想执行X类的main方法怎么办?java X
  6. 这里只是测试一下语法,在实际的开发中,对于一个软件来说,一般入口只有1个。

二.Java基础语法

标识符

  • 程序员有权利自己命名的单词都叫标识符,可以标识变量/方法/类/包

  • 标识符的命名规则和规范

    • 规则(语法级别)

      • 字母、数字、下划线、美元符号,不能含有其他字符

        (这里的“字母”代表的是任何一个国家的文字,Java是采用的Unicode编码,支持全球任何一个国家的语言)

      • 标识符不能以数字开头

      • 标识符严格区分大小写

      • 关键字不能做标识符(紫色显示的,如public,class)

      • 标识符理论上没有长度限制,但是最好不要太长

        public class IdentifierTest01{
            public static void main(String[] args){
                
                //定义一个变量,用来存储一个人的年龄
                //age是一个变量名,是一个标识符
                int age = 20;
                
                int age_ = 20;
                
                int $_age = 20;
                
                int $_age123 = 50;
                
                int 年龄 = 20; 
                
                int a = 100;
                int A = 100;
            }
        }
        
        //学生类是一个标识符
        class 学生类{
            
        }
        
    • 规范(约定俗成)

      • 见名知意
      • 遵循驼峰式命名方式。StudentService,BankService…
      • 类名,接口名:首字母大写,后面每个单词首字母大写。StudentService,BankService…
      • 变量名,方法名:首字母小写,后面每个单词首字母大写。doSome,productPrice…
      • 常量名:全部大写,每个单词之间采用“_”分隔。LOGIN_ERROR,LOGIN_SUCCESS…
      • 包名:全部小写。powernode…

关键字

  • 在Java语言中具有特殊含义的单词叫做关键字,每个关键字都已经被Java语言本身占用了,不能用作标识符

  • 所有的关键字都是小写(50个,有两个保留字goto,const也不能用)

在这里插入图片描述

字面量

  • **程序中的的数据就是字面量。**字面量是Java中最基本的表达式,无需转换,直接使用

  • 字面量包括那些类型

    整数型

    浮点型

    布尔型

    字符型

    字符串型

public class ConstTest01 {
    public static void main(String[] args){
        
        //整数型的字面量
        System.out.println(10);
        System.out.println(-100);
        
        //浮点型
        System.out.println(3.14);
        
        //布尔型
        System.out.println(true);
        System.out.println(false);
        
        //字符型(单个字符)
        //所有字符型字面量必须使用单引号括起来
        System.out.println('A');
        System.out.println('中');
        //System.out.println('AB');编译报错
        
        //字符串型
        //所有字符串型字面量必须使用双引号括起来
        System.out.println("Hello World!");
        System.out.println("中文输入");
        System.out.println("A");
              
        System.out.println("10");
        System.out.println(10);//二者区别
        
        System.out.println("true");
        System.out.println(true);//二者区别
    }
}

加号运算符

  • +的两个作用
    • 求和:两边都是数字
    • 字符串拼接:+两边只要有一个是字符串,一定会做字符串拼接工作,并且拼接完之后的结果还是一个字符串
  • 一个表达式当中出现多个+,如果没有小括号,遵循从左到右
public class PlusTest01{
    public static void main(String[] args){
        
        //求和
        System.out.println(10 + 20);//30
        
        //字符串拼接
        System.out.println("10" + 20);//"1020"
        
        //第一个 + 是求和
        //第二个 + 是字符串拼接
        System.out.println(10 + 20 + "30");//"3030"
        
        //添加了小括号优先级比较高
        //这两个+都是字符串拼接
        System.out.println(10 + (20 + "30"));//102030
        
        System.out.println("10" + 20 + 30);//102030
        
        System.out.println("10" + (20 + 30));//1050
    }
}

变量

概述

  • 变量是内存中的一块空间。是计算机中存储数据的最基本单元。

    变量是用来解决数据存储问题的。

    先把数据存储起来,后续的程序需要使用的时候,可以从变量中取来用

  • 三要素:

    • 数据类型(决定空间大小):int,double,String…

    • 变量名

    注意:

    ​ 数据类型是决定空间和大小的

    ​ 数据类型 和 值的数据类型要一致

    在这里插入图片描述

变量的声明、赋值和访问

  • 声明语法格式

    数据类型 变量名;

    int 整数型

    double 浮点型

    String 字符串型

  • 赋值的语法格式

    变量名 = 变量值;

  • 访问怎么做?(包括两种情况:一种是读,一种是修改)

    • 读:System.out.println(变量名);
    • 修改:变量名 = 变量值;
public class VarTest01{
    public static void main(String[] args){
        int age;//声明
        age = 20;//赋值
        
        //读
        System.out.println("年龄=" + age);
        
        //改(重新赋值)
        age = 30;
        System.out.println("年龄=" + age);
        
        //age = "50";String无法转换成int
        
        double Π = 3.14;
        System.out.println("圆周率:" + Π);
        
        //声明和赋值可以一起完成
        String name = "jack";
        System.out.println("name:" + name);
    }
}

变量的作用

  • 便于代码的维护
  • 增强代码的可读性
public class VarTest02{
    public static void mian(String[] args){
        //修改只要改num就可以了
        int num = 100;
        System.out.println(num + 456);
        System.out.println(num + 123);
        
        //需求:计算半径是10.0的圆的面积
        //不用变量
        System.out.println(3.14 * 10.0 * 10.0);
        
        //使用变量
        double Π = 3.14;
        double r = 10.0;
        System.out.println(Π * r * r);
    }
}

变量使用的小细节

  1. 变量必须先声明,再赋值,才能访问

  2. 方法体中的代码代码自上而下,先访问再赋值肯定是不行的

  3. 一行代码上可以同时声明多个变量

    int a,b,c = 300;
    //声明了a,b,c。a,b没赋值,c赋值300
    
    int a = 500,b = 600,c = 700;
    
  4. 在一个作用域中,变量名不能重名,可以重新赋值

    作用域就是有效范围。在Java中,一个{}就是一个作用域

    int i = 100;
    int i = 200;//错误
    
    int i = 100;
    i = 200;//正确
    

变量的作用域

在Java程序中通常一个{}就是一个作用域

记住一句话:出了大括号就不认识了

public class VarTest04{
    public static void main(String[] args){
        
        //age是main方法声明的,所以作用域是整个main方法
        int age = 20;
        System.out.println("age = " + age);
        
        int num = 100;
        
        if(num > 50){
            int i = 666;
            System.out.println("i = "+ (i + age));
            //这个i只在这个打括号里面起作用
        }
    }
    
    //另一个方法
    public static void doSome(){
        //错误:找不到符号
        System.out.println("age = " + age);
    }
} 

变量的分类

  • 局部变量
  • 成员变量
    • 静态变量
    • 实例变量
public class VarTest05{
    public static void mian(String[] args){
        //凡是在方法体当中定义的变量,一定是局部变量
        //局部变量只在当前方法体中有效
        int a = 100;
        
    }
    //在类体当中定义的变量叫做成员变量
    //实例变量
    int b = 200;
    
    //静态变量
    static int c = 300;
}

进制

二进制

二进制011011100101110111100010011010
十进制012345678910
权值

在这里插入图片描述

1,2,4,8就是权值(20,21,22,23)

二进制与十进制的转换
  • 十进制转二进制:除2取余,一直到商0为止,最后将所有的余数逆输出
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b6f6ca55826a4095b767b1f0c2cb30cc.png)

    public class BinaryTest01{
        public static void mian(String[] args){
            //输出75,0b后面看作是二进制,二进制的字面量以0b开头
            System.out.println(0b1001011) 
        }
    }		
    
  • 二进制转十进制:每一位与权数相乘,最后求和

在这里插入图片描述

八进制和十六进制

八进制:满8进1
  • Java中规定,以0开始的字面量是一个八进制的字面量

    System.out.println(0211);
    
  • 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20

  • 与十进制的转换:和二进制一样

    • 十转八:除8取余,逆序输出
      在这里插入图片描述

    • 八转十:先平方后求和
      在这里插入图片描述

十六进制
  • Java中规定,以0x开始的字面量是一个十六进制的字面量

    System.out.println(0x146);//326
    
  • 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20

  • 转换(和之前的一样)

    • 10转16
      在这里插入图片描述

    • 16转10

      在这里插入图片描述

进制总结和补充

//十进制
System.out.println(10);//10
//二进制
System.out.println(0b10);//2
//八进制
System.out.println(010);//8
//十六进制
System.out.println(0x10);//16
  • 二进制和十六进制转换:四个四个转,不足四位左侧补0

    1011 1111 = bf
    0xb1e2 = 1011 0001 1110 0010
    

原码反码补码

byte与bit

  1. byte(字节):八个二进制位就是一个字节

  2. bit(比特):一个二进制位就是一个比特

  3. 二者关系:1 byte = 8 bit

  4. 在计算机中,通常以字节(byte)为最小单位进行存储和传输,而比特(bit)则是用来表示数据的最小单位

  5. 1KB = 1024 byte

    1MB = 1024 KB

    1GB = 1024 MB

    1 TB = 1024 GB

原码反码补码:是计算机二进制的三种表现形式,计算机底层存的是补码

正数的原码反码补码
  • 正数的原码反码补码都是相同的
  • 127的原码反码补码是 0111 1111 (128-1)
负数的原码反码补码
  • 原码:将绝对值转换为二进制后,最高位改为1(最高位是符号位,1代表负数,0代表正数)

    //-6的原码
    6 = 0000 0110
    -6 = 1000 0110
        
    20 = 0001 0100
    -20 = 1001 0100
    
  • 反码(原则是:以原码作为参考,符号位不变,其他位取反)

    -20 = 1110 1011
    
  • 补码(原则是:以反码作为参考,符号位不变,加1)

    -20 = 1110 1100
    
  • 补码转原码:符号位不变,取反再加1

  • 特殊:-128 原码和补码相同

    128 = 1000 0000
    -128 = 1000 0000 //原码
    -128 = 1111 1111 //反码
    -128 = 1000 0000 //补码
    
  • 1byte的取值范围:1000 0000 ~ 0111 111(-128~127)共256种情况

数据类型

概述

  • 分类(如下图)

在这里插入图片描述

要记的:

在这里插入图片描述

  • 关于八种基本数据类型的默认值:(记住)

    byteshortintlongfloatdoublebooleanchar
    0000L0.0F0.0false\u0000
  • 所有的引用数据类型,默认值是:null

  • 语法规则:在Java中,成员变量如果没有手动赋值的话,系统会赋默认值

    public class DefaultValueTest{
        static int k;
        static boolean sex;
        static String name;
        public static void main(String[] args){
            int i = 100; //局部变量必须要赋值
            System.out.println(i); //
            System.out.println("k = " + k); //输出0
            System.out.println("sex = " + sex); //输出false
            System.out.println("name = " + name); //输出null
        }
    }
    

整数型(byte,short,int,long)

四种表现形式
int a = 10; //10
int b = 0b10; //2
int c = 010; //8
int d = 0x10; //16
自动类型转换
  • Java中任何一个“整数型字面量”都会默认被当做int类型来处理
  • Java中允许小容量的数据直接赋值给大容量的变量

byte < short < int < long < float < double

  • 如果在整数型字面量后面添加 L 或者 l ,那么这个整数型字面量被当做long类型来处理了(建议使用大写L,否则容易跟1混淆)
//= 是赋值运算符,=右边先执行
//右边先执行,默认给100当做int型,分配四个字节。a变量正好也是4个字节,所以不存在类型转换
int a = 100; 

//右边先执行,默认给100当做int型,分配四个字节,b变量为8个字节,小的容量自动转换为大的容量。这个被称为自动类型转换
long b = 100; 

//100L一上来就是分配8个字节。所以这个代码不存在类型转换
long c = 100L;

//2147483647被当做int处理,4个字节,存在类型转换
long d = 2147483647; 

//错误:整数太大(不是long存不下)
//原因是:2147483648默认被当做int来处理,分配4个字节
//解决方法:添加一个L long e = 2147483648L;
long e = 2147483648;
强制类型转换
  • Java中大容量不能直接赋值给小容量(大容量是不能自动转换成小容量的)
long x = 1000L;
//错误:不兼容的类型:从long转换到int可能会有损失
int y = x;
  • 大容量转换成小容量的时候,想让其编译通过的话,必须由程序员手动添加“强制类型转换符来操作”(有可能会精度损失)
long x = 1000L;
//强制类型转换
int y = (int)x;
long a = 55L;
int b = (int)a;
System.out.println("b =" + b); //55

//long 00000000 00000000 00000000 00000000 00000000 00000000 00110111
//int                             00000000 00000000 00000000 00110111
//int将前面的直接去掉,输出还是55(正数的补码是它本身)

int k = 128;
byte e = (byte)k;
System.out.println("e = " + e); //-128

//int 00000000 00000000 00000000 10000000
//byte                           10000000
//                               10000000的补码为10000000,十进制为-128

int m = 129;
byte n = (byte)m;
System.out.println("n = " + n); //-127

//int 00000000 00000000 00000000 10000001
//byte                           10000001
//                               10000001的补码为11111111,十进制为-127
(特殊)请记住这个语法规则:当一个整数型字面量没有超出 byte 和 short 取值范围的时候,可以直接赋值给 byte 和 short 类型的变量。
public class IntTest04{
    public static void mian(String[] args){
        
        //可以直接赋值,不需要强制类型转换
        byte b = 1;
        byte a = 127;
        
        //编译出错,128超出byte取值范围
        byte c = 128;
        
        //如果想编译通过,只能做强制类型转换
        byte c = (byte)128;
        System.out.println("c = " + c); //-128精度损失
        
    }
}
//short取值范围-32768~32767
short s = 32767;

//编译报错,必须进行强制转换
//short s1 = 32768;
short s1 = (short)32768;
System.out.println(s1); //-32768精度损失
当两个int类型的数据进行运算之后,结果还是int类型

注意:多种数据类型在混合运算的时候,先各自转换成容量最大的,再做运算。

public class IntTest05{
    public static void main(String[] args){
        
        int a = 10;
        
        int b = 3;
        
        //应该是这样的结果:3.333333333333......
        //但Java中不是,结果是:int类型的3
        System.out.println(a / b); //输出结果为3
        
        byte x = 10;
        int y = 3;
        long z = 100L;
        
        //编译出错 X + y + z转换成了long类型
        int result = x + y + z;
        
        //修改
        long result = x + y + z;
        System.out.println(result);
    }
}
编译器的小心思:byte和short混合运算的时候,各自先转换成int再做计算

byte + byte = int

byte + short = int

short + short = int

public class IntTest06{
    public static class void main(String[] args){
        
        short m = 10;
        byte n = 10;
        int result = m + n; //最后结果是int类型
        System.out.println(result);
        
        byte b = 10 / 3; //编译优化:编译阶段会直接算出来3,在class文件中时就已经是byte b = 3;了
        System.out.println(b);
        
        byte x = 10;
        byte y = 3;
        //编译报错,类型不兼容
        byte c = x / y;编译阶段只知道结果是int类型,不知道具体的结果
        
        //修改    
        int c = x / y;
        
        //编译出错
        byte e = 3;
        byte f = 10 / e; //只要有一个变量在,就不会计算,只知道e是int
        
        //第一种修改方式
        int f = 10 / e;
        
        //第二种修改方式
        byte = (byte)(10 / e);
    }
}

浮点型(float,double)

  • 包括两个类型

    float(4个字节):单精度,可以精确到7位小数

    double(8个字节):双精度,可以精确到15位小数

  • double是常用的

  • 浮点型的字面量默认都会被当做double类型来处理,如果想让其当做float类型来处理的话,需要在字面量后面添加F/f

    public class FloatTest01{
        public static void main(String[] args){
            
            //不存在类型转换
            double d = 3.14;
            
            //编译出错,3.14默认是double类型,大容量不能直接转换成小容量
            float f = 3.14;
            
            //修改
            //第一种方案:不存在类型转换
            float f = 3.14F;
            
            //第二种方案:强制类型转换
            float f = (float)3.14
        }
    }
    
  • double精度要高

    double x = 1.5656856894; //输出为1.5656856894
    float y = 1.5656856894f; //输出为1.5656856(精度损失)
    
  • 浮点型数据两种表现形式(整数型为四种进制)

    • 十进制(实际开发中就是用它)

      double x = 1.23;

      double x =0.23;

      double x =.23; //就是0.23

    • 科学计数法

      double x = 0.123E2; //0.123 * 10^2

      double x =123.34E-2; //123.34 / 10^2

  • 浮点型数据存储原理

    在这里插入图片描述

    • 一旦有浮点型数据参与运算得出的结果,一定不要用“==”与其他数字进行“相等比较”

      主要原因是:任何浮点型数据,在计算机底层存储的都是它的近似值(仅限于浮点型)

      public class DoubleTest05{
      	public static void main(String[] args){
      		double a = 6.9;
      		double b = 3.0;
      		double c = a / b;
      		System.out.println("c = " + c); //c = 2.3000000000000003
              
              if(c == 2.3){
                  System.out.println("相等"); //不输出
              }
              
              //一般做法
              if(c - 2.3 < 0.00000001){
                  System.out.println("相等");
              }
      }
      
      

字符型(char)

char类型概述:
  1. char类型是字符型

  2. char类型占用2个字节

  3. char类型取值范围:0~65535

    char和short都是2个字节

    char可以取到更大的正整数(short有负数)

    char和short所能表示的数量是一样的

  4. 在java中,字符char类型的字面量必须使用单引号括起来:

    ‘A’,‘a’,‘中’

  5. 在Java中,char类型统一采用的字符编码方式:Unicode编码

  6. 在Java中,char可以存储一个汉字

  7. char的默认值是:\u0000(\u后面数字默认为16进制编码)

public class CharTest01{
    public static void main(String[] args){
        char c1 = 'A';
        char c2 = 'B';
        char c3 = 'a';
        char c4 = '中';
        
        //错误:String无法转换成char,"中"为String类型,加了双引号
        char c5 = "中";
        
        //错误:char类型只能存储一个字
        char c6 = 'ab';
        
        //错误:空字符文字(不是空格)
        char c7 = '';
    }
}

​ 8.当整数型字面量没有超出char的取值范围,可以直接将其赋值给char类型的变量,且会直接将这个整数当成ASCII码

​ 当整数型字面量没有超出byte short char的范围,可以直接赋值给它们的变量

char c1 = 97; //当做ASCII码,输出a
char c2 = 65536; //报错
转义字符

\t: 表示制表符,相当于按下 Tab 键
\n: 表示换行符
“: 表示双引号(”)
‘: 表示单引号(’)
\: 表示反斜线(\)本身

\u:后面是一个16进制的数字,对应Unicode码

public class CharTest02{
	public static void main(String[] args){
		// 这是一个普通的t字符
		char c1 = 't';

		// 按说应该编译报错。因为看到的是一个字符串。不是字符。
		// 但是编译通过了,说明这是1个字符。
		// 这个字符叫做:制表符。tab
		// \ 反斜杠在java语言中具有转义功能。把普通的t字符转义成了制表符tab。
		char c2 = '\t';

		System.out.println("abc" + c2 + "def");

		// \n 换行符
		System.out.print("hello\n");
		System.out.print("world\n");
		System.out.print("test\n\n\n\n\n\n");

		// \"
		// 需求:输出一个双引号到控制台。
		//System.out.println("""); //编译报错
		System.out.println("\""); 
		System.out.println("\"\""); 
		System.out.println('"');


		// 需求:输出一个单引号到控制台
		System.out.println("'");
		// 编译错误
		//System.out.println(''');
		System.out.println('\'');

		// 字符char只能是单个字符。
		//System.out.println('\'\'');

		// 需求:输出一个反斜杠到控制台。 \
		//System.out.println("\"); // 编译错误

		// 在java中两个 \\ ,最终转换完成之后是一个普通的 \ 字符。
		System.out.println("\\");
        
        //输出两个\
		System.out.println("\\\\");
	}
}
字符编码(在写转码工具:jsons.cn)
  • ASCII码(占用1个字节):包含了键盘上所有的键。程序员要记住以下几个(注意都是字符,0不是数字0,而是字符"0")

    aA0
    97(b是98,以此类推)65(B是66,以此类推)48(1是49,以此类推)

    乱码出现的原因:编码(Encoding)和解码(Decoding)用的不是同一套码表,但是ASCII码是计算机最基本的编码方式,其它编码方式兼容。

  • Lantin-1编码(ISO 8859-1):1个字节,支持256字符,向上兼容ASCII。表示欧洲语言。

  • ANSI编码:1个字节,两个ANSI能表示一个汉字。

  • Unicode编码(Java使用):16进制表示,占用2个或4个字节,可以表示所有语言(浪费空间,'a’采用一个字节就够了)

    char c = '\u0041'; //'\u0041'是一个字符,表示A
    
  • UTF-8编码(web开发常用):基于Unicode编码的可变长度字符编码,使用1~4个字节来表示一个字符。

  • UTF-16编码:2或4个字节。

  • UTF-32编码:固定长度4个字节。

  • GB2312编码(小):2个字节表示一个汉字,是GBK编码的前身。

  • GBK(Guo Biao Ku)(中):2个字节。

  • GB18030编码(大)

  • Big5编码(大五码):2个字节,台湾地区用于表示繁体中文。

  • char类型变量定义有三种方式

    char c = 'A'; //直接定义
    char c = '\u0041'; //Unicode码
    char c = 65; //ASCII码
    
  • char参与的运算

    byte short char 在混合运算的时候,各自先转换成int再做运算

    Systm.out.println('a' + 1); //98
    
    char c = 'a' + 1; //98
    System.out.println(c); //98的值赋给了c,输出b
    

布尔类型(boolean)

  • 布尔型:boolean

    1. 在Java中,boolean值只有两个true false,没有0和1这一说(C语言是0和1)
    2. boolean类型主要用于:逻辑判断,条件判断等
    public class BooleanTest01{
        public static void main(String[] args){
            //不兼容的类型:int无法转换为boolean
            //boolean flag = 1;
            
            boolean flag = true;
            boolean gender = false;
            
            if(gender){
                System.out.println("男士");
            }else{
                System.out.println("女士");
            }
            
            int a = 1000;
            int b = 200;
            
            System.out.println(a > b); //输出true
            
            if(a > b){  //a > b 是boolean类型
                System.out.println(a + ">" + b);
            }else{
                System.out.println(a + "<" + b);
            }
        }
    }
    

总结:基本数据类型转换规则

​ 1.八种基本数据类型中除了boolean类型之外,剩下7个都是可以互相转换的。
​ 2.小容量可以自动转换成大容量,称为自动类型转换,容量从小到大排序:
​ byte < short < int < long < float < double
​ char <
​ 3.大容量不能自动转换成小容量,必须添加强制类型转换符,编译才能通过。但是运行时可能损失精度。
​ 4.当整数型字面量没有超出byte short char的范围时,可以直接将其赋值给byte short char类型的变量。
​ 5.byte short char混合运算时,各自先转换成int再做运算。
​ 6.多种数据类型混合运算时,各自先转换成最大的容量,再做运算。

public class DataTypeHomework03{
	public static void main(String[] args){
		// 通过
		short s = 100;
		// 报错:大容量不能直接赋值给小容量
		s = s - 99;
		// 通过
		byte b = 100;
		// 报错
		b = b + 1;
		// 通过
		char c = 'a';
		// 通过
		int i = 20;
		// 通过
		float f = .3F;
		// 通过
		double d = c + i + f;
		// 通过
		byte b1 = 11;
		// 通过
		short s1 = 22;
		// 报错
		short x = b1 + s1;
	}
}

运算符

在这里插入图片描述

算数运算符

  • 包括:

    +:求和;字符串拼接;表示正数

    -:相减;负数

    *:乘积

    /:商(除以)

    %:取模(求余数)

    ​ 取模公式:x - (x / y) * y

    ​ 10 % 3 = -10 - (-10) / 3 * 3

    ​ = -10 - (-3) * 3

    ​ = -10 + 9

      	  = -1
    

    ++:让变量自身加1

    –:让变量自身减1

public class OperatorTest01{
	public static void main(String[] args){
		
		int a = 10;
		int b = +3;
		int c = a + b;
		System.out.println(a + "+" + b + "=" + c);

		int d = 10;
		int e = -3;
		int f = d - e;
		System.out.println(d + "-(" + e + ")=" + f);

		/*
		int x = 10;
		int y = 3;
		System.out.println(x + "*" + y + "=" + x * y);
		*/

		int m = 10;
		int n = 3;
		System.out.println(m + "/" + n + "=" + m / n);
		
		int x = 10;
		int y = 3;
		System.out.println(x % y); // 1

		// x - x / y * y
		// -10 - (-10) / 3 * 3
		// -10 - (-3) * 3
		// -10 - (-9)
		// -10 + 9
		// -1
		x = -10;
		System.out.println(x % y); // -1


		// x - x / y * y
		// 10 - 10 / (-3) * (-3)
		// 10 - (-3) * (-3)
		// 10 - 9
		// 1
		x = 10;
		y = -3;
		System.out.println(x % y); // 1

		int i = 10;
		// 一元运算符
		i++;
		System.out.println("i = " + i); // 11

		i = 100;
		i--;
		System.out.println("i = " + i); // 99

	}
}
  • ++ 自加1;-- 自减1

    1. 可以出现在变量前,也可以出现在变量后

      ++i;

      i++;

      像++这种运算符,只有一边有操作数,我们把这种运算符称为:一元运算符

      a + b,这里的+两边都有操作数,我们把这种运算符称为:二元运算符

    2. 无论++出现在变量前,还是变量后,执行结束后,都会让变量中的值自加一

      int i = 10;
      i++;
      ++i;
      
    3. 当++出现在变量后:先做赋值运算,后自加1

      int k = 10;
      int f = k++; //先将k中的值赋值给f,后自加1
      System.out.println(k); //11
      System.out.println(f); //10
      
    4. 当++出现在变量前:先做自加1运算,然后再做赋值运算

      int e = 100;
      int x = ++k; //e先自加1,后赋值给x
      System.out.println(e); //101
      System.out.println(x); //101
      
      //注意!!!
      int y = 100;
      System.out.println(y++); //100
      System.out.println(y); //101
      
      //根据源码, y++ 传给了源码中的x
      //实现原理:int x = y++
      //public void println(int x){
      
      int z = 100;
      System.out.println(++z); //101
      
    5. 练习题

      1. 经典面试题(实际开发中用不上)
      public class OpeartorHomework03{
          public static void mian(String[] args){
              int i = 10;
              i = i++;
              System.out.println(i); //10
          }
      }
      
      1. 从键盘上接收一个整数三位数,请分别输出它的个位、十位、百位

        public class OperatorHomework04{
            public static void main(String[] args){
                java.util.Scanner scanner = new java.util.Scanner(System.in);
                System.out.print("请输入一个三位数:");
                int num = Scanner.nextInt();
                
                System.out.println("个位:" + num % 10);
                System.out.println("十位:" + num / 10 % 10);
                System.out.println("百位:" + num / 100);
            }
        }
        
      2. 681分钟是多少个小时+多少分钟

        int total = 681;
        int h = 681 / 60;
        int m = 681 % 60;
        

(补充)栈数据结构(Stack)

在这里插入图片描述

  • 栈结构特点:
    • 先进后出
    • 后进先出
  • 相关术语
    • 入栈、压栈、push
    • 出栈、弹栈、pop
    • 栈帧
    • 栈顶、栈底

(补充)字节码解读

  • 查看以下程序的字节码,命令是:

    javap -c ReadClass01.class
    
  • 举个例子:

    public class ReadClass01{
        public static void main(String[] args){
            int i = 10;
        }
    }
    
    //字节码文件
    Compiled from "ReadClass01.java"
    public class ReadClass01 {
      public ReadClass01();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: bipush        10
           2: istore_1
           3: return
    }
    
    1. 在Java语言中,任何一个方法执行时,都会专门为这个方法分配所属的内存空间。供这个方法使用。每个方法都有自己独立的内存空间,这个内存空间中有两块比较重要的内存空间:

      一块叫做:局部变量表(存储局部变量的)

      另一块叫做:操作数栈(存储程序运行过程中参与运算的数据)

    2. 重点要解读的字节码是

      bipush 10 :将10这个字面量压入操作数栈当中
      istore_1 :将操作数栈顶元素弹出,然后将其存储到局部变量表的1号槽位上。

在这里插入图片描述

  • 例2

    public class ReadClass02{
        public static void main(String[] args){
            int i = 10;
            int j = i;
        }
    }
    
Compiled from "ReadClass02.java"
public class ReadClass02 {
  public ReadClass02();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: bipush        10
       2: istore_1
       3: iload_1
       4: istore_2
       5: return
}

​ iload_1 :将局部变量表1号槽位上的数据复制一份,压入操作数栈
​ istore_2 :将操作数栈元素弹出,存储到局部变量表的2号槽位上

在这里插入图片描述

  • 例3

    public class ReadClass03{
        public static void main(String[] args){
            int i = 10;
            int j = i;
            j++;
        }
    }
    
    Compiled from "ReadClass03.java"
    public class ReadClass03 {
      public ReadClass03();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: bipush        10
           2: istore_1
           3: iload_1
           4: istore_2
           5: iinc          2, 1
           8: return
    }
    

    iinc 2, 1 :将局部变量表2号槽位上的值加1

    在这里插入图片描述

  • 例4

    public class ReadClass04{
        public static void main(String[] args){
            int i = 10;
            int j = ++i;
        }
    }
    
    /*
    Compiled from "ReadClass04.java"
    public class ReadClass04 {
      public ReadClass04();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: bipush        10
           2: istore_1
           3: iinc          1, 1
           6: iload_1
           7: istore_2
           8: return
    }
    */
    
    class ReadClass05{
        public static void main(String[] args){
            int i = 10;
            int j = i++;
        }
    }
    
    /*
    class ReadClass05 {
      ReadClass05();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: bipush        10
           2: istore_1
           3: iload_1
           4: iinc          1, 1
           7: istore_2
           8: return
    }
    */
    

关系运算符(又叫比较运算符)

  • 包括:>、>=、<、<=、==、!=
  • 所有关系运算符的运算结果都是布尔型,不是true,就是false

逻辑运算符

  1. 包括:

    & 逻辑与(并且):全真才为真 5 > 1 & 5 >4 true

    | 逻辑或(或者):有一真结果即为true

    ^ 逻辑异或:左右不一样,结果就是true(true+false)

    ! 逻辑非:结果取反(!false = true)

    && 短路与(并且):和逻辑与运算结果相同,只不过存在短路现象。效率比&更高,大多数情况下使用&&(左边是false时发生短路现象)

    int x = 99;
    int y = 100;
    System.out.println(x > y & x > ++y); //不管左边是真是假,右边一定会执行
    System.out.println("y = " + y); //101
    
    int x = 99;
    int y = 100;
    System.out.println(x > y && x > ++y); //左边即可判断出值,右边不执行
    System.out.println("y = " + y); //100
    

    || 短路或(或者):原理与&&相同(左边是true时发生短路现象),优先使用||

  2. 特点:逻辑运算符两边操作数要求是布尔类型

    并且最终运算结果也是一个布尔类型

public class OperatorTest04{
    public static void main(String[] args){
        int a = 100;
        int b = 99;
        
        System.out.println(a > b & a > ++b); //false
    }
}

按位运算符(操作的都是补码)

注意:按位运算符的操作数要求必须是整数,否则会出现编译错误

左移 <<
  1. 将二进制数左移n位,相当于将数值乘于2的n次方

  2. 左移运算符不会改变操作数的符号。左移后,右补0

  3. 左移运算符会对溢出进行截断

  4. 注意:任何位运算符,操作的都是补码

    在这里插入图片描述

/*
原码:			00000000 00000000 00000000 00000001
反码:			00000000 00000000 00000000 00000001
补码:         00000000 00000000 00000000 00000001
左移3位: (000)00000 00000000 00000000 00000001000 (补码)
*/
int a = 1;
System.out.println(a << 3); //8 (1 * 2的3次方)

/*
原码:			00000000 00000000 00000000 10000000
反码:			00000000 00000000 00000000 10000000
补码:         00000000 00000000 00000000 10000000
左移2位    (00)00000000 00000000 00000100 00000000
*/
int b =128;
System.out.println(b << 2); //128 * 2^2 = 512

/*
原码:		10000000 00000000 00000000 01100100
反码:		11111111 11111111 11111111 10011011
补码:		11111111 11111111 11111111 10011100
左移2位:	111111 11111111 11111111 1001110000(补码)
左移后的原码:100000 00000000 00000000 0110010000 (-400 = -100 * 2^2)
*/
int c = -100;
System.out.println(c << 2);
//经典面试题:怎么让2快速变成8?
int x = 2;
System.out.println(x << 2);
右移 >>
  1. 将二进制数右移n位,相当于将数值除以2的n次方

  2. 右移运算符对正数、负数和0的处理方式不同

    对于正数,符号位不变,右移时左补0

    对于负数,符号位不变,右移时左补1

    对于0,右移运算符操作后结果仍为0

  3. 右移运算符会对溢出进行截断

    /*
    原码:		00000000 00000000 00000000 00000001
    反码:		00000000 00000000 00000000 00000001
    补码:		00000000 00000000 00000000 00000001
    右移1位:	00000000 00000000 00000000 00000000
    */
    int a = 1;
    System.out.println(a >> 1); //0
    
    /*
    原码:		00000000 00000000 00000000 10000000
    反码:		00000000 00000000 00000000 10000000
    补码:		00000000 00000000 00000000 10000000
    右移4位:	00000000 00000000 00000000 00001000
    */
    int b = 128;
    System.out.println(b >> 4); //8
    
    /*
    原码:		10000000 00000000 00000000 10000000
    反码:		11111111 11111111 11111111 01111111
    补码:		11111111 11111111 11111111 10000000
    右移4位:	111111111111 11111111 11111111 1000
    右移后原码: 100000000000 00000000 00000000 1000(取反再加1)
    */
    int b = -128;
    System.out.println(b >> 4); //-8
    
无符号右移 >>>
  1. 溢出后的截断。

  2. 无符号右移之后,最终的结果一定是0或者正整数。

  3. 无符号右移之后,左侧补0.(不管是正数还是负数,都是补0)

    public class OperatorTest07{
    	public static void main(String[] args){
    		
    		/*
    			原码:10000000
    			反码:11111111
    			补码: 10000000
    			      00100000(无符号右移2位)
    		*/
    		byte b = -128;
    		
    		/*
    			为什么输出结果不是32?
    				b >>> 2。
    				byte和int混合运算。会先将byte转换成int,再做运算。
    			
    			int b = -128;
    			原码:10000000 00000000 00000000 10000000
    			反码:11111111 11111111 11111111 01111111
    			补码:11111111 11111111 11111111 10000000
    			右移:0011111111 11111111 11111111 100000(补码)
    		*/
    		System.out.println(b >>> 2); // 1073741792
    
    		System.out.println(0b00111111111111111111111111100000); // 1073741792
    
    		// 11100000(补码)
    		// 10100000(原码)
    		System.out.println((byte)(b >>> 2)); // -32
    
    		/*
    			原码:10000000 00000000 00000000 01011010
    			反码:11111111 11111111 11111111 10100101
    			补码:11111111 11111111 11111111 10100110
    			右移:00011111111 11111111 11111111 10100
    		*/
    		int x = -90;
    		System.out.println(x >>> 3);
    		System.out.println(0b00011111111111111111111111110100);
    
    		/*
    			00000000 00000000 00000000 01011010
    			00000000000 00000000 00000000 01011
    		*/
    		int y = 90;
    		System.out.println(y >>> 3); // 11
    	}
    }
    
按位与 & (区别逻辑运算符的方式:逻辑运算符左右两边都是布尔型,但是按位运算符是整数)
  • 运行机制(有一个1结果才为1)

    1 & 1 --> 1

    1 & 0 --> 0

    0 & 1 --> 0

    0 & 0 --> 0

public class OperatorTest08{
    public static void main(String[] args){
        // 00100011
        int a = 35;
        // 00011010
        int b = 26;
        /*
        	00100011
        &	00011010
        ---------------
        	00000010
        */
        System.out.println(a & b); // 2
        
        
        /*
        	怎么判断一个数字是否为奇数?
        	法1:对2取模,结果!=0,为奇数
        	法2:与1按位与,结果是1,为奇数(只有第一位是奇数1)
        */
        int num = 35;
        /*
        	00100011
        &	00000001
        ----------------
        	00000001
        */
        if((num & 1) == 1){		//注意运算符优先级问题
            System.out.println(num + "是奇数");
        }
    }
}
按位或 |
  • 运行机制:都为0才为0,否则结果为1

    1 | 0 : 1

    0 | 1 : 1

    1 | 1 : 1

    0 | 0 : 0

    // 00100011
    int a = 35;
    // 00011011
    int b = 27;
    /*
    	00100011
    |	00011011
    --------------
    	00111011
    */
    System.out.println(a | b); //59
    
  • 具体应用:设置标志位

    将0这个数字的二进制位低位第4个二进制位设置为1

    int flag = 0;
    flag = flag | (1 << 3);
    System.out.println(flag); // 8
    
按位异或 ^
  • 操作机制:不同为1,相同为0

    1 ^ 1 : 0

    0 ^ 0 : 0

    1 ^ 0 : 1

    0 ^ 1 : 1

  • 具体应用:按位异或运算符具有自反性(加密解密)

    ​ a ^ b ^ b ==> a

//00001010
int a = 10;
//00000011
int b = 3;
/*
	00001010
^	00000011
--------------
	00001001
*/
System.out.println(a ^ b); // 9

/*
	00001001
^	00000011
--------------
	00001010
*/
System.out.println(a ^ b ^ b); // 10
int data = 2147483647; //原始数据
//对以上的data进行加密
//秘钥(私人的,只有我知道这个钥匙)
int key = 483;

//加密
int password = data ^ key;
System.out.println(password); //2147483164

//解密
int num = password ^ key;
System.out.println(a ^ b ^ b); //2147483647
按位取反 ~
  • 运行机制

    ~1 : 0

    ~0 : 1

    // 00000000 00000000 00000000 00001010
    int a = 10;
    
    // 11111111 11111111 11111111 11110101(补码)
    // 10000000 00000000 00000000 00001011(原码)-11
    System.out.println(~a); // -11
    
  • 具体应用:位清除操作,将某个二进制位清0

int value = 0b1111111111; //将低位第4个清0
int flag = (1 << 3);

// 00000000 00000000 00000000 00001000
// 11111111 11111111 11111111 11110111
//&00000000 00000000 00000011 11111111
//--------------------------------------
// 00000000 00000000 00000011 11110111
value = value & (~flag);
System.out.println(value);

赋值运算符

  • 基本的赋值运算符:

    =

  • 扩展的赋值运算符:(不能使用空格)

    +=

    -=

    *=

    /=

    以下的很少用:>>=、<<=、>>>=、&=、|=、^=、~=

    //基本的赋值运算符
    int i = 10;
    i = 20; //重新赋值
    
    //+=累加
    int k = 100;
    k += 200; //300。等同于k = k + 200;
    
    int x = 10;
    x *= 3; // 30
    
    x = 10;
    x /= 3; // 3
    
    x = 10;
    x %= 3; // 1
    
    x -= 100; // -99
    
  • 扩展类的赋值运算符都会自动强转(看原来的类型)

    对于扩展的赋值运算符来说,永远都不会改变运算结果类型,哪怕精度损失

    byte m = 10;
    //错误:不兼容的类型
    m = m + 10;
    
    m += 20; //底层实际上对应的是:m = (byte)(m + 100);
    

条件运算符

语法格式

布尔表达式 ? 表达式1 : 表达式2

运算原理

​ 为true执行1,false执行2

注意:常见的错误

10;

‘男’;

……都不是Java语句

sex ? '男' : '女'; //编译不通过

System.out.println(sex ? '男' : '女'); //可以通过

char c1 = sex ? '男' : "女"; //类型不兼容,c1是char,不能接收String

char c = sex ? '男' : '女'; //可以通过

System.out.println(sex ? '男' : "女"); //可以通过,println可以输出任何类型 
//使用三目运算符筛选两个数字中较大的
int a = 100;
int b = 200;
System.out.println(a > b ? a : b);

运算符作业题

  1. 编写 Java 代码,输入一个半径值,计算圆的面积和周长,并输出结果。注意:圆的面积公式为 π * r * r,周长公式为 2 * π * r,其中 π 取 3.14

    public class Test01{
        public static void main(String[] args){
            java.util.Scanner s = new java.util.Scanner(System.in);
            System.out.println("请输入一个半径值:");
            int r = s.nextInt();
            
            System.out.println("圆的面积为:" + (3.14 * r * r));
            System.out.println("圆的周长为:" + (2 * 3.14 * r));
            
        }
    }
    
  2. 假设变量 a、b、c 分别为 6、9、10,请编写 Java 代码输出它们的最大值

    public class Test02{
        public static void main(String[] args){
            int a = 6;
            int b = 9;
            int c = 10;
            
            int d = a > b ? a : b;
            int e = d > c ? d : c;
            //法2:int max = a > b ? (a > c ? a : c) : (b > c ? b : c);
            System.out.println(e);
        }
    }
    
  3. 假设变量 n 为整数,请编写 Java 代码判断它是不是一个偶数

    public class Test03{
        public static void main(String[] args){
            java.util.Scanner s = new java.util.Scanner(System.in);
            System.out.println("请输入一个整数:");
            int n = s.nextInt();
            System.out.println(((n & 1) == 1) ? n + "不是偶数" : n + "是偶数"); 
        }
    }
    
  4. 编写 Java 代码,输入三个整数,分别判断第一个数是否大于 0,第二个数是否小于 10,第三个数是否是偶数。如果都满足条件,则输出“三个条件都满足”,否则输出“不满足所有条件”

    public class Test04{
        public static void main(String[] args){
            java.util.Scanner s = new java.util.Scanner(System.in);
            System.out.println("请输入3个整数:");
            int a = s.nextInt();
            int b = s.nextInt();
            int c = s.nextInt();
            System.out.println(((a > 0) && (b < 10) && (c & 1 == 0)) ? "三个条件都满足" : "不满足所有条件");
        }
    }
    
  5. 编写 Java 代码,输入一个年份,判断它是否是闰年。若该年份能被 4 整除且不能被 100 整除,或者能被 400 整除,则该年份为闰年。输出结果为“该年是闰年”或“该年不是闰年”

    public class Test05{
        public static void main(String[] args){
            java.util.Scanner s = new java.util.Scanner(System.in);
            System.out.println("请输入一个年份:");
            int year = s.nextInt();
            System.out.println(((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)) ? "改年是闰年" : "该年不是闰年");
        }
    }
    

补充:接收用户键盘输入(暂时死记硬背,四个方法)

public class KeyInput{
    public static void main(String[] args){
        
        //创建一个键盘扫描器对象
        //以下代码中s是变量名,也可以叫做键盘扫描器
        java.util.Scanner s = new java.util.Scanner(System.in);
        
        System.out.println("请输入一个数字:");
        //程序执行到这里就会停下来,键盘输入、回车后继续运行
        //nextInt()方法只能接收整数数字,输入其他的字符串会报错
        int num = s.nextInt();
        System.out.println("您输入的数字是:" + num);
        
        System.out.println("请输入一个浮点型数据:");
        double num2 = s.nextDouble(); //浮点型数据的接收
        System.out.println("您输入的浮点型数据是:" + num2);
        
        System.out.println("请输入一个字符串:");
        //从键盘上接收一个字符串,但是接收的是第一个空格之前的内容
        //输入jackson,输出jackson。输入jack son,输出jack。
        String username = s.next(); 
        System.out.println("您输入的字符串是:" + username);
        
        System.out.println("请输入一个字符串:");
        //从键盘上接收一个字符串,但是接收的是第一个换行符(\n)之前的内容。(接收一行)
        s.nextLine(); //第一次调用这个方法,读取缓存中的回车符(\r)
        String name = s.nextline();
        System.out.println("您输入的字符串是:" + name);
    }
}
//求和运算
public class Compute{
    public static void main(String[] args){
        //创建键盘扫描器对象
        java.util.Scanner s = new java.util.Scanner(System.in);
        
        //输出欢迎信息
        System.out.println("欢迎使用计算器1.0版本!我现在只能帮你进行加法运算");
        System.out.println("请输入第一个数字:");
        int num1 = s.nextInt();
        
        System.out.println("请输入第二个数字:");
        int num2 = s.nextInt();
        
        int result = num1 + num2;
        System.out.println("num1 + "+" + num2 "=" + result");
    }
}
  • 第二种写法

    import java.util.Scanner;
    punlic class KeyInput{
        Scanner s = new Scanner(System.in);
        int a = s.nextInt();
    }
    

控制语句

分支语句

if语句
  • 第一种写法

    if(布尔表达式){

    ​ 分支语句;

    }

    注意:如果分支中只有一条Java语句,大括号可以省略

    • 例子

    1.编写一个程序,输入一个人的年龄age,如果他的年龄大于等于18岁,则输出"你已经成年了",否则不输出任何东西。

    import java.util.Scanner;
    public class IfTest01{
        public static void main(String[] args){
            Scanner s = new Scanner(System.in);
            System.out.println("请输入年龄:");
            int age = s.nextInt();
            if(age > 18){
                System.out.println("你已经成年了");
            }
        }
    }
    

    2.编写一个程序,输入一个学生的分数score(百分制),如果学生的分数大于等于60,则输出"你已经及格了",否则不输出任何东西。

    import java.util.Scanner;
    public class IfTest02{
        public static void main(String[] args){
            Scanner s = new Scanner(System.in);
            System.out.println("请输入分数:");
            int score = s.nextInt();
            if(score >= 60){
                System.out.println("你已经及格了");
            }
        }
    }
    

    3.编写一个程序,输入一个学生的分数score(百分制),如果学生的分数大于等于60,则输出"你已经及格了",如果学生的分数小于60,则输出“很抱歉,你不及格”。

    import java.util.Scanner;
    public class IfTest03{
        public static void main(String[] args){
            Scanner s = new Scanner(System.in);
            System.out.println("请输入分数:");
            double score = s.nextDouble();
            if(score >= 60){
                System.out.println("你已经及格了");
            }
            if(score < 60){
                System.out.println("很抱歉,你不及格");
            }
        }
    }
    
    //以上程序的效率比较低,判断了两次
    //像这种只有两种情况的,建议使用if else语句
    
  • 第二种写法

    if(布尔表达式){

    ​ 分支1;

    }else{

    ​ 分支2;

    }

    注意:一条语句大括号可以省略

    • 例子

      1. 编写一个程序,输入一个数字num,判断它是否为7的倍数。如果是,则输出"num是7的倍数",否则输出"num不是7的倍数"。

        import java.util.Scanner;
        public class IfTest04{
            public static void main(String[] args){
                Scanner s = new Scanner(System.in);
                System.out.println("请输入一个数字:");
                int num = s.nextInt();
                if(num % 7 == 0){
                    System.out.println(num + "是7的倍数");
                }else{
                    System.out.println(num + "不是7的倍数");
                }
            }
        }
        
      2. 编写一个程序,输入一个数字num,判断它是否同时为3的倍数和5的倍数。如果是,则输出"num既是3的倍数又是5的倍数",否则输出"num不同时是3的倍数和5的倍数"。

        import java.util.Scanner;
        public class IfTest05{
            public static void main(String[] args){
                Scanner s = new Scanner(System.in);
                System.out.println("请输入一个数字:");
                int num = s.nextInt();
                if((num % 3 == 0) && (num % 5 == 0)){
                    System.out.println(num + "既是3的倍数又是5的倍数");
                }else{
                    System.out.println(num + "不同时是3的倍数和5的倍数");
                }
            }
        }
        
      3. 编写程序模拟用户登录,用户名和密码正确则登录成功,反之则登录失败。

        注意:字符串的比较不能使用“==”,必须手动调用equals方法来进行比较(先死记硬背)

        if(name == “admin”){} 这种写法是不专业的,错误的,不建议的。

        应该这样写:

        ​ if(name.equals(“admin”)){}

        import java.util.Scanner;
        public class IfTest06{
            public static void main(String[] args){
                
                Scanner s = new Scanner(System.in);
                
                System.out.println("请输入用户名:");
                String name = s.next();
                
                System.out.println("请输入密码:");
                String passwd = s.next();
                
                if((name.equals("admin")) && (passwd.equals("abc123"))){
                    System.out.println("登录成功。欢迎进入系统," + name);
                }else{
                    System.out.println("用户名不存在或者密码错误,登录失败");
                }
            }
        }
        
  • 第三种写法(从上往下执行,只会执行一个分支,只要遇到true即执行,整个if结束,后面就不执行了

    if(布尔表达式){

    ​ 分支1;

    }else if(布尔表达式){

    ​ 分支2;

    }else if(布尔表达式){

    ​ 分支3;

    }

  • 第四种写法

    if(布尔表达式){

    ​ 分支1;

    }else if(布尔表达式){

    ​ 分支2;

    }else if(布尔表达式){

    ​ 分支3;

    }else{

    ​ 分支4;

    }

    • 例子

      1.编写一个程序,输入一个学生的分数score(百分制),根据成绩的不同输出不同的评价。如果学生的分数大于等于90分,则输出"你的成绩是优秀";如果分数大于等于80分但小于90分,则输出"你的成绩是良好";如果分数大于等于70分但小于80分,则输出"你的成绩是中等";如果分数大于等于60分但小于70分,则输出"你的成绩是及格";否则输出"你的成绩不及格"。

    import java.util.Scanner;
    
    public class IfTest07{
    	public static void main(String[] args){
    		Scanner s = new Scanner(System.in);
    		System.out.print("请输入您的考试成绩:");
    		double score = s.nextDouble();
    		
    		// 百分制(如果输入的成绩小于0,或者大于100,认为不合法的成绩,程序直接退出。)
    		if(score < 0 || score > 100){
    			System.out.println("对不起,您输入的成绩不合法!");
    			// 直接结束当前方法。
    			return;
    		}
    
    		// 程序如果能够执行到这里,说明成绩一定是合法的。
    		
    		if(score >= 90){
    			System.out.println("你的成绩是优秀");
    		}else if(score >= 80 && score < 90){
    			System.out.println("你的成绩是良好");
    		}else if(score >= 70 && score < 80){
    			System.out.println("你的成绩是中等");
    		}else if(score >= 60 && score < 70){
    			System.out.println("你的成绩是及格");
    		}else{
    			System.out.println("你的成绩不及格");
    		}
    		
    
    		// 第一次改进
    		
    		if(score >= 90){
    			System.out.println("你的成绩是优秀");
    		}else if(score >= 80){
    			System.out.println("你的成绩是良好");
    		}else if(score >= 70){
    			System.out.println("你的成绩是中等");
    		}else if(score >= 60){
    			System.out.println("你的成绩是及格");
    		}else{
    			System.out.println("你的成绩不及格");
    		}
    		
    		
    		// 第二次改进
    		String str = "你的成绩不及格";
    
    		if(score >= 90){
    			str = "你的成绩是优秀";
    		}else if(score >= 80){
    			str = "你的成绩是良好";
    		}else if(score >= 70){
    			str = "你的成绩是中等";
    		}else if(score >= 60){
    			str = "你的成绩是及格";
    		}
    
    		System.out.println(str);
    
    	}
    }
    

    2.编写一个程序,输入一个年份year和一个月份month,判断这个月份有多少天。判断方法如下:

    1. 如果month为1、3、5、7、8、10、12中的一个,输出"month有31天";

    2. 如果month为4、6、9、11中的一个,输出"month有30天";

    3. 如果month为2并且year为闰年,输出"month有29天";(如果一个年份能够被4整除但不能被100整除,或者能够被400整除,那么它就是闰年)

    4. 如果month为2并且year不是闰年,输出"month有28天"。

      //我写的
      import java.util.Scanner;
      
      public class IfTest08{
          public static void main(String[] args){
              Scanner s = new Scanner(System.in);
              System.out.println("请输入一个年份:");
              int year = s.nextInt();
              System.out.println("请输入一个月份:");
              int month = s.nextInt();
              
              if(((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))){
                  if(month == 2){
                      System.out.println(month + "有29天");
                  }else{
                      System.out.println(month + "有28天");
                  }
              }else{
                  if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12){
                  System.out.println(month + "有31天");
              }else if(month == 4 || month == 6 || month == 9 || month == 11){
                  System.out.println(month + "有30天");
              }
              }   
          } 
      }
      
      //老杜写的
      import java.util.Scanner;
      
      public class IfTest07{
      	public static void main(String[] args){
      		Scanner s = new Scanner(System.in);
      
      		System.out.println("请告诉我一个年份,以及一个月份,我可以告诉你这一年的这个月有多少天。");
      
      		System.out.print("请输入年份:");
      		int year = s.nextInt();
      
      		System.out.print("请输入月份:");
      		int month = s.nextInt();
      		
      		if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12){
      			System.out.println(year + "年" + month + "月有31天");
      		}else if(month == 4 || month == 6 || month == 9 || month == 11){
      			System.out.println(year + "年" + month + "月有30天");
      		}else{
      			// 程序执行到这里,月份一定是2月。
      			// if语句嵌套是可以的。
      			if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
      				System.out.println(year + "年" + month + "月有29天");
      			}else{
      				System.out.println(year + "年" + month + "月有28天");
      			}
      		}
      
  • if语句的使用注意事项:

    1. 对于任何一个if语句来说,最多只能有一个分支执行。
    2. 分支中如果只有一条Java语句,大括号可以省略。
    3. 对于以上第2种和第4种,这两种写法是可以保证一定会有一个分支执行的。因为这两种写法都有else分支。
    4. 对于以上第1种和第3种,这两种写法可能会没有分支执行。在if选择结构中还可以嵌套别的选择结构或循环结构。
switch语句
  • 完整格式

    在这里插入图片描述

    1. expression是一个表达式,执行完之后是一个值(int、枚举、String这三种类型)

      当然,也可以把byte short char 放进去,会进行自动类型转换(char可以通过ASCII码转成int)

    2. value也是int、枚举、String三种类型,判断expression是否与value相等

    3. default可以不写,不是必须的,建议写上,这样程序更加健壮

    4. break; 语句只要执行,switch就会结束

      /*
      switch语句的完整格式:
      	switch(表达式){
      	case 值1:
      		分支1;
      		break;
      	case 值2:
      		分支2;
      		break;
      	case 值3:
      		分支3;
      		break;
      	case 值4:
      		分支4;
      		break;
      	default:
      		默认分支;
      	}
      
      1. 表达式最后执行完是一个值,这个值要求类型是:int,枚举类型,字符串类型。
      	当然,也可以直接把byte short char放进去,会进行自动类型转换。
      
      2. default语句不是必须的。建议写上,这样程序更加健壮。
      
      3. break;语句只要执行,switch语句就会结束。
      */
      import java.util.Scanner;
      
      public class SwitchTest01{
      	public static void main(String[] args){
      		
      		// 编译报错,long类型是不允许的。
      		/*
      		long x = 100L;
      		switch(x){}
      		*/
      
      		// 修改
      		
      		long x = 100L;
      		switch((int)x){}
      		
      		
      		// byte可以自动转换成int类型。
      		byte b = 1;
      		switch(b){}
      
      		short s = 1;
      		switch(s){}
      
      		char c = 'a';
      		switch(c){}
      
      		//String season = "春季";
      		//switch(season){}
      		
      		// 不支持boolean类型。
      		/*
      		boolean sex = true;
      		switch(sex){}
      		*/
      
      		//编写一个程序,根据输入的月份,输出该月份所属的季节
      		// 3 4 5 春季
      		// 6 7 8 夏季
      		// 9 10 11 秋季
      		// 12 1 2 冬季
      		Scanner scanner = new Scanner(System.in);
      
      		System.out.print("请输入月份:");
      
      		int month = scanner.nextInt();
      		
      		switch(month){
      		case 3:
      			System.out.println("春季");
      			break;
      		case 4:
      			System.out.println("春季");
      			break;
      		case 5:
      			System.out.println("春季");
      			break;
      		case 6:
      			System.out.println("夏季");
      			break;
      		case 7:
      			System.out.println("夏季");
      			break;
      		case 8:
      			System.out.println("夏季");
      			break;
      		case 9:
      			System.out.println("秋季");
      			break;
      		case 10:
      			System.out.println("秋季");
      			break;
      		case 11:
      			System.out.println("秋季");
      			break;
      		case 12:
      			System.out.println("冬季");
      			break;
      		case 1:
      			System.out.println("冬季");
      			break;
      		case 2:
      			System.out.println("冬季");
      			break;
      		}
      		
      
      		//case是可以合并的。
      		
      		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;
      		}
      		
      		
      		
      		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;
      		default:
      			System.out.println("您输入的月份不存在!");
      		}
      		
      		
      		// break;语句缺少的话,可能会发生case穿透现象。
      		switch(month){
      		case 3: case 4: case 5:
      			System.out.println("春季!");
      		case 6: case 7: case 8:
      			System.out.println("夏季!");
      		case 9: case 10: case 11:
      			System.out.println("秋季!");
      			break;
      		case 12: case 1: case 2:
      			System.out.println("冬季!");
      			break;
      		default:
      			System.out.println("您输入的月份不存在!");
      		}
      
      		
      		String season = "您输入的月份不存在!";
      		switch(month){
      		case 3: case 4: case 5:
      			season = "春季!";
      			break;
      		case 6: case 7: case 8:
      			season = "夏季!";
      			break;
      		case 9: case 10: case 11:
      			season = "秋季!";
      			break;
      		case 12: case 1: case 2:
      			season = "冬季!";
      			break;
      		}
      		System.out.println(season);
      		
      
      		// 请在控制台接收输入:A B C D
      		// 当A时,输出优秀
      		// 当B时,输出良好
      		// 当C时,输出及格
      		// 当D时,输出不及格
      		System.out.print("请输入等级:");
      		int grade = scanner.nextInt();
      
      		char ccc = 'A';
      
      		// case后面只能是字面量这样的值,不能使用变量。
      		switch(grade){
      		case 'A':
      		//case ccc: 
      			System.out.println("优秀");
      			break;
      		case 'B':
      			System.out.println("良好");
      			break;
      		case 'C':
      			System.out.println("及格");
      			break;
      		case 'D':
      			System.out.println("不及格");
      			break;
      		default:
      			System.out.println("您输入的有误!");
      		}
      
      	}
      }
      
      /*
      编写一个程序,根据输入的运算符符号,输出两个数的运算结果。
      例如输入符号为“+”,则输出两个数的和;输入符号为“-”,则输出两个数的差,以此类推
      */
      import java.util.Scanner;
      
      public class SwitchTest02{
      	public static void main(String[] args){
      		System.out.println("欢迎使用简易版的计算器。");
      		Scanner s = new Scanner(System.in);
      		System.out.print("请输入第一个数字:");
      		int num1 = s.nextInt();
      		System.out.print("请输入运算符 + - * / % 中的一个:");
      		String oper = s.next();
      		System.out.print("请输入第二个数字:");
      		int num2 = s.nextInt();
      		int result = 0;
      		switch(oper){
      		case "+":
      			result = num1 + num2;
      			break;
      		case "-":
      			result = num1 - num2;
      			break;
      		case "*":
      			result = num1 * num2;
      			break;
      		case "/":
      			result = num1 / num2;
      			break;
      		case "%":
      			result = num1 % num2;
      			break;
      		default : 
      			System.out.println("不支持此运算!");
      			return;
      		}
      		System.out.println(num1 + oper + num2 + "=" + result);
      	}
      }
      
  • switch语句的小技巧

    /*
    编写一个程序,根据输入的成绩,输出对应的等级。例如
    输入成绩为 90~100,则输出“优秀”;
    输入成绩为 70~89,则输出“良好”,
    输入成绩为 60~69,则输出“及格”,
    输入成绩为 0~59,则输出“不及格”,
    
    必须用switch,不能用if。
    */
    import java.util.Scanner;
    
    public class SwitchTest03{
    	public static void main(String[] args){
    
    		Scanner s = new Scanner(System.in);
    
    		System.out.println("请输入考试成绩:");
    
    		double score = s.nextDouble();
    
    		// 这是一个算法,经过这个算法之后,数就变少了。
    		int grade = (int)(score / 10);
            
            String result = "不及格";
    		switch(grade){
    		case 9:case 10:
    			result = "优秀";
    			break;
    		case 7: case 8:
    			result = "良好";
    			break;
    		case 6:
    			result = "及格";
    			break;
    		}
            System.out.println("result");
    	}
    }
    
  • switch语句使用注意事项:

    1. switch 语句适用于判断固定值。if语句适用于判断范围或区间时使用。switch能做的if肯定能做,if能完成的switch不一定能完成。

    2. JDK7之前,switch只支持int类型、枚举类型,在JDK7之后,增加了对字符串类型的支持。

    3. case 语句中的值必须是字面量,不能是变量。

    4. case 语句中的值必须和switch后面的值是同一类型,或者能够相互转换。

    5. case可以合并

    6. 在每个 case 分支中要加上 break 语句,以避免case穿透现象。

    7. 在 switch 语句中,一般都应该有一个 default 分支,用于处理一些特殊情况,以避免程序出错。 (当然,default语句不写,也不会编译报错。)

    8. switch 语句中的 default 分支可以放在 switch 块的任意位置,但是通常建议将 default 分支放在所有 case 分支的最后面。(可读性好)

  • 例题(月份程序的优化)

    /*
    编写一个程序,输入一个年份year和一个月份month,判断这个月份有多少天。判断方法如下:
    如果month为1、3、5、7、8、10、12中的一个,输出"month有31天";
    如果month为4、6、9、11中的一个,输出"month有30天";
    如果month为2并且year为闰年,输出"month有29天";(如果一个年份能够被4整除但不能被100整除,或者能够被400整除,那么它就是闰年)
    如果month为2并且year不是闰年,输出"month有28天"。
    */
    import java.util.Scanner;
    
    public class IfTest07{
    	public static void main(String[] args){
    		Scanner s = new Scanner(System.in);
    
    		System.out.println("请告诉我一个年份,以及一个月份,我可以告诉你这一年的这个月有多少天。");
    
    		System.out.print("请输入年份:");
    		int year = s.nextInt();
    
    		System.out.print("请输入月份:");
    		int month = s.nextInt();
            
            switch(month){
    		case 1:case 3:case 5:case 7:case 8:case 10:case 12:
    			System.out.println(year + "年" + month + "月有31天");
    			break;
    		case 4:case 6:case 9:case 11:
    			System.out.println(year + "年" + month + "月有30天");
    			break;
    		default:
    			if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
    				System.out.println(year + "年" + month + "月有29天");
    			}else{
    				System.out.println(year + "年" + month + "月有28天");
    			}
    		}
    
  • Java12新特性

    Java12中switch引入了新特性,代码变得更加简洁:

    但是不能新旧混用

    switch(x){
        case 1 -> System.out.println(1); //不需要break了,也不会有穿透现象
        case 2 -> System.out.println(2);
        default -> System.out.println("default");
    }
    
    switch(x){
        case 1, 2, 3 -> System.out.println("123");
    }
    
    switch(x){
        case 1 -> {
            System.out.println(1);
            System.out.println(1);
        } //只有一条Java语句时,大括号可以省略
    }
    

    上述程序的改进:

    import java.util.Scanner;
    
    public class IfTest07{
    	public static void main(String[] args){
    		Scanner s = new Scanner(System.in);
    
    		System.out.println("请告诉我一个年份,以及一个月份,我可以告诉你这一年的这个月有多少天。");
    
    		System.out.print("请输入年份:");
    		int year = s.nextInt();
    
    		System.out.print("请输入月份:");
    		int month = s.nextInt();
    
    		//java12新特性
    		switch(month){
    			case 1,3,5,7,8,10,12 -> System.out.println(year + "年" + month + "月有31天!!!");
    			case 4,6,9,11 -> System.out.println(year + "年" + month + "月有30天!!!");
    			default -> {
    				if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
    					System.out.println(year + "年" + month + "月有29天!!!");
    				}else{
    					System.out.println(year + "年" + month + "月有28天!!!");
    				}
    			}
    		}
    
    	}
    }
    
    

循环语句

当某代码片段需要频繁多次执行时,可以采用循环语句

在这里插入图片描述

在这里插入图片描述

for循环(循环次数固定)
语法结构

for(初始化表达式; 条件表达式; 更新表达式){

​ 循环体;

}

执行原理
  • 初始化表达式:最先执行,并且只执行一次

  • 条件表达式:的执行结果必须是一个布尔类型的值

  • 更新表达式:一般是负责更新某个变量值的(只有更新了某个变量值,条件表达式才有机会变成false,循环终止)

    在这里插入图片描述

注意点
  1. for后面小括号中的三个表达式都不是必须的

    死循环

    for(;😉{

    ​ 循环体;

    }

  2. 可以将括号里面的表达式拿出来,改变作用域

    for(int i = 0; i < 10; i ++){} //循环结束后访问不了i变量
    
    int i = 0; //循环结束后仍然可以访问到i
    for(; i < 10; i ++){}
    
for循环基础练一练
  1. 输出1~10

    public class ForTest01{
        public static void main(String[] args){
            for(int i = 1; i <= 10; i++){
                System.out.println(i);
            }
        }
    }
    
  2. 输出1~100中所有的偶数

    public class ForTest02{
        public static void main(String[] args){
            for(int i = 2; i <= 100; i += 2){
                System.out.println(i);
            }
        }
    }
    
  3. 输出100,97,94,91…1

    public class ForTest03{
        public static void main(String[] args){
            for(int i = 100; i >= 1; i -= 3){
                System.out.println(i);
            }
        }
    }
    
  4. 计算1~100所有奇数的和。

    public class ForTest04{
        public static void main(String[] args){
            int sum = 0;
            for(int i = 1; i <= 100; i += 2){
                sum += i;
            }
            System.out.println(sum);
        }
    }
    
  5. 计算n的阶乘。

    import java.util.Scanner;
    public class ForTest05{
        public static void main(String[] args){
            Scanner s = new Scanner(System.in);
            System.out.println("请输入一个整数:");
            int n = s.nextInt();
            int result = 1;
            for(; n >= 1; n--){
                result *= n;
            }
            System.out.println(result);
        }
    }
    
for循环嵌套

九九乘法表

public class ForTest06{
    public static void main(String[] args){
        for(int i = 1; i <= 9; i++){
            for(int j = 1; j <= i; j++){
                System.out.print(j + "*" + i + "=" + i*j + " ");
            }
            System.out.println(); //换行
        }
    }
}
for循环嵌套练一练
  1. 找出1~1000的所有质数,输出时每8个换一行

    先学会如何判断一个数是否为质数

    两种思想:boolean标记,计数器

    public class ForTest{
        public static void main(String[] args){
            
            //计数器思想。定义一个计数器
            int count = 0;
            
            for(int j = 2; j <= 1000; j++){
                
                int num = j;
                
                //一种思想,boolean标记
                boolean isPrime = true;
                
                //只要判断 num/2 即可,大于 num/2 的数肯定除不尽,最好的方法是num开平方根
                //用math方法开平方根
                for(int i = 2; i <= num/2; i++){
                    if(num % i == 0){
                        isPrime = false;
                    }               
                    }
    				if(isPrime){
                        count++;
                        System.out.println(num + " ");
                        if(count % 8 == 0){
                            System.out.println();
                        /*
                        法二:
                        if(count == 8){
                            System.out.println();
                            count = 0;
                        */
                        }
                }
            }
        }
    }
    
    /*
    输入一个正整数n,计算1-2+3-4+5-6+…-(n-1)+n的和
    */
    public class ForTest08{
    	public static void main(String[] args){
    		
    		int n = 6;
    		int result = 0;
    		for(int i = 1; i <= n; i++){
    			//System.out.println(i);
    			if(i % 2 == 0){
    				result -= i;
    			}else{
    				result += i;
    			}
    		}
    		System.out.println("result = " + result);
    
    	}
    }
    
    /*
    输出1到1000之间既能被5整除又能被3整除的数,并且每行输出5个
    */
    public class ForTest09{
    	public static void main(String[] args){
    
    		int count = 0;
    		for(int i = 1; i <= 1000; i++){
    			if(i % 5 == 0 && i % 3 == 0){
    				System.out.print(i + " ");
    				count++;
    			}
    			if(count == 5){
    				System.out.println();
    				count = 0;
    			}
    		}
    	}
    }
    
    /*
    求100到999之间的水仙花数。水仙花数的每个位上的数字的3次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153)
    */
    public class ForTest10{
    	public static void main(String[] args){
    		for(int i = 100; i <= 999; i++){
    			int num = i;
    			// 判断153这个数字是否为水仙花数
    			int 个位 = num % 10;
    			int 十位 = num / 10 % 10;
    			int 百位 = num / 100;
    			if(个位 * 个位 * 个位 + 十位 * 十位 * 十位 + 百位 * 百位 * 百位 == num){
    				System.out.println(num + "是水仙花数");
    			}	
    		}
    	}
    }
    
    /*
    找1~100之间的质数,并输出两两相邻的质数差值等于 2 的质数对,例如(3,5),(5,7),(11,13),(17,19)等等
    */
    public class ForTest11{
    	public static void main(String[] args){
    
    		for(int j = 2; j <= 98; j++){  //j <= 98 防止溢出问题
    
    			// 判断num是否为质数
    			int num = j;
    			boolean isPrime = true;
    			for(int i = 2; i <= num / 2; i++){
    				if(num % i == 0){
    					isPrime = false;
    				}
    			}
    			
    			if(isPrime){
    				// 如果第一个数字是质数。才有必要继续判断。
    				num += 2;
    				
    				boolean isPrime2 = true;
    				for(int i = 2; i <= num / 2; i++){
    					if(num % i == 0){
    						isPrime2 = false;
    					}
    				}
    
    				if(isPrime2){
    					System.out.println("(" + (num-2) + "," + num + ")");
    				}
    
    			}
    
    		}
    
    	}
    }
    
    /*
    ********
    ********
    ********
    ********
    ********
    
        ********  1-->4
       ********   2-->3
      ********    3-->2
     ********     4-->1
    ********      5-->0
    
        *		 1->4
       ***		 2->3
      *****	     3->2
     *******	 4->1
    *********	 5->0
    
    */
    public class ForTest12{
    	public static void main(String[] args){
    		
    		for(int i = 1; i <= 5; i++){
    			for(int j = 1; j <= 8; j++){
    				System.out.print("*");			
    			}
    			System.out.println();
    		}
    		
    		System.out.println("===================================");
    
    		for(int i = 1; i <= 5; i++){
    			
    			for(int k = 5 - i; k > 0; k--){
    				System.out.print(" ");
    			}
    
    			for(int j = 1; j <= 8; j++){
    				System.out.print("*");			
    			}
    			System.out.println();
    		}
    
    		System.out.println("===================================");
    		
    		int n = 10;
    		for(int i = 1; i <= n; i++){ 
    
    			for(int k = n - i; k > 0; k--){
    				System.out.print(" ");
    			}
    
    			for(int j = 1; j <= i * 2 - 1; j++){
    				System.out.print("*");
    			}
    			System.out.println();
    		}
    
    	}
    }
    
while循环(循环次数不固定)
语法结构

while(布尔表达式){

​ 循环体;

}

循环次数是0~n次(适合循环次数不固定的情况)

public class WhileTest01{
    public static void main(String[] args){
        
        /*
        while(true){
            System.out.println("死循环");
        }
        */
        
        int i = 0;
        while(i < 10){
            System.out.println("i = " + i);
            i++;
        }
        
    }
}

猜数字小游戏

import java.util.Scanner;
import java.util.Random;
public class WhileTest02{
    public static void main(String[] args){
        
        //专门生成随机数的一个类
        Random random = new Random();
        int num = random.nextInt(100) + 1;
        
        Scanner scanner = new Scanner(System.in);
        
        //计数器
        int count = 0;
        
        while(true){
            
            count++;
            
            System.out.println("请输入你猜的数字:");
        
            int guess = scanner.nextInt();

            if(guess == num){
                System.out.println("猜对了!");
                System.out.println("您一共猜了" + count + "次");
                //终止程序执行
                return;
            }else if(guess > num){
                System.out.println("猜大了");
            }else{
                System.out.println("猜小了");
       		}
        }
        
    }
}
do while循环

do{

​ 循环体; //至少循环一次

}while(布尔表达式); //括号里面的变量大括号里面找不到,变量定义一般在外面

/*
求平均数:要求用户输入一组数字,用 -1 表示输入结束,使用 do-while 循环计算这些数字的平均数并输出。
要使用一个计数器来记录输入的数字个数,遇到 -1 则终止输入并计算平均数
*/
import java.util.Scanner;

public class DoWhileTest02{
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		
		/*
		while(true){
			int num = scanner.nextInt();
			System.out.println("您输入的数字是:" + num);
			if(num == -1){
				System.out.println("再见!");
				return;
			}
		}
		*/
		
		// 计数器
		//int count = 0;

		// 求和的结果
		//int sum = 0;
		
		/*
		do{
			count++;
			int num = scanner.nextInt();
			sum += num;
			System.out.println("您输入的数字是:" + num);
			if(num == -1){
				System.out.println("您一共输入了" + (--count) + "个数字");
				int avgValue = (sum + 1) / count;
				System.out.println("平均值是:" + avgValue);
				System.out.println("再见!");
				return;
			}
		}while(true);
		*/
		
        //优化
		// 计数器
		int count = 0;
		// 求和结果
		int sum = 0;
		// 用户输入的数字(默认值是0)
		int num = 0; 
		do{
			sum += num;
			System.out.print("请输入数字:");
			num = scanner.nextInt();
			count++;
		}while(num != -1);

		System.out.println("平均值:" + sum / (--count));
	}
}

跳转语句

break语句
  1. break;语句可以使用在switch当中,终止switch的执行。

  2. break;可以使用在循环中,用来终止循环的执行。
    for
    while
    do while
    这些循环中都可以使用break;

  3. 默认情况下,单独使用“break;”语句,终止的是离它最近的循环。

    public class BreakTest01{
    	public static void main(String[] args){
    		
    		/*
    		for(int i = 1; i <= 10; i++){
    			if(i == 5){
    				break;
    			}
    			System.out.println("i = " + i);
    		}
    		*/
    		
    		/*
    		for(int j = 0; j < 2; j++){
    			for(int i = 1; i <= 10; i++){
    				if(i == 5){
    					break;
    				}
    				System.out.println("i = " + i);
    			}
    		}
    		*/
    
    
    		f1:for(int j = 0; j < 2; j++){
    			f2:for(int i = 1; i <= 10; i++){
    				if(i == 5){
    					break f1;
    				}
    				System.out.println("i = " + i);
    			}
    		}
    
    
    
    
    		System.out.println("Hello World!");
    
    	}
    }
    
continue语句
  1. continue;语句翻译为:继续

  2. 也是使用在循环语句当中。

  3. 作用:终止当前本次循环,直接进入下一次循环继续执行。

    public class ContinueTest01{
    	public static void main(String[] args){
    		
    		/*
    			i = 0
    			i = 1
    			i = 2
    			i = 3
    			i = 4
    		*/
    		for(int i = 0; i < 10; i++){
    			if(i == 5){
    				break;
    			}
    			System.out.println("i = " + i);
    		}
    
    		System.out.println("===================================");
    
    		for(int i = 0; i < 10; i++){
    			if(i == 5){
    				continue;
    			}
    			System.out.println("i = " + i);
    		}
    
    		System.out.println("===================================");
    		
    		f1:for(int j = 0; j < 2; j++){
    			f2:for(int i = 0; i < 10; i++){
    				if(i == 5){
    					continue f1;
    				}
    				System.out.println("i = " + i);
    			}
    		}
    		
    
    
    	}
    }
    

控制语句作业

  1. 请设计一个程序,不断的从键盘上接收一个正整数或者负整数,要求计算所有正整数的和,如果接收到0,则程序退出。

    import java.util.Scanner;
    public class ControlHonework01{
        public static void main(String[] args){
            Scanner s = new Scanner(System.in);
            
            int num = 0;
            int sum = 0;
            
            do{
                System.out.println("请输入一个整数:");
                num = s.nextInt();
                if(num > 0){
                    sum += num;
                }
            }while(num != 0);
            
            System.out.println("sum = " + sum);
        }
    } 
    
  2. 请编写一个程序,打印1~100所有的奇数,但是跳过所有以数字 3 结尾的数字

    public class ControlHomework02{
    	public static void main(String[] args){
    		
    		for(int i = 1; i <= 100; i+=2){
    			if(i % 10 == 3){
    				continue;
    			}
    			System.out.println("i = " + i);
    		}
    
    	}
    }
    
  3. 韩信点兵,三人一组余两人,五人一组余三人,七人一组余四人,请问最少需要多少士兵

    public class ControlHomework03{
    	public static void main(String[] args){
    		
    		int i = 1;
    		
    		/*
    		while(true){
    			i++;
    			if(i % 3 == 2 && i % 5 == 3 && i % 7 == 4){
    				System.out.println("至少" + i + "个士兵");
    				break;
    			}
    		}
    		*/
    
    		while(!(i % 3 == 2 && i % 5 == 3 && i % 7 == 4)){
    			i++;
    		}
    		System.out.println("至少" + i + "个士兵");
    	}
    }
    

方法(重要,在C语言里面叫函数)

方法的本质就是一段可以被重复利用的代码片段,并且每一个方法都是一个独立的封装好的功能。

​ 方法只定义,不去调用,是不会执行的。
​ 方法要执行的话,肯定是有一个位置调用了这个方法。

	public class MethodTest01{

	// 入口
	public static void main(String[] args){
		// 调用sum方法,完成求和功能。
		// 请编写程序计算100和200的和。
		sum(100, 200); // 方法的调用。

		// 请编写程序计算666和888的和。
		sum(666, 888); // 方法的调用。

		// 请编写程序计算123和456的和。
		sum(123, 456); // 方法的调用。
	}


	// 单独定义一个方法,这个方法完成一个具体的功能。求和功能。
	// 方法的定义。
	public static void sum(int a, int b){
		int c = a + b;
		System.out.println(a + "+" + b + "=" + c);
	}
}

方法的定义与调用

  • 方法的定义

    1. 语法格式:

      [修饰符列表] 返回值类型 方法名(形式参数列表){

      ​ 方法体;

      }

    2. 修饰符列表:目前统一写 public static

    3. 返回值类型:

      可以是java语言中任何一种数据类型,可以是基本数据类型,也可以是应用数据类型

      例如:byte short int long float double boolean char String…

      如果方法执行结束后没有返回任何数据给调用者,返回值类型写 void(main方法的调用者是jvm,不要返回任何数据给jvm)

      切记:不能空着不写

      ​ 例如:返回值类型是int表示:方法结束的时候会返回一个整数给调用者。
      ​ 返回值类型是String表示:方法结束的时候会返回一个字符串给调用者。
      ​ 返回值类型是void表示:方法结束的时候不返回任何数据给调用者。

    4. 当返回值类型不是void的时候,方法在结束的时候必须使用“return 值;”语句来完成数据的返回。

    5. return语句有两种写法:
      第一种:return 值;
      第二种:return;
      不管是哪一种,只要return语句执行,方法必然结束。

    6. 当返回值类型是void的时候:
      不能编写"return 值;" 这样的语句。
      但是可以编写"return;"语句,主要是用来终止方法的执行。也可以不编写“return;”,这个要看具体的业务。

    7. 当调用一个返回值类型不是void的方法时,方法结束的时候会返回值,这个值可以采用变量接收。注意变量的类型。
      变量的类型一定要和返回值类型一致。或者能够自动类型转换,或者强制类型转换。

    8. 方法执行结束有返回值,但是对于调用者来说,可以选择接收,也可以选择不接收。

    9. 方法名:只要是合法的标识符即可。首字母小写,后面每个单词首字母大写。(一般方法都是一个行为,所以方法名一般都是动词。)
      方法名最好是反映了这个方法所实现的功能。
      deleteUser
      saveUser
      login
      logout

    10. 形式参数列表一般简称为:形参。形参个数是:0-N个。多个的话,使用逗号隔开。

      形参是局部变量。形参中起决定性作用的是:形参的类型。形参名随意。

    11. 方法体:任何一个方法都有一个方法体。方法体用大括号括起来:
      在大括号中编写“java语句;”
      并且方法体中的代码有执行顺序,遵循自上而下。

  • 方法的调用

    当这个方法修饰符列表有static关键字的时候:
    调用的语法格式:
    类名.方法名(实际参数列表);

    实际参数列表简称为:实参。

    实参和形参列表必须一一对应:
    类型要一一对应。
    个数要一一对应。

    public class MethodTest03{
    	public static void main(String[] args){
    
    		// 调用方法
    		int result = add(1, 2);
    		System.out.println(result);
    		
    		// 这个过程就存在自动类型转换。
    		long result2 = add(200, 300);
    		System.out.println(result2);
    		
    		// concat方法结束后返回的是String值,必须使用String类型变量接收这个值。
    		String content = concat("hello,", "jack");
    		System.out.println(content);
    
    		add(1111, 2222);
    
    		// 错误
    		//add(false, 1);
    		
    		// 错误
    		//add(1);
    
    		// 用完整语法调用一次方法。
    		String retValue = MethodTest03.concat("abc", "def");
    		System.out.println(retValue);
    	}
    
    	// 求和的一个方法。
    	public static int add(int a, int b){
    		System.out.println("add..........");
    		//int z = x + y;
    		//return z;
    		return a + b;
    	}
    
    	public static String concat(String x, String y){
    		//String z = x + y;
    		//return z;
    		return x + y;
    	}
    // 报错原因:因为返回值类型是int,那么结束时就必须要返回一个整数。但是没有写 return 返回语句来完成数据的返回
    	/*
    	public static int sum(int a, int b){
    	
    	}
    	*/
    
    	// 解决错误:添加了返回语句。
    	public static int sum(int a, int b){
    		//int c = a + b;
    		//return c;
    		return 0;
    	}
    
    	public static boolean m1(){
    		// 不兼容的类型: int无法转换为boolean
    		//return 1;
    
    		// 修改
    		return true;
    	}
    	
    	// 缺少返回语句
    	/*
    	public static String m2(){
    		
    	}
    	*/
    
    	// 修改
    	public static String m2(){
    		return "say hello";
    	}
    
    	public static void m3(){
    	
    	}
    	
    	// 编译报错:言行不一。
    	/*
    	public static void m4(){
    		return 100;
    	}
    	*/
    
    //作用:整个方法结束
    	public static void m5(){
    		return;
    	}
    		
    	// 缺少返回值
    	/*
    	public static int m6(){
    		return;
    	}
    	*/
    }
    
  • 调用方法时,类名. 什么时候可以省略

    调用者和被调用者在同一个类中时,可以省略

    public class MethodTest04{
    	public static void main(String[] args){
    		// 调用方法m1
    		MethodTest04.m1();
    
    		// 省略 类名.
    		m1();
    
    		// 调用m2方法
    		A.m2();
    
    		// 编译报错。
    		//m2();
    	}
    
    	public static void m1(){
    		System.out.println("m1方法执行了");
    	}
    }
    
    class A{
    	public static void m2(){
    		System.out.println("m2方法执行了");
    	}
    }
    
  • 常见的错误

    public class MethodTest05{
    
    	// 缺少返回语句
        //return 1; 可能不执行
    	/*
    	public static int m1(){
    		int i = 100;
    		if(i > 99){
    			return 1;
    		}
    	}
    	*/
    	
    	// 可以
    	/*
    	public static int m1(){
    		int i = 100;
    		if(i > 99){
    			return 1;
    		}else{
    			return 0;
    		}
    	}
    	*/
    
        //在同一个域中:return语句后面的代码是无法执行的。请不要写。
    	public static int m1(){
    		int i = 100;
    		if(i > 99){
    			System.out.println("位置1");
    			return 1;
    			//错误:无法访问的语句
    			//System.out.println("位置2");
    		}
    		System.out.println("位置3");
    		return 0;
    		//错误:无法访问的语句
    		//System.out.println("位置4");
    	}
    }
    

判断质数的方法

找出1-100所有的质数。请使用方法。

public class MethodTest06{
    public static void main(String[] args){
        for(int i = 2; i <= 100; i++){
            if(isPrime(i)){
                System.out.println(i);
            }
        }  
    }
    
    public static boolean isPrime(int num){
        for(int i = 2; i <= num / 2; i++){
            if(num % i == 0){
                return false;
            }
        }
        return true;
    }
}

实现登录的方法

系统可以接收用户名和密码,判断用户名和密码,如果用户名是admin,密码是123,则登录成功。

如果用户名或密码不对,请继续让用户输入用户名和密码,直到登录成功。

import java.util.Scanner;
public class MethodTest07{
    public static void main(String[] args){
        login();
    }
    
    public static void login(){
        Scanner s = new Scanner(System.in);
        
        while(true){
            System.out.print("请输入用户名:");
       		String username = s.next();
        
        	System.out.print("请输入密码:");
        	String password = s.next();
            
            if((check(username,password))){
                System.out.println("账号名或密码不正确,请重新输入!");
            }else{
                System.out.println("登录成功!");
            }
    }
    
    public static boolean check(String username, String password){
        //后面这里链接数据库
        return (username.equals("admin") && password.equals("123"));
    }
} 

方法执行时内存的变化

  1. 方法如果只定义,不掉用,是不会分配内存空间的。(从Java8开始,方法的字节码指令存储在元空间metaspace当中。元空间使用的是本地内存。)
  2. 方法调用的瞬间,会在jvm的栈内存当中分配活动场所,此时发生压栈操作。
  3. 方法一旦结束,给该方法分配的内存空间就会释放。此时发生弹栈动作。
public class MethodTest08{
	public static void main(String[] args){
		System.out.println("main begin");
		m1();
		System.out.println("main over");
	}
	
	public static void m1(){
		System.out.println("m1 begin");
		m2();
		System.out.println("m1 over");
	}

	public static void m2(){
		System.out.println("m2 begin");
		m3();
		System.out.println("m2 over");
	}

	public static void m3(){
		System.out.println("m3 begin");
		System.out.println("m3 over");
	}
}

/*
main begin
m1 begin
m2 begin
m3 begin
m3 over
m2 over
m1 over
main over
*/

在这里插入图片描述

方法重载机制(overload)

方法重载是编译阶段的机制,在编译阶段已经确定要用哪个方法了

  • 当前代码先不使用方法重载

​ 缺点:1.代码不美观
2.不方便调用,程序员需要记忆很多方法名

public class OverloadTest01{
    public static void main(String[] args){
        //调用方法
        sumInt(10, 20);
        sumLong(10L, 20L);
        sumDouble(3.0, 2.0);
    }
    
    public static void sumInt(int a, int b){
        int c = a + b;
        System.out.println(a + "+" + b + "=" + c);
    }
    
    public static void sumLong(long a, long b){
        long c = a + b;
        System.out.println(a + "+" + b + "=" + c);
    }
    
    public static void sumDouble(double a, double b){
        double c = a + b;
        System.out.println(a + "+" + b + "=" + c);
    }
}
  • 在java语言中,允许在一个类中定义多个方法,这些方法的名字可以一致(全部变成sum)
public class OverloadTest02{
    public static void main(String[] args){
        //调用方法
        sum(10, 20);
        sum(10L, 20L);
        sum(3.0, 2.0);
    }
    
    public static void sum(int a, int b){
        int c = a + b;
        System.out.println(a + "+" + b + "=" + c);
    }
    
    public static void sum(long a, long b){
        long c = a + b;
        System.out.println(a + "+" + b + "=" + c);
    }
    
    public static void sum(double a, double b){
        double c = a + b;
        System.out.println(a + "+" + b + "=" + c);
    }
}
  • 构成条件:

    1. 在同一个类中

    2. 方法名一致

    3. 形式参数(跟变量名无关)列表不同(类型、顺序、个数不同)

      public class OverloadTest03{
          public static void main(String[] args){
              m1();
              m1("abc");
              
              m2(10, 20);
              m2(10L, 20L);
              
              m3("x", 10);
              m3(10,"x");
          }
          //构成方法重载
          //形参的个数不同
      	public static void m1(){}
      	public static void m1(String s){}
          
          //形参的类型不同
          public static void m2(int a, int b){}
          public static void m2(long a, long b){}
          
          //形参的顺序不同
          public static void m3(String s, int a){}
          public static void m3(int a, String s){}
          
          //以下两种未够成,是一样的方法,编译报错
          /*
          public static void doSome(int a, int b){}
          public static void doSome(int x, int y){}
          */
      }
      
  • 什么时候使用?

    在以后的开发中,在一个类中,功能类似的情况下,建议将方法类似的方法名定义成一样。

  • 实例(println)

    System.out.println();
    

    这个println方法是PrintStream类中的方法

    在java.io.PrintStream类中有很多println方法,这些方法都已经构成了方法的重载

方法的递归调用

  1. 什么事方法的递归调用?

    方法自己调用自己

    public class RecursionTest01{
        public static void main(String[] args){
            recursion();
        }
        
        public static void recursion(){
            System.out.println("recursion begin");
            recursion();
            System.out.println("recursion over");
        }
    }
    
  2. 以上程序一直在压栈,不会弹栈,会导致栈内存溢出错误

    java.lang.StackOverflowError

  3. 所有的递归调用必须要有结束条件

    也有可能在结束条件执行之前就出现栈内存溢出错误,递归太深,栈内存不够

  4. 原则:能用循环解决的尽量不要用递归调用

  5. 在实际开发中,如果因为递归调用发生了栈内存溢出错误,如何解决?

    首先可以调整栈内存的大小,扩大栈内存。

    如果扩大之后运行一段时间还是出现了栈内存溢出错误,可能是因为递归结束条件不对,需要进行代码的修改。

  6. 举个栗子(以及内存图):

    先不使用递归调用,计算1~n的和

    public class RecursionTest02{
        public static void main(String[] args){
            int n = 5;
            System.out.println(sum(n));
        }
        
        //计算1~n的和
        public static int sum(int n){
            int sum = 0;
            for(int i = 1; i <= n; i++){
                sum += i;
            }
            return sum;
        }
    }
    

    使用递归调用:

    public class RecursionTest03{
        public static void main(String[] args){
            int n = 5;
            System.out.println(sum(n));
        }
        
        //计算1~n的和
        public static int sum(int n){
            if(n == 1){
                return 1;
            }
            return n + sum(n - 1);
        }
    }
    

    在这里插入图片描述

    使用递归计算n的阶乘

    public class RecursionTest04{
        public static void main(String[] args){
            int n = 5;
            System.out.println(jieCheng(n));
        }
        
        public static int jieCheng(int n){
            if(n == 1){
                return 1;
            }
            return n * jiecheng(n - 1);
        }
    }
    

    斐波那契数列

    假如有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长大后到第3个月后每个月又生一对兔子,假如兔子都不死,请问第n个月后的兔子有多少对。

    如下规律:

    当前数字 = 前两个相邻数字之和

    当月兔子总数 = 上个月兔子总数 + 上上个月兔子总数

    1

    1

    2

    3

    5

    8

    13

    21

    34

    55

    89

    144 12月时兔子总对数

    public class Rabbit{
        public static void main(String[] args){
            int n = 12;
            System.out.println(n + "月得时候兔子总数:" + rabbit(n));
        }
        
        public static int rabbit(int n){
            if(n == 1 || n == 2){
                //递归的结束条件
                return 1;
            }
            return rabbit(n - 2) + rabbit(n - 1);
        }
    }
    

    在这里插入图片描述

package和import

package包机制

  1. 包机制作用:便于代码管理。

  2. 怎么定义包:在java源码第一行编写 package 语句。注意:package语句只能出现在java代码第一行。

    ​ package 包名;

  3. 如果带包编译:(也可以不带包编译,可以编译之后手动创建目录)

    语法:javac -d 编译后的存放目录 java源文件路径

    package com;
    public class PackageTest01{}
    

    以上程序的带包编译

    javac -d . PackageTest01.java //编译。在当前路径下生成com文件夹,里面是class文件
    
  4. 有了包机制后,完整类名是包含包名的,运行的时候一定要加上包名。例如类名是:com.powernode.javase.chapter02.PackageTest

    java com.powernode.javase.chapter02.PackageTest

    java com.PackageTest01 //运行
    
  5. 包名的命名规范:

    1. 包名命名规范中要求是全部小写。
    2. 包名命名规范:公司域名倒序 + 项目名 + 模块名 + 功能名。例如:com.powernode.oa.empgt.service
package com;
public class PackageTest01{		//类名为:com.PackageTest01,放在com文件夹下
    public static void main(String[] args){
        System.out.println("Java语言中的包机制!");
    }
}

import语句详解

  1. import语句只能出现在package和class定义之间

  2. import语句可以编写多个

  3. 什么时候使用import语句?

    A类中使用B类,当A和B类不在同一个包下。并且B类也不属于java.lang包,必须使用import导入

  4. import语句可以模糊导入:

    import java.util.Scanner;

    import java.util.*;

    不能这样:import *; *是类名

  5. import静态导入(不常用):

    import static java.lang.System.*;	//将System类中的所有静态变量和静态方法全部导入
    import static java.lang.Math.*;
    
    out.println("1");
    abs("-110");	//求绝对值
    
package com;

//导入其他类
import com.powernode.oa.empgt.service.UserService;

public class PackageTest01{
    public static void main(String[] args){
        System.out.println("Java语言中的包机制!");
        
        com.PackageTest03.doSome();
        
        //在同一个com包下面,可以不加com
        PackageTest03.doSome();
        
        com.powernode.oa.empgt.service.UserService.delUser();
        
        //使用import导入以后
        UserService.delUser();
        
        //java.long.String name = "jackson";
        String name = "jackson";
    }
}

Intellij IDEA 的使用

IDEA工具的安装

下载地址

如何新建空工程

如何设置JDK以及编译器版本

如何新建模块

如何新建包,新建类

如何运行Java程序

如何设置字体大小

常用的IDEA快捷操作(包括以上所有问题)

  1. alt+insert(新建/新增任何东西)
  2. 退出任何窗口:ESC
  3. 编写源码的窗口最大化:ctrl+shift+F12
  4. psvm生成main方法
  5. 快速生成输出语句:sout
  6. IDEA会自动保存,自动编译
  7. 打开Project窗口:alt+1
  8. 查找某个类:敲两次shift,选择classes,输入类名
  9. 切换选项卡:alt + 左右方向键
  10. 自动生成变量:变量.var
  11. 删除一行:ctrl+y
  12. 复制一行:ctrl+d
  13. 在一个类当中查找方法:ctrl+F12
  14. 生成for循环:fori
  15. 自动生成if语句.if
  16. 单行注释:ctrl + /
  17. 多行注释:ctrl + shift + /
  18. 查看源码:按ctrl别松手,鼠标移动到对应的类名下方,出现下划线,点击过去,可以查看类源码。
  19. 多行编辑:按alt别松手,鼠标拖动多行,完成多行编辑。
  20. 怎么快速生成创建对象语句:类名.new.var
  21. 怎么快速生成if语句:布尔类型值.if
  22. 怎么快速生成setter和getter方法:alt + insert,然后选择setter and getter生成。
  23. 怎么快速生成构造方法:alt + insert,然后选择Constructor。
  24. 在IDEA当中如何自动纠错:将光标移动到错误的位置,按atl + enter。会有提示,根据提示进行纠错。
  25. 移动代码到上一行:alt + shift + 上/下方向
  26. 怎么快速重写方法?alt + insert,选择Override…
  27. 怎么快速重写方法?ctrl + o
  28. 快速向下转型,并同时生成变量名:变量名.castvar
  29. 快速查看方法的参数:ctrl + p
  30. 返回上一步:ctrl + alt + 左方向键。 下一步:ctrl + alt + 右方向键。
  31. 代码格式化:ctrl + alt + L。
  32. 查看继承结构:ctrl + H
  33. 自动代码包裹:ctrl + alt + t
  • 10
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谢氏理综集团

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值