java学习

MarkDown

标题

三级标题

四级标题

字体

hello,World!

hello,World!

hello,World!

hello,World!

引用

shiyimuya学java

分割线



图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JXWnOjJs-1651326229913)(F:\322861.jpg)]

超链接

点击跳转到博客

列表

  1. zzw
  2. ywr
  3. zzw

(-加回车)

  • zzw
  • ywr
  • zzw

表格

名字性别生日

代码

(```)


计算机

计算机硬件组成

  • CPU
  • 主板
  • 内存
  • 电源,主机箱
  • 硬盘
  • 显卡
  • 鼠标,键盘
  • 显示器
  • 等…

计算机软件

  • 计算机软件可以使用计算机按照事先预定好的顺序完成特定的功能
  • 计算机软件按照其功能划分为系统软件和应用软件

系统软件

DOS(Disk Operating System),Windows,Linux,Unix,Mac,Android,iOS

应用软件

WPS,QQ,微信,英雄联盟,绝地求生等

打开CMD的方式

打开方法

  • 开始+系统+命令提示符
  • win+R 输入cmd
  • 资源管理器的地址栏上输入cmd

管理员方式运行

选择以管理员方式运行

常用Dos命令

#盘符切换  磁盘名:
#查看当前目录下的所有文件  dir
#切换目录 cd /d 磁盘名:
#cd ..
#清楚屏幕 cls (clear screen)
#退出终端 exit
#查看电脑的ip ipconfig
#打开计算器  calc       打开画图工具  mspaint     打开记事本  notepad
#ping命令 
    ping www.baidu.com
#文件操作
   md  目录名
   rd  目录名
   cd>  文件名
   del  文件名

C和C++

C

  • 贴近硬件,运行极快,效率极高
  • 操作系统,编译器,数据库,网络系统等
  • 指针和内存管理

C++

  • 面向对象
  • 兼容C
  • 图形领域,游戏等

java特性和优势

特性

  1. 简单性
  2. 面向对象
  3. 可移植性
  4. 高性能
  5. 分布式
  6. 动态性
  7. 多线程
  8. 安全性
  9. 健壮性

java三大版本

javaSE javaME javaEE

JDK,JRE,JVM

Java Development Kit : java开发者工具

Java Runtime Environment: java运行时环境

Java Virtual Machine: java虚拟机

jvm可以用软件实现,也可以用硬件实现

HelloWorld

  1. 随便新建一个文件夹,存放代码
  2. 新建一个Java文件

​ 1) 文件后缀名为.java

​ 2) hello.java

  1. 编写代码
public class Hello{
    public static void main(String[] args){
        System.out.print("Hello,World!");
    }
}
  1. 编译javac java文件,会生成一个class文件

  2. 运行class文件,java class文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gpx51m3z-1651326248393)(C:\Users\ywrdsg\AppData\Roaming\Typora\typora-user-images\image-20220425215620604.png)]

    可能会遇到的情况

    1. 每个单词的大小写不能出现问题,java是大小写敏感的
    2. 尽量使用英文
    3. 文件名 和 类名必须保持一致,并且首字母要大写
    4. 符号使用了中文

Idea写HelloWorld

helloworld

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello,World!");
    }
}

关于java类,方法,对象,封装,多态,继承的扩展举例讲解

类:狗这类动物
方法:狗会吠 ,狗会摇尾巴 等等
对象:某一条狗
封装:你只需知道狗会吠就好,无需知道它为什么可以吠,喉咙和舌头怎么运作也不需要知道
继承:狗类继承自犬类,狼类继承自犬类,他们都吃肉,都能跑,这些都是犬类的方法
多态:虽然狼和狗都继承自犬类,但狗类实现了听主人话接口接口,狼类实现了嗷嗷叫接口接口,所以他们就呈现出多态。
https://blog.csdn.net/qq_60750453/article/details/120829332

第一章 Java基础语法

1.1 注释

单行注释

// xxxxxxxxxxxxxxx

多行注释

/*
这是多行注释
这是多行注释
这是多行注释
*/

文档注释

/**
         * JavaDoc:文档注释
         */
        /**
         * @Description HelloWorld
         * @Author ywr学Java
         */
public class HelloWorld {
    public static void main(String[] args) {
        //单行注释
        //输出一个Hello,World!
        System.out.println("Hello,World!");

        //有趣的代码注释
        /**
         *               ii.                                         ;9ABH,          
         *              SA391,                                    .r9GG35&G          
         *              &#ii13Gh;                               i3X31i;:,rB1         
         *              iMs,:,i5895,                         .5G91:,:;:s1:8A         
         *               33::::,,;5G5,                     ,58Si,,:::,sHX;iH1        
         *                Sr.,:;rs13BBX35hh11511h5Shhh5S3GAXS:.,,::,,1AG3i,GG        
         *                .G51S511sr;;iiiishS8G89Shsrrsh59S;.,,,,,..5A85Si,h8        
         *               :SB9s:,............................,,,.,,,SASh53h,1G.       
         *            .r18S;..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,....,,.1H315199,rX,       
         *          ;S89s,..,,,,,,,,,,,,,,,,,,,,,,,....,,.......,,,;r1ShS8,;Xi       
         *        i55s:.........,,,,,,,,,,,,,,,,.,,,......,.....,,....r9&5.:X1       
         *       59;.....,.     .,,,,,,,,,,,...        .............,..:1;.:&s       
         *      s8,..;53S5S3s.   .,,,,,,,.,..      i15S5h1:.........,,,..,,:99       
         *      93.:39s:rSGB@A;  ..,,,,.....    .SG3hhh9G&BGi..,,,,,,,,,,,,.,83      
         *      G5.G8  9#@@@@@X. .,,,,,,.....  iA9,.S&B###@@Mr...,,,,,,,,..,.;Xh     
         *      Gs.X8 S@@@@@@@B:..,,,,,,,,,,. rA1 ,A@@@@@@@@@H:........,,,,,,.iX:    
         *     ;9. ,8A#@@@@@@#5,.,,,,,,,,,... 9A. 8@@@@@@@@@@M;    ....,,,,,,,,S8    
         *     X3    iS8XAHH8s.,,,,,,,,,,...,..58hH@@@@@@@@@Hs       ...,,,,,,,:Gs   
         *    r8,        ,,,...,,,,,,,,,,.....  ,h8XABMMHX3r.          .,,,,,,,.rX:  
         *   :9, .    .:,..,:;;;::,.,,,,,..          .,,.               ..,,,,,,.59  
         *  .Si      ,:.i8HBMMMMMB&5,....                    .            .,,,,,.sMr
         *  SS       :: h@@@@@@@@@@#; .                     ...  .         ..,,,,iM5
         *  91  .    ;:.,1&@@@@@@MXs.                            .          .,,:,:&S
         *  hS ....  .:;,,,i3MMS1;..,..... .  .     ...                     ..,:,.99
         *  ,8; ..... .,:,..,8Ms:;,,,...                                     .,::.83
         *   s&: ....  .sS553B@@HX3s;,.    .,;13h.                            .:::&1
         *    SXr  .  ...;s3G99XA&X88Shss11155hi.                             ,;:h&,
         *     iH8:  . ..   ,;iiii;,::,,,,,.                                 .;irHA  
         *      ,8X5;   .     .......                                       ,;iihS8Gi
         *         1831,                                                 .,;irrrrrs&@
         *           ;5A8r.                                            .:;iiiiirrss1H
         *             :X@H3s.......                                .,:;iii;iiiiirsrh
         *              r#h:;,...,,.. .,,:;;;;;:::,...              .:;;;;;;iiiirrss1
         *             ,M8 ..,....,.....,,::::::,,...         .     .,;;;iiiiiirss11h
         *             8B;.,,,,,,,.,.....          .           ..   .:;;;;iirrsss111h
         *            i@5,:::,,,,,,,,.... .                   . .:::;;;;;irrrss111111
         *            9Bi,:,,,,......                        ..r91;;;;;iirrsss1ss1111
         */
       

        /*
          多行注释,可以注释多行文字
         */
        /*
        这是多行注释
        这是多行注释
        这是多行注释
         */

        /**
         * JavaDoc:文档注释
         */
        /**
         * @Description HelloWorld
         * @Author ywr学Java
         */
    }
}

1.2 标识符

关键字

  • 所有的标识符都应该是以字母(A-Z或者a-z),美元符($),或者下划线(_)开始
  • 首字母之后可以是字母(A-Z或者a-z),美元符($),或者下划线(_)或数字的任意字符组合
  • 不能使用关键字作为变量名或者方法名
  • 标识符是大小写敏感
  • 合法标识符举例:age,$salary,_value,__1_value
  • 非法标识符举例:123abc,-salary,#abc
public class Demo01 {
    public static void main(String[] args) {

        //不规范
        String 王者荣耀 = "最强王者";
        System.out.println(王者荣耀);

        //大小写敏感
        String Man = "ywr";
        String man = "ywr";

        String Ahello = "ywr";
        String hello = "ywr";
        String $hello = "ywr";
        String _hello = "ywr";

        String _1 = "ywr";

    }
}

*数据类型

  • 强类型语言

    要求变量的使用严格符合规定,所有变量都必须要先定义后才能使用

  • Java的数据类型分为两大类

    • 基本类型(primitive type)

      • 数值类型
        • 整数类型:byte(1个字节),short(2个字节),int(4个字节),long(8个字节)
        • 浮点类型:float(4个字节),double(8个字节)
        • 字符类型:char(2个字节)
      • boolean类型(1位)
      public class Demo02 {
          public static void main(String[] args) {
              //八大基本类型
              
              //整型
              int num1 = 10;//最常用
              byte num2 = 20;
              short num3 = 30;
              long num4 = 30L;//Long类型要在数字后加上L
              
              //小数:浮点数
              float num5 = 50.6f;
              double num6 = 3.141592653589793238462643;
              
              //字符
              char name = '国';
              //字符串,String不是关键字,是类
              //String names = "ywr";
              
              //布尔值:是非
              boolean flag = true;
      //        boolean flag = false;
          }
      }
      
    • 引用类型(reference type)

      • 接口
      • 数组

什么是字节

  • 位(bit):是计算机内部数据储存的最小单位,11001100是一个八位二进制数

  • 字节(byte):是计算机中数据处理的基本单位,习惯上用大写B来表示

  • 1B(byte,字节) = 8bit(位)

  • 字符:是指计算机使用的字母,数字,字和符号

  • 1bit表示1位

  • 1Byte表示一个字节 1B=8b

  • 1024B=1KB

  • 1024KB=1M

  • 1024M=1G

1.3 *拓展

整数拓展
/**
 * 整数拓展   进制   二进制0b     八进制0      十进制       十六进制0x
 */
int i1 = 10;
int i2 = 010;//八进制0
int i3 = 0x10;//十六进制0x     0~9 A~F

System.out.println(i1);
System.out.println(i2);
System.out.println(i3);
浮点数拓展
/**
 * 浮点数拓展? 银行业务怎么表示?钱
 */
//BigDecimal   数学工具类
//float  有限的,离散的,舍入误差,大约的,接近但不等于
//double
/**
 * 最好完全避免使用浮点数进行比较
 * 最好完全避免使用浮点数进行比较
 * 最好完全避免使用浮点数进行比较
 */
float f = 0.1f;//0.1
double d = 1.0 / 10;//0.1
System.out.println(f == d);//false

float d1 = 232323233f;
float d2 = d1 + 1;
System.out.println(d1 == d2);//true
字符拓展
char c1 = 'A';
char c2 = '中';

System.out.println(c1);
System.out.println((int) c1);//强制转换
System.out.println(c2);
System.out.println((int) c2);//强制转换

//所有的字符本质还是数字
//编码  Unicode 表:(a = 97  A = 65)  2字节      65536   2的16次方

char c3 = '\u0061';
System.out.println(c3);
转义字符
/**
 * \t  制表符
 * \n  换行
 * 等等
 */
System.out.println("Hello\tWorld");
System.out.println("Hello\nWorld");
关于String
String sa = new String("Hello,World");
String sb = new String("Hello,World");
System.out.println(sa == sb);//false

String sc = "Hello,World";
String sd = "Hello,World";
System.out.println(sc == sd);//true
//对象 从内存分析
布尔值拓展
boolean flag = true;
if (flag==true){}//新手写法
if(flag){}//老手写法
//Less is More! 代码要精简易读

1.4 类型转换

由于Java是强类型语言,所以要进行有些运算时,需要用到类型转换

低 ----------------------------------> 高

byte,short,char -> int -> long -> float -> double

运算中,不同类型的数据先转换为同一类型,然后进行运算

  • 强制类型转换

    • 高 --> 低

      int i = 128;
      byte b = (byte) i;//内存溢出
      
  • 自动类型转化

    • 低 --> 高

      int i2 = 128;
      double b2 = i2;
      

*注意

  • 不能对布尔值进行转换
  • 不能把对象类型转换为不相干的类型
  • 在把高容量转换到低容量的时候,强制转换
  • 转换的时候可能存在内存溢出,或者精度问题
        //操作比较大的数的时候,注意溢出问题
        //JDK新特性,数字之间可以用下划线分割
        int money = 10_0000_0000;
//        System.out.println(money);
        int years = 20;
        int total = money * years;
        System.out.println(total);//-1474836480 ,计算的时候溢出了
        long total2 = money * years;
        System.out.println(total2);// 默认是int,转换之前已经存在问题?

        long total3 = money * ((long) years);
        System.out.println(total3);

        //L   l
    }

1.5 变量

  • 变量是什么:就是可以变化的量!

  • Java是一种强类型语言,每个变量都必须声明其类型

  • Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域

*注意事项

  • 每个变量都有类型,类型可以是基本类型,也可以是引用类型
  • 变量名必须是合法的标识符
  • 变量声明是一条完整的语句,因此每一个声明都必须以分号结束

变量作用域

类变量

要加关键字static

实例变量

实例变量:从属于对象,如果不初始化值,这个值这个类型的默认值 0 0.0

布尔值默认值false,除了基本类型,其余的默认值都是null

局部变量

写在方法里面的,必须声明和初始化值

public class Demo08 {

    //类变量 static
    static double salary = 2500;

    //属性:变量

    //实例变量:从属于对象,如果不初始化值,这个值这个类型的默认值  0  0.0
    //布尔值默认值false
    //除了基本类型,其余的默认值都是null
    String name;
    int age;

    //main方法
    public static void main(String[] args) {

        //局部变量:必须声明和初始化值
        int i = 10;
        System.out.println(i);

        //变量类型 变量名字 = new Demo08();
        Demo08 demo08 = new Demo08();
        System.out.println(demo08.name);
        System.out.println(demo08.age);
        
        //类变量输出
        System.out.println(salary);
    }

    //其他方法
    public void add() {

    }
}

常量

  • 常量(Constant):初始化(initialize)后不能再改变值!不会变动的值

  • 所谓常量可以理解成一种特殊的变量,他的值被设定后,在程序运行过程中不允许被改变

    final 常量名 =;
    final double PI = 3.14;
    
  • 常量名一般使用大写字符

变量的命名规范

  • 所有变量,方法,类名:见名知意
  • 类成员变量:首字母小写和驼峰原则“monthSalary
  • 局部变量:首字母小写和驼峰原则
  • 常量:大写字母和下划线:MAX_VALUE
  • 类名:首字母大写和驼峰原则:Man,GoodMan
  • 方法名:首字母小写和驼峰原则:run(),runRun()

1.6 运算符

Java语言支持的运算符

  • 算数运算符:+, -, *, /, %(模运算), ++, –
  • 赋值运算符: =
  • 关系运算符:>, <, >=, <=, ==, !=, instanceof
  • 逻辑运算符:&&, ||, !
  • 位运算符:&,| , ^, ~, >>, <<, >>>
  • 条件运算符 : (? :)
  • 扩展赋值运算符:+=, -=, *=, /=
一元运算符
  • a++:先使用a,再给a+1

  • ++a:先给a+1,再使用a

public class Demo04 {
    public static void main(String[] args) {
        //一元运算符
        //++   --   自增,自减
        int a = 3;
        int b = a++;   //先给b赋值,再自增
        //a++  a = a + 1
        System.out.println(a);
        int c = ++a;   //先自增,再给b赋值

        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
}
逻辑运算符
  • &&:逻辑与运算:两个变量都为true,结果才为true

    对于&&运算,如果左边为false,则右边不会执行直接输出结果false(短路运算)

  • ||:逻辑或运算:两个变量有一个为true,结果为true

  • !:如果是true,结果则为false;如果为false,结果则为true

//逻辑运算符
public class Demo05 {
    public static void main(String[] args) {
        // 与  或   非
        boolean a = true;
        boolean b = false;
        System.out.println("a && b:" + (a && b));//逻辑与运算:两个变量都为true,结果才为true
        System.out.println("(a || b):" + (a || b));//逻辑或运算:两个变量有一个为true,结果为true
        System.out.println("!(a && b):" + !(a && b));//如果是true,结果则为false;如果为false,结果则为true

        //短路运算    对于&&运算,如果左边为false,则右边不会执行直接输出结果false
        int c = 5;
        boolean d = (c < 4) && (c++ < 4);
        System.out.println(c);
        System.out.println(d);
    }
}
位运算符
           A = 0011 1100
           B = 0000 1101
          ----------------
          A&B  0000 1100      如果都为1,结果为1
          A|B  0011 1101      只要有一个1,结果就为1
          A^B  0011 0001      两个相同为0,不同为1
          ~B   1111 0010      取反
         
          2*8怎么运算最快    2*2*2*2
          效率极高!!!
          <<   *2
          >>   /2
         
           0000 0000     0
           0000 0001     1
           0000 0010     2
           0000 0011     3
           0000 0100     4
           0000 1000     8
           0001 0000     16

扩展运算符

public class Demo07 {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;

        a += b;// a = a + b
        a -= b;// a = a - b
        System.out.println(a);

        //字符串连接符   +
        System.out.println(a + b);
        System.out.println("赵紫薇" + a + b);
        System.out.println(a + b + "赵紫薇");
    }
}
面试题:
  • 字符串拼接:碰到String类型就会拼接成String类型
    • (“赵紫薇” + a + b):赵紫薇1020
    • (a + b + “赵紫薇”):30赵紫薇
  • 由于代码是从左往右运行的,所以上面的先运行字符串,后面的所有结果都以字符串拼接,但是下面是先运行a+b,再与字符串进行拼接
三元运算符
public class Demo08 {
    public static void main(String[] args) {
        //三元运算符
        //x ? y : z
        //如果x==true,结果为y,反正结果为z
        //int score = 80;
        int score = 50;
        String type = score < 60 ? "不及格" : "及格";
        System.out.println(type);
    }
}

运算符优先级

  • 记忆方法:单目乘除为关系,逻辑三目后赋值

  • 单目运算符:一次作用一个变量的运算符,又叫一元运算符

  • 单目:单目运算符+ –(正负数) ,++ –,!(逻辑非),~(按位取反)

  • 乘除:算数运算符:* / % + - (* / %优先级肯定是大于±的)

  • 为:位运算符:~(按位取反)<<(左移) >>(右移),^(也可以位运算,二进制异或)

  • 关系:关系运算符:> < >= <= == !=

  • 逻辑:逻辑运算符(除!)&& || & | ^

  • 三目:条件运算符A > B ? X : Y

  • 后:无意义,仅仅为了凑字数

  • 赋值:= += -= *= /= %= |= &= ^=

1.7 包机制

  • 为了更好的组织类,Java提供了包机制,用于区别类名的命名空间

  • 包语句的语法格式为:

    package pkg1[.pkg2[.pkg3…]];

  • 一般利用公司域名倒置作为包名;
  • 为了能够使用某一包的成员,我们需要在Java程序中明确导入该包,使用"import"语句可完成此项目

    import package[.package2…].(classname|*);

1.8 JavaDoc

https://www.matools.com/api/java8

  • javadoc命令是用来生成自己的API文档
  • 参数信息
    • @author 作者名
    • @version 版本号
    • @since 指明需要最早使用的jdk版本
    • @param 参数名
    • @return 返回值情况
    • @throws 异常抛出情况

在这里插入图片描述

如何用idea生成JavaDoc文档

  1. 在这里插入图片描述

  2. 在这里插入图片描述

可以看这个链接https://blog.csdn.net/weixin_42140580/article/details/89635775

第二章 Java流程控制

2.1 Scanner对象

  • Java给我们提供了这样一个工具类,我们可以获取用户的输入。java.util.Scanner是Java5的新特征,我们可以通过Scanner类来获取用户的输入。

  • 基本语法:

    Scanner s = new Scanner(System.in);

  • 通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前,我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据。

  1. next()

    1. 一定要读取到有效字符后才可以结束输入
    1. 对输入有效字符之前遇到的空白,next()方法会自动将其去掉
    1. 输入有效字符后,next()方法会将其后面输入的空白作为分隔符或者结束符
    1. next()不能得到带有空格的字符串
public class Demo01 {
    public static void main(String[] args) {
        //创建一个扫描器对象,用于接收键盘数据
        Scanner scanner = new Scanner(System.in);

        System.out.println("使用next方法接收:");

        //判断用户有没有输入字符串
        if (scanner.hasNext()) {
            //使用next方法接收
            String str = scanner.next();//程序会等待用户输入完毕
            System.out.println("输出的内容为:" + str);
        }

        //凡是属于IO流的类如果不关闭会一直被占用资源,要养成好习惯用完就关闭
        scanner.close();
    }
}

在这里插入图片描述

  1. nextLine()

    1. 以Enter为结束符,也就是说nextLine()方法放回的是输入回车之前的所有字符
    1. 可以获得空白
public class Demo02 {
    public static void main(String[] args) {
        //创建一个扫描器对象,用于接收键盘数据
        Scanner scanner = new Scanner(System.in);

        System.out.println("使用nextLine方法接收:");

        //判断是否还有输入
        if (scanner.hasNextLine()) {
            //使用nextLine方法接收
            String str = scanner.nextLine();
            System.out.println("输出的内容为:" + str);
        }
        scanner.close();
    }
}

在这里插入图片描述

public class Demo03 {
    public static void main(String[] args) {
        //接收键盘数据
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入数据:");

        String str = scanner.nextLine();
        
        System.out.println("输出的内容为:" + str);
        scanner.close();
    }
}

在这里插入图片描述

  1. 判断输出数字的类型
public class Demo04 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        //从键盘接收数据
        int i = 0;
        float f = 0.1f;

        System.out.println("请输入整数:");

        //如果--那么
        if (scanner.hasNextInt()) {
            i = scanner.nextInt();
            System.out.println("整数数据:" + i);
        } else {
            System.out.println("输入的不是整数数据!");
        }

        System.out.println("请输入小数:");

        //如果--那么
        if (scanner.hasNextFloat()) {
            f = scanner.nextFloat();
            System.out.println("小数数据:" + f);
        } else {
            System.out.println("输入的不是小数数据!");
        }

        scanner.close();
    }
}

在这里插入图片描述

  1. 输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束并输出执行结果
public class Demo05 {
    public static void main(String[] args) {
        //我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束并输出执行结果

        Scanner scanner = new Scanner(System.in);

        //和
        double sum = 0;
        //计算输入了多少个数字
        int m = 0;

        //通过循环判断是否还有输入,并在里面对每一次进行求和和统计
        while (scanner.hasNextDouble()) {
            double x = scanner.nextDouble();
            m = m + 1;
            sum = sum + x;
            System.out.println("你输入了第" + m + "个数据,总和sum = " + sum);
        }

        System.out.println(m + "个数的和为" + sum);
        System.out.println(m + "个数的平均值为" + (sum / m));

        scanner.close();
    }
}

在这里插入图片描述

2.2 顺序结构

  • Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。
  • 顺序结构是最简单的算法结构
  • 语句与语句之间,框与框之间是按照从上到下的顺序进行的,他是由若干个依次执行的处理步骤组成的,他是任何一个算法都离不开的一种基本算法结构。

2.3 选择结构

  • if单选择结构

  • if双选择结构

  • if多选择结构

  • 嵌套的if结构

  • switch多选择结构

if单选择结构

  • 很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示

  • 语法:

    if(布尔表达式){
        //如果布尔表达式为true将执行的语句
    }
    

public class IfDemo01 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入内容:");
        String s = scanner.nextLine();

        //equals:判断字符串是否相等
        if (s.equals("Hello")) {
            System.out.println(s);
        }
        System.out.println("End!");

        scanner.close();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wg41oiyf-1662112709430)(C:\Users\ywrdsg\AppData\Roaming\Typora\typora-user-images\image-20220430220649606.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dSrcmG4S-1662112709437)(C:\Users\ywrdsg\AppData\Roaming\Typora\typora-user-images\image-20220430220712663.png)]

if双选择结构

语法:

if(布尔表达式){
    //如果布尔表达式的值为true
}else{
    //如果布尔表达式的值为false
}

在这里插入图片描述

public class IfDemo02 {
    public static void main(String[] args) {
        //考试分数大于60就是及格,小于60就是不及格

        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入成绩:");
        int score = scanner.nextInt();

        if (score >= 60) {
            System.out.println("及格");
        } else {
            System.out.println("不及格");
        }

        scanner.close();
    }
}

aaa

if多选择结构

语法:

if(布尔表达式 1){
    //如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
    //如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
    //如果布尔表达式 3的值为true执行代码
}else{
    //如果以上布尔表达式都不为true执行代码
}

在这里插入图片描述

public class IfDemo03 {
    public static void main(String[] args) {
        //成绩评级

        Scanner scanner = new Scanner(System.in);

        /**
         * if语句至多有一个else语句,else语句在所有的else if语句之后
         * if语句可以有若干个else if语句,他们必须在else语句之前
         * 一旦其中一个else if语句检测为true,其他else if以及else语句都将跳过执行
         */
        
        System.out.println("请输入成绩:");
        int score = scanner.nextInt();

        if (score <= 100 && score >= 90) {
            System.out.println("A");
        } else if (score < 90 && score >= 80) {
            System.out.println("B");
        } else if (score < 80 && score >= 70) {
            System.out.println("C");
        } else if (score < 70 && score >= 60) {
            System.out.println("D");
        } else if (score < 60 && score >= 0) {
            System.out.println("不及格");
        } else {
            System.out.println("成绩不合法");
        }

        scanner.close();
    }
}
  • f语句至多有一个else语句,else语句在所有的else if语句之后
  • if语句可以有若干个else if语句,他们必须在else语句之前
  • 一旦其中一个else if语句检测为true,其他else if以及else语句都将跳过执行

switch多选择结构

  • 多选择结构还有一个实现方式就是switch case语句
  • switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
  • switch 语句中的变量类型可以是:
    • byte,short,int或者char
    • 从Java SE 7开始switch支持字符串String类型
    • 同时case标签必须为自负床常量或者字面量

在这里插入图片描述

public static void main(String[] args) {
    //case穿透    //switch   匹配一个具体的值
    char grade = 'C';

    switch (grade) {
        case 'A':
            System.out.println("优秀");
            break;//可选
        case 'B':
            System.out.println("良好");
            break;
        case 'C':
            System.out.println("一般");
            break;
        case 'D':
            System.out.println("及格");
            break;
        case 'E':
            System.out.println("不及格");
        default:
            System.out.println("输入错误");
    }
}
public static void main(String[] args) {
    String name = "zzw";
    //JDK7的新特性,表达式结果可以是字符串!!!
    //字符的本质还是数字

    //反编译   java---class(字节码文件)---反编译(IDEA)

    switch (name) {
        case "zzw":
            System.out.println("zzw");
            break;
        case "ywr":
            System.out.println("ywr");
            break;
        default:
            System.out.println("???");
    }
}

2.4循环结构

  • while循环
  • do…while循环
  • for循环
  • 在Java5中引入了一种主要用于数组的增强型for循环

while循环

  • while是最基本的循环,他的结构为:

    while(布尔表达式){
        //循环内容
    }
    
  • 只要布尔表达式为true,循环就会一直执行下去

  • 我们大多数情况是会让循环停止下来的,我们需要一个表达式失效的方式来结束循环

  • 少数部分情况需要循环一直执行,比如服务器的请求响应监听等

  • 循环条件一直为true就会造成无限循环(死循环),我们正常的业务编程中应该尽量避免死循环,会影响程序的性能或者造成程序卡死崩溃!

public static void main(String[] args) {

    //输出1~100

    int i = 0;

    while (i < 100) {
        i++;
        System.out.println(i);
    }
}
  • 计算1+2+3+…+100=?

    public static void main(String[] args) {
            //计算1+2+3+...+100=?
            int i = 0;
            int sum = 0;
    
            while (i <= 100) {
                sum = sum + i;
                i++;
            }
            System.out.println(sum);
        }
    

do…while循环

  • 对于while语句而言,如果不满足条件,则不能进入循环,但有时候我们需要即使不满足条件也要至少执行一次

  • do…while循环和while循环相似,不同的是,do…while循环至少会执行一次

    do{
        //代码语句
    }while(布尔表达式);
    
  • while和do…while的区别:

    • while先判断后执行,dowhile是先执行后判断!
    • do…while总是保证循环体会被至少执行一次!这是他们的主要差别
public static void main(String[] args) {
        int a = 0;
        while (a < 0) {
            System.out.println(a);
            a++;
        }
        System.out.println("===========");
        do {
            System.out.println(a);
            a++;
        } while (a < 0);
    }

for循环

  • 虽然所有循环结构都可以用while或者do…while表示,但Java提供了另一种语句–for循环,使一些循环结构变得更加简单

  • for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构

  • for循环执行的次数是在执行前就确定的,语法格式如下:

    for(初始化;布尔表达式;更新){
        //代码语句
    }
    
    public static void main(String[] args) {
        int a = 1;//初始化条件
    
        while (a <= 100) {//条件判断
            System.out.println(a);//循环体
            a = a + 2;//迭代
        }
        System.out.println("while循环结束");
    
        //初始化条件;条件判断;迭代
        for (int i = 1; i <= 100; i++) {
            System.out.println(i);
        }
        System.out.println("for循环结束");
    }
    

关于for循环有一下几点说明:

  • 最先执行初始化步骤,可以声明一种类型,但可初始化一个或者多个循环控制变量,也可以是空语句
  • 检测布尔表达式的值是,如果为true,循环体被执行;如果为false,循环终止,开始执行循环体后面的语句
  • 执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)
  • 再次检测布尔值表达式,循环执行上面的过程
  1. 计算0到100之间的奇数和偶数的和

    public static void main(String[] args) {
            //计算0到100之间的奇数和偶数的和
            /*int sum1 = 0;
            int sum2 = 0;
            for (int a = 0; a <= 100; a = a + 2) {
                sum1 = sum1 + a;
            }
            for (int b = 1; b <= 100; b = b + 2) {
                sum2 = sum2 + b;
            }
            System.out.println("奇数的和=" + sum2);
            System.out.println("偶数的和=" + sum1);*/
    
            int oddSum = 0;
            int evenSum = 0;
            for (int i = 0; i <= 100; i++) {
                if (i % 2 != 0) {
                    oddSum = oddSum + i;
                } else {
                    evenSum = evenSum + i;
                }
            }
            System.out.println("奇数的和=" + oddSum);
            System.out.println("偶数的和=" + evenSum);
        }
    
  2. 用while或者for循环输出1-1000之间能被5整除的数,并且每行输出3个

    • for循环

      public static void main(String[] args) {
              //用for循环输出1-1000之间能被5整除的数,并且每行输出3个
              for (int i = 1; i <= 1000; i++) {
                  if (i % 5 == 0) {
                      System.out.print(i+"  ");
                      //System.out.print(i+"\t");
                      int a = 0;
                      a = a + i;
                      if (a % 3 == 0) {//换行
                          System.out.println("  ");
                          //System.out.print("\n");
                      }
                  }
              }
          }
      
    • while循环

      public static void main(String[] args) {
              //用while循环输出1-1000之间能被5整除的数,并且每行输出3个
              int i = 1;
              int a = 0;
              while (i <= 1000) {
                  if (i%5==0) {
                      System.out.print(i + " ");
                      a++;
                      }
                  i++;
                  if (a % 3 == 0) {
                      System.out.println();
                  }
              }
          }
      
  3. 打印99乘法表

    • 先打印第一列
    • 把固定值用一个循环包起来
    • 去掉重复项,i<=j
    • 调整样式
public static void main(String[] args) {
        //打印九九乘法表
        for (int j = 1; j <= 9; j++) {
            for (int i = 1; i <= j; i++) {
                System.out.print(i + "x" + j + "=" + (i * j)+"\t");
            }
            System.out.println();
        }
    }

增强for循环

  • Java增强for循环语法格式:

    for(声明语句:表达式){
        //代码句子
    }
    
  • 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配,其作用域限定在循环语句块,其值与此时数组元素的值相等

  • 表达式:表达式是要访问的数组名,或者是返回值为数组的方法

public static void main(String[] args) {
    int[] numbers = {10, 20, 30, 40, 50};//定义数组

    for (int i = 0; i < 5; i++) {
        System.out.println(numbers[i]);
    }
    System.out.println("====================");
    //遍历数组的元素
    for (int x : numbers) {
        System.out.println(x);
    }
}

break,continue

  • break:在任何循环语句的主体部分,均可用break控制循环的流程,break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
  • continue:在循环体中用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定
public static void main(String[] args) {
    int i = 0;
    while (i < 100) {
        i++;
        System.out.println(i);
        if (i == 30) {
            break;
        }
    }
    System.out.println("123");
}
public static void main(String[] args) {
    int i = 0;
    while (i < 100) {
        i++;
        if (i % 10 == 0) {
            System.out.println();
            continue;
        }
        System.out.print(i+"\t");
    }
}

关于goto关键字

  • goto关键字很早就在程序设计语言中出现,尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。然而在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子–带标签的break和continue
  • “标签”是指后面跟一个冒号的标识符,例如:label:
  • 对于Java来说唯一用到标签的地方是在循环语句之前,而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,他就会中断到存在标签的地方

标签:

public static void main(String[] args) {
    //打印101-150之间所有的质数

    int count = 0;

    //a 标签    不建议使用!
    a:for (int i = 101; i <= 150; i++) {
        for (int j = 2; j < i / 2; j++) {
            if (i % j == 0) {
                continue a;
            }
        }
        System.out.println(i + "");
    }
}

Test 打印三角形

public static void main(String[] args) {
    //打印三角形 5行

    for (int i = 1; i <= 5; i++) {
        for (int j = 5; j >= i; j--) {
            System.out.print(" ");
        }
        for (int j = 1; j <= i; j++) {
            System.out.print("*");
        }
        for (int j = 1; j < i; j++) {
            System.out.print("*");
        }
        System.out.println();
    }
}

第三章 Java方法详情

3.1什么是方法

  • Java方法是语句的集合,它们在一起执行一个功能

    • 方法是解决一类问题的步骤的有序组合
    • 方法包含于类或者对象中
    • 方法在程序中被创建,在其他地方被引用
  • 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。设计方法的时候最好保持方法的原子性,就是一个方法只完成一个功能,这样有利于我们后期的扩展

  • 方法的命名规则:首字母小写的驼峰命名原则

3.2方法的定义

  • Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
    • 方法包含一个方法头和一个方法体,下面是一个方法的所有部分:
      • 修饰符:这是可选的,告诉编译器如何调用该方法,定义了该方法的访问类型
      • 返回值类型:方法可能会返回值,returnValueType是方法返回值的数据类型,有些方法执行所需的操作,但没有返回值,在这种情况下,returnValueType是关键字void
      • 方法名:是方法的实际名称,方法名和参数表共同构造成方法签名
      • 参数类型:参数像是一个占位符,当方法被调用是,传递值给参数,这个值被称为实参或变量。参数列表是指方法的参数类型,顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
        • 形式参数:在方法被调用时用于接收外界输入的数据
        • 实参:调用方法时实际传给方法的数据
      • 方法体:方法体包含具体的语句,定义该方法的功能
修饰符  返回值类型  方法名(参数类型 参数名){
    ...
    方法体
    ...
    return 返回值;
}
public static void main(String[] args) {
    int max = max(10, 10);
    System.out.println(max);
}

//比大小
public static int max(int num1, int num2) {
    int result = 0;

    if (num1 == num2) {
        System.out.println("num1=num2");
        return 0;//终止大小
    }
    if (num1 > num2) {
        result = num1;
    } else {
        result = num2;
    }
    return result;
}

3.3方法调用

  • 调用方法:对象名.方法名(实参列表)

  • Java支持两种调用方法的方式,根据方法是否返回值来选择

  • 当方法返回一个值的时候,方法调用通常被当做一个值。例如:

    int larger = max(30,40);
    
  • 如果方法返回值是void,方法调用一定是一条语句

    ystem.out.println("Hello,YWR");
    
  • 扩展了解:值传递(Java)和引用传递

3.4方法的重载

  • 重载就是在一个类中,有相同的函数名称,但形参不同的函数

  • 方法的重载规则:

    • 方法名称必须相同
    • 参数列表必须不同(个数不同,或类型不同,参数排列顺序不同等)
    • 方法的返回类型可以相同也可以不相同
    • 仅仅返回类型不同不足以成为方法的重载
  • 实现理论:

    方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译报错

public static void main(String[] args) {
    int max = max(10, 20, 30);
    System.out.println(max);
}

//比大小
public static int max(int num1, int num2) {
    int result = 0;

    if (num1 == num2) {
        System.out.println("num1=num2");
        return 0;//终止大小
    }
    if (num1 > num2) {
        result = num1;
    } else {
        result = num2;
    }
    return result;
}

public static int max(double num1, double num2) {
    int result = 0;

    if (num1 == num2) {
        System.out.println("num1=num2");
        return 0;//终止大小
    }
    if (num1 > num2) {
        result = (int) num1;
    } else {
        result = (int) num2;
    }
    return result;
}

public static int max(int num1, int num2, int num3) {
    int result = 0;

    if (num1 == num2) {
        System.out.println("num1=num2");
        return 0;//终止大小
    }
    if (num1 > num2) {
        result = num1;
    } else {
        result = num2;
    }
    return result;
}

3.5命令行传参

有时候你希望运行一个程序时候再传递给它消息,这要靠传递命令行参数给main()函数实现

public static void main(String[] args) {
    //args.length  数组长度
    for (int i = 0; i < args.length; i++) {
        System.out.println("args[" + i + "]" + args[i]);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E3QLrmYX-1662112709442)(C:\Users\ywrdsg\AppData\Roaming\Typora\typora-user-images\image-20220504214054502.png)]

3.6可变参数

  • JDK1.5开始,Java支持传递同类型的可变参数给一个方法
  • 在方法声明中,在指定参数类型后加一个省略号(…)
  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数,任何普通的参数必须在它之前声明
public static void main(String[] args) {
    //调用可变参数的方法
    printMax(34, 3, 3, 2, 56.6);
    printMax(new double[]{1, 2, 3});
}

public static void printMax(double...numbers) {
    if (numbers.length == 0) {
        System.out.println("请输入数字!");
        return;
    }

    double result = numbers[0];

    //遍历比较
    for (int i = 1; i < numbers.length; i++) {
        if (numbers[i] > result) {
            result = numbers[i];
        }
    }
    System.out.println("最大值是" + result);
}

3.7递归

  • A方法调用B方法
  • 递归就是:A方法调用A方法!就是自己调用自己
  • 利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可以描述出解题过程所需要的多次复杂计算,大大的减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
  • 递归结构包括两个部分:
    • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环
    • 递归提:什么时候需要调用自身方法

能不用递归就不用递归!

public static void main(String[] args) {
    System.out.println(f(5));
}

//阶乘
public static int f(int n) {
    if (n == 1) {
        return 1;
    } else {
        return n * f(n - 1);
    }
}

3.8写一个计算器

思路推荐:

  • 写4个方法:加减乘除
  • 利用循环+switch进行用户交互
  • 传递需要操作的两个数
  • 输出结果
public static void main(String[] args) {
    //设计计算器6
    double m = 0;
    Scanner scanner = new Scanner(System.in);
    System.out.println("请输入第一个数字");
    String first = scanner.nextLine();
    double a = Double.parseDouble(first);

    System.out.println("请输入第二个数字");
    String second = scanner.nextLine();
    double b = Double.parseDouble(first);

    System.out.println("请输入 + - * /");
    String symbol = scanner.nextLine();
    switch (symbol) {
        case "+":
            m = add(a, b);
            break;
        case "-":
            m = subtract(a, b);
            break;
        case "*":
            m = multiply(a, b);
            break;
        case "/":
            m = divide(a, b);
            break;
        default:
            System.out.println("输入错误!");
    }
    System.out.println(m);
    scanner.close();
}

public static double add(double a, double b) {
    return a + b;
}

public static double subtract(double a, double b) {
    return a - b;
}

public static double multiply(double a, double b) {
    return a * b;
}

public static double divide(double a, double b) {
    return a / b;
}

第四章 数组

4.1 数组的定义

  • 数组师相同的类型数据的有序集合
  • 数组描述的师相同类型的若干个数据,按照一定的先后次序排列组合而成
  • 其次,每个数据称作一个数组元素,每个数组元素可以通过一个下标来访问他们

4.2 数组声明创建

  • 首先必须声明数组变量,才能在程序中使用数组。下面师声明数组变量的语法:

    dataType[] arrayRefVar;   //首选方法
    或
    dataType arrayRefVar[];    //效果相同,但不是首选方法
    
  • Java语言使用new操作符来创建数组,语法如下:

    dataType[] arrayRefVar = new dataType[arraySize];
    
  • 数组的元素是通过索引访问的,数组索引从0开始

  • 获取数组长度:arrays.length

public static void main(String[] args) {

        //声明一个数组
        int[] nums;
//        int nums2[];

        //创建一个数组
        nums = new int[10];//这里面可以存放10个int类型的数字
        //给数组元素赋值
        nums[0] = 1;
        nums[1] = 2;
        nums[2] = 3;
        nums[3] = 4;
        nums[4] = 5;
        nums[5] = 6;
        nums[6] = 7;
        nums[7] = 8;
        nums[8] = 9;
        nums[9] = 10;
        
        //计算所有元素的和
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum = sum + nums[i];
        }
        System.out.println("总和为:" + sum);
    }

4.3 内存分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P8CjK5vs-1662112709443)(C:\Users\ywrdsg\AppData\Roaming\Typora\typora-user-images\image-20220505221808691.png)]

4.4 三种初始化

  • 静态初始化

    int[] a = {1,2,3};
    Man[] mans = {new Man(1,1),new Man(1,2)};
    
  • 动态初始化

    int[] a = new int[2];
    a[0] = 1;
    a[1] = 2;
    
  • 数组的默认初始化

    • 数组是引用类型,它的元素相当于类的是咧变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
public static void main(String[] args) {
    //静态初始化
    int[] a = {1, 2, 3, 4, 5, 6, 7, 8};
    System.out.println(a[0]);

    //动态初始化:包含默认初始化
    int[] b = new int[10];
    b[0] = 10;
    b[1] = 15;
    System.out.println(b[0]);
    System.out.println(b[1]);
    System.out.println(b[2]);
}

4.5 数组的四个基本特点

  • 长度是确定的。数组一旦被创建,它的大小就是不可以改变的

  • 其元素必须是相同类型,不允许出现混合类型

  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型

  • 数字变量属于引用类型,数组也可以看成是对象,输注在每个元素相当于该对象的成员变量。

    数组本身就是对象,Java对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身就是在堆中的。

4.6 数组边界

  • 下标的合法区间:[0,length-1],如果越界就会报错

    public static void main(String[] args){
        int[] a = new int[2];
        System.out.println(a[2]);
    }
    
  • ArrayIndexOutOfBoundsException:数组下标越界异常!

  • 小结:

    • 数组是相同数据类型(数据类型可以为任意类型)的有序集合
    • 数组也是对象。数组元素相当于对象的成员变量
    • 数组长度是确定的,不可变的。如果越界,则报:ArrayIndexOutOfBoundsException

4.7 数组的使用

  • 普通的For循环

    public static void main(String[] args) {
        int[] arrays = {1, 2, 3, 4, 5};
    
        //打印全部的数组元素
        for (int i = 0; i < arrays.length; i++) {
            System.out.println(arrays[i]);
        }
        System.out.println("=========");
    
        //计算所有元素的和
        int sum = 0;
        for (int i = 0; i < arrays.length; i++) {
            sum = sum + arrays[i];
        }
        System.out.println("sum = " + sum);
        System.out.println("=========");
    
        //查找最大元素
        int max = arrays[0];
        for (int i = 1; i < arrays.length; i++) {
            if (arrays[i] > max) {
                max = arrays[i];
            }
        }
        System.out.println(max);
    }
    
  • For-Each循环

    public static void main(String[] args) {
            int[] arrays = {1, 2, 3, 4, 5};
    
            //没有下标
            for (int array : arrays) {
                System.out.println(array);
            }
        }
    
  • 数组作方法入参

    public static void main(String[] args) {
            int[] arrays = {1, 2, 3, 4, 5};
    
            printArray(arrays);
        }
    
        //打印数组元素
        public static void printArray(int[] arrays) {
            for (int i = 0; i < arrays.length; i++) {
                System.out.print(arrays[i] + " ");
            }
        }
    
  • 数组作返回值

    public static void main(String[] args) {
            int[] arrays = {1, 2, 3, 4, 5};
    
            int[] reverse = reverse(arrays);
            printArray(reverse);
        }
    
        //反转数组
        public static int[] reverse(int[] arrays) {
            int[] result = new int[arrays.length];
    
            //反转的操作
            for (int i = 0, j = result.length - 1; i < arrays.length; i++, j--) {
                result[j] = arrays[i];
            }
    
            return result;
        }
    

4.8 多维数组

  • 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一堆数组,其每个元素都是一个一维数组

  • 二维数组

    int a[][] = new int[2][5];
    
public static void main(String[] args) {
        //[4][2]
        /*
        * 1,2  arrays[0]
        * 2,3  arrays[1]
        * 3,4  arrays[2]
        * 4,5  arrays[3]
        * */
        int[][] arrays = {{1, 2}, {2, 3}, {3, 4}, {4, 5}};

        for (int i = 0; i < arrays.length; i++) {
            for (int j = 0; j < arrays[i].length; j++) {
                System.out.println(arrays[i][j]);
            }
        }
    }

4.9 Arrays类

  • 数组的工具类java.util.Arrays
  • 由于数组对象本身并没有什么方法可以提供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作
  • Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:是“不是”而不是“不能”)
  • 具有一下常用功能:
    • 给数组赋值:通过fill方法
    • 对数组排序:通过sort方法,按升序
    • 比较数组:通过equals方法比较数组中元素值是否相等
    • 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作
public static void main(String[] args) {
    int[] a = {1, 2, 3, 4, 9090, 31231, 543, 21, 3, 23};

    //System.out.println(a);//[I@1540e19d

    //打印数组元素
    //System.out.println(Arrays.toString(a));
    //printArray(a);

    //数组进行排序  升序
    Arrays.sort(a);
    System.out.println(Arrays.toString(a));

    //数组填充
    //Arrays.fill(a, 0);
    //2~4之间的元素被填充
    Arrays.fill(a, 2, 4, 0);
    System.out.println(Arrays.toString(a));
}

public static void printArray(int[] a) {
    for (int i = 0; i < a.length; i++) {
        if (i == 0) {
            System.out.print("[");
        } else if (i == a.length - 1) {
            System.out.print(a[i] + "]");
        } else {
            System.out.print(a[i] + ", ");
        }
    }
}

4.10 冒泡排序

  • 冒泡排序无疑是最为出名的排序算法之一,总共有八大排序
  • 冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较
  • 时间复杂度为O(n2)
public static void main(String[] args) {
        /**
         * 冒泡排序
         * 1.比较数组中两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置
         * 2.每次比较,都会产生出一个最大的或者最小的数字
         * 3.下一轮则可以少一次排序
         * 4.依次循环,直到结束
         */
        int[] a = {1, 4, 5, 2, 6, 7, 2, 3, 5};
        int[] sort = sort(a);
        System.out.println(Arrays.toString(sort));
    }

    public static int[] sort(int[] array) {
        //临时变量
        int temp = 0;

        //外层循环,判断我们要走多少次
        for (int i = 0; i < array.length - 1; i++) {

            //通过flag标识位减少没有意义的比较
            boolean flag = false;

            //内层循环,比较两个数字,如果第一个数比第二个数大,则交换位置
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j + 1] < array[j]) {
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    flag = true;
                }
            }
            if (flag == false) {
                break;
            }
        }
        return array;
    }

4.11 稀疏数组

  • 当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组

  • 稀疏数组的处理方式是:

    • 记录数组一共有几行几列,有多少个不同值
    • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
  • 如图:左边是原始数组,右边是稀疏数组

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jAiBcWv2-1662112709444)(C:\Users\ywrdsg\AppData\Roaming\Typora\typora-user-images\image-20220803171554896.png)]

 public static void main(String[] args) {
        // 1.创建二维数组  11*11     0:没有棋子, 1:黑棋, 2:白棋
        int[][] array1 = new int[11][11];
        array1[1][2] = 1;
        array1[2][3] = 2;
        // 输出原始数组
        System.out.println("输出原始数组");

        for (int[] ints : array1) {
            for (int anInt : ints) {
                System.out.print(anInt + "\t");
            }
            System.out.println();
        }

        System.out.println("================");
        // 转换为稀疏数组保存
        // 获取有效值的个数
        int sum = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (array1[i][j] != 0) {
                    sum++;
                }
            }
        }
        System.out.println("有效值的个数:" + sum);

        // 2.创建一个稀疏数组
        int[][] array2 = new int[sum + 1][3];
        array2[0][0] = 11;
        array2[0][1] = 11;
        array2[0][2] = sum;

        // 遍历二维数组,将非零的值存放的稀疏数组中
        int count = 0;
        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                if (array1[i][j] != 0) {
                    count++;
                    array2[count][0] = i;
                    array2[count][1] = j;
                    array2[count][2] = array1[i][j];
                }
            }
        }
        
        // 打印稀疏数组
        System.out.println("稀疏数组");

        for (int i = 0; i < array2.length; i++) {
            System.out.println(array2[i][0] + "\t" + array2[i][1] + "\t" + array2[i][2]);
        }

        System.out.println("================");
        // 还原稀疏数组
        System.out.println("还原");

        // 1.读取稀疏数组
        int[][] array3 = new int[array2[0][0]][array2[0][1]];
        // 2.给其中的元素还原它的值
        for (int i = 1; i < array2.length; i++) {
            array3[array2[i][0]][array2[i][1]] = array2[i][2];
        }
        // 3.打印
        for (int[] ints : array3) {
            for (int anInts : ints) {
                System.out.print(anInts + "\t");
            }
            System.out.println();
        }
    }

第五章 面向对象编程

Java的核心思想就是oop

5.1 面向对象

面向过程&面向对象

  1. 面向过程思想
    • 步骤清晰简单,第一步做什么,第二步做什么…
    • 面对过程适合处理一些较为简单的问题
  2. 面向对象思想
    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后才对某个分类下的细节进行面向过程的思索。
    • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题
  3. 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统,但是,具体到微观操作,仍然需要面向过程的思路去处理

什么是面向对象

  • 面向对象编程(Object-Oriented Programming,oop)
  • 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
  • 抽象
  • 三大特性
    • 封装
    • 继承
    • 多态
  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板

5.2 回顾加深方法

  • 方法的定义

    • 修饰符
    • 返回类型
    • break:跳出switch,结束循环 和return的区别
    • 方法名:注意规范,见名知意
    • 参数列表:(参数类型,参数名)…
    • 异常抛出
  • 方法的调用(静态方法随着类的加载而创建,非静态方法随着对象的创建而创建)

    • 静态方法

    • 非静态方法

      //
      // 静态方法  static
          // 非静态方法
      
          public static void main(String[] args) {
      
              Student.say();
      
              // 实例化类 new
              // 对象类型 对象名 = 对象值;
              Student2 student2 = new Student2();
              student2.say();
          }
      
          // 和类一起加载的
          public static void a() {
              //b();
          }
      
          // 类实例化之后才存在
          public void b() {
      
          }
      
      // Student 类
      // 静态方法
          public static void say() {
              System.out.println("学生说话了");
          }
      
      // Student2 类
      // 非静态方法
          public void say() {
              System.out.println("学生安静了");
          }
      
    • 形参和实参

    • 值传递和引用传递

      // 值传递
      public static void main(String[] args) {
      
              int a = 1;
              System.out.println(a);// 1
      
              Demo04.change(a);
              System.out.println(a);// 1
          }
      
          public static void change(int a) {
              a = 10;
          }
      
      // 引用传递
      public class Demo05 {
          public static void main(String[] args) {
              Person person = new Person();
              System.out.println(person.name);// null
      
              Demo05.change(person);
              System.out.println(person.name);// shiyimuya
          }
      
          public static void change(Person person) {
              // person是一个对象:指向的 ---> Person person = new Person();这是一个具体的人,可以改变属性!
              person.name = "shiyimuya";
          }
      }
      
      // person类,有一个属性:name
      class Person {
          String name;
      }
      
    • this关键字

5.3 创建与初始化对象

  • 使用new关键字创建对象
  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中的构造器的调用
  • 类中的构造器也成为构造方法,是在进行创建对象的时候必须要调用的,并且构造器有一下两个特点:
    1. 必须和类的名字相同
    2. 必须没有返回类型,也不能写viod
  • 构造器必须要掌握
public class Student {

    // 属性:字段
    String name;
    int age;

    // 方法
    public void study() {
        System.out.println(this.name + "在学习");
    }
}


// main方法
/*
* public static void main(String[] args) {

        // 类:抽象的,实例化
        // 类实例化后会返回一个自己的对象
        // student对象就是一个Student类的具体实例
        Student shiyimuya = new Student();
        Student sakura = new Student();

        sakura.name = "樱";
        sakura.age = 23;
        System.out.println(sakura.name);
        System.out.println(sakura.age);

        shiyimuya.name = "是一沐呀";
        shiyimuya.age = 23;
        System.out.println(shiyimuya.name);
        System.out.println(shiyimuya.age);
    }
* */
public class Person {

    // 一个类即使什么都不写,他也会存在一个方法
    // 显示的定义构造器

    String name;
    int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}


/**
 * public static void main(String[] args) {
 *         // 实例化一个对象
 *         Person person = new Person("sakura", 23);
 *         System.out.println(person.name);
 *     }
 *
 *     构造器:
 *         1.和类名相同
 *         2.没有返回值
 *     作用:
 *         1.new 本质在调用构造方法
 *         2.初始化对象的值
 *     注意点:一旦定义了有参构造,无参构造就必须显示定义
 *
 *     this.当前类 = 传进来的参数值
 */  

5.4 封装

  • 该露的露,该藏的藏
    • 我们的程序设计要追求“高内聚,低耦合”。高内聚:类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
  • 封装(数据的隐藏)
    • 通常应禁止直接访问一个对象中数据的实际表达,而应通过操作接口来访问,这称为信息隐藏
  • 记住这句话:私有属性,get/set
/**
 * 1.提高程序的安全性,保护数据
 * 2.隐藏代码的实现细节
 * 3.统一接口
 * 4.系统可维护性增加
 */
public class Student {
    // 属性私有

    /**
     * 名字
     */
    private String name;

    /**
     * 学号
     */
    private int id;

    /**
     * 性别
     */
    private String gender;

    /**
     * 年龄
     */
    private int age;

    // 提供一些可以操作这个属性的方法
    // 提供一些public 的get、set方法

    // get  获得这个数据

    // set 给这个数据设置值

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age > 120 || age < 0) { // 不合法
            this.age = 3;
        } else {
            this.age = age;
        }
    }
}

/*
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setName("sakura");
        System.out.println(s1.getName());

        //s1.setAge(999);// 不合法的
        s1.setAge(23);
        System.out.println(s1.getAge());
    }*/

5.5 继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的构建
  • extends的意思是“扩展”,子类是父类的扩展
  • Java中类的只有单继承,没有多继承!(一个儿子只能有一个爸爸,一个爸爸可以有多个儿子)
  • 继承是类和类之间的一种关系。此外类和类之间的关系还有依赖、组合、聚合等
  • 子类和父类之间,从意义上讲应该具有“is a”的关系
  • object类

子类继承了父类,就会拥有父类的全部方法!

在Java中所有的类,都默认直接或者间接的继承Object类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vlNZ81sf-1662112709444)(C:\Users\ywrdsg\AppData\Roaming\Typora\typora-user-images\image-20220831105021838.png)](ctrl+h查看)

// Person类
public class Person /*extends Object*/ {

    private int money = 10_0000_0000;

    public void say() {
        System.out.println("说了一句话");
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}
// Person类
public class Student extends Person{
}
public static void main(String[] args) {
    Student student = new Student();
    student.say();
    System.out.println(student.getMoney());
}
  • super – this (this指向当前类,super指向父类)

    私有的东西无法被继承

    public Person() {
            System.out.println("Person无参执行了");
        }
    
    public Student() {
        // 隐藏代码:调用了父类的无参构造
        super();// 调用父类的构造器,必须要在子类构造器的第一行
        System.out.println("Student无参执行了");
    }
    
    super注意点:
        1. super调用父类的构造方法,必须要在构造器方法的第一个
        2. super必须只能出现在子类的方法或者构造方法中!
        3. super和this不能同时调用构造方法!
    
    Vs this:
        1.代表的对象不同:
             this:自身调用者这个对象
             super:代表父类对象的引用
        2.前提不同:
             this:没有继承也可以使用
             super:只能在继承条件下才可以使用
        3.构造方法不同:
             this():调用自身类的构造
             super():调用父类的构造
    
    // Person类
    public class Person /*extends Object*/ {
    
        //protected String name = "樱";
    
        /*public void print() {
            System.out.println("Person");
        }*/
    
        public Person() {
            System.out.println("Person无参执行了");
        }
    }
    
    // Student类
    public class Student extends Person {
    
        public Student() {
            // 隐藏代码:调用了父类的无参构造
            super();// 调用父类的构造器,必须要在子类构造器的第一行
            System.out.println("Student无参执行了");
        }
    
        /*private String name = "sakura";
    
        public void print() {
            System.out.println("Student");
        }
    
        public void test(String name) {
            System.out.println(name);
            System.out.println(this.name);
            System.out.println(super.name);
        }
    
        public void test1() {
            print(); // Student
            this.print(); // Student
            super.print(); // Person
        }*/
    }
    
    public class Application {
    
        public static void main(String[] args) {
            Student student = new Student();
            //student.test("shiyimuya");
            //student.test1();
        }
    }
    
  • 方法重写

    重写都是方法的重写,和属性无关

public class A extends B {
    public static void test() {
        System.out.println("A=>test()");
    }

    // Override:重写
    @Override// 注解:有功能的注释!
    public void test1() {
        System.out.println("A=>test1()");
    }
}
public class B {
    public static void test() {
        System.out.println("B=>test()");
    }

    public void test1() {
        System.out.println("B=>test1()");
    }
}
public static void main(String[] args) {
    // 方法的调用只和左边有关,定义的数据类型有关
    // 定义的是什么类就调用什么类的静态方法
    A a = new A();
    a.test();// A

    // 父类的引用指向了子类
    B b = new A();
    b.test();// B

    A a1 = new A();
    a1.test1();

    // 子类重写的父类的方法
    B b1 = new A();
    b1.test1();
}
重写:需要有继承关系,子类重写父类的方法!
     1. 方法名必须相同
     2. 参数列表必须相同
     3. 修饰符:范围可以扩大:  public>protected>Default>private
     4. 抛出的异常:范围可以被缩小,但不能扩大:  ClassNotFoundException  -->  Exception(大)

重写:子类的方法和父类必须要一致,方法体不同!

为什么需要重写:
        父类的功能子类不一定需要,或者不一定满足!
        alt+insert,override

5.6 多态

  • 即同一个方法可以根据发送对象的不同而采取多种不同的行为方式

  • 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多种

  • 多态的存在条件

    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象
  • 注意:多态是方法的多态,属性没有多态性

    /**
     * 多态注意事项:
     * 1. 多态是方法的多态,属性没有多态
     * 2. 父类和子类,有联系     类型转换异常!ClassCastException!
     * 3. 存在的条件:继承关系,方法需要重写,父类引用指向子类对象!  Father f = new Son();
     *
     * static:方法,属于类,它不属于实例
     * final:常量
     * private:私有 
     */
    
    public class Person {
        public void run() {
            System.out.println("run");
        }
    }
    
    public class Student extends Person {
        @Override
        public void run() {
            System.out.println("son");
        }
    
        public void eat() {
            System.out.println("eat");
        }
    }
    
    public static void main(String[] args) {
        /**
         * 一个对象的实际类型是确定的
         * new Student();
         * new Person();
         *
         * 可以指向的引用类型就不确定了
         */
        // 父类的引用指向子类
    
        // Student 能调用的方法都是自己的或者继承父类的!
        Student s1 = new Student();
        // Person 父类型,可以指向子类,但不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();
    
        // 对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
        s2.run();// 子类重写了父类的方法,执行子类的方法
        s1.run();
        s1.eat();
    }
    
  • instanceof (类型转换) 引用类型

/**
 * 1. 父类的引用指向子类的对象
 * 2. 把子类转换为父类,向上转型
 * 3. 把父类转换为子类,向下转型   强制转换
 * 4. 方便方法的调用,减少重复的代码
 */
public class Student extends Person {
    public void go() {
        System.out.println("go");
    }
}
public class Teacher extends Person {

}
public static void main(String[] args) {
    // 类型之间的转化: 父  子

    /*// 高         低
    Person person = new Student();
    // Student将这个对象转换为Student类型,我们就可以使用Student类型的方法了!
    ((Student)person).go();*/

    // 子类型转换为父类型,可能会丢失自己的本来的一些方法
    Student student = new Student();
    student.go();
    Person person = student;
}

5.7 static关键字

public class Student {
    private static int age;// 静态变量  多线程!
    private double score;// 非静态变量

    public void run() {
        System.out.println("run");
    }

    public static void go() {
        System.out.println("go");
    }

    public static void main(String[] args) {
        Student s1 = new Student();
        System.out.println(Student.age);
        System.out.println(s1.age);
        System.out.println(s1.score);

        go();
        s1.run();
    }
}
public class Person {

    // (2):可以赋初始值
    {
        // 匿名代码块
        System.out.println("匿名代码块");
    }

    // 最先执行(1)只执行一次
    static {
        // 静态代码块
        System.out.println("静态代码块");
    }

    // (3)
    public Person() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        Person person1 = new Person();
        System.out.println("=================");
        Person person2 = new Person();
    }
}

静态导包

// 静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;

public class test {

    public static void main(String[] args) {
        System.out.println(random());
        System.out.println(PI);
    }
}

5.8 抽象类

  • abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,该类就是抽象类
  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类
  • 抽象类不能使用new关键字来创建对象,它是用来让子类实现的
  • 抽象方法,只有方法声明,没有方法实现,它是用来让子类实现的
  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
/**
 * 1. 不能new抽象类,只能靠子类去实现它;约束!
 * 2. 抽象类里可以写普通方法
 * 3. 抽象方法必须在抽象类中
 * 抽象的抽象:约束
 */

// abstract 抽象类:类    extends:单继承
public abstract class Action {

    // abstract,抽象方法,只有方法的名字,没有方法的实现!
    public abstract void doSomething();
}
// 抽象类的所有方法,继承了他的子类,都必须要实现它的方法;除非也是个抽象类
public class A extends Action{
    @Override
    public void doSomething() {

    }
}

5.9 接口

  • 普通类:只有具体实现
  • 抽象类:具体实现和规范(抽象方法)都有!
  • 接口:只有规范!自己无法写方法-专业的约束! 约束和实现分离:面向接口编程
  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞;如果你是汽车,则必须能跑;如果你是好人,则必须干掉坏人;如果你是好人,则必须欺负坏人
  • 接口的本质就是契约,就像我们的法律一样,制定好了大家就必须要遵守
  • OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++、Java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象
作用:
   1. 约束
   2. 定义一些方法,让不同的人实现
   3. public abstract
   4. public static final
   5. 接口不能被实例化,接口中没有构造方法
   6. implements可以实现多个接口
   7. 必须要重写接口中的方法
public interface UserService {

    //常量  public static final
    int age = 23;

    // 接口中所有的定义都是抽象的 public abstract

    void add(String name);

    void delete(String name);

    void update(String name);

    void query(String name);
}
public interface TimeService {
    void timer();
}
// 类 可以实现接口 implements 接口
// 实现了接口的类,就需要重写接口的方法
// 多继承-利用接口实现多继承
public class UserServiceImpl implements UserService , TimeService {
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void timer() {

    }
}

5.10 内部类

  • 内部类就是在一个类的内部定义一个类,比如A类中定义了一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了

  • 成员内部类

  • 静态内部类

    // 静态内部类
    public static class Inner2 {
        public void in() {
            System.out.println("这是内部类的方法");
        }
    }
    
  • 局部内部类

    public class Outer {
        private int id = 10;
    
        public void out() {
            System.out.println("这是外部类的方法");
        }
    
        // 局部内部类
        public void method() {
            class Inner3{
                public void in() {
    
                }
            }
        }
    }
    
  • 匿名内部类

    public class Test {
        public static void main(String[] args) {
            // 匿名内部类
            // 没有名字初始化类,不用将实例保存到变量中
            new Apple().eat();
    
            UserService userService = new UserService() {
    
                @Override
                public void hello(String a) {
    
                }
            };
        }
    }
    class Apple{
        public void eat() {
            System.out.println("1");
        }
    }
    interface UserService{
        void hello(String a);
    }
    

第六章 异常机制 Exception

6.1 什么是异常

  • 实际工作中,遇到的情况不可能是非常完美的。比如你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序在跑着,内存或者硬盘可能满了等等。
  • 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些例外情况,或者叫异常,怎么让我们写的程序做出合理的处理,而不至于程序崩溃。
  • 异常指程序运行中出现的不期而至的各种情况,如:文件找不到、网络连接失败、非法参数等
  • 异常发生在程序运行期间,它影响了正常的程序执行流程

6.2 三种异常

要理解Java异常处理是如何工作的,需要掌握一下三种类型的异常:

  • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在的文件时,一个异常就发生了,这些异常在编译时不能简单地忽略
  • 运行时异常:运行时异常时可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略
  • 错误ERROR:错误不是异常,而是脱离程序员控制的问题,错误在代码中通常被忽略。例如:当栈溢出时,一个错误就发生了,他们在编译也检查不到的

6.3 异常体系结构

  • Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有的异常的超类
  • 在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijBii9tb-1662112709445)(C:\Users\ywrdsg\AppData\Roaming\Typora\typora-user-images\image-20220901111416727.png)]

6.4 Error

  • Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关
  • Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需要的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止
  • 还有发生在虚拟机视图执行应用时,如类定义错误(NoClassDefFoundError)、连接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况

6.5 Exception

  • 在Exception分支中有一个重要的子类RuntimeException(运行时异常)
    • ArrayIndexOutOfBoundsException(数组下标越界)
    • NullPointerException(空指针异常)
    • ArithmeticException(算术异常)
    • MissingResourceException(丢失资源)
    • ClassNotFoundException(找不到类)等异常,这些异常时不检查异常,程序中可以选择捕获处理,也可以不处理
  • 这些异常一般是有程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生
  • Error和Exception的区别:Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常

6.6 异常处理机制

  • 抛出异常

    public static void main(String[] args) {
            try {
                new Test3().test(1, 0);
            } catch (ArithmeticException e) {
                e.printStackTrace();
            }
        }
    
        public void test(int a, int b) throws ArithmeticException{
            if (b == 0) {
                // 主动抛出异常 throw ,一般在方法体中使用
                throw new ArithmeticException();
            }
    //        System.out.println(a / b);
        }
    
  • 捕获异常

    public static void main(String[] args) {
        int a = 1;
        int b = 0;
    
        // ctrl+alt+t
        try {
            System.out.println(a / b);
        } catch (Exception e) {
            e.printStackTrace(); // 打印错误的栈信息
        } finally {
        }
    }
    
  • 异常处理的五个关键字

    • try、catch、finally、throw、throws
    public static void main(String[] args) {
            int a = 1;
            int b = 0;
    
            // 捕获多个异常:从小到大!
            try { // try监控区域
                System.out.println(a / b);
    //            new Test().a();
            } catch (Error e) { // catch(想要捕获的异常类型!)  捕获异常
                System.out.println("Error");
            } catch (Exception e) {
                System.out.println("Exception");
            } catch (Throwable t) {
                System.out.println("Throwable");
            } finally { // 处理善后工作
                // finally 可以不要, 假如IO,资源,关闭!
                System.out.println("finally");
            }
        }
    
        public void a() {
            a();
        }
        public void b() {
            b();
        }
    

6.7 自定义异常

  • 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需要继承Exception类即可。
  • 在程序中使用自定义异常类,大体可分为以下几个步骤:
    • 创建自定义异常类
    • 在方法中通过throw关键字抛出异常对象
    • 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
    • 在出现异常方法的调用者中捕获并处理异常
// 自定义的异常类
public class MyException extends Exception {

    private static final long serialVersionUID = -3957670645192826339L;

    // 传递数字 > 10
    private int detail;

    public MyException(int a) {
        this.detail = a;
    }

    // toString

    @Override
    public String toString() {
        return "MyException{" +
                "detail=" + detail +
                '}';
    }
}
public class Test {

    // 可能会存在的方法
    static void test(int a) throws MyException {

        System.out.println("传递的参数为:" + a);

        if (a > 10) {
            MyException myException = new MyException(a);
            throw myException;
        }

        System.out.println("OK");
    }

    public static void main(String[] args) {
        try {
            test(1);
            test(11);
        } catch (MyException e) {
            System.out.println("MyException=>" + e);
        }
    }
}

6.8 总结

  • 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
  • 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句去释放占用的资源
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值