JavaSE笔记

JavaSE笔记

  • Hello,World!
    • 可能出现的问题
  • Java程序运行机制
  • JAVA基础语法
    • 注释
    • 标识符
    • 数据类型
      • 强类型语言
      • 弱类型语言
      • JAVA的数据类型分为两大类
        • 基本类型(primitive type)
        • 引用类型(reference type)
    • 变量
      • 什么是字节?
    • 数据类型扩展
    • 类型转换
    • 变量
    • 变量作用域
    • 常量
    • 运算符
        • < > % /运算
      • **自增自减**
      • 逻辑运算
      • 扩展赋值运算
      • 三元运算符
    • 包机制
    • JavaDoc
  • Java流程控制
    • Scanner对象
    • 顺序结构
      • if单选择结构
      • if双选择结构
      • if多选择结构
      • 嵌套的if结构
      • Switch结构
      • while循环
      • do...while循环
      • for循环
        • 练习
          • 1
          • 2
          • 3
      • 增强for循环
      • break continue
      • 打印三角形
  • JAVA方法
    • 何谓方法?
    • 方法的定义
    • 方法的调用
    • 方法的重载
    • 命令行传参
    • 可变参数
    • 递归
  • JAVA数组
    • 数组的定义
    • 数组声明创建
    • 内存分析
      • Java内存分析:
    • 数组的三种初始化
      • 静态初始化
      • 动态初始化
      • 数组的默认初始化
    • 数组的四个基本特点
    • 数组边界
    • 数组使用
    • 多维数组
    • Arrays 类
    • 冒泡排序
    • 稀疏数组
    • 稀疏数组介绍
  • 面向对象编程
    • 面向过程&面向对象
    • 什么是面向对象
    • 回顾方法及加深
    • 类和对象的关系
    • 创建与初始化对象
    • 创建对象内存分析
    • 简单小结类和对象
    • 封装
    • 继承
    • 重写
    • 多态
    • 多态2
    • Static关键字详解
    • 抽象类
    • 接口
    • 内部类
    • 异常
      • **什么是异常?**
      • **简单分类**
      • **异常体系结构**
        • Error
        • Exception
    • 异常处理机制
    • 自定义异常
    • 异常处理机制
    • 自定义异常

Hello,World!

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

2.新建一个Java文件

  • 文件后缀名为.java

  • Hello.java

  • 【注意点】系统可能没有显示文件名后缀名,我们需要手动打开

3.编写代码

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

4.编译文件 Javac java文件,会生成一个class文件

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

JavaSE笔记_第1张图片

可能出现的问题

1.每个单词的大小不能出现问题,Java是大小写敏感的

2.尽量使用英文;

3.文件名和类名必须保证一致,并且首字母大写

4.符号使用的了中文

Java程序运行机制

1.编译型

2.解释型

JavaSE笔记_第2张图片

JAVA基础语法

psvm 快捷创建主函数

sout输出语句

注释

//有趣的代码注释
//多行注释   /* 注释 */
/*
 * 我是多行注释
 * 我是多行注释
 * 我是多行注释
 */

//JavaDoc:文档注释      /**     */
/**
 * @Description HelloWorld
 * @Auther yh
 */

标识符

JavaSE笔记_第3张图片

Java所有的组成部分都需要名字。类名、变量名以及方法名都被成为标识符。

JavaSE笔记_第4张图片

数据类型

强类型语言

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

弱类型语言

JAVA的数据类型分为两大类

基本类型(primitive type)

//八大基本数据类型
String a = "Hello" ;
//整数
int num = 10;
byte num2 = 20;
short num3 = 30;
long num4 = 30L; //Long类型要在数字后面加个L
//小数:浮点数
float num5 = 50.1F;
double num6 = 3.14159265358979323846;
System.out.println(a);
System.out.println(num);
//字符
char name = 'A';
//字符串,String不是关键字,类
String namea = "阿号";
//布尔值
boolean flag = true;
//boolean flag =false;

引用类型(reference type)

JavaSE笔记_第5张图片

变量

变量:可以变化的量

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

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

什么是字节?

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

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

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

字符:是指计算机中使用的字母、数字、字和符号

1bit表示1位,

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

1024B=1KB

1024KB=1M

1024M=1G.

JavaSE笔记_第6张图片

数据类型扩展

public class Demo03 {
    public static void main(String[] args) {
        //整数拓展: 进制 二进制0b 十进制 八进制0 十六进制0x
        int i = 10;
        int i2 = 010;//八进制0
        int i3 = 0x10;//十六进制0x  0~9 A~F 16

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

        float f = 0.1f;   //0.1
        double d = 1.0/10; //0.1

        System.out.println(f==d);//false

        float d1 = 23131312312312313f;
        float d2 = d1 + 1;
        System.out.println(d1==d2);//true

        //==================================================
        //字符拓展?
        //==================================================
        System.out.println("============================");
        char c1 = 'a';
        char c2 = '中';
        System.out.println(c1);
        System.out.println((int)c1);
        System.out.println(c2);
        System.out.println((int)c2);
        //所有的字符本质还是数字
        //编码 Unicode 表:(97 = a 65 = A)
        //U0000 UFFFF
        char c3 = '\u0061';
        System.out.println(c3); //a

        //转移字符
        // \t 制表符
        // \n 换行
        // ...
        System.out.println("Hello\tWorld");
        System.out.println("Hello\nWorld");

        System.out.println("============================");
        String sa = new String("hello world");
        String sb = new String("hello world");
        System.out.println(sa==sb);
        String sc = "hello world";
        String sd = "hello world";
        System.out.println(sc==sd);
        //对象 从内存分析

        //布尔值扩展
        boolean flag = true;
        if (flag==true){}
        if (flag){} //老手
        //Less is More! 代码要精简易读
    }
}

注意:

new分配的对象,即使输入的参数一致,但是其变量值仍然不相等。

类型转换

public class Demo04 {
    public static void main(String[] args) {
        int i = 129;
        byte b = (byte)i;  //内存溢出

        //强制转换 (类型)变量名  高--低
        //自动转换     低--高


        System.out.println(i);
        System.out.println(b);
        /*
        注意点:
        1.不能对布尔值进行转换
        2.不能把对象类型转换为不相干的类型
        3.在把高容量转换到低容量的时候,强制转换
        4.转换的时候存在内存溢出,或者精度问题!
         */
        System.out.println("==================");
        System.out.println((int)23.7);  //23
        System.out.println((int)-45.89f);  //45


        System.out.println("==================");
        char c = 'a';
        int d = c+1;
        System.out.println(d);
        System.out.println((char)d);
    }
}

**注意:!!!**直接在要转换的变量前加(),括号内输入想要转换成的类型。例:(int)a;

**注意:!!!**int 与 long之间的转换,如果int溢出,后续计算的数都将溢出。

**注意:!!!**如果先将int值转化位long型,则计算出来的数变得正常。

public class Demo05 {
    public static void main(String[] args) {
        //操作比较大的数的时候,注意溢出问题
        //JDK7新特性,数字之间可以用下划线分割
        int money = 10_0000_0000;
        int years = 20;
        int total = money*years;//-1474836480,计算的时候溢出了
        long total2 = money*years;//默认是int,转换之前已经存在问题了
        long total3 = money*((long)years);//先把一个数转换为long
        long total4 = years*((long)money);//先把一个数转换为long
        System.out.println(total);
        System.out.println(total2);
        System.out.println(total3);
        System.out.println(total4);
    }
}

变量

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

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

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

type varName [=value] [{,varName[=value]}] ;
//数据类型 变量名 = 值;可以使用逗号隔开来声明多个同类型变量。

注意事项:

  • 每个变量都有类型,类型可以是基本类型,也可以是引用类型。

  • 变量名必须是合法的标识符。

  • 变量声明是一条完整的语句,因此每一个声明都必须以分号结束。

变量作用域

  • 类变量

  • 实例变量

  • 局部变量

public class Variable{
    static int allClicks=0; //类变量
    String str="hello world"; //实例变量
    public void method(){
        int i = 0; //局部变量
    }
}

常量

常量:初始化后不能再改变值!不会变动的值。

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

final 常量名=值;
final double PI=3.14;

常量名一般使用大写字符。

public class Demo09 {
    //修饰符,不存在先后顺序
    //final 定义常量
    static final double PI =3.14;

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

public class Demo07 {
    public static void main(String[] args) {
        //int a,b,c
        //int a=1,b=2,c=3; //程序可读性
        String name = "yh";
        char x = 'X';
        double pi = 3.14;
    }
}
package base;

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对象之后输出.var然后回车
        //base.Demo01 demo01 = new base.Demo01();
        Demo08 demo08 = new Demo08();
        System.out.println(demo08.age);
        System.out.println(demo08.name);

        //类变量 static
        System.out.println(demo08.salary);
    }
    //其他方法
    public void add(){
        ;
    }
}

运算符

Java语言支持如下运算符:

  • 算术运算符:+,-,*,/,%,++,–
  • 赋值运算符:=
  • 关系运算符:>,<,>=,<=,==,!= instanceof
  • 逻辑运算符:&&,||,!
  • 位运算符:&,|,^,~,>>,<<,>>>(了解!!!)
  • 条件运算符 ?:
  • 扩展赋值运算符:+=,-=,*=,/=

注意:运算的时候,如果有高级类型最后算出来的结果也是高级类型。

package operator;

public class Demo02 {
    public static void main(String[] args) {
        //二元运算符
        //Ctrl + D : 复制当前行到下一行
        long a = 123123123123123L;
        int b = 123;
        int c = 10;
        int d = 8;

        System.out.println(a+b+c+d);   //Long
        System.out.println(b+c+d);  //Int
        System.out.println(c+d);  //Int
        
    }
}

< > % /运算

package operator;

public class Demo03 {
    public static void main(String[] args) {
        //关系运算符返回的结果: 正确,错误   布尔值

        int a = 10;
        int b = 20;
        int c = 21;

        //取余 模运算
        System.out.println(c%a); //c / a     21 / 10 = 2
        System.out.println(c/a);
        System.out.println(a>b);
        System.out.println(a<b);
        System.out.println(a==b);
        System.out.println(a!=b);
        
    }
}

自增自减

a++ ++a

a++ ++a中a的值均会增加,区别在于b=a++ 先赋值再自增,b=++a 先自增再赋值

package operator;

public class Demo04 {
    public static void main(String[] args) {
        //++ -- 自增,自减 一元运算符
        int a = 3;

        int b = a++; //执行完这行代码后,先给b赋值,再自增
        //a = a + 1;
        System.out.println(a);
        //a = a + 1;
        int c = ++a; //执行完这行代码前,先自增,再给b赋值

        System.out.println(a);
        System.out.println(b);
        System.out.println(c);

        //幂运算 2^3 2*2*2 = 8 很多运算,我们会使用一些工具类来操作!
        double v = Math.pow(2,3);
        double pow = Math.pow(3, 2);
        System.out.println(v);
        System.out.println(pow);

    }
}

逻辑运算

package operator;

public class Demo05 {
    public static void main(String[] args) {
        //与(and) 或(or) 非(取反)
        boolean a = true;
        boolean b = false;

        System.out.println("a && b: "+(a && b));  //逻辑与运算;两个变量都为真,结果才为true
        System.out.println("a || b:"+(a ||b));  //逻辑或运算:两个变量有一个为真,则结果才为true
        System.out.println("!(a && b):"+!(a && b)); //如果为真,则变为假,如果为假则变为真

        //短路运算
        int c = 5;
        boolean d = (c<4)&&(c++<4);
        System.out.println(d);
        System.out.println(c);
    }
}

注意:与运算中,如果前一个为假的话,后面的就不再计算了

注意:或运算中,如果前一个为真的话,后面的就不再计算了

package operator;

public class Demo06 {
    public static void main(String[] args) {
        /*
        A = 0011 1100
        A = 0000 1101
        A&B = 0000 1100
        A|B = 0011 1101
        ~B = 1111 0010
        2*8 = 16  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
         */
        System.out.println(2<<3);
    }
}

2进制移位运算比原来的快一倍

扩展赋值运算

package operator;

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);

        //字符串连接符  + ,String
        System.out.println(""+a+b);
        System.out.println(a+b+"");

        //如果双引号在前面,则输出的将int型直接转换成string型
        //如果双引号在后面,则输出的将是求和后的值在转成string型
        
    }
}

如果双引号在前面,则输出的将int型直接转换成string型

如果双引号在后面,则输出的将是求和后的值在转成string型

三元运算符

等价于简单的if

package operator;

//三元运算符
public class Demo08 {
    public static void main(String[] args) {
        //x ? y : z
        //如果x==true,则结果为y,否则结果为z
        int score = 80;
        String type = score < 60 ? "不及格":"及格"; //必须掌握
        //if
        System.out.println(type);

    }
}

包机制

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

包语句的语法格式为:

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

一般利用公司域名倒置作为包名;

为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用"import"语句可完成此功能

import package1[.package2...].(classname|*);

JavaDoc

Java帮助文档

  • Javadoc 命令是用来生成自己的API文档的

  • 参数信息

    • @author 作者名
    • @version 版本名
    • @since 指明需要最早使用的jdk版本
    • @param 参数名
    • @return 返回值情况
    • throws 异常抛出情况

注:输入/**回车

package com.yan.base;

/**
 * @author Ahao
 * @version 1.0
 * @since 1.8
 */
public class Doc {
    String name;

    /**
     * @author Ahao
     * @param name
     * @return
     * @throws Exception
     */
    public String test(String name) throws Exception{
        return name;
    }
}

通过命令行生成JavaDoc注释文档

javadoc -encoding UTF-8 -charset UTF-8 Doc.java

JavaSE笔记_第7张图片

//作业:学会查找使用IDEA生产JavaDoc文档!

Java流程控制

Scanner对象

之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户的输入。java.util.Scanner是Java5的新特征,我们可以通过Scanner类来获取用户的输入。

基本语法:

Scanner s = new Scanner(System.in);

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

next():

1.一定要读取到有效字符后才可以结束输入。

2.对输入有效字符之前遇到的空白,next()方法会自动将其去掉。

3.只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。

4.next()不能得到带有空格的字符串。

nextLine():

1.以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。

2.可以获得空白。

next方式:

package com.yan.scanner;

import java.util.Scanner;

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();

    }
}

注意:扫描器和关闭扫描是一对一的

nextLine方式

package com.yan.scanner;

import java.util.Scanner;

public class Demo02 {
    public static void main(String[] args) {
        //从键盘接收数据
        Scanner scanner = new Scanner(System.in);
        System.out.println("使用nextLine方式接收:");
        //判断是否还有输入
        if (scanner.hasNextLine()){
            String str = scanner.nextLine();
            System.out.println("输出的内容为:"+str);
        }

        scanner.close();

    }
}

nextInt和nextFloat方式

package com.yan.scanner;

import java.util.Scanner;

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

        //从键盘接收数据
        int i = 0;
        float f = 0.0f;
        //如果,,,那么
        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("输入的不是小数数据!");
        }
    }
}

求和取平均

package com.yan.scanner;

import java.util.Scanner;

public class Demo05 {
    public static void main(String[] args) {
        //和
        double sum = 0;
        //计算输入了多少个数字
        int m =0;

        Scanner scanner = new Scanner(System.in);
        //通过循环判断是否还有输入,并在里面对每一次进行求和和统计
        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();
    }
}

顺序结构

JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行。

顺序结构是最简单的算法结构。

JavaSE笔记_第8张图片

语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。

package com.yan.struct;

public class ShunXuDemo {
    public static void main(String[] args) {
        System.out.println("hello1");
        System.out.println("hello2");
        System.out.println("hello3");
        System.out.println("hello4");
        System.out.println("hello5");
    }
}

if单选择结构

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

语法:

if(布尔表达式){

​ //如果布尔表达式为true将执行的语句

}

JavaSE笔记_第9张图片

package com.yan.struct;

import java.util.Scanner;

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

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

    }
}

if双选择结构

那现在有个需求,公司要收购一个软件,成功了,给人支付100万元,失败了,自己找人开发。

这样的需求用一个if就搞不定了,我们需要有两个判断,需要一个双选择结构,所以就有了if-else结构。

语法:

if(布尔表达式){

​ //如果布尔表达式为true将执行的语句

}else{

​ //如果布尔表达式的值为false

}

JavaSE笔记_第10张图片

package com.yan.struct;

import java.util.Scanner;

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();
    }
}

if多选择结构

我们发现刚才的代码不符合实际情况,真实的情况还可能存在ABCD,存在区间多级判断。比如90-100就是A,80-90就是B…等等,在生活中我们很多时候的选择也不仅仅只有两个,所以我们需要一个多选择结构来处理这类问题!

语法:

if(布尔表达式1){

​ //如果布尔表达式1的值为true将执行的语句

}else if(布尔表达式2){

​ //如果布尔表达式2为true将执行的语句

}else if(布尔表达式3){

​ //如果布尔表达式3为true将执行的语句

}else{

​ //如果以上布尔表达式都不为true将执行的语句

}

JavaSE笔记_第11张图片

package com.yan.struct;

import java.util.Scanner;

public class IfDemo03 {
    public static void main(String[] args) {
        //考试分数大于60就是及格,小于60分就不及格。
        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){
            System.out.println("恭喜满分");
        }else 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("成绩不合法");
        }
    }
}

嵌套的if结构

使用嵌套的if…else语句是合法的。也就是说你可以在另一个if或者else if语句中使用if或者else if语句。你可以像if语句一样嵌套else if…else。

语法:

if(布尔表达式 1){

//如果布尔表达式1的值为true执行代码

​ if(布尔表达式 2){

​ //如果布尔表达式 2的值为true执行代码

​ }

}

思考?我们需要寻找一个数,在1-100之间。

Switch结构

case会有穿透,所以最好加上break;

package com.yan.struct;

public class SwitchDemo01 {
    public static void main(String[] args) {
        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("再接再励");
            case 'E':
                System.out.println("挂科");
                
        }
package com.yan.struct;

public class SwitchDemo02 {
    public static void main(String[] args) {
        String name = "yan";
        //JDK7的新特性,表达式结果可以是字符串!!!
        //字符的本质还是数字

        //反编译 java---class(字节码文件)----反编译(IDEA)
        switch(name){
            case"yan":
                System.out.println("yan");
                break;
            case"yh":
                System.out.println("yh");
                break;
            default:
                System.out.println("弄啥嘞!");
        }
    }
}

while循环

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

while(布尔表达式){
    //循环内容
}

只要布尔表达式为true,循环就会一直执行下去。

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

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

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

思考:计算1+2+3+…+100=?

package com.yan.struct;

public class WhileDemo01 {
    public static void main(String[] args) {
        //输出1~100
        int i = 0;
        while(i<100){
            i++;
            System.out.println(i);
        }
    }
}
package com.yan.struct;

public class WhileDemo02 {
    public static void main(String[] args) {
        //死循环
        while(true){
            //等待客户端连接
            //定时检查
            //。。。。。。
        }
    }
}

小心卡死

package com.yan.struct;

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

do…while循环

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

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

do{
    //代码语句
}while(布尔表达式);

While和do-While的区别:

​ while先判断后执行。dowhile是先执行后判断!

​ Do…while总是保证循环体会被至少执行一次!这是他们的主要差别。

package com.yan.struct;

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

        //计算1+2+3+...+100=?
        int i = 0;
        int sum = 0;
        do {
            i++;
            sum = sum + i;
        }while(i<100);
        System.out.println(sum);
    }
}

while和do…while循环的对比

package com.yan.struct;

public class DoWhileDemo02 {
    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(初始化;布尔表达式;更新){
    //代码语句
}

练习

1.计算0到100之间的奇数和偶数的和

2.用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个

3.打印九九乘法表

1
package com.yan.struct;

public class ForDemo02 {
    public static void main(String[] args) {
        //练习1:计算0到100之间的奇数和偶数的和
        int oddsum=0;
        int ou_sum=0;
        for (int i=0;i<=100;i++){
            if (i%2==0){
                oddsum = oddsum + i;
            }
            if (i%2==1){
                ou_sum = ou_sum + i;
            }
        }
        System.out.println(oddsum);
        System.out.println(ou_sum);
    }
}
2
package com.yan.struct;

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

        //用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
        int count=0;
        for (int i = 1; i <= 1000; i++) {
            if (i%5==0){
                count = count + 1;
                System.out.print(i+"\t");
                if (count == 3) {
                    //System.out.print("\n");
                    System.out.println();
                    count = 0;
                }
            }
        }

        //println 输出完会换行
        //print 输出完不会换行
    }
}
3
package com.yan.struct;

public class ForDemo05 {
    public static void main(String[] args) {
        //1.我们先打印第一列,这个大家应该都会
        //2.我们把固定的1再用一个循环包起来
        //3.去掉重复项,i<=j
        //4.调整样式
        for (int j = 1; j <= 9; j++) {
            for (int i = 1; i < j; i++) {
                System.out.print(j+"*"+i+"="+(j*i)+"\t");
            }
            System.out.println();
        }
    }
}
//倒序
package com.yan.struct;

public class ForDemo04 {
    public static void main(String[] args) {
        int count=1;
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                if (j>=i) {
                    System.out.print(i + "x" + j + "=" + i * j+"\t");
                    if (j==9){
                        System.out.print("\n");
                    }
//                    if (j==count){
//                        System.out.print("\n");
//                    }else{
//                        System.out.print(i + "x" + j + "=" + i * j);
//                    }
                }
            }
        }
    }
}

增强for循环

这里我们先只是见一面,做个了解,之后数组我们重点使用

Java5引入了一种主要用于数组或集合的增强型for循环。

Java增强for循环语法格式如下:

for(声明语句:表达式)
{
    //代码句子
}

声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定再循环语句块,其值与此时数组元素的值相等。

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

package com.yan.struct;

public class ForDemo06 {
    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]);
        }
        //遍历数组的元素
        for (int x:numbers){
            System.out.println(x);
        }
    }
}

break continue

break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)

continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。

关于goto关键字

​ goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子—带标签的break和continue。

​ “标签”是指后面跟一个冒号的标识符,例如:label:

​ 对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。

package com.yan.struct;

public class LabelDemo {
    public static void main(String[] args) {
        //打印101-150之间所有的质数
        int count = 0;
        //不建议使用
        outer:for (int i = 101; i < 150; i++) {
            for (int j=2; j<i/2;j++){
                if (i % j == 0){
                    continue outer;
                }
            }
            System.out.print(i+" ");
        }
    }
}

打印三角形

package com.yan.struct;

public class TestDemo01 {
    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方法

何谓方法?

System.out.println(),那么它是什么呢?

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

​ 方法是解决一类问题的步骤的有序组合

​ 方法包含于类或对象中

​ 方法在程序中被创建,在其他地方被引用

设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展。

回顾:方法的命名规则?

注意:新定义的方法要使用的时候需要加上static否则无法进行调用

package com.yan.method;

public class Demo01 {
    //main方法
    public static void main(String[] args) {
        int sum = add(1, 2);
        System.out.println(sum);
    }

    //加法
    public static int add(int a,int b){
        return a+b;
    }
}

方法的定义

Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:

方法包含一个方法头和一个方法体。下面是一个方法的所有部分:

​ 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。

​ 返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。

​ 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。

​ 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。

​ 形式参数:在方法被调用时用于接受外界输入的数据。

​ 实参:调用方法时实际传给方法的数据。

​ 方法体:方法体包含具体的语句,定义该方法的功能。

JavaSE笔记_第12张图片

package com.yan.method;

public class Demo02 {
    public static void main(String[] args) {
        int max = max(30,20);
        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;
    }
}

方法的调用

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

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

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

int larger = max(30,40);

如果返回值是void,方法调用一定是一条语句。

System.out.println("Hello,yh!");

课后拓展了解:值传递(Java)和引用传递

方法的重载

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

方法的重载的规则:

​ 方法名称必须相同。

​ 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。

​ 方法的返回类型可以相同也可以不相同。

​ 仅仅返回类型不同不足以成为方法的重载。

实现理论:

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

package com.yan.method;

public class Demo03 {
    public static void main(String[] args) {
        int max = max(30,20);
        double max1 = max(30.0,20.0);
        double max2 = max(30,20);
        int max3 = max(30,20,40);
        System.out.println(max);
        System.out.println(max1);
        System.out.println(max2);
        System.out.println(max3);
    }

    //比大小
    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 double max(double num1,double num2){
        double 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(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;
    }
}

命令行传参

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

package com.yan.method;

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

JavaSE笔记_第13张图片

可变参数

  • JDK1.5开始,Java支持传递同类型的可变参数给一个方法。

  • 在方法声明中,在指定参数类型后加一个省略号(…)。

  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。

package com.yan.method;

public class Demo05 {
    public static void main(String[] args) {
        Demo05 demo05 = new Demo05();
        demo05.test(1,2,3,4,45,5);
    }
    public void test(int... i){
        System.out.println(i[0]);
        System.out.println(i[1]);
        System.out.println(i[2]);
        System.out.println(i[3]);
        System.out.println(i[4]);
        System.out.println(i[5]);
    }
}
package com.yan.method;

public class Demo06 {
    public static void main(String[] args) {
        //调用可变参数的方法
        printMax(34,3,3,2,56.5);
        printMax(new double[]{1,2,3});
    }
    public static void printMax(double... numbers){
        if (numbers.length == 0){
            System.out.println("No argument passed");
            return;
        }
        double result = numbers[0];
        //排序!
        for (int i = 0; i < numbers.length; i++) {
            if (numbers[i] > result){
                result = numbers[i];
            }
        }
        System.out.println("The max value is " + result);
    }
}

递归

A方法调用B方法,我们很容易理解!

递归就是:A方法调用A方法!就是自己调用自己

利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。

递归结构包括两个部分:

递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。

递归体:什么时候需要调用自身方法。

package com.yan.method;

public class Demo07 {
    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);
        }
    }
}

JavaSE笔记_第14张图片

JavaSE笔记_第15张图片

package com.yan.method;

import java.util.Scanner;

public class compute_Device {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入第一个数值");
        double str=0;
        double str1=0;
        while(scanner.hasNextDouble()){
            str = scanner.nextDouble();
            System.out.println("请输入操作符");
            String a = scanner.next();
            System.out.println("请输入第二个数值");
            str1 = scanner.nextDouble();
            switch (a){
                case "+":{
                    add(str,str1);
                    break;
                }
                case "-":{
                    down(str,str1);
                    break;
                }
                case "*":{
                    cheng(str,str1);
                    break;
                }
                case "/":{
                    chu(str,str1);
                    break;
                }
                default:
                    System.out.println("输入运算符错误!");
                    break;
            }
            System.out.println("输入任意字母退出");
        }
        System.out.println("感谢使用本计算器!");
        scanner.close();

    }
    public static void add(double a,double b){
        System.out.println("a+b: "+(a+b));
    }
    public static void down(double a,double b){
        System.out.println("a-b: "+(a-b));
    }
    public static void cheng(double a,double b){
        System.out.println("a*b: "+(a*b));
    }
    public static void chu(double a,double b){
        if (b==0){
            System.out.println("分母不能为0");
        }else{
            System.out.println("a/b: "+a/b);
        }
    }
}

JAVA数组

数组的定义

数组是相同类型数据的有序集合。

数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。

其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。

数组声明创建

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

dataType[] arrayRefVar;	//首选的方法
或
dataType arrayRefVar[]; //效果相同,但不是首选方法 

Java语言使用new操作符来创建数组,语法如下:

dataType[] arrayRefVar = new dataType[arraySize];

数组的元素是通过索引访问的,数组索引从0开始。

获取数组长度:

arrays.length

内存分析

Java内存分析:

JavaSE笔记_第16张图片

写代码画图分析内存!

数组的三种初始化

静态初始化

int[] a = {1,2,3};

Man[] mans = {new Man(1,1),new Man(2,2)};

动态初始化

int[] a = new int[2];

a[0]=1;

a[1]=2;

数组的默认初始化

​ 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。

package com.yan.array;

public class ArrayDemo01 {
    public static void main(String[] args) {
        //变量的类型  变量的名字  =  变量的值;
        //数组类型
        int[] nums;//1.定义 声明一个数组
        //int num2[];
        nums = new int[10]; //2.创建一个数组

        //3.给数组中元素赋值
        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;
        //获取数组长度: arrays.length

        for (int i = 0; i < nums.length; i++) {
            sum = sum + nums[i];
        }
        System.out.println("总和为:" + sum);
    }
}
package com.yan.array;

public class ArrayDemo02 {
    public static void main(String[] args) {
        //静态初始化:创建 + 赋值
        int[] a = {1,2,3,4,5,6,7,8};
        System.out.println(a[0]);
        Man[] mans = {new Man(),new Man()};
        int[] b = new int[10];
        b[0] = 10;
        b[1] = 10;
        System.out.println(b[0]);
        System.out.println(b[1]);
        System.out.println(b[2]);
        System.out.println(b[3]);
    }
}

JavaSE笔记_第17张图片

数组的四个基本特点

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

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

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

数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。

数组边界

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

public static void main(String[] args){
    int[] a = new int[2];
    System.out.println(a[2]);
}

ArrayIndexOutOfBoundsException:数组下标越界异常!

小结:

数组是相同数据类型(数据类型可以为任意类型)的有序集合

数组也是对象。数组元素相当于对象的成员变量

数组长度的确定的,不可变的。如果越界,则报:ArrayIndexOutofBounds

数组使用

  • 普通的For循环
  • For-Each循环
  • 数组作方法入参
  • 数组作返回值
package com.yan.array;

public class ArrayDemo04 {
    public static void main(String[] args) {
        int[] arrays = {1,2,3,4,5};

        //JDK1.5 没有下标
        for (int array : arrays) {
            System.out.print(array);
        }
        printArray(arrays);
        int[] reverse = reverse(arrays);
        printArray(reverse);
    }

    //打印数组元素
    public static void printArray(int[] arrays){
        for (int i = 0; i < arrays.length; i++) {
            System.out.print(arrays[i]+" ");
        }
    }

    //反转数组
    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;
    }
}

多维数组

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

二维数组

int a[][] = new int[2][5];

解析:以上二维数组a可以看成一个两行五列的数组。

思考:多维数组的使用?

num[1][0];

Arrays 类

数组的工具类java.util.Arrays

由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。

查看JDK帮助文档

Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:是“不用”而不是“不能”)

具有以下常用功能:

给数组赋值:通过fill方法。

对数组排序:通过sort方法,按升序。

比较数组:通过equals方法比较数组中元素值是否相等。

查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。

package com.yan.array;

import java.util.Arrays;

public class ArrayDemo06 {
    public static void main(String[] args){
        int[] a = {1,2,3,4,9090,31231,543,21,3,23};
        System.out.println(Arrays.toString(a));

        Arrays.sort(a);
        System.out.println(Arrays.toString(a));
        Arrays.fill(a,2);
        System.out.println(Arrays.toString(a));
    }
}

冒泡排序

冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!

冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。

我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)。

思考:如何优化?

package com.yan.array;

import java.util.Arrays;

public class ArrayDemo07 {
    public static void main(String[] args) {
        //冒泡排序
        //1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换它们的位置
        //2.每一次比较,都会产生出一个最大,或者最小的数字;
        //3.下一轮则可以少一次排序!
        //4.依次循环,直到结束!
        int[] a = {4,7,2,1,664,434,999,767};
        System.out.println(Arrays.toString(sort(a)));
    }

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

        //外层循环,判断我们这个要走多少次;
        for (int i = 0; i < array.length-1; i++) {
            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;
                }

            }
        }
        return  array;
    }
}

稀疏数组

需求:编写五子棋游戏中,有存盘退出和续上盘的功能。

JavaSE笔记_第18张图片

分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据。

解决:稀疏数组

稀疏数组介绍

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

稀疏数组得处理方式是:

​ 记录数组一共有几行几列,有多少个不同值

​ 把具有不同值得元素和行列及值记录在一个小规模得数组中,从而缩小程度的规模

如下图:左边是原始数组,右边是稀疏数组

JavaSE笔记_第19张图片

package com.yan.array;

public class ArrayDemo09 {
    public static void main(String[] args) {
        //创建一个二维数组11*11 0:没有棋子,  1:黑棋   2:白棋
        int[][] array1 = new int[11][11];
        array1[1][2] = 1;
        array1[2][3] = 2;
        for (int[] ints : array1) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
        change(array1);

    }

    //转换为稀疏数组
    //获取有效值的个数
    public static void change(int[][] a) {
        int sum = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (a[i][j] != 0) {
                    sum++;
                }
            }
        }

        int[][] arrays = new int[sum + 1][3];
        arrays[0][0] = a.length;
        arrays[0][1] = a.length;
        arrays[0][2] = sum;
        int count = 0;
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[i].length; j++) {
                if (a[i][j] != 0) {
                    count++;
                    arrays[count][0] = i;
                    arrays[count][1] = j;
                    arrays[count][2] = a[i][j];
                }
            }
        }
        //输出稀疏数组
        System.out.println("稀疏数组");
        for (int i = 0; i < arrays.length; i++) {
            System.out.println(arrays[i][0]+"\t"+arrays[i][1]+"\t"+arrays[i][2]+"\t");
        }
        System.out.println("====================");
        System.out.println("还原");
        //1.读取稀疏数组
        int[][] arrays1 = new int[arrays[0][0]][arrays[0][1]];
        //2.给其中的元素还原它的值
        for (int i = 1; i < arrays.length; i++) {
            arrays1[arrays[i][0]][arrays[i][1]] = arrays[i][2];
        }
        for (int[] ints : arrays1) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
    }

}

面向对象编程

Java的核心思想就是00P

面向过程&面向对象

面向过程思想

​ 步骤清晰简单,第一步做什么,第二步做什么…

​ 面对过程适合处理一些较为简单的问题

面向对象思想

​ 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。

​ 面对对象适合处理复杂的问题,适合处理需要多人协作的问题!

对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

什么是面向对象

面向对象编程(Object-Oriented Programming,OOP)

面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。

抽象

三大特性:封装、继承、多态

从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象

从代码运行角度考虑是先有类后有对象。类是对象的模板。

回顾方法及加深

方法的定义

​ 修饰符

​ 返回类型

​ break:跳出switch,结束循环,和return的区别

​ 方法名:注意规范就OK 见名知意

​ 参数列表:(参数类型,参数名)…

​ 异常抛出:疑问,后面讲解

方法的调用

​ 静态方法(调用时候直接 类.方法()

​ 非静态方法(调用时候需要new一个类名

​ 形参和实参

​ 值传递和引用传递

​ this关键字

值传递的话:传参之后数不会发生变化

引用传递:传参之后数就发生了实质性的变化,直接进行赋值

package com.oop.demo01;

//引用传递:对象 ,本质还是值传递
public class Demo02 {
    public static void main(String[] args) {
        Person person = new Person();

        System.out.println(person.name);//null

        Demo02.change(person);
        System.out.println(person.name);//yh
    }

    public static void change(Person person){
        //person是一个对象:指向的 ---> Person person = new Person();这是一个具体的人,可以改变属性!
        person.name = "yh";
    }

}

class Person{
    String name;//null
}

类和对象的关系

类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。

​ 动物、植物、手机、电脑…

​ Person类、Pet类、Car类等等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为。

对象是抽象概念的具体实例

​ 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。

​ 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。

我们可以将这些思想转换为代码实现

创建与初始化对象

使用new关键字创建对象

使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。

类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下俩个特点:

​ 1.必须和类的名字相同

​ 2.必须没有返回类型,也不能写void

构造器必须要掌握

类定义

package com.oop.demo02;

public class Student {

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

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

调用类

package com.oop.demo02;

public class Application {

    public static void main(String[] args) {
        //类:抽象的,实例化
        Student xiaoming = new Student();
        Student xh = new Student();

        xiaoming.name = "小明";
        xiaoming.age = 3;
        System.out.println(xiaoming.name);
        System.out.println(xiaoming.age);

        xh.name = "小红";
        xh.age = 3;
        System.out.println(xh.name);
        System.out.println(xh.age);
    }
}
package com.oop.demo02;

public class Person {

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

    String name;
    int age;

    //实例化初始值
    //1.使用new关键字,本质实在调用构造器
    //2.用来初始化值
    public Person(){

    }
    //有参构造:一旦定义了有参构造,无参就必须显示定义
    public Person(String name){
        this.name = name;
    }

    //alt+insert

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

    构造器:
        1.和类名相同
        2.没有返回值
    作用:
        1.new本质在调用构造方法
        2.初始化对象的值
    注意点:
        1.定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
*/

创建对象内存分析

JavaSE笔记_第20张图片

package com.oop.demo03;

public class Pet {

    //注意:要写public
    public String name;
    public int age;

    public void shout(){
        System.out.println("叫了一声");
    }
}
package com.oop;

import com.oop.demo03.Pet;
public class Application {

    public static void main(String[] args) {
        Pet dog = new Pet();
        dog.name = "旺财";
        dog.age = 3;
        dog.shout();

        System.out.println(dog.name);
        System.out.println(dog.age);
        dog.shout();
    }
}

简单小结类和对象

/*
1.类与对象
    类是一个模板:抽象,对象是一个具体的实例
2.方法
    定义、调用!
3.对应的引用
    引用类型: 基本类型(8)
    对象是通过引用来操作的:栈--->堆
4.属性:字段Field 成员变量
    默认初始化:
         数字:0   0.0
         char:u0000
         boolean:false
         引用:null
    修饰符 属性类型 属性名 = 属性值!
 5.对象的创建和使用
    - 必须使用new 关键字创造对象,构造器 Person yh = new Person();
    - 对象的属性  yh.name
    - 对象的方法  yh.sleep()

 6.类:
    静态的属性   属性
    动态的行为   方法
 */

封装

该露的露,该藏的藏

​ 我们程序设计要求”高内聚,低耦合“。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。

封装(数据的隐藏)

​ 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

记住这句话就够了:属性私有,get/set

先定义一个Student类

package com.oop.demo04;

public class Student {
    private String name;
    private int id;
    private char sex;
    private int age;

    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 char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

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

    }
}

然后间接调用

package com.oop;

import com.oop.demo04.Student;

/*
    1. 提高程序的安全性,保护数据
    2. 隐藏代码的实现细节
    3. 统一接口
    4. 系统可维护增加了
 */
public class Application_1 {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setName("yh");
        System.out.println(s1.getName());
        s1.setAge(-1); //不合法的
        System.out.println(s1.getAge());
        s1.setAge(999); //不合法的
        System.out.println(s1.getAge());
        s1.setAge(20); //合法的
        System.out.println(s1.getAge());
    }
}

继承

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

extends的意思是”扩展“。子类是父类的扩展。

JAVA中类只有单继承,没有多继承

继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。

继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。

子类和父类之间,从意义上讲应该具有”is a“的关系。

object类

super

方法重写

  • 父类
package com.oop.demo05;

//在Java中,所有的类,都默认直接或者间接继承Object
//Person 人  : 父类
public class Person {

    //public
    //protected
    //default
    //private


    public int money = 10_0000_0000;
    public void say(){
        System.out.println("说了一句话");
    }
}
  • 子类
package com.oop.demo05;

//学生 is 人 :派生类,子类
//子类继承了父类,就会拥有父类的全部方法!
public class Student extends Person{
        //CTRL+H
}
  • 应用
package com.oop;

import com.oop.demo05.Student;

public class Application_jicheng {

    public static void main(String[] args) {
        Student student = new Student();
        student.say();
        System.out.println(student.money);
    }

}

super注意点:
1.super调用父类的构造方法,必须在构造方法的第一个
2.super必须只能出现在子类的方法或者构造方法中!
3.super和this不能同时调用构造方法!

Vs this:
代表的对象不同:
this:本身调用者这个对象
super:代表父类对象的应用
前提
this:没有继承也可以使用
super:只能在继承条件才可以使用
构造方法
this();本类的构造
super():父类的构造!

Student类—子类

package com.oop.Demo06;

//学生 is 人 : 派生类,子类
//子类继承了父类,就会拥有父类的全部方法!!
public class Student extends Person {

    public Student() {
        //隐藏代码;调用了父类的无参构造
        super(); //调用父类的构造器,必须要在子类的第一行
        System.out.println("Student无参执行了");
    }

    private String name = "yh";

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

    public void test1(){
        print();
        this.print();
        super.print();
    }

    public void test(String name){
        System.out.println(name);//yh
        System.out.println(this.name);//yh
        System.out.println(super.name);//yan
    }
}

Person类—父类

package com.oop.Demo06;

//在Java中,所有的类,都默认直接或者间接继承Object
//Person 人 : 父类
public class Person {

    public Person() {
        System.out.println("Person无参执行了");
    }

    protected String name = "yan";

    //私有的东西无法被继承!!
    public void print(){
        System.out.println("Person");
    }

}

主函数调用

package com.oop;

import com.oop.Demo06.Student;

public class Application_super {

    public static void main(String[] args) {

        Student student = new Student();
        student.test("yh");
        student.test1();
    }
}

重写

A类

package com.oop.demo07;

public class A extends B{

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

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

}

B类

package com.oop.demo07;

//重写都是方法的重写,和属性无关
public class B {

    public static void test(){
        System.out.println("B=>test()");
    }
    public void test1(){
        System.out.println("D=>test()");
    }



}

应用

package com.oop;

import com.oop.demo07.A;
import com.oop.demo07.B;

public class Application_chongxie {

    //静态的方法和非静态的方法区别很大!
    //静态方法: //方法的调用只和左边,定义的数据类型有关
    //非静态:重写
    public static void main(String[] args) {
        A a = new A();
        a.test();//A

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

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

为什么需要重写:
    1.父类的功能,子类不一定需要,或者不一定满足!
    ALT + Insert ; override;

多态

动态编译:类型:可扩展性

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

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

多态存在的条件

​ 有继承关系

​ 子类重写父类方法

​ 父类引用指向子类对象

注意:多态是方法的多态,属性没有多态性。

instanceof

父类

package com.oop.demo08;

public class Person {

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

}

/*
多态注意事项:
    1. 多态是方法的多态,属性没有多态
    2.父类和子类,有联系  类型转换异常!  ClassCastException
    3.存在条件 : 继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new Son();
        1.static 方法,属于类,它不属于实例
        2.final 常量;
        3.private 方法

 */

子类

package com.oop.demo08;

public class Student extends Person{
    @Override
    public void run() {
        System.out.println("son");
    }

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

}

调用多态

package com.oop;

import com.oop.demo08.Person;
import com.oop.demo08.Student;

public class Application_duotai {

    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.eat();//子类重写了父类的方法,执行子类的方法
        s1.eat();
        s1.run();

    }
}

多态2

Person类

package com.oop.demo09;

public class Person {

    public void run(){

    }
}

Student类

package com.oop.demo09;

public class Student extends Person {

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

Teacher类

package com.oop.demo09;

public class Teacher extends Person{

}

调用Application_instance_of

package com.oop;

import com.oop.demo09.Person;
import com.oop.demo09.Student;
import com.oop.demo09.Teacher;

import java.time.Year;

public class Application_instance_of {

    public static void main(String[] args) {

        //类型之间的转化: 父   子
        //高                  低
        Person obj = new Student();

        //Student student = (Student) obj;
        //student.go();
        //student将这个对象转换为Student类型,我们就可以使用Student类型的方法了!
        ((Student) obj).go();

    }
}

/*
1.父类引用指向子类的对象
2.把子类转化为父类,向上转型;
3.把父类转化为子类,向下转型;强制转换
4.方便方法的调用,减少重复的代码!简洁

抽象:  封装、继承、多态!
 */


/*
        //Object > String
        //Object > Person > Teacher
        //Object > Person > Student
        Object object = new Student();

        //System.out.println(X instanceof Y); //能不能编译通过!

        System.out.println(object instanceof Student); //true
        System.out.println(object instanceof Person); //true
        System.out.println(object instanceof Object); //true
        System.out.println(object instanceof Teacher); //false
        System.out.println(object instanceof String); //false

        System.out.println("================================");
        Person person = new Student();

        System.out.println(person instanceof Student); //true
        System.out.println(person instanceof Person); //true
        System.out.println(person instanceof Object); //true
        System.out.println(person instanceof Teacher); //false
        //person和String属于同一级别无法比较
        //System.out.println(person instanceof String); //false
        System.out.println("================================");
        Student student = new Student();

        System.out.println(student instanceof Student); //true
        System.out.println(student instanceof Person); //true
        System.out.println(student instanceof Object); //true
        //System.out.println(student instanceof Teacher); //false
        //person和String属于同一级别无法比较
        //System.out.println(student instanceof String); //false

 */

Static关键字详解

Person类

package com.oop.demo10;

public class Person {

    //顺序:静态代码块>匿名代码块>构造方法
    //2
    {
        System.out.println("匿名代码块");
    }

    //1 静态方法只执行一次 非静态调用(new)一次,执行一次
    static {
        System.out.println("静态代码块");
    }

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

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

    }
}

Student类

package com.oop.demo10;

public class Student {

    private static int age;//静态的变量  多线程!
    private double score;//非静态的变量

    public void run(){

    }

    public static void go(){

    }

    public static void main(String[] args) {
        new Student().run();
        Student.go();
    }
}

Test类

package com.oop.demo10;

//静态导入包!
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);
    }

}

抽象类

abstract 只有方法名字,没有方法的实现

抽象类定义

package com.oop.demo11;

//abstract 抽象类:类 extends:   单继承~        (接口可以多继承)   插座~
public abstract class Action {

    //约束~有人帮我们实现~
    //abstract , 抽象方法,只有方法名字,没有方法的实现!
    public abstract void doSomething();

    //1. 不能new这个抽象类,只能靠子类去实现它;约束!!!
    //2. 抽象类中可以写普通的方法~
    //3. 抽象方法必须在抽象类中~
    //抽象的抽象:约束~

    //思考题? new , 存在构造器么?
                //存在的意义     抽象出来~   提高开发效率

}

抽象类调用重写方法

package com.oop.demo11;

public class A extends Action{
    @Override
    public void doSomething() {

    }
}

接口

public interface UserService{}里面只写接口函数就好void run(String name);

**public class UserServiceImpl implements UserService,TimeService{}**里面写接口函数的重写Alt+Insert

普通类:只有具体实现

抽象类:具体实现和规范(抽象方法)都有!

接口:只有规范!自己无法写方法~专业的约束!约束和实现分离:面向接口编程~

接口就是规范,定义的是一组规则,体现了现实世界中”如果你是...则必须能...“的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你是好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。

接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++、java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。

声明类的关键字是class,声明接口的关键字是interface

UserService接口的声明

package com.oop.demo12;

//interface 定义的关键字

public interface UserService {
    //接口中不能定义方法,默认的都是抽象类abstract

    void run(String name);
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);

}

TimeService接口2的声明

package com.oop.demo12;

public interface TimeService {
    void timer();
}

两个接口的调用

package com.oop.demo12;

//抽象类:extends
// 类 可以实现接口 implements 接口
// 实现了接口的类,就需要重写接口中的方法~

//多继承~
public class UserServiceImpl implements UserService,TimeService{
    public UserServiceImpl() {
        super();
    }

    @Override
    public void run(String name) {

    }

    @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() {

    }
}
作用:
    1.约束
    2.定义一些方法,让不同的人实现~ 10  ---->  1
    3.public abstract
    4.public static final
    5.接口不能被实例化~,接口中没有构造方法~
    6.implements 可以实现多个接口
    7.必须要重写接口中的方法
    8.总结博客~

内部类

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

1.成员内部类

package com.oop.demo13;

public class Outer {
    private int id=10;
    public void out(){
        System.out.println("这是外部类的方法");
    }

    public class Inner{
        public void in(){
            System.out.println("这是内部类的方法");
        }

        //获得外部类的私有属性~
        public void getID(){
            System.out.println(id);
        }
    }
}

2.静态内部类 加了一个static

package com.oop.demo13;

public class Outer {
    private int id=10;
    public void out(){
        System.out.println("这是外部类的方法");
    }

    public static class Inner{
        public void in(){
            System.out.println("这是内部类的方法");
        }

        //获得外部类的私有属性~
        public void getID(){
            System.out.println(id);
        }
    }
}

3.局部内部类

package com.oop.demo13;

public class Outer {
    private int id=10;
    public void out(){
        System.out.println("这是外部类的方法");
        class A{
            xxxxx;
        }
    }
}

4.匿名内部类

package com.oop.demo13;

public class Test {
    public static void main(String[] args) {
        //没有名字初始化类,不用讲实例保存到变量
        new Apple().eat();

        UserService userService = new UserService(){
            @Override
            public void hello() {

            }
        };
    }
}

class Apple{
    public void eat(){
        System.out.println("1");
    }
}

interface UserService{
    void hello();
}

5.lamada

异常

什么是异常?

实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再跑着,内存或硬盘可能满了。等等。

软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。

异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。

异常发生在程序运行期间,它影响了正常的程序执行流程。

简单分类

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

异常处理框架:

检查性异常:最具代表的检查性异常时用户错误或问题引起的异常,这是程序员无法遇见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单的忽略。

运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。

错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们再编译也检查不到的。

异常体系结构

Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。

在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。

JavaSE笔记_第21张图片

Error

Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。

Java虚拟机运行错误(Virtual Machine Error),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;

还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。

Exception

在Exception分支中有一个重要的子类RuntimeException(运行时异常)

​ ArrayIndexOutOfBoundsException(数组小标越界)

​ NullPointerException(空指针异常)

​ ArithmeticException(算数异常)

​ MissingResourceException(丢失资源)

​ ClassNotFoundException(找不到类)等异常,这些异常时不检查异常,程序中可以选择捕获处理,也可以不处理。

这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;

Error和Exception的区别:Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

异常处理机制

抛出异常

捕获异常

异常处理五个关键字

​ try、catch、finally、throw、throws

package com.exception;

public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        try {
            //try监控区域
            System.out.println(a/b);
            //new Test().a();
        }catch (ArithmeticException e){
            System.out.println("程序出现异常,变量b不能为0");
        }finally {  //处理善后工作
            System.out.println("finally");
        }

        //finally 可以不要finally, 假设IO,资源,关闭!
    }

    public void a(){
        b();
    }
    public void b(){
        a();
    }
}
catch(想要捕获的异常类型!) 捕获异常

其中,最高级的异常为Throwable,然后按照上面的异常类型图片层层展开,下一级Error和Exception等等等等…

其次,catch可以捕获多了异常,但只能生效一个,其中最高级的异常应该放在最后

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 e){
    System.out.println("Throwable");
}finally {  //处理善后工作
    System.out.println("finally");
}

打印错误的栈信息

e.printStackTrace(); //打印错误的栈信息

向上抛出异常

package com.exception;

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

        try {
            new Test2().test(1,0);
        }catch (ArithmeticException e){
            e.printStackTrace();
        }

    }

    //假设这方法中,处理不了这个异常。方法上抛出异常
    public void test(int a,int b) throws ArithmeticException{
        if (b==0){ //throw  throws
            throw new ArithmeticException();//主动的抛出异常,一般在方法中使用
        }
        System.out.println(a/b);
    }
}

自定义异常

使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。

在程序中使用自定义异常类,大体可分为以下几个步骤:

​ 1.创建自定义异常类。

​ 2.在方法中通过throw关键字抛出异常对象。

​ 3.如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。

​ 4.在出现异常方法的调用者中捕获并处理异常。

异常自定义

package com.exception.Demo02;

//自定义的异常类
public class MyException extends Exception {

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

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

    //toString:异常的打印信息
    @Override
    public String toString() {
        return "MyException{" +
                "detail=" + detail +
                '}';
    }
}

异常呼出

package com.exception.Demo02;

public class Test {
    //可能会存在的异常的方法
    static void test(int a) throws MyException{
        System.out.println("传递的参数为:"+a);
        if (a>10){
            throw new MyException(a); //抛出异常
        }
        System.out.println("OK");
    }

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

实际应用中的经验总结

处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理

在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常

对于不确定的代码,也可以加上try-catch,处理潜在的异常

尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出

具体如何处理异常,要根据不同的业务需求和异常类型去决定

尽量添加finally语句块去释放占用的资源,IOScanner

JavaSE回顾复习

的子类RuntimeException(运行时异常)

​ ArrayIndexOutOfBoundsException(数组小标越界)

​ NullPointerException(空指针异常)

​ ArithmeticException(算数异常)

​ MissingResourceException(丢失资源)

​ ClassNotFoundException(找不到类)等异常,这些异常时不检查异常,程序中可以选择捕获处理,也可以不处理。

这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;

Error和Exception的区别:Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

异常处理机制

抛出异常

捕获异常

异常处理五个关键字

​ try、catch、finally、throw、throws

package com.exception;

public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        try {
            //try监控区域
            System.out.println(a/b);
            //new Test().a();
        }catch (ArithmeticException e){
            System.out.println("程序出现异常,变量b不能为0");
        }finally {  //处理善后工作
            System.out.println("finally");
        }

        //finally 可以不要finally, 假设IO,资源,关闭!
    }

    public void a(){
        b();
    }
    public void b(){
        a();
    }
}
catch(想要捕获的异常类型!) 捕获异常

其中,最高级的异常为Throwable,然后按照上面的异常类型图片层层展开,下一级Error和Exception等等等等…

其次,catch可以捕获多了异常,但只能生效一个,其中最高级的异常应该放在最后

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 e){
    System.out.println("Throwable");
}finally {  //处理善后工作
    System.out.println("finally");
}

打印错误的栈信息

e.printStackTrace(); //打印错误的栈信息

向上抛出异常

package com.exception;

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

        try {
            new Test2().test(1,0);
        }catch (ArithmeticException e){
            e.printStackTrace();
        }

    }

    //假设这方法中,处理不了这个异常。方法上抛出异常
    public void test(int a,int b) throws ArithmeticException{
        if (b==0){ //throw  throws
            throw new ArithmeticException();//主动的抛出异常,一般在方法中使用
        }
        System.out.println(a/b);
    }
}

自定义异常

使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。

在程序中使用自定义异常类,大体可分为以下几个步骤:

​ 1.创建自定义异常类。

​ 2.在方法中通过throw关键字抛出异常对象。

​ 3.如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。

​ 4.在出现异常方法的调用者中捕获并处理异常。

异常自定义

package com.exception.Demo02;

//自定义的异常类
public class MyException extends Exception {

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

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

    //toString:异常的打印信息
    @Override
    public String toString() {
        return "MyException{" +
                "detail=" + detail +
                '}';
    }
}

异常呼出

package com.exception.Demo02;

public class Test {
    //可能会存在的异常的方法
    static void test(int a) throws MyException{
        System.out.println("传递的参数为:"+a);
        if (a>10){
            throw new MyException(a); //抛出异常
        }
        System.out.println("OK");
    }

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

实际应用中的经验总结

处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理

在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常

对于不确定的代码,也可以加上try-catch,处理潜在的异常

尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出

具体如何处理异常,要根据不同的业务需求和异常类型去决定

尽量添加finally语句块去释放占用的资源,IO 、Scanner~

JavaSE回顾复习
JavaSE总结

你可能感兴趣的:(java,开发语言,后端)