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

环境

安装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]);//Luckyfor (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("老虎睡");}
}
class Animal {public void makeSound() {System.out.println("动物发出声音");}
}class Dog extends Animal {@Overridepublic void makeSound() {System.out.println("狗发出汪汪声");}
}class Cat extends Animal {@Overridepublic void makeSound() {System.out.println("猫发出喵喵声");}
}public class Main {public static void main(String[] args) {Animal animal1 = new Dog(); // 使用父类引用指向子类对象Animal animal2 = new Cat(); // 使用父类引用指向另一个子类对象animal1.makeSound(); // 调用被重写的方法,输出:狗发出汪汪声animal2.makeSound(); // 调用被重写的方法,输出:猫发出喵喵声}
}

这就是多态的体现,通过父类的引用调用被子类重写的方法

接口

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

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

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

  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 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() 返回枚举常量,不存在的会报错 IllegalArgumentExceptionSystem.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()); // 输出: 0System.out.println(ErrorCodeEn.ERROR_A.getCode()); // 输出: 100System.out.println(ErrorCodeEn.ERROR_B.getCode()); // 输出: 200// 获取枚举常量的描述System.out.println(ErrorCodeEn.OK.getDescription()); // 输出: 成功System.out.println(ErrorCodeEn.ERROR_A.getDescription()); // 输出: 错误ASystem.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 {@Testpublic 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.txtSystem.out.println("文件构造路径:"+f.getPath());        //文件构造路径:C:\Users\FF\Desktop\1.txtSystem.out.println("文件名称:"+f.getName());          //文件名称:1.txtSystem.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@Testpublic 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没有删掉}@Testpublic 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();//遍历filesfor (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就是244fos.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 {@Testpublic 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.txtSystem.out.println("文件构造路径:"+f.getPath());        //文件构造路径:C:\Users\FF\Desktop\1.txtSystem.out.println("文件名称:"+f.getName());          //文件名称:1.txtSystem.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@Testpublic 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没有删掉}@Testpublic 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();//遍历filesfor (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就是244fos.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 {@Testpublic 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();}@Testpublic void delTxt() {new File("a.txt").delete();}@Testpublic 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();}@Testpublic 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();
//        改进3int len;// 定义字节数组,作为装字节数据的容器byte[] b = new byte[2];// 循环读取while ((len = fis.read(b)) != -1) {// 每次读取后,把数组变成字符串打印System.out.println(new String(b, 0, len));//len是每次读取有效的个数}// 关闭资源fis.close();}@Testpublic 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();}@Testpublic 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);}}@Testpublic 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是加入缓存@Testpublic 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}@Testpublic 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 毫秒}@Testpublic 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();}@Testpublic 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);//非法参数异常IllegalArgumentExceptiontry {//  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"))) {//如果多个;隔开继续newwhile ((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.htmlSystem.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,查找这个字符,没查到则返回-1System.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返回5System.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,相同返回0System.out.println("12789".compareTo("123"));              //4,回字符串长度,比较7和3返回4System.out.println("abc".equals("a"));                     //false,判断2个字符串是否相等,需要完全一样System.out.println("abc".equals("abc"));                   //TrueSystem.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.mzph.cn/news/852672.shtml

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

相关文章

如何一键拷贝PPT中的所有文字?

有时我们可能需要引用PPT的文字&#xff0c;但一个幻灯片一个幻灯片拷贝很是麻烦&#xff0c;我们想一键拷贝PPT中所有幻灯片中的内容&#xff08;最近我就遇到了这个需求&#xff09;。今天就来讲讲这个一键拷贝的技巧。因为大家可能会遇到同样的问题&#xff0c;所以在此记录…

一文彻底理解机器学习 ROC-AUC 指标

在机器学习和数据科学的江湖中&#xff0c;评估模型的好坏是非常关键的一环。而 ROC&#xff08;Receiver Operating Characteristic&#xff09;曲线和 AUC&#xff08;Area Under Curve&#xff09;正是评估分类模型性能的重要工具。 这个知识点在面试中也很频繁的出现。尽管…

【机器学习】与【数据挖掘】技术下【C++】驱动的【嵌入式】智能系统优化

目录 一、嵌入式系统简介 二、C在嵌入式系统中的优势 三、机器学习在嵌入式系统中的挑战 四、C实现机器学习模型的基本步骤 五、实例分析&#xff1a;使用C在嵌入式系统中实现手写数字识别 1. 数据准备 2. 模型训练与压缩 3. 模型部署 六、优化与分析 1. 模型优化 模…

零基础入门学用Arduino 第二部分(二)

重要的内容写在前面&#xff1a; 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。个人把这个教程学完之后&#xff0c;整体感觉是很好的&#xff0c;如果有条件的可以先学习一些相关课程&#xff0c;学起来会更加轻松&#xff0c;相关课程有数字电路…

通用大模型与垂直大模型:双轨并进的人工智能未来

在人工智能(AI)的浩瀚宇宙中&#xff0c;大模型以其强大的学习能力和广泛的适用性&#xff0c;正逐步成为推动技术进步和产业革新的核心动力。在这股浪潮中&#xff0c;通用大模型与垂直大模型如同两颗璀璨的星辰&#xff0c;各自散发着独特的光芒&#xff0c;共同照亮了AI发展…

VirtualBox配置双网卡实现宿主机和虚拟机相互访问以及虚拟机外网访问

目录 一&#xff1a;背景 二&#xff1a;实现 三&#xff1a;总结 一&#xff1a;背景 在VirtualBox中配置虚拟机以实现本地主机远程登录、访问外网以及虚拟机之间的相互访问&#xff0c;是一种常见的虚拟化实践&#xff0c;适用于多种场景&#xff0c;如开发、测试和远程工…

openh264 帧内预测编码原理:WelsMdI4x4Fast 函数

介绍 说明&#xff1a;该函数内部原理类似WelsMdI4x4函数&#xff0c;具体可以参考&#xff1a;openh264 帧内预测编码原理&#xff1a;WelsMdI4x4 函数。 功能&#xff1a;针对4x4像素块的帧内模式决策的快速实现逻辑原型&#xff1a; int32_t WelsMdI4x4Fast (sWelsEncCtx…

react的自定义组件

// 自定义组件(首字母必须大写) function Button() {return <button>click me</button>; } const Button1()>{return <button>click me1</button>; }// 使用组件 function App() {return (<div className"App">{/* // 自闭和引用自…

React Redux

React Redux是Redux的官方React UI绑定层。它允许您的React组件从Redux存储读取数据&#xff0c;并将操作分派到存储以更新状态。redux是一个管理状态数据state的容器。提供了可预测的状态管理。 React Redux 8.x需要React 16.8.3或更高版本/Rect Native 0.59或更高&#xff0c…

在AMD GPU上加速大型语言模型的Flash Attention

Accelerating Large Language Models with Flash Attention on AMD GPUs — ROCm Blogs 引言 在这篇博客文章中&#xff0c;我们将指导您如何在AMD GPU上安装Flash Attention&#xff0c;并提供与在PyTorch中标准SDPA比较其性能的基准测试。我们还将测量Hugging Face中多个大型…

【Java】解决Java报错:FileNotFoundException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 文件路径错误2.2 文件名拼写错误2.3 文件权限问题2.4 文件路径未正确拼接 3. 解决方案3.1 检查文件路径3.2 使用相对路径和类路径3.3 检查文件权限3.4 使用文件选择器 4. 预防措施4.1 使用配置文件4.2 使用日志记录4.3 使用单元测…

上网行为管理的作用是什么?有哪些上网行为管理软件?

上网行为管理在现代企业及家庭环境中扮演着至关重要的角色&#xff0c;其作用不仅限于提升网络安全性&#xff0c;还涉及保护企业信息安全、提高员工工作效率等多个方面。以下将详细阐述上网行为管理的作用&#xff0c;并介绍几款主流的上网行为管理软件。 一、上网行为管理的作…

Neo4j 桌面版打不开踩坑贴

真的踩坑。。。没有人告诉我为啥桌面版和社区版不能一起下啊&#xff01;&#xff01; 我是先下载了社区版之后再下载的桌面版&#xff0c;结果桌面版界面一直打不开。 尝试了网上多种办法都没效果&#xff0c;好多都是说jdk不兼容导致无法打开&#xff0c;让我从JDK 17 ->…

AUTOSAR平台中的信息安全标准模块

面向MCU端的AUTOSAR CP平台加密组件——Crypto ECU中所有的软件单元都遭受到信息安全攻击的可能。AUTOSAR为保障ECU信息和数据安全&#xff0c;定义了CRYPTO 组件,包含 SecOC、KeyM、IdsM、Csm、CryIf 和Crypto Driver 等标准模块。CRYPTO组件提供各种加解密算法以及密钥管理功…

物联网对智慧驾考应用的价值

随着物联网技术的快速发展&#xff0c;传统行业正经历着前所未有的变革。在智慧驾考领域&#xff0c;4G DTU&#xff08;数据传输单元&#xff09;和工业路由器的应用&#xff0c;不仅提升了考试的规范性和效率&#xff0c;更为驾考行业带来了深远影响。作为工业物联网的资深工…

JVM 类加载器的工作原理

JVM 类加载器的工作原理 类加载器&#xff08;ClassLoader&#xff09;是一个用于加载类文件的子系统&#xff0c;负责将字节码文件&#xff08;.class 文件&#xff09;加载到 JVM 中。Java 类加载器允许 Java 应用程序在运行时动态地加载、链接和初始化类。 2. 类加载器的工…

今年的就业环境不容乐观,你想好怎么应对了吗

今年的就业环境不容乐观&#xff0c;你想好怎么应对了吗 毕业生进入职场的历程往往充满挑战和未知&#xff0c;尤其是在当前经济环境下&#xff0c;失业问题愈发凸显。本文通过分享几位年轻人的真实经历&#xff0c;剖析大学生及职场人士面临的困境&#xff0c;并提供应对策略…

手把手带你搭建一个语音对话机器人,5分钟定制个人AI小助手(新手入门篇)

写在前面 如果你的身边有一个随时待命、聪明绝顶的AI小助手&#xff0c;能够听懂你的话&#xff0c;理解你的需求&#xff0c;用温暖的声音回应你&#xff0c;会是一种什么体验&#xff1f; 今天&#xff0c;带大家一起搭建一个语音对话机器人&#xff0c;拥有一个专属的个人…

games101作业7光线追踪 含多线程和微表面提高

对于光线追踪进行综合运用。 光线与三角形求交 其它的emit那些&#xff0c;现在先不用管&#xff0c;后面看看作用是什么。 inline Intersection Triangle::getIntersection(Ray ray) {Intersection inter;if (dotProduct(ray.direction, normal) > 0)//光线从里面打&…

[Shell编程学习路线]——深入理解Shell编程中的变量(理论与实例)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f6e0;️Shell编程专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月12日11点40分 &#x1f004;️文章质量&#xff1a;95分 文章目录 ————前言———— 1 自定义变量 &#x1fae0;…