【后端】Java学习笔记(二周目-1)

news2024/11/24 1:29:11

环境

安装JDK8并配置环境变量

jvm+核心类库=jre
jre+开发工具=jdk

Java基础运行流程,代码从上到下,从左往右,只运行一次

桌面—>新建文件夹—>新建记事本—>打开编写代码

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

—>修改记事本名称为 Hello.java ---->路径栏输入cmd回车出现终端---->

javac Hello.java  

---->生成class文件—>运行

java Hello

过程:源文件A.java—>javac编译—>A.class—>java运行到JVM中

再打印中加入中文发现乱码,解决

文件改成ANSI格式另存覆盖原来的utf-8 或者在javac那指令改成如下

javac -encoding UTF-8 Hello.java 

IDEA的快捷键

ctrl+/ 单行注释

/**回车 文档注释

/* */ 多行注释

shift+ctrl+enter 光标到下一行,也可以补齐;

mian 生成入口函数

alt +enter 用于前面的变量定义 比如 new Scanner(System.in);

ctrl+n 查类的说明文档 比如Math类

fori 回车直接打出循环 数组a.for回车 foreach快捷键

shift+tab 向前退一格

ctrl+alt+t 可以添for while try catch 等

基础篇

命名规范

标识符(变量)规则:由字母,数字,下划线和$组成,不能以数字开头 ,不能用关键字

业内规定:

类:首字母大写,驼峰命名法

包:小写字母组成,域名倒置

变量/方法:首字母小写,驼峰命名法,需要语义化,见名知意

常量:全部大写字母,单词之间下划线隔开 要加个final修饰,不可改变

关键字:Java官方用掉的名字

数据类型

数据类型分为基本数据类型和引用数据类型(复合数据类型)

基本数据类型(四类八型)

整数类型: byte 8 short 16 int(默认) 32 long 64 数字是位数

浮点类型: float 32 单精度 double(默认) 64 双精度 float范围比long大因为它是小数的。浮点数不能用来表示精确的值,如货币

字符型: char 只有这用单引号,其他基本都是双引号 char letter = ‘A’;

布尔型 Boolean: true false(默认)

引用数据类型

它们是通过类来定义的。Java 中的引用数据类型包括:

  • 接口
  • 数组

复合数据类型有无数种,自带方法和属性,如String、Scanner、Random等

基本数据类型在内存中存储实际的值,而引用数据类型则存储对对象的引用(即内存地址)。在使用基本数据类型时,实际的值直接存储在变量中,而在使用引用数据类型时,变量存储的是对象的引用,对象本身存储在堆内存

数据类型转换

低的变高,是自动转换;高的变低必须强转,会精度损失

浮点转整需要舍弃小数位

byte到double 从低到高,byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出

------------------------------------>byte,short,char> int> long> float> double 
int i =128;   
byte b = (byte)i;

float型转换为double型

float f1=100.00f;
Float F1=new Float(f1);
double d1=F1.doubleValue();//F1.doubleValue()为Float类的返回double值型的方法

简单类型的变量转换为相应的包装类,可以利用包装类的构造函数。即:Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)

而在各个包装类中,总有形为××Value()的方法,来得到其对应的简单类型数据。

运算符

  • 算术运算符

    +、-、*、/、% 、++、-- (%取余5%2=1)

  • 关系运算符

    == 、!=、>、<、>=、<=

  • 位运算符

    & |(计算二进制的,用处少)

    7 二进制过程—> 7/2 =3 1 3/2=1 1 1/2= 1 0111 7的二进制结果倒着余数 111

    9 二进制过程—> 9/2=4 1 4/2=2 0 2/2=1 0 1/2= 1 1001 结果倒着余数 1001

    ​ 0001 7&9结果1 &必须2个是1才是1

  • 逻辑运算符

    &&(逻辑与,2真才真,也叫短路运算符,1假则不会继续下个判断了) 、||(逻辑或,1真就真)、 !(逻辑非)

  • 赋值运算符

    =、+=,-=…(c-=a 等价于 c=c-a 其他同理)

  • 条件运算符

    条件运算符也被称为三元运算符。该运算符有3个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量。

    int a = 10;
    int b = 20;
    int max = a < b ? b : a;  //10<20所以将b的值给max否则a,就是三元运算符

条件

Java 中的条件语句允许 程序 根据条件的不同执行不同的代码块

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

上面可以各种用

switch case

判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。

switch(expression){
    case value :
       //语句
       break; //可选
    case value :
       //语句
       break; //可选
    //你可以有任意数量的case语句
    default : //可选
       //语句
}
public class Test {
   public static void main(String args[]){
      int i = 2;
      switch(i){
         case 0:
            System.out.println("0");
         case 1:
            System.out.println("1");
         case 2:
            System.out.println("2");
         default:
            System.out.println("default");
      }
   }
}

匹配成功后,从当前 case 开始,后续所有 case 的值都会输出

2
default

如果i是6,都匹配不到则返回默认的default里的值,一般匹配到就break打断了

循环

Java中有三种主要的循环结构:

  • while 循环

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

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

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

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

    for循环执行的次数是在执行前就确定的

    for(初始化; 布尔表达式; 更新) {
        //代码语句
    }
    

java5引入foreach—>数组的增强型 for 循环 数组a.for回车快速生成

for(声明语句 : 表达式)
{
   //代码句子
}
public class Demo1 {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30, 40, 50};
        for (int item : numbers) {
            System.out.println(item);
        }
    }
}

配合的关键字

break主要用于停止,整个循环语句或者 switch 语句,循环语句后面的代码还会运行

continue用于循环里面让程序跳过当前循环,立刻进入下一次的循环

return用于返回方法类型指定的值也可以是对象,还能可以结束后面代码的执行

public class Demo1 {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30, 40, 50};
        for (int item : numbers) {
//            if (item == 10) {
//                continue;//跳过当前满足的条件,继续循环          ---->20,30,40,50,哈哈
//            }
            System.out.print(item);
            System.out.print(",");
            if (item == 10) {
//                break;//满足条件时候跳出循环,循环后面的哈哈还是打印---->10,哈哈
                return;//直接返回,不执行后续代码                  ---->10
            }
        }
        System.out.println("哈哈");
    }
}

总结

for和while都被称为前置判断循环 do…while是后置判断循环

while和do while都属于不确定次数的循环语句

for 是属于确定次数的循环语句

数组

数组的创建

入口函数那是推荐main(String[] args) 或者写main(String args[])

声明

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

创建数组

dataType[] arrayRefVar = new dataType[arraySize];  //动态声明
dataType[] arrayRefVar = new dataType[]{value0, value1, ..., valuek};//用的少,使用1、3
dataType[] arrayRefVar = {value0, value1, ..., valuek}; //静态声明方式

一维数组

public class Demo1 {
    public static void main(String[] args) {
        // 数组大小
        int size = 5;
        double[] myList = new double[size];
        myList[0] = 5.6;
        myList[1] = 4.5;
        myList[2] = 3.3;
        myList[3] = 13.2;
        myList[4] = 4.0;
        // 计算所有元素的总和
        double total = 0;
        for (int i = 0; i < size; i++) {
            total += myList[i];
        }
        System.out.println("总和为: " + total);
        // 查找最大元素
        double max = myList[0];
        for (int i = 1; i < myList.length; i++) {
            if (myList[i] > max) max = myList[i];
        }
        System.out.println("Max is " + max);
        System.out.println("-------------------");
        int[] arr = {1, 2, 3, 4, 5};
        for (int x : arr) {  //这里x只是变量名
            System.out.println(x);//如果里面还有一个循环int y :x
        }
    }
}

二维数组

type[][] typeName = new type[typeLength1][typeLength2];

type 可以为基本数据类型和复合数据类型,typeLength1 和 typeLength2 必须为正整数,typeLength1 为行数,typeLength2 为列数

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

a 可以看成一个两行三列的数组

public class Demo1 {
    public static void main(String[] args) {
        String[][] s = new String[2][];
        s[0] = new String[2];
        s[1] = new String[3];
        s[0][0] = new String("Good");
        s[0][1] = new String("Luck");
        s[1][0] = new String("to");
        s[1][1] = new String("you");
        s[1][2] = new String("!");
//        System.out.println(s[0][1]);//Lucky
        for (String[] strings : s) {
            for (String string : strings) {
                System.out.print(string.concat("\t"));
            }
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        String[] stu1 = {"张三", "Jx202211", "男", "22"};
        String[] stu2 = {"李四", "Jx202212", "女", "21"};
        String[] stu3 = {"王五", "Jx202213", "男", "25"};
        String[] stu4 = {"小六", "Jx202214", "女", "20"};
        String[][] stu = {stu1, stu2, stu3, stu4};
        for (int i = 0; i < stu.length; i++) {
            for (int j = 0; j < stu[i].length; j++) {
                System.out.print(stu[i][j] + "\t");
            }
            System.out.println();
        }
    }
}

函数(方法)

函数是一段具备特定功能的、高度封装的代码块

函数声明:

修饰符 返回值类型 方法名(参数类型 参数名){
    ...
    方法体
    ...
    return 返回值;
}

1、修饰符 public static 公开的 静态的
2、返回值类 void 表返回值为null,就不需要return,其他都需要
3、函数名 小驼峰命名
4、参数列表
5、方法体 要执行的代码块

public class Demo1 {
    public static void main(String[] args) {
        Demo1.nPrintln("lucky", 2);//正常静态方法调用-->类名.方法名称() 
        Demo1 demo1 = new Demo1();//如果不是静态在类上需要new出来再.
        System.out.println("最大值是" + demo1.max(1, 2));
        System.out.println("最大值是" + demo1.max(11.2, 32.2));
        printMax(new double[]{1, 2, 3});//在本类中可以直接调用,无需类名
        printMax(new double[]{});
    }

    public static void nPrintln(String message, int n) {
        for (int i = 0; i < n; i++) {
            System.out.println(message);
        }
    }

    public int max(int num1, int num2) {
        return num1 > num2 ? num1 : num2;
    }

    public Double max(Double num1, Double num2) {
        return num1 > num2 ? num1 : num2;
    }

    public static void printMax(double... numbers) {//JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法
        if (numbers.length == 0) {                  //在指定参数类型后加一个省略号...,传了个数组过来
            System.out.println("No argument passed");
            return;
        }
        double result = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            if (numbers[i] > result) {
                result = numbers[i];
            }
        }
        System.out.println("The max value is " + result);
    }
}

形参与实参:函数声明里就是形参,而调用那里输入则是实参

返回值:看声明里返回值类,void则没有返回值,如int则返回整型n,如果是类,返回一个对象类

函数的递归:即函数里调用函数自己

变量作用域:方法内声明的变量(局部变量),方法外不可用

方法重载:同一类中方法名相同,参数数量和类型不同。构造方法(对象里的)就可以利用重载

对象

世界万物皆对象,对象的特点是属性、对象的行为是方法,对象的行为必须是自发的

特征

  • 封装
  • 继承
  • 多态
封装

私有化属性并设置公有的get、set方法 IDEA右键—>生成—选择需要的

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问

比如该类是公开的属性,那么外部new这个对象时候便可以直接.属性去修改,现在我们封装了它无法直接修改需要调用set方法去修改,比如年龄想修改1000岁是不正常的,我们便可以再set方法中加逻辑

public class Lucky {
    private String name;

    public Lucky() {					//默认存在这个空构造

    }

    public Lucky(String name) {			//方法的重载
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override                 //方法的重写,原来是打印这个对象的引用地址
    public String toString() {//下面的值
        return "Lucky{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Lucky name = new Lucky("小维");
        System.out.println(name);
        Lucky name2 = new Lucky();
        name2.setName("小米");
        System.out.println(name2);
    }
}

结果:

Lucky{name=‘小维’}
Lucky{name=‘小米’}

this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突

构造函数

是一个没有返回值,并且函数名和类型相同的函数,在对象实例化的一瞬间就会执行,利用构造函数的参数,对属性进行赋值

继承

继承就是子类继承父类的属性和方法 苹果是水果可以继承水果类 食草动物是动物可以继承动物类

必须满足is-a关系 父类更通用 子类更具体

关键字是extends 写在类名后面

一个类只能继承一个抽象类, 继承不可滥用,牵一发而动全身,父类改变一次,其他全部受到影响,即耦合性过高,

继承一般继承Java官方的类

class 父类 {
}
 
class 子类 extends 父类 {
}

现在有3个类如下

public class Penguin {
    private String name;
    private int id;

    public Penguin(String myName, int myid) {
        name = myName;
        id = myid;
    }

    public void eat() {
        System.out.println(name + "正在吃");
    }

    public void sleep() {
        System.out.println(name + "正在睡");
    }

    public void introduction() {
        System.out.println("大家好!我是" + id + "号" + name + ".");
    }
}
public class Mouse {
    private String name;
    private int id;

    public Mouse(String myName, int myid) {
        name = myName;
        id = myid;
    }

    public void eat() {
        System.out.println(name + "正在吃");
    }

    public void sleep() {
        System.out.println(name + "正在睡");
    }

    public void introduction() {
        System.out.println("大家好!我是" + id + "号" + name + ".");
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Penguin penguin = new Penguin("企鹅", 1);
        penguin.eat();
        penguin.sleep();
        penguin.introduction();
        Mouse mouse = new Mouse("老鼠", 2);
        mouse.eat();
        mouse.sleep();
        mouse.introduction();
    }
}

会发现代码存在重复,导致代码量大且臃肿,而且维护性不高(主要表现是后期需要修改的时候,需要修改很多的代码,容易出错)

要从根本上解决这两段代码的问题,就需要继承,将两段代码中相同的部分提取出来组成 一个父类

public class Animal {
    private String name;
    private int id;
    public Animal(String myName, int myid) {
        name = myName;
        id = myid;
    }
    public void eat(){
        System.out.println(name+"正在吃");
    }
    public void sleep(){
        System.out.println(name+"正在睡");
    }
    public void introduction() {
        System.out.println("大家好!我是"         + id + "号" + name + ".");
    }
}

改造子类,extends单继承,子类只能有一个父类,可以多重继承比如a给b继承,b给c继承,没用过。子类不继承父类的构造器

public class Penguin  extends Animal{
    public Penguin(String myName, int myid) {
        super(myName, myid);
    }
}
public class Mouse extends Animal {
    public Mouse(String myName, int myid) {
        super(myName, myid);//调用父类的构造并传入参数
    }
}

关键字 super :放在代码里 用来子类给父类的构造函数的参数传参,还能调用父类的方法 ,不过继承就有父方法了

如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器

继承关系下

首先,会调用父类的构造函数。如果子类构造函数的第一行没有显式调用父类构造函数(通过 super()),则会自动调用父类的无参构造函数。如果父类没有无参构造函数,并且子类没有显式调用父类的其他构造函数,则编译器会报错

然后,执行父类的构造函数体

接着,再执行子类的构造函数。如果子类构造函数的第一行没有显式调用其他构造函数(通过 this()super()),则会自动调用父类的无参构造函数,然后执行子类的构造函数体

最后,执行子类的构造函数体

重写(Override)

子类定义了一个与其父类中具有相同名称、参数列表和返回类型的方法,并且子类方法的实现覆盖了父类方法的实现。 即外壳不变,核心重写!

父类的方法,子类写的一模一样,最终执行的是子类的方法

重写规则:修饰符不能强于父类,返回值类型、方法名、参数列表必须一样

重载(overloading)

在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同

多态

多态指同一个事物能呈现出多种形态的能力 多态是继承的一种体现

方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现

多态就是同一个接口,使用不同的实例而执行不同操作

多态存在的三个必要条件:

  • 继承
  • 重写
  • 父类引用指向子类对象:Parent p = new Child();

AnimalT能呈现出多种形态的能力

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法

public class Demo1 {
    public static void main(String[] args) {
        AnimalT a = new Lion();//父类引用指向子类对象,执行的是子类的方法,这就是多态   向上转型  
        a.eat();
        a.sleep();
    }
}
// 动物类 AnimalT.java
abstract class AnimalT {
    abstract void eat();
    abstract void sleep();

}
// 狮子类 Lion.java
class Lion extends AnimalT {
    public void eat() {
        System.out.println("狮子吃");
    }
    public void sleep() {
        System.out.println("狮子睡");
    }
}
// 老虎类 Tiger.java
class Tiger extends AnimalT {
    public void eat() {
        System.out.println("老虎吃");
    }
    public void sleep() {
        System.out.println("老虎睡");
    }
}
接口

接口并不是类,类描述对象的属性和方法。接口则包含类要实现的方法

接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类

接口:没有方法体的方法的集合

  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(JDK8后default也行,其他修饰符会报错)
  • JDK 1.8 以后,接口里可以有静态方法和方法体

implements关键字

使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)

public interface A {              //定义A接口interface关键字
     void eat();
     void sleep();
}
 
public interface B {               //定义B接口
     void show();
}
 
public class C implements A,B {    //实现类 需要全部实现接口中的方法
}

有方法体的方法 被称为 实例方法

没方法体的方法 被称为 抽象方法

包装类

所有的包装类**(Integer、Long、Byte、Double、Float、Short)**都是抽象类 Number 的子类

这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类。相似的,编译器也可以把一个对象拆箱为内置类型。Number 类属于 java.lang 包

public class Test{
   public static void main(String[] args){
      Integer x = 5; // x 被赋为整型值时,由于x是一个对象,所以编译器要对x进行装箱
      x =  x + 10;   //为了使x能进行加运算,所以要对x进行拆箱
      System.out.println(x); 
   }
}
修饰符
访问控制修饰符

Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

  • default (无修饰): 本类、同一包的类可见
  • private : 私有的 能且仅能在本类中使用 注意:不能修饰类(private class Demo1 )错误
  • public : 对所有类可见。使用对象:类、接口、变量、方法
  • protected : 本类、子类、同一包的类可见 注意:不能修饰类(外部类)
static

static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量

static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据

它的特性:只会在类加载的时候执行一次。

final

final 表示"最后的、最终的"含义,变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值

final修饰类中的属性或者变量 无论属性是基本类型还是引用类型,final所起的作用都是变量里面存放的“值”不能变,这个值,对于基本类型来说,变量里面放的就是实实在在的值,而引用类型变量里面放的是个地址,所以用final修饰引用类型变量指的是它里面的地址不能变,并不是说这个地址所指向的对象或数组的内容不可以变,这个一定要注意

final 修饰符通常和 static 修饰符一起使用来创建类常量。

public class MyClass {
    public static int count = 0;                 //静态变量
    public static final int MAX_SIZE = 100;      // 使用大写蛇形命名法 常量
}

访问

MyClass.count = 10; // 通过类名访问
MyClass obj = new MyClass();
obj.count = 20; // 通过实例名访问

final 属性 声明变量时可以不赋值,而且一旦赋值就不能被修改了,用来new的那个对象里有final修饰的属性那个属性必须赋值

final 方法 可以被子类继承,但是不能被子类重写。声明 final 方法的主要目的是防止该方法的内容被修改

final 类 不能被继承

abstract(抽象类)

抽象类不能用来实例化对象

一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误

抽象类可以包含抽象方法和非抽象方法

abstract class Caravan{  //被abstract修饰就是抽象类
   private double price;
   private String model;
   private String year;
   public abstract void goFast(); //抽象方法
   public abstract void changeColor();
}

抽象方法是一种没有任何实现的方法,该方法的具体实现由子类提供

抽象方法不能被声明成 final 和 static

如果一个类包含抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法

继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也必须声明为抽象类

构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法

抽象方法的声明以分号结尾,例如:public abstract sample();

public abstract class SuperClass{
    abstract void m(); //抽象方法
}
 
class SubClass extends SuperClass{
     //实现抽象方法
      void m(){
          .........
      }
}
synchronized

synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。

public synchronized void showDetails(){
.......
}
枚举类

枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一年的 12 个月份,一个星期的 7 天,方向有东南西北等—>场景:颜色(红黄蓝绿…)、星期、反射做多个oss桶时候

常量类是指一组声明为静态的、不可改变的常量变量,它们通常用于定义一些全局性的常量,如数学常数π、还有一些不变的值,项目中必定有一个常量类,final关键字,表示这些变量不能被修改—> 场景:分页的当前页、限制页数、返回的数据成功、失败…

Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割

enum Color {
    RED, GREEN, BLUE;
    private Color()    // 构造函数只能使用 private 访问修饰符,所以外部无法调用
    {
        System.out.println("Constructor called for : " + this.toString());
    }
    public void colorInfo() {//枚举既可以包含具体方法,也可以包含抽象方法。 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它
        System.out.println("枚举的方法");
    }
}

每个枚举都是通过 Class 在内部实现的,且所有的枚举值都是 public static final 的,所以可以 类名.名称

  • values() 返回枚举类中所有的值。
  • ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
  • valueOf()方法返回指定字符串值的枚举常量。
public class Demo1 {
    public static void main(String[] args) {
        Color c1 = Color.RED;
        System.out.println(c1);
        for (Color myVar : Color.values()) {
            System.out.println(myVar);
        }
        // ------------------------------------------------
        Color myVar = Color.BLUE;
        switch (myVar) {
            case RED:
                System.out.println("红色");
                break;
            case GREEN:
                System.out.println("绿色");
                break;
            case BLUE:
                System.out.println("蓝色");
                break;
        }
        // ------------------------------------------------
        Color[] arr = Color.values();
        // 迭代枚举
        for (Color col : arr) {
            // 查看索引
            System.out.println(col + " at index " + col.ordinal());
        }
        // 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException
        System.out.println(Color.valueOf("RED"));
        // ------------------------------------------------
        Color green = Color.GREEN;//下面2个结果一样
        green.colorInfo();
        Color red = Color.RED;
        red.colorInfo();
    }
}

工作中的写法1

public enum ErrorCode {
    OK(0) {
        public String getDescription() {
            return "成功";
        }
    },
    ERROR_A(100) {
        public String getDescription() {
            return "错误A";
        }
    },
    ERROR_B(200) {
        public String getDescription() {
            return "错误B";
        }
    };                            //分号
    private int code;
    // 构造方法:enum的构造方法只能被声明为private权限或不声明权限
    private ErrorCode(int number) { // 构造方法
        this.code = number;
    }
    public int getCode() { // 普通方法
        return code;
    } // 普通方法
    public abstract String getDescription(); // 抽象方法
}

写法2 效果和调用一样

public enum ErrorCodeEn {
    OK(0, "成功"),
    ERROR_A(100, "错误A"),
    ERROR_B(200, "错误B");
    ErrorCodeEn(int number, String description) {
        this.code = number;
        this.description = description;
    }
    private int code;
    private String description;
    public int getCode() {
        return code;
    }
    public String getDescription() {
        return description;
    }
}
public class Demo1 {
    public static void main(String[] args) {
        // 获取枚举常量的值
        System.out.println(ErrorCodeEn.OK.getCode()); // 输出: 0
        System.out.println(ErrorCodeEn.ERROR_A.getCode()); // 输出: 100
        System.out.println(ErrorCodeEn.ERROR_B.getCode()); // 输出: 200
        // 获取枚举常量的描述
        System.out.println(ErrorCodeEn.OK.getDescription()); // 输出: 成功
        System.out.println(ErrorCodeEn.ERROR_A.getDescription()); // 输出: 错误A
        System.out.println(ErrorCodeEn.ERROR_B.getDescription()); // 输出: 错误B

    }
}
补充

面向对象与面向过程区别

面向过程:只关注事情本身的完成,不关注谁去做,就像大象塞进冰箱,不管是谁把冰箱打开,谁把大象弄进去

面向对象:更多关注 谁去做事情 各有各的好处

对象的生命周期

对象的出生:一旦被声明被赋值之后 对象即出现

对象的销毁:当该对象没有被指向 就会被自动销毁

String a;这是空,没有对象,所以没有出生和销毁

IO流

IO 流:按照流动的方向,以内存为基准,分为输入 input 和输出 output ,即流向内存是输入流,流出内存的输出流

(1)明确要操作的数据是数据源还是数据目的(也就是要读还是要写)
(2)明确要操作的设备上的数据是字节还是文本
(3)明确数据所在的具体设备
(4)明确是否需要额外功能(比如是否需要转换流、高效流等)

输入流(读数据 硬盘---->内存)、输出流(写数据 内存—>硬盘)

分类:

1.字节流:字节流又分为字节输入流、字节输出流 2.字符流:字符流由分为字符输入流、字符输出流

字符流的由来:因为数据编码的不同,字节流直接读中文会乱码 字符流 = 字节流 + 编码表

数据流向内存就是输入流,流出内存就是输出流,根据数据的类型分为

字节流和字符流,如名字的为单位

字节流对应的输入流 InputStream 输出流 OutputStream

字符流对应的输入流 Reader 输出流 Writer

超类(父类)以这四个名称结尾都是它的子类

比如常见的 FileInputStream 文件输入流

1 个字符=2 个字节

字节流适合读取视频、音乐、图片等二进制文件,字符流比较适合读取纯文本文件

字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据

File 类

java.io.File 类是专门对文件进行操作的类,只能对文件本身进行操作,不能对文件进行读和写也就是输入和输出

File 类构造方法不会给你检验这个文件或文件夹是否真实存在,因此无论该路径下是否存在文件或者目录,都不影响 File 对象的创建。

下面一个测试类

package com.nwa;

import org.junit.Test;


import java.io.*;

/**
 * @Author Lucky友人a
 * @Date 2023/8/10 -10:34
 */
public class FileDemo {
    @Test
    public void fun1() throws IOException {
        File f = new File("C:\\Users\\FF\\Desktop\\1.txt");  //就算文件1.txt不存在也不影响file对象的创建
        if (!f.exists()) {
                System.out.println("是否创建:"+f.createNewFile()); // true 如果没有文件则创建并返回true
        }
        System.out.println("是否创建:"+f.createNewFile());  //已经存在,所以就false了
        System.out.println("文件绝对路径:"+f.getAbsolutePath());//文件绝对路径:C:\Users\FF\Desktop\1.txt
        System.out.println("文件构造路径:"+f.getPath());        //文件构造路径:C:\Users\FF\Desktop\1.txt
        System.out.println("文件名称:"+f.getName());          //文件名称:1.txt
        System.out.println("文件长度:"+f.length()+"字节");
        // 判断是文件还是目录
        System.out.println("文件:"+f.isFile());
        System.out.println("目录:"+f.isDirectory());
        //一个路径下全部文件名,先将字符串转目录
//        String path = "D:\\workspace";
//        File file = new File(path);
//        printFile(file);
    }
//结果1   传进的file不一样结果不一样,如果是绝对位置那么构造啥的都是绝对的
//    是否创建:false
//    文件绝对路径:C:\Users\FF\Desktop\1.txt
//    文件构造路径:C:\Users\FF\Desktop\1.txt
//    文件名称:1.txt
//    文件长度:0字节
//    文件:true
//    目录:false


//结果2 如果是直接1.txt则会相对这个项目来创建这个文件
//    是否创建:true
//    是否创建:false
//    文件绝对路径:E:\LuckyWorckSpace\lucky_api\1.txt
//    文件构造路径:1.txt
//    文件名称:1.txt
//    文件长度:0字节
//    文件:true
//    目录:false
    @Test
    public void testDemo2() {   //目录的创建等,使用相对这个项目下的目录来测试了
        // 目录的创建
        File f2= new File("newDira");
//        System.out.println("是否存在:"+f2.exists());// false
//        System.out.println("是否创建:"+f2.mkdir());	//  这个是创建的意思,并返回true
//        System.out.println("是否存在:"+f2.exists());// true
        // 创建多级目录
//        File f3= new File("newDira\\newDirb");
//        System.out.println(f3.mkdir());// false,没有加s指南创建单层的目录
        File f4= new File("newDira\\newDirb");
  //      System.out.println(f4.mkdirs());// true,可以创建多级别的目录

        // 文件和目录的删除  delete方法,如果此File表示目录,则目录必须为空才能删除。
      //  System.out.println(f2.delete());// true
   //     System.out.println(f4.delete());// false如果是删除多层目录只能删除最底层的比如这个的newDirb目录,外newDira没有删掉
    }

    @Test
    public void demo3() {
        File file = new File("E:\\other\\study\\学习sp\\实用篇");
        printFile(file);
    }
    public  static void printFile(File file) {
//        //获取当前目录下的文件以及文件夹的名称。
//        File[] files = file.listFiles();
//        for (File a:files) {
//
//            if (a.isFile()) {
//                System.out.println( a.getName());
//            }else {
//                printFile(a);
//            }
//        }

//        //下面的只获取一层,上面是里面全部获取
//        String[] names = file.list();
//        for(String name : names){
//            System.out.println(name);
//        }
//        //获取当前目录下的文件以及文件夹对象,只要拿到了文件对象,那么就可以获取更多信息
//        File[] files = file.listFiles(); //listFiles指定的必须是目录。否则容易引发返回数组为null,出现NullPointerException异常
//        for (File fi : files) {
//            System.out.println(fi);
//        }

//        递归全部
        //1、判断传入的是否是目录
        if(!file.isDirectory()){
            //不是目录直接退出
            return;
        }
        //已经确保了传入的file是目录
        File[] files = file.listFiles();
        //遍历files
        for (File f: files) {
            //如果该目录下文件还是个文件夹就再进行递归遍历其子目录
            if(f.isDirectory()){
                //递归
                printFile(f);
            }else {
                //如果该目录下文件是个文件,则打印对应的名字
                System.out.println(f.getName());
            }

        }
    }


    public static void demo2(){
         //从d盘下的a.txt文件拷贝到另个盘下
        try {
            File file1 = new File("D:\\workspace\\a.txt");//这是源文件
            long flen=file1.length();
            System.out.println("源文件的大小是"+flen+"字节");
            FileInputStream fis = new FileInputStream(file1);
            File file2 = new File("D:\\workspace\\b.txt");//这是复制到的地方
            FileOutputStream fos = new FileOutputStream(file2);
            byte[] bytes = new byte[1024]; //这是1兆1兆传
            int len = 0;
            long readSize=0;
            while ((len = fis.read(bytes)) != -1) {//-1就是最后一个结束
                fos.write(bytes,0,len); //比如一个文件是1024*8+244,那么len就是244
                fos.flush();//强制输出,推送数据
                readSize+=len;
                if (readSize== flen) {
                    break;
                }
            }
            System.out.println("读的大小"+readSize+"字节");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void demo1() {
        File file = new File("E:\\1.txt");
        File file1 = new File("E:\\222.txt");
        try {
            FileInputStream fis = new FileInputStream(file);
            FileOutputStream fos = new FileOutputStream(file1);
            BufferedInputStream bis = new BufferedInputStream(fis);
            byte[] bytes = new byte[1024];
            while (bis.read(bytes) != -1) {
                fos.write(bytes);
                fos.flush();
                System.out.println("aaaa");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

FileOutputStream
FileOutputStream outputStream = new FileOutputStream("abc.txt");

这行代码做了下面的事情
1、调用系统功能去创建文件【输出流对象才会自动创建】
2、创建outputStream对象
3、把foutputStream对象指向这个文件

创建输出流对象的时候,系统会自动去对应位置创建对应文件,而创建输出流对象的时候,文件不存在则会报 FileNotFoundException 异常,也就是系统找不到指定的文件异常。

当你创建一个流对象时,必须直接或者间接传入一个文件路径。比如现在我们创建一个 FileOutputStream 流对象,在该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据

为什么是输入流呢

1、因为流是相对于内存来说的,现在 abc.txt 就是要保存到磁盘里面的文本,就是说从内存---->磁盘,那必须是输出流,用 FileWrite 和 FileOutputStream 都可以

2、传入路径时候是它的一种构造方法,不会继续写到文本中,所以用它的另外的构造函数即可解决这个问题。

  • public FileOutputStream(File file, boolean append) 一般不需要用这个,因为文件创建,输出流自动会帮我们生成,没必要多此一举暂时

  • public FileOutputStream(String name, boolean append) true 表示追加数据

Windows 系统里,每行结尾是 回车+换行 ,即\r\n;
Unix 系统里,每行结尾只有 换行 ,即\n;
Mac 系统里,每行结尾是 回车 ,即\r。从 Mac OS X 开始与 Linux 统一。

FileInputStream

流进内存的,输入流

1、 FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File 对象 file 命名。
2、 FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name 命名。

当你创建一个输入流对象时,必须传一个文件路径。该路径下,如果没有该文件,会抛出 FileNotFoundException

使用字节数组读取:read(byte[] b) 效率更高

            int len = 0 ;
            byte[] bys = new byte[1024];
            while ((len = inputStream.read(bys)) != -1) {
                System.out.println(new String(bys,0,len));//len输出有效的字节数
Reader

字符输入流的所有类的超类 输入流

FileWriter

写出字符到文件的便利类 输出流

//关闭资源时,与 FileOutputStream 不同。 如果不关闭,数据只是保存到缓冲区,并未保存到文件。

// fw.close();

关闭 close 和刷新 flush
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要 flush 方法了。

flush :刷新缓冲区,流对象可以继续使用。清空缓冲区的数据流
close:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

缓冲流

1、使用了底层流对象从具体设备上获取数据,并将数据存储到缓冲区的数组内。
2、通过缓冲区的 read()方法从缓冲区获取具体的字符数据,这样就提高了效率。
3、如果用 read 方法读取字符数据,并存储到另一个容器中,直到读取到了换行符时,将另一个容器临时存储的数据转成字符串返回,就形成了 readLine()功能。

也就是说在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统 IO 次数,从而提高读写的效率。

缓冲书写格式为 BufferedXxx,按照数据类型分类:

字节缓冲流:BufferedInputStream,BufferedOutputStream
字符缓冲流:BufferedReader,BufferedWriter
构造方法
public BufferedInputStream(InputStream in) :创建一个新的缓冲输入流,注意参数类型为 InputStream。
public BufferedOutputStream(OutputStream out): 创建一个新的缓冲输出流,注意参数类型为 OutputStream。

BufferedReader:public String readLine(): 读一行数据。 读取到最后返回 null,就这个特别一点,判断条件都需要修改了
BufferedWriter:public void newLine(): 换行,由系统属性定义符号。

转换流

简单一点的说就是:

编码:字符(能看懂的)–字节(看不懂的)

解码:字节(看不懂的)–>字符(能看懂的)

String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组
byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组

编码:把看得懂的变成看不懂的
String -- byte[]

解码:把看不懂的变成看得懂的
byte[] -- String

字符集 Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。

在 java 开发工具 IDEA 中,使用 FileReader 读取项目中的文本文件。由于 IDEA 的设置,都是默认的 UTF-8 编码,所以没有任何问题。但是,当读取 Windows 系统中创建的文本文件时,由于 Windows 系统的默认是 GBK 编码,就会出现乱码。

转换流 java.io.InputStreamReader,是 Reader 的子类,从字面意思可以看出它是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法
InputStreamReader(InputStream in): 创建一个使用默认字符集的字符流。
InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集的字符流。

构造代码如下:

InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt") , "GBK");

OutputStreamWriter同理

案例 1
package com.nwa;

import org.junit.Test;


import java.io.*;

/**
 * @Author Lucky友人a
 * @Date 2023/8/10 -10:34
 */
public class FileDemo {
    @Test
    public void fun1() throws IOException {
        File f = new File("C:\\Users\\FF\\Desktop\\1.txt");  //就算文件1.txt不存在也不影响file对象的创建
        if (!f.exists()) {
                System.out.println("是否创建:"+f.createNewFile()); // true 如果没有文件则创建并返回true
        }
        System.out.println("是否创建:"+f.createNewFile());  //已经存在,所以就false了
        System.out.println("文件绝对路径:"+f.getAbsolutePath());//文件绝对路径:C:\Users\FF\Desktop\1.txt
        System.out.println("文件构造路径:"+f.getPath());        //文件构造路径:C:\Users\FF\Desktop\1.txt
        System.out.println("文件名称:"+f.getName());          //文件名称:1.txt
        System.out.println("文件长度:"+f.length()+"字节");
        // 判断是文件还是目录
        System.out.println("文件:"+f.isFile());
        System.out.println("目录:"+f.isDirectory());
        //一个路径下全部文件名,先将字符串转目录
//        String path = "D:\\workspace";
//        File file = new File(path);
//        printFile(file);
    }
//结果1   传进的file不一样结果不一样,如果是绝对位置那么构造啥的都是绝对的
//    是否创建:false
//    文件绝对路径:C:\Users\FF\Desktop\1.txt
//    文件构造路径:C:\Users\FF\Desktop\1.txt
//    文件名称:1.txt
//    文件长度:0字节
//    文件:true
//    目录:false


//结果2 如果是直接1.txt则会相对这个项目来创建这个文件
//    是否创建:true
//    是否创建:false
//    文件绝对路径:E:\LuckyWorckSpace\lucky_api\1.txt
//    文件构造路径:1.txt
//    文件名称:1.txt
//    文件长度:0字节
//    文件:true
//    目录:false
    @Test
    public void testDemo2() {   //目录的创建等,使用相对这个项目下的目录来测试了
        // 目录的创建
        File f2= new File("newDira");
//        System.out.println("是否存在:"+f2.exists());// false
//        System.out.println("是否创建:"+f2.mkdir());	//  这个是创建的意思,并返回true
//        System.out.println("是否存在:"+f2.exists());// true
        // 创建多级目录
//        File f3= new File("newDira\\newDirb");
//        System.out.println(f3.mkdir());// false,没有加s指南创建单层的目录
        File f4= new File("newDira\\newDirb");
  //      System.out.println(f4.mkdirs());// true,可以创建多级别的目录

        // 文件和目录的删除  delete方法,如果此File表示目录,则目录必须为空才能删除。
      //  System.out.println(f2.delete());// true
   //     System.out.println(f4.delete());// false如果是删除多层目录只能删除最底层的比如这个的newDirb目录,外newDira没有删掉
    }

    @Test
    public void demo3() {
        File file = new File("E:\\other\\study\\学习sp\\实用篇");
        printFile(file);
    }
    public  static void printFile(File file) {
//        //获取当前目录下的文件以及文件夹的名称。
//        File[] files = file.listFiles();
//        for (File a:files) {
//
//            if (a.isFile()) {
//                System.out.println( a.getName());
//            }else {
//                printFile(a);
//            }
//        }

//        //下面的只获取一层,上面是里面全部获取
//        String[] names = file.list();
//        for(String name : names){
//            System.out.println(name);
//        }
//        //获取当前目录下的文件以及文件夹对象,只要拿到了文件对象,那么就可以获取更多信息
//        File[] files = file.listFiles(); //listFiles指定的必须是目录。否则容易引发返回数组为null,出现NullPointerException异常
//        for (File fi : files) {
//            System.out.println(fi);
//        }

//        递归全部
        //1、判断传入的是否是目录
        if(!file.isDirectory()){
            //不是目录直接退出
            return;
        }
        //已经确保了传入的file是目录
        File[] files = file.listFiles();
        //遍历files
        for (File f: files) {
            //如果该目录下文件还是个文件夹就再进行递归遍历其子目录
            if(f.isDirectory()){
                //递归
                printFile(f);
            }else {
                //如果该目录下文件是个文件,则打印对应的名字
                System.out.println(f.getName());
            }

        }
    }


    public static void demo2(){
         //从d盘下的a.txt文件拷贝到另个盘下
        try {
            File file1 = new File("D:\\workspace\\a.txt");//这是源文件
            long flen=file1.length();
            System.out.println("源文件的大小是"+flen+"字节");
            FileInputStream fis = new FileInputStream(file1);
            File file2 = new File("D:\\workspace\\b.txt");//这是复制到的地方
            FileOutputStream fos = new FileOutputStream(file2);
            byte[] bytes = new byte[1024]; //这是1兆1兆传
            int len = 0;
            long readSize=0;
            while ((len = fis.read(bytes)) != -1) {//-1就是最后一个结束
                fos.write(bytes,0,len); //比如一个文件是1024*8+244,那么len就是244
                fos.flush();//强制输出,推送数据
                readSize+=len;
                if (readSize== flen) {
                    break;
                }
            }
            System.out.println("读的大小"+readSize+"字节");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void demo1() {
        File file = new File("E:\\1.txt");
        File file1 = new File("E:\\222.txt");
        try {
            FileInputStream fis = new FileInputStream(file);
            FileOutputStream fos = new FileOutputStream(file1);
            BufferedInputStream bis = new BufferedInputStream(fis);
            byte[] bytes = new byte[1024];
            while (bis.read(bytes) != -1) {
                fos.write(bytes);
                fos.flush();
                System.out.println("aaaa");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

案例 2
package com.nwa;

import org.junit.Test;
import org.omg.CORBA.PUBLIC_MEMBER;

import java.io.*;

/**
 * @Author Lucky友人a
 * @Date 2023/8/10 -14:14
 */
public class IoDemo {
    @Test
    public void demo1() throws IOException {
        //public void write(int b)
        //public void write(byte[] b)
        //public void write(byte[] b,int off,int len)  //从`off`索引开始,`len`个字节
        //构造方法中加入true即可追加数据,否则就是清空了
        FileOutputStream fos = new FileOutputStream("a.txt", true);//输出流,如果没有文件则帮忙创,有的话清空里面数据
        fos.write(97);//对于内存里流向本地磁盘,所以是输出流,而且会帮忙创建文件,并写入数据,所以才会清空
        fos.write(("我要吃汉堡").getBytes());
        fos.close();
        //a我要吃汉堡    97字节对于的是小写的a,字符串这个是转字节了
        FileWriter fileWriter = new FileWriter("b.txt");
        fileWriter.write("ss");//这个可以直接写入
        fileWriter.close();

        //写出指定长度字节数组:write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节
        // 使用文件名称创建流对象
        FileOutputStream fos2 = new FileOutputStream("a2.txt");
        // 字符串转换为字节数组
        byte[] b = "abcde".getBytes();
        // 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。
        fos2.write(b, 2, 2);
        // 关闭资源
        fos2.close();
    }

    @Test
    public void delTxt() {
        new File("a.txt").delete();
    }

    @Test
    public void arrDemo() throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        // 定义字节数组
        byte[] words = {97, 98, 99, 100, 101};
        // 遍历数组
        for (int i = 0; i < words.length; i++) {
            // 写出一个字节
            fos.write(words[i]);
            // 写出一个换行, 换行符号转成数组写出
            fos.write("\r\n".getBytes());
        }
        // 关闭资源
        fos.close();
    }

    @Test
    public void inputS() throws IOException {
        // 使用File对象创建流对象
        File file = new File("a2.txt");//这个文本中只有cd2个字符
        FileInputStream fis = new FileInputStream(file);//我把a.txt删了它就找不到了报错
//        int read = fis.read();
//        System.out.println((char)read);//不加char的话会转数字那种99---c
//        int read1 = fis.read();//继续读取下一个字符
//        System.out.println((char)read1);
//        int read2 = fis.read();//如果是最后一个字符,它会返回-1,通过-1知道到底了
//        System.out.println(read2);
//        fis.close();
        //改进版1
//        int b;
//        while ((b = fis.read()) != -1) {
//            System.out.println((char)b);
//        }
//        fis.close();
        //改进版2将文本里的值变成的abced,一次读取2个,结果出现了abcded
        //1 a  b  2  c  d  3e  d  因为没替换就流着了,要解决一下改进3
        // 定义变量,作为有效个数
//        int len;
//        // 定义字节数组,作为装字节数据的容器
//        byte[] b = new byte[2];
//        // 循环读取
//        while (( len= fis.read(b))!=-1) {
//            // 每次读取后,把数组变成字符串打印
//            System.out.println(new String(b));
//        }
        // 关闭资源
        //  fis.close();
//        改进3
        int len;
        // 定义字节数组,作为装字节数据的容器
        byte[] b = new byte[2];
        // 循环读取
        while ((len = fis.read(b)) != -1) {
            // 每次读取后,把数组变成字符串打印
            System.out.println(new String(b, 0, len));//len是每次读取有效的个数
        }
        // 关闭资源
        fis.close();
    }

    @Test
    public void copyPic() throws IOException {//将本地图片复制到项目下面
        FileInputStream fis = new FileInputStream("C:\\Users\\FF\\Desktop\\6.png");//输入流到内存
        FileOutputStream fos = new FileOutputStream("1.png");//内存输出到项目下面
        byte[] b = new byte[1024];
        int len;
        while ((len = fis.read(b)) != -1) {
            fos.write(b, 0, len);
        }
        fos.close();
        fis.close();
    }

    @Test
    public void readI() throws IOException {
        FileInputStream fis = new FileInputStream("1.txt");//输入流。文本中是中文你是大聪明,正常字节流去解析会乱码
        int len;
        byte[] bytes = new byte[1024];
        while ((len = fis.read(bytes)) != -1) {
            System.out.println((char) len);  //乱码
            System.out.print(new String(bytes, 0, len));//String里自带了utf8解码所以可以。不过比较麻烦直接字符流解决
        }
        //下面用字符流
        FileReader fr = new FileReader("1.txt");
        int len2;
        while ((len2 = fr.read()) != -1) {
            System.out.print((char) len2);
        }
    }

    @Test
    public void copyText() throws  IOException{
        FileWriter fileWriter = new FileWriter("66.md");
        FileReader fileReader = new FileReader("E:\\后端代码接收解析.md");
        char[] c=new char[1024];
        int len;
        while ((len = fileReader.read(c)) != -1) {
            fileWriter.write(c, 0, len);

        }
        fileWriter.flush();//清空缓冲区的数据流
        fileWriter.close();
        fileReader.close();
    }
    //下面开始测试缓存流的速度效率,1是正常,2是加入缓存

    @Test
    public void Buff1() throws  IOException{
        long start = System.currentTimeMillis();
        FileOutputStream fos = new FileOutputStream("ps2015.zip");
        FileInputStream fis = new FileInputStream("E:\\other\\装机必备软件\\必备软件\\ps2015.zip");
        byte[] bytes = new byte[1024];
        int len;
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }
        fis.close();
        fos.close();
        // 记录结束时间
        long end = System.currentTimeMillis();
        System.out.println("普通流复制时间:"+(end - start)+" 毫秒");//33000
    }
    @Test
    public void Buff2() throws  IOException{
        long start = System.currentTimeMillis();
        BufferedOutputStream fos =new   BufferedOutputStream(new FileOutputStream("ps2015.zip")) ;
        BufferedInputStream fis =new BufferedInputStream(new FileInputStream("E:\\other\\装机必备软件\\必备软件\\ps2015.zip")) ;
        byte[] bytes = new byte[1024];
        int len;
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }
        fis.close();
        fos.close();
        // 记录结束时间
        long end = System.currentTimeMillis();
        System.out.println("缓冲流复制时间:"+(end - start)+" 毫秒");//缓冲流复制时间:4314 毫秒
    }

    @Test
    public void BuffRead() throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("b.txt"));//       两个黄鹂鸣翠柳,一行白鹭上青天。 窗含西岭千秋雪,门泊东吴万里船。
        System.out.println(br.readLine()); // 读取一行的
        String len=null;
        while ((len = br.readLine()) != null) {
            System.out.println((len));
        }
        br.close();
    }

    @Test
    public void transform() throws IOException{
        // 定义文件路径,文件为gbk编码
        String FileName = "C:\\Users\\FF\\Desktop\\1.txt";
        // 创建流对象,默认UTF8编码
        InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName));
        // 创建流对象,指定GBK编码
        InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName) , "GBK");
        // 定义变量,保存字符
        int read;
        // 使用默认编码字符流读取,乱码
        while ((read = isr.read()) != -1) {
            System.out.print((char)read);
        }
        isr.close();

        // 使用指定编码字符流读取,正常解析
        while ((read = isr2.read()) != -1) {
            System.out.print((char)read); //如果这个txt默认是ANSI编码就需要GBK就不会乱码,如果本身就utf就不需要编码了
        }
        isr2.close();
    }


}

异常处理

异常处理是一种重要的编程概念,用于处理程序执行过程中可能出现的错误或异常情况

必须捕获的异常,包括Exception及其子类,但不包括RuntimeException及其子类,这种类型的异常称为Checked Exception

不需要捕获的异常,包括Error及其子类,RuntimeException及其子类

  • 数值类型的格式错误------------NumberFormatException
  • 要打开的文件不存在------------FileNotFoundException
  • 空指针------------NullPointerException------------对某个null的对象调用方法或字段
  • 数组索引越界------------ArrayIndexOutOfBoundsException
  • 数据库表不存在
  • 向方法传递了一个不合法或不正确的参数
  • 无法加载某个Class------------NoClassDefFoundError
  • 栈溢出------------StackOverflowError

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

所有的异常类是从 java.lang.Exception 类继承的子类。

Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error

异常类有两个主要的子类:IOException 类和 RuntimeException 类

捕获异常

如果不捕获异常,就需要抛出异常,直到有人捕获或者最高一级

使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。ctrl+alt+t

throws 是写在类那里--------------------throw 是直接在方法里面抛出

try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:

try
{
   // 程序代码
}catch(ExceptionName e1)
{
   //Catch 块
}

throw 关键字用于在代码中抛出异常,而 throws 关键字用于在方法声明中指定可能会抛出的异常类型

当方法内部throws抛出指定类型的异常时,该异常会被传递给调用该方法的代码,并在该代码中处理异常。

public class Demo1 {
    public static void main(String[] args) {
//        Scanner scanner = new Scanner(System.in);
//        scanner = null;
//        scanner.next();                                               //空指针java.lang.NullPointerException

//        int[] a = new int[]{1, 2};
//        System.out.println(a[2]);                                     //数组索引越界java.lang.ArrayIndexOutOfBoundsException

//        try {
//            System.out.println(11 / 0);                               //0不能为除数java.lang.ArithmeticException异常
//        } catch (ArithmeticException e) {
//            System.out.println("捕获到了0不能为除数的异常");//这里抛出了运行时异常
//        } catch (Exception e) {//最大异常,上面捕获了下面就捕获了
//            throw new RuntimeException(e); //这里抛出了运行时异常
//        } finally {
//            System.out.println("这里必运行,一般用来关闭");
//        }

//        checkNumber(-1);//非法参数异常IllegalArgumentException
        try {
            //  readFile("D:\\1.txt");//去d盘新建1.txt,内容随便写点
            readFile("D:\\1.txt");//没找到就会有异常
            System.out.println("找到了");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    public static void checkNumber(int num) {
        if (num < 0) {
            throw new IllegalArgumentException("Number must be positive");//当代码执行到某个条件下无法继续正常执行时,可以使用 throw 关键字抛出异常,以告知调用者当前代码的执行状态
        }
    }

    public static void readFile(String filePath) throws IOException {// 包含了文件没找到异常,如果还有其他异常,隔开继续写
        BufferedReader reader = new BufferedReader(new FileReader(filePath));
        String line = reader.readLine();
        while (line != null) {
            System.out.println(line);
            line = reader.readLine();
        }
        reader.close();
    }
}

JDK7 之后,Java 新增的 try-with-resource 语法结构,旨在自动管理资源,确保资源在使用后能够及时关闭,避免资源泄露 。

try (resource declaration) {
  // 使用的资源
} catch (ExceptionType e1) {
  // 异常块
}
public class Demo1 {
    public static void main(String[] args) {
        String line;
        try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {//如果多个;隔开继续new
            while ((line = br.readLine()) != null) {
                System.out.println("Line =>" + line);
            }
        } catch (IOException e) {
            System.out.println("IOException in try block =>" + e.getMessage());
        }
    }
}

结果:IOException in try block =>test.txt (系统找不到指定的文件。)

public class Demo1 {
    public static void main(String[] args) {
        BufferedReader br = null;
        String line;
        try {
            System.out.println("Entering try block");
            br = new BufferedReader(new FileReader("test.txt"));
            while ((line = br.readLine()) != null) {
                System.out.println("Line =>" + line);
            }
        } catch (IOException e) {
            System.out.println("IOException in try block =>" + e.getMessage());
        } finally {//比较繁琐
            System.out.println("Entering finally block");
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                System.out.println("IOException in finally block =>" + e.getMessage());
            }
        }
    }
}
全局异常处理器

在应用程序中,当抛出异常时,如果没有特定的异常处理器来处理该异常,就会尝试使用全局异常处理器来处理

@RestControllerAdvice
public class RRExceptionHandler {
	private Logger logger = LoggerFactory.getLogger(getClass());
	/**
	 * 处理自定义异常
	 */
	@ExceptionHandler(RRException.class)
	public R handleRRException(RRException e){
		R r = new R();
		r.put("code", e.getCode());
		r.put("msg", e.getMessage());

		return r;
	}
	@ExceptionHandler(NoHandlerFoundException.class)
	public R handlerNoFoundException(Exception e) {
		logger.error(e.getMessage(), e);
		return R.error(404, "路径不存在,请检查路径是否正确");
	}
	@ExceptionHandler(DuplicateKeyException.class)
	public R handleDuplicateKeyException(DuplicateKeyException e){
		logger.error(e.getMessage(), e);
		return R.error("数据库中已存在该记录");
	}
	@ExceptionHandler(AuthorizationException.class)
	public R handleAuthorizationException(AuthorizationException e){
		logger.error(e.getMessage(), e);
		return R.error("没有权限,请联系管理员授权");
	}
	@ExceptionHandler(Exception.class)
	public R handleException(Exception e){
		logger.error(e.getMessage(), e);
		return R.error();
	}
}

自定义异常类

public class RRException extends RuntimeException {
	private static final long serialVersionUID = 1L;
    private String msg;
    private int code = 500;
   
    public RRException(String msg) {
		super(msg);
		this.msg = msg;
	}
	public RRException(String msg, Throwable e) {
		super(msg, e);
		this.msg = msg;
	}
	public RRException(String msg, int code) {
		super(msg);
		this.msg = msg;
		this.code = code;
	}
	public RRException(String msg, int code, Throwable e) {
		super(msg, e);
		this.msg = msg;
		this.code = code;
	}
	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}
	public int getCode() {
		return code;
	}
	public void setCode(int code) {
		this.code = code;
	}
}

API

Random

获取随机数

public class Demo1 {
    public static void main(String[] args) {
        Random random = new Random(); //new出这个对象
        int randomValue1 = random.nextInt(2);  //调用这个对象的方法 范围是0~1的整数
        System.out.println(randomValue1);
        int randomValue2 = random.nextInt(90) + 10;//范围是10-99的整数
        System.out.println(randomValue2);
        int randomValue3 = random.nextInt(1000) - 500;//范围-500~500,500取不到
        System.out.println(randomValue3);
    }
}
Scanner

获取控制台输入的值

public class Demo1 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入名称:");
        String name = scanner.nextLine();
        System.out.println("请输入密码:");
        String pwd = scanner.nextLine();
        System.out.println(name + "--左名称右密码--" + pwd);
        System.out.println("请输入整数n:");
        int i = 0;
        if (scanner.hasNextInt()) {                        //加个判断防止异常,还有hasNextDouble等
            i = scanner.nextInt();                         // 判断输入的是否是整数
            System.out.println("整数数据:" + i);
        } else {
            System.out.println("输入的不是整数!");           // 输入错误的信息
        }
        System.out.println("i为" + i);
        scanner.close();                                   //用完就关闭
    }
}

Date

java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象

public class Demo1 {
    public static void main(String[] args) {
        Date date = new Date();
        // 参考https://www.runoob.com/java/java-date-time.html
        System.out.printf("全部日期和时间信息:%tc%n", date);
        System.out.printf("年-月-日格式:%tF%n", date);
        System.out.printf("月/日/年格式:%tD%n", date);
        System.out.printf("HH:MM:SS PM格式(12时制):%tr%n", date);
        System.out.printf("HH:MM:SS格式(24时制):%tT%n", date);
        System.out.printf("HH:MM格式(24时制):%tR%n", date);
        System.out.printf("%tY-%tm-%td %tH:%tM:%tS %tZ%n", date, date, date, date, date, date, date);
        System.out.println("-----------------------------------");
        Date dNow = new Date();
        //yyyy 是完整的公元年,MM 是月份,dd 是日期HH:mm:ss 是时、分、秒 SSS毫秒
        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS");
        String format = ft.format(dNow);
        System.out.println("当前时间为: " + format);//当前时间为: 2024-06-12 04:59:08:803
    }
}
Calendar

Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可

我们如何才能设置和获取日期数据的特定部分呢,比如说小时,日,或者分钟? 我们又如何在日期的这些部分加上或者减去值呢? 答案是使用Calendar 类

public class Demo1 {
    public static void main(String[] args) {
        String months[] = {
                "Jan", "Feb", "Mar", "Apr",
                "May", "Jun", "Jul", "Aug",
                "Sep", "Oct", "Nov", "Dec"};

        int year;
        // 初始化 Gregorian 日历
        // 使用当前时间和日期
        // 默认为本地时间和时区
        GregorianCalendar gcalendar = new GregorianCalendar();
        // 显示当前时间和日期的信息
        System.out.print("Date: ");
        System.out.print(months[gcalendar.get(Calendar.MONTH)]);
        System.out.print(" " + gcalendar.get(Calendar.DATE) + " ");
        System.out.println(year = gcalendar.get(Calendar.YEAR));
        System.out.print("Time: ");
        System.out.print(gcalendar.get(Calendar.HOUR) + ":");
        System.out.print(gcalendar.get(Calendar.MINUTE) + ":");
        System.out.println(gcalendar.get(Calendar.SECOND));

        // 测试当前年份是否为闰年
        if (gcalendar.isLeapYear(year)) {
            System.out.println("当前年份是闰年");
        } else {
            System.out.println("当前年份不是闰年");
        }
    }
}
Math

Java 的 Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数

Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用

public class Test {  
    public static void main (String []args)  
    {  
            System.out.println("返回两个参数中的最大值:" + Math.max(1, 2));
            System.out.println("返回两个参数中的最小值:" + Math.min(0, 3));
            System.out.println("60度的正切值:" + Math.tan(Math.PI / 3));
            System.out.println("1的反正切值: " + Math.atan(1));
            System.out.println("π/2的角度值:" + Math.toDegrees(Math.PI / 2));
            System.out.println(Math.PI);
    }  
}
String

String 类是不可改变的final修饰,所以你一旦创建了 String 对象,那它的值就无法改变

如果需要对字符串做很多修改,那么应该选择使用 StringBuffer & StringBuilder 类

String 创建的字符串存储在公共池中,而 new 创建的字符串对象在堆上

public class Demo1 {
    public static void main(String[] args) {
        String s1 = "Runoob";                       // String 直接创建
        String s2 = "Runoob";                       // String 直接创建
        String s3 = s1;                             // 相同引用
        String s4 = new String("Runoob");    // String 对象创建
        String s5 = new String("Runoob");    // String 对象创建
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);           //s1、s2、s3都是直接创建,都指向同一个公共池里的值和对象
        System.out.println(s1.equals(s3));      //true    值肯定相等、并且都在公共池中
        System.out.println(s4 == s5);           //false   这个比较是对象引用,2个不同对象在不同堆中,值相同
        System.out.println(s4.equals(s5));      //true    这个比较的是值
    }
}

public class Demo1 {
    public static void main(String[] args) {
        String str = "Hello World";
        System.out.println(str.length());                          //结果11,返回字符串的长度空格和!都算,用于不确定字符串长度时候
        System.out.println(str.charAt(1));                         //e,返回字符串1的位置,从0开始,长度是str的长度-1,可用于验证码的实现
        System.out.println(str.indexOf("h"));                      //-1,查找这个字符,没查到则返回-1
        System.out.println(str.indexOf("o"));                      //4,查找第一个,并返回索引值
        System.out.println(str.substring(4));            //o World,字符串的截取 从下标4开始
        System.out.println(str.substring(4, str.length() - 2));    //o Wor,[4,9)参数1是开始位置 参数2是结束,左闭右开
        System.out.println(str.toLowerCase());                     //全部转小写
        System.out.println(str.toUpperCase());                     //全部转大写
        String[] split = str.split(" ");
        //Hello
        //World
        //根据空格切割
        for (int i = 0; i < split.length; i++) {
            System.out.println(split[i]);
        }
        System.out.println("-----------------------------------");
        String str1 = "Hello1 World2";
        System.out.println(str1.indexOf("1", 4));    //5,查的必须是字符串类型,第二次参数是开始位置,这是正向搜、4,5刚好就是1返回5
        System.out.println(str1.lastIndexOf("l"));            //10,查找最后一个l,并返回它的索引值
        System.out.println(str1.lastIndexOf("l", 11));//10,11是d,然后开始反向搜到l直接返回索引
        System.out.println("-----------------------------------");
        System.out.println("abc".compareTo("abcde"));              //-2,返回整型,比较对应字符的大小(ASCII码顺序)
        System.out.println("abc".compareTo("abc"));                //0,相同返回0
        System.out.println("12789".compareTo("123"));              //4,回字符串长度,比较7和3返回4
        System.out.println("abc".equals("a"));                     //false,判断2个字符串是否相等,需要完全一样
        System.out.println("abc".equals("abc"));                   //True
        System.out.println("abc".equalsIgnoreCase("ABC"));   //true,忽略大小写
        System.out.println("abc".concat("derfg"));                   //abcderfg 字符串拼接,用+也可以
        System.out.println("nnnwa".replace("n", "g"));  //gggwa,替换所有n,第一个参数是需要被替换的,第二个是替换的
        System.out.printf("浮点型变量的值为 " +
                "%f, 整型变量的值为 " +
                " %d, 字符串变量的值为 " +
                "is %s", 1.12f, 16, "LuckyNwa");
        System.out.println("nwa".contains("nw"));                        //true,包含它返回布尔值,顺序有影响
        System.out.println("nwa".endsWith("a"));                         //true,包含它返回布尔值,测试是否以字符a结尾
        System.out.println("  hello world  ".trim());                    //hello world,去除前后空格,不去中间

    }
}

https://www.runoob.com/java/java-string.html 参考这

总结

length方法使用地方特别多,比如数组遍历时候就需要,字符串同,不知道长度可以直接用这方法获取

s=“aascsaxaca”;它的下标就是0到s.length()-1

indexOf可以用来查询是否存在,返回值为-1则不存在,也可以查询这个字符串第一次出现的地方

charAt方法可用于验证码的实现,把验证码需要的字符串存在一个变量里,通过charAt(new Random().nextInt(codeBox.length()))来获取随机字符

trim方法去首尾空格,用于登录时候输入有空格的把空格直接去掉,用的范围也挺广 以及split用的很多,可以根据空格,-等分割

isEmpty判断是否为空

StringBuffer 和 StringBuilder

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象

StringBuilder 类在 Java 5 中被提出,StringBuilder不是线程安全,StringBuffer 线程安全

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类

public class Demo1 {
    public static void main(String[] args) {
        StringBuilder sb;
        sb = new StringBuilder(10);
        sb.append("Runoob..");
        System.out.println(sb);
        sb.append("!");
        System.out.println(sb);
        sb.insert(8, "Java");
        System.out.println(sb);
        sb.delete(5, 8);
        System.out.println(sb);
        StringBuilder luckyNwa = new StringBuilder("LuckyNwa");
        luckyNwa.append("你好啊");
        System.out.println(luckyNwa);
    }
}

其他

转义序列

前面有反斜杠(\)的字符代表转义字符,它对编译器来说是有特殊含义的

列表展示了Java的转义序列:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1819398.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

sizeof和strlen

1.sizeof和strlen的对比 1.1sizeof sizeof是计算变量所占内存空间大小的&#xff0c;单位是&#xff1a;字节 如果操作数是类型的话&#xff0c;计算的是使用类型创建的变量所占内存空间的大小。 sizeof只关注占用内存空间的大小&#xff0c;不在乎内存中存放的是什么数据 …

深入理解MySQL分区技术

前言&#xff1a; 在数据量不断增长的当今时代&#xff0c;数据库的性能优化变得尤为重要。MySQL作为一款广泛使用的数据库管理系统&#xff0c;提供了多种性能优化手段&#xff0c;其中分区技术是提升大型表处理效率的有效方法之一。通过将数据分散到多个独立的物理子表中&am…

ArcGIS Pro SDK (三)Addin控件 2 窗格界面类

ArcGIS Pro SDK &#xff08;三&#xff09;Addin控件 2 窗格界面类 目录 ArcGIS Pro SDK &#xff08;三&#xff09;Addin控件 2 窗格界面类15 ArcGIS Pro 后台选项卡15.1 添加控件15.2 Code15.2.1 选项卡按钮15.2.2 选项卡页 16 ArcGIS Pro 窗体16.1 添加控件16.2 Code 17 A…

Bean基础配置

黑马程序员SSM 文章目录 一、Bean基础配置二、bean别名配置2.1 ban的别名配置2.2 注意事项 三、Bean作用范围配置3.1 Bean作用范围3.2 bean作用范围说明 一、Bean基础配置 二、bean别名配置 2.1 ban的别名配置 2.2 注意事项 获取bean无论是通过id还是name获取&#xff0c;如果…

webp2jpg网页在线图片格式转换源码

源码介绍 webp2jpg-免费在线图片格式转化器, 可将jpeg、jpg、png、gif、 webp、svg、ico、bmp文件转化为jpeg、png、webp、webp动画、gif文件。 无需上传文件&#xff0c;本地即可完成转换! 源码特点&#xff1a; 无需上传&#xff0c;使用浏览器自身进行转换批量转换输出we…

汇编语言程序设计之数据传输类指令

文章目录 数据传送类指令通用数据传送指令MOVXCHGXLAT 换码指令 堆栈操作指令标志传送指令标志位操作指令地址传送指令 算术运算类指令常用标志位加法指令ADDADCINC 减法指令SUBSBBDECNEGCMP 乘法指令MUL(无符号&#xff09;IMUL&#xff08;有符号&#xff09;MUL和IMUL对符号…

Sa-Token鉴权与网关服务实现

纠错&#xff1a; 在上一部分里我完成了微服务框架的初步实现&#xff0c;但是先说一下之前有一个错误&#xff0c;就是依赖部分 上次的学习中我在总的父模块下引入了spring-boot-dependencies&#xff08;版本控制&#xff09;我以为在子模块下就不需要再引用了&#xff0c;…

传输层——TCP

在学习计算机网络的过程中&#xff0c;我们知道OSI七层协议模型&#xff0c;但是在实际开发应 用中我们发现OSI七层协议模型并不适合实施&#xff0c;因为OSI上三层通常都是由开 发人员统一完成的&#xff0c;这三层之间在实现过程中没有一个明确的界限&#xff0c;所以我 们更…

数据结构逻辑

一&#xff1a;逻辑关系 1、线性关系 2&#xff1a;树型关系 3&#xff1a;图像关系 二&#xff1a;存储关系 1&#xff1a;顺序存储、数据在存储中会开辟一块连续的空间进行存储。一般使用数组来存储数据 2&#xff1a;链式存储、数据在内存中不需要开辟连续的空间进行存储 3…

vba学习系列(5)--指定区域指定字符串计数

系列文章目录 文章目录 系列文章目录前言一、需求背景二、vba自定义函数1.引入库 总结 前言 一、需求背景 想知道所有客诉项目里面什么项目最多&#xff0c;出现过多少次。 二、vba自定义函数 1.引入库 引用&#xff1a; CountCharInRange(区域,“字符串”) Function CountCh…

Mysql数据类型解析

1、MySQL 数据类型 MySQL 支持多种类型&#xff0c;大致可以分为三类&#xff1a;数值、日期/时间和字符串&#xff08;字符&#xff09;类型。 1.2、查看Mysql编码格式 mysql> show variables like "%char%"; ----------------------------------------------…

【中颖】SH79F9202 呼吸灯(PWM)

源文件pwm.c #include "pwm.h"// 频率 占空比 极性 void Pwm1_Init(volatile U16 frequency, volatile U16 duty, volatile U16 polar) {// 周期,单位是msvolatile U16 period = 1000 / frequency; //32.25ms(T=1/F=1/0.032S=1000/32ms) // volatile U16 PWM1P …

vscode卡顿问题处理(vue-official插件)

vue官方扩展由volar升级为vue-official&#xff0c;部分人的ide会变得非常卡顿&#xff0c;这是由于vscode本身一些问题导致&#xff0c;如下图作者解释&#xff1a; 解决方式&#xff1a; 通过禁用Hybrid模式&#xff0c;不使用tsserver来接管语言支持&#xff0c;卡顿会缓解…

在线音乐播放器测试

在线音乐播放器测试报告 文章目录 1. 项目背景2. 项目简介2.1登录页面2.2 主页面2.3 收藏页面2.4 上传音乐页面2.5 注册页面 3. 需求评测4. 制定测试计划5. 设计测试用例5.1 注册5.2 登录5.3 主页面5.4 收藏页面5.5 添加歌曲 6. 执行测试用例6.1 注册6.2 登录6.2 主页面6.3 收藏…

凭什么现货白银这么受欢迎?现货白银是什么交易模式

近期现货白银投资颇为火热&#xff0c;很多朋友入场开户成为了正式的现货白银投资者。不过也有一些相对谨慎的投资者&#xff0c;他们想弄明白现货白银交易是什么&#xff0c;运行机制是怎么样的之后再入场&#xff0c;这也是合理的。而他们提出的一个问题就是&#xff0c;现货…

AI “黏土画风”轻松拿捏,手把手带你云端部署 ComfyUI

作者&#xff1a;鸥弋、筱姜 AI 绘画领域&#xff0c;Stable Diffusion WebUI、Midjourney 、DALL-E 都聚拢了一大批的应用开发者和艺术创作者。ComfyUI 出现时间略晚&#xff0c;但是它让创作者通过工作流的方式&#xff0c;实现自动化水平更高的 AI 生图流程&#xff0c;一面…

【Qt 学习笔记】Qt窗口 | 标准对话框 | 文件对话框QFileDialog

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt窗口 | 标准对话框 | 文件对话框QFileDialog 文章编号&#xff1a;Q…

github ssh key的SHA256是什么

github ssh key的SHA256是什么 怎么知道github上自己的公钥指纹和本地的公钥是否一致&#xff1f; 计算方法如下&#xff1a; cat .ssh/id_rsa.pub |awk { print $2 } | # Only the actual key data without prefix or commentsbase64 -d | # decode as base64s…

SqlSugar有实体CURD应用-C#

本文所述开发环境&#xff1a;.C#、NET8、Visual Studio2022 SqlSugar有实体查询数据表 首先根据《SqlSugar使用DbFirst对象根据数据库表结构创建实体类-C#》中的描述的表结构创建所有表的实体类如下&#xff1a; 表名创建的实体类名tb_studentStudenttb_teacherTeachertb_c…

在Lua解释器中注册自定义函数库

本文目录 1、引言2、注册原理3、实例4、程序验证 文章对应视频教程&#xff1a; 暂无&#xff0c;可以关注我的B站账号等待更新。 点击图片或链接访问我的B站主页~~~ 1、引言 在现代软件开发中&#xff0c;Lua因其轻量级、高效和可嵌入性而被广泛使用。作为一种灵活的脚本语言…