java详细笔记总结持续完善

news2025/4/2 12:05:06

一.Java开发环境的搭建

1. 单位换算

1TB = 1024GB

1GB = 1024MB

1MB = 1024KB

1KB = 1024Byte (字节)

1Byte = 8 bit(位)

注意:一个字节占8位

2. DOS命令

DOS : Disk Operation System 磁盘操作系统 即用于操作本地磁盘的系统

命令操作符号
盘符切换命令盘符名:
查看当前文件夹内容dir
进入文件夹命令cd 文件夹名
退出文件夹命令cd ..
退出到磁盘根目录cd \
清屏cls
退出exit

3. 名词解释

  • JVM(Java Virtual Machine ): Java虚拟机 JVM相当于一个软件 在不同的平台模拟相同的环境 以实现跨平台的效果

  • JRE(Java Runtime Environment) : Java运行环境,包含JVM 和运行时所需要的核心类库

  • JDK(Java Development Kit) : Java开发工具包 ,包含JRE 和开发人员使用的工具。

三者关系:JDK包含 JRE JRE包含JVM

4. 安装JDK

5.配置环境变量

右键此电脑===》高级系统设置===》高级====》环境变量

系统变量====》新建变量

名:JAVA_HOME

值: C:\Program Files\Java\jdk1.8.0_131

找到Path变量===》编辑 ====》新建

直接写值:%JAVA_HOME%\bin

所有已打开的窗口全部确定即可

用户变量 vs 系统变量

用户变量 :当前用户自己独有的变量,切换到其他用户后就不能使用来了

系统变量:当前系统中,所有的用户都共享的变量

6.测试

徽标 + R 输入 CMD

javac -version

java -version

以上两个命令都出现版本号表示安装JDK并且环境变量配置成功

7.关于配置环境变量问题补充

1.为什么不直接在Path变量中配置C:\Program Files\Java\jdk1.8.0_131\bin

直接在Path变量中写为C:\Program Files\Java\jdk1.8.0_131\bin 这样的格式目前也是没有问题的 也可以使用

但是后续我们使用的一些工具将默认查找JAVA_HOME变量 比如 tomcat maven等等

2.为什么要配置环境变量?

配置环境变量相当于把bin目录下的命令通知给操作系统 便于我们使用当前目录下对应的命令

3.为什么不配置classpath ?

classpath表示类路径 (即JVM加载类会寻找的路径)

早期(JDK1.5之前)的JDK都需要配置此环境变量 从JDK1.5开始 不需要人为的配置此变量

如果配置了,一定删掉!!!

二.第一个Java程序

2.1 源代码

public class HelloWorld{
    public static void main(String [] args){ 
        System.out.print("hello world 0724");
    }
}

2.2 单词解释

public 公开的

class 类

static 静态的

void 无效的 空的

main 主要的

String 字符串

args arguments 参数 复数形式

System 系统

out 出

print 打印

2.3 注意事项

1.文件名必须与类名完全保持一致 包括大小写

2.注意单词大小写

3.代码中的标点符号默认都是英文模式的

4.注意合适的缩进 每遇到一个大括号就缩进一个tab键的距离

3. 测试运行

在java源文件上方的地址栏中输入CMD 打开DOS命令窗口

1.输入 javac + java文件名 编译 ,将java文件编译为class文件(c 表示单词 Complier 即编译的意思)

2.输入 java + class文件名 执行class文件

4.关键字

  • 1.什么是关键字?

    • 被Java官方赋予了特殊含义的单词 全部小写

  • 2.注意事项:

    • 关键字众多,不需要记忆,注意后续取名字避免和关键字冲突即可

第一个Java程序的扩展

1.详解代码

/**
*/
​
//公有的类叫做Hello 
public class Hello{
​
    //这种固定写法的方法叫做主方法
    public static void main(String[] args){
​
        //打印语句
        System.out.println("HelloWorld...1");
        System.out.println("HelloWorld...2");
        System.out.println("HelloWorld...3");
    }
}
​
/*
    public-公有的  class-类     Hello-类名
    static-静态的  void-无返回值的  main-方法名
    String-字符串类型 ps:"用良心做教育"
    String[]-字符串类型的数组 ps:["小红","小绿","小黄","明日花绮罗"]
    args-数组名
*/

2.代码细节

  1. public修饰的类名必须和文件名一致

  2. Java是一门大小写敏感的语言

  3. 括号都是成双成对的

  4. 方法里的代码都是从上往下执行-顺序执行

  5. 方法中的代码又叫做执行语句,执行语句用分号结束

2、Java代码规范

1.书写格式

经验:灵活使用tab(缩进键)

优先级别:类 > 方法 > 执行语句

2.代码注释

注释描述
//注释内容单行注释
/*注释内容*/多行注释
/**注释内容*/文档注释

编译的过程:Hello.java -> Hello.class

反编译的过程:Hello.class -> Hello.java

注意:

  1. 使用Xjad工具进行反编译

  2. 注释不会随着编译,而编译到class文件中

3、Path的作用

%JAVA_HOME%/bin --> javac.exe 和 java.exe

理解:在path中配置了某个目录,代表在其他任何目录里都可以打开配置的目录中的文件

见 path的作用.png

4、Java的扩平台特性

见 Java跨平台特性.png

三.Java 基本数据类型与算数运算符

1. 基本数据类型的深入

取值范围顺序

Java 中基本数据类型的取值范围从小到大依次为:byte < short < int < long < float < double

其中,

byte 占 1 个字节(8 位),取值范围是 -128 到 127;

short 占 2 个字节(16 位);

int 占 4 个字节(32 位);

long 占 8 个字节(64 位);

float 占 4 个字节(32 位),用于表示单精度浮点数;

double 占 8 个字节(64 位),用于表示双精度浮点数。

特殊情况

  • char 类型char 类型用于表示单个字符,它可以转换为 int 类型,从而获取字符对应的 ASCII 值。例如:

char c1 = 'A'; 
char c2 = 'a';
int i1 = c1;
int i2 = c2;
System.out.println(i1); // 输出 65
System.out.println(i2); // 输出 97
  • boolean 类型boolean 类型只有两个值:truefalse,它不能与其他基本数据类型进行转换。例如:

boolean bool = true;
// 以下代码会编译错误
// System.out.println((int)bool); 

字面量赋值

  • byteshort 类型:如果赋值的字面量在其取值范围内,可以直接赋值。例如:byte b1 = 1;。如果字面量超出了其取值范围,需要进行强制类型转换。例如:byte b2 = (byte)128;,此时会发生溢出,b2 的值为 -128。这是因为 128 的二进制表示(32 位)为 0000 0000 0000 0000 0000 0000 1000 0000,强制转换为 byte 类型(8 位)后变为 1000 0000,在补码表示中,这表示 -128。

  • long 类型:如果赋值的字面量超出了 int 类型的取值范围,需要在字面量后面加上 Ll。例如:long l2 = 12345678901L;

  • float 类型int 类型可以自动转换为 float 类型。例如:float f1 = 1;double 类型转换为 float 类型需要进行强制类型转换或使用 f 后缀。例如:float f2 = (float)1.0;float f2 = 1.0f;

2. 基本数据类型的转型(注意特殊点)

自动转型

取值范围小的类型会自动转换为取值范围大的类型,这是由 Java 编译器自动完成的,无需手动干预。例如:

byte b = 100;
short s = b;
int i = s;
long l = i;
float f = l;
double d = f;
System.out.println(d); // 输出 100.0

强制转型

取值范围大的类型转换为取值范围小的类型时,需要使用强制类型转换符 (type)。例如:

double d = 123.123;
float f = (float)d;
long l = (long)f;
int i = (int)l;
short s = (short)i;
byte b = (byte)s;
System.out.println(b); // 输出 123

特殊点

  • 类型提升:在进行运算时,如果操作数的类型不同,会自动将取值范围小的类型提升为取值范围大的类型。例如,byteshort 类型进行运算时,会自动转换为 int 类型,结果也为 int 类型。如果需要将结果赋值给 byteshort 类型,需要进行强制类型转换。例如:

byte b1 = 10;
byte b2 = 20;
byte result = (byte)(b1 + b2);
System.out.println(result);
  • 溢出问题:强制类型转换可能会导致数据溢出。例如,将一个超出目标类型取值范围的数进行强制转换,会得到一个错误的结果。如上面的 byte b2 = (byte)128;//-128 示例。

3. 算数运算符的使用

基本算数运算符

Java 中的基本算数运算符包括 +(加法)、-(减法)、*(乘法)、/(除法)、%(取模,即取余数)。例如:

int a = 10;
int b = 3;
int result = a + b;
System.out.println(result); // 输出 13
System.out.println(a + b); // 输出 13
System.out.println(10 + 3); // 输出 13
System.out.println(10 - 3); // 输出 7
System.out.println(10 * 3); // 输出 30
System.out.println(10 / 3); // 输出 3,整数除法会舍去小数部分
System.out.println(10 % 3); // 输出 1

自增自减运算符

  • ++:自增 1,分为前缀自增(先自增,后使用)和后缀自增(先使用,后自增)。例如:

  • 底层实现需要考虑byte或short:++a  等价于  (type)(a+1)

int a = 10;
System.out.println(++a); // 先将 a 自增为 11,然后输出 11
System.out.println(a); // 输出 11
​
int b = 10;
System.out.println(b++); // 先输出 b 的值 10,然后 b 自增为 11
System.out.println(b); // 输出 11
  • --:自减 1,分为前缀自减(先自减,后使用)和后缀自减(先使用,后自减)。例如:

int c = 10;
System.out.println(--c); // 先将 c 自减为 9,然后输出 9
System.out.println(c); // 输出 9
​
int d = 10;
System.out.println(d--); // 先输出 d 的值 10,然后 d 自减为 9
System.out.println(d); // 输出 9

4. 算数运算符的深入(注意特殊点和面试题)

特殊点

  • byteshort 运算byteshort 类型进行运算时,会自动转换为 int 类型,结果也为 int 类型。如果需要将结果赋值给 byteshort 类型,需要进行强制类型转换。例如:

byte b1 = 10;
byte b2 = 20;
byte result = (byte)(b1 + b2);
System.out.println(result);
  • 浮点数运算floatdouble 类型进行运算时可能会出现精度丢失的问题。这是因为浮点数在计算机中是以二进制形式存储的,有些十进制小数无法精确表示为二进制小数。例如:

double d1 = 0.5d;
double d2 = 0.4d;
System.out.println(d1 - d2); // 输出 0.0999999998,而不是 0.1
  • 字符参与运算:字符在参与运算时,会使用其对应的 ASCII 值。例如:

char c = 'a'; // 'a' 的 ASCII 值为 97
System.out.println(c + 1); // 输出 98

面试题

  • 复杂表达式计算

int a = 8;
int b = (a++) + (++a) + (a * 10);
// 首先,a++ 先使用 a 的值 8,然后 a 变为 9
// 接着,++a 先将 a 自增为 10,然后使用 a 的值 10
// 最后,a * 10 即 10 * 10 = 100
// 所以 b = 8 + 10 + 100 = 118
System.out.println(b); // 输出 118
  • 自增赋值问题

int i = 0;   
i = ++i; 
// ++i 先将 i 自增为 1,然后将 1 赋值给 i
System.out.println(i); // 输出 1
​
int j = 0;   
j = j++; 
// 首先,j++ 先使用 j 的值 0,将 0 保存到一个临时变量中
// 然后,j 自增为 1
// 最后,将临时变量中的 0 赋值给 j
System.out.println(j); // 输出 0

四.Java 基础语法与运算符详解

1.赋值运算符

符号

  • 注意:=为赋值号,将赋值号右侧的数据赋值给左侧的变量

  • =, +=, -=, *=, /=, %=

复合赋值运算符会自动进行类型转换:

short s = 1; // 等价于 s = (short)(1);
s += 1; // 等价于 s = (short)(s + 1);

赋值规则:
                     s   += 1                 s  = (T)((s)   +   (1))
            复合赋值 E1 op= E2等价于简单赋值 E1 = (T)((E1) op     (E2)),
            其中T是E1的类型。
 

2.字符串拼接符

规则

  • + 两侧均为数值时,执行算术运算。

  • 任意一侧为字符串时,执行字符串拼接。

示例

System.out.println(1 + 2 + "abc" + "def" + 1 + 2);
// 运算顺序:3 → "3abc" → "3abcdef" → "3abcdef1" → "3abcdef12"

3.Scanner 输入类

使用步骤

  1. 导包import java.util.Scanner;

  2. 实例化Scanner scan = new Scanner(System.in);

  3. 读取输入注意:没有char类型的数据输入

    int i = scan.nextInt();      // 读取整数
    double d = scan.nextDouble();// 读取浮点数
    String str = scan.next();    // 读取字符串(空格分隔)

4.关系运算符

符号

  • ==, !=, >, >=, <, <=

注意事项

  • == 比较值是否相等,= 是赋值。

  • 结果始终为 boolean 类型。

经典面试题

int x = 10, y = 10;
boolean flag = (x = y); // 编译错误:int 不能赋给 boolean
import java.util.Scanner;
public class Test04{
	/**
		知识点:关系运算符
		符号:==、!=、>、>=、<、<=
		
		注意:
			1.=是赋值运算符,将右侧的值赋值给左侧的变量
			2.==是关系运算符,判断两个值是否相等
			3.!=是关系运算符,判断两个值是否不相等
			4.关系运算符的结果必须是boolean类型
			

	*/
	public static void main(String[] args){
				boolean bool = 10 == 20;
		System.out.println(bool);//false
		System.out.println(10 != 20);//true
		System.out.println(10 >  20);//false
		System.out.println(10 >= 20);//false
		System.out.println(10 <  20);//true
		System.out.println(10 <= 20);//true
		
		需求:在控制台输入两个int类型的数字,比较大小
			Scanner scan = new Scanner(System.in);
		
			System.out.println("请输入第一个数字:");
			int a = scan.nextInt();
			System.out.println("请输入第二个数字:");
			int b = scan.nextInt();
			
			boolean bool = a > b;
			System.out.println("第一个数字是否比第二个数字大:" + bool);
			
		经典面试题一:输出结果为?
			int x = 10;
			int y = 10;
			boolean flag = (x == y);
			System.out.println(flag);//true
			flag = (x = y);//会报错,原因boolean类型不能与其他类型兼容
			System.out.println(flag);
			
		经典面试题二:输出结果为?
			boolean b1 = true;
			boolean b2 = false;
			boolean b3 = (b1 == b2);
			System.out.println(b3);//false -- 比较是否相同
			boolean b4 = (b1 = b2);
			System.out.println(b4);//false -- 连续赋值
		
		
		
		
	}
}

5.逻辑运算符

符号与特性

运算符名称特性
&逻辑与两侧均执行
&&短路与左侧为 false 则短路
|逻辑或逻辑或两侧均执行
||短路或左侧为true则短路
^异或两侧不同为 true
!取反

应用示例

boolean inRange = num > 50 && num < 100; // 判断数字是否在区间内
System.out.println(false && 10/0 > 5);   // 不报错(短路特性)
import java.util.Scanner;
public class Test05{
	/**
		知识点:逻辑运算符
		符号:
			&与		&&短路与
			|或		||短路或
			^异或
			!非
			
		注意:
			1.逻辑运算符运行结果都是boolean类型
			2.&、&&、|、||、^ 两侧都是boolean类型数据
			
		
	*/
	public static void main(String[] args){
		
		//&与:前后两侧都接boolean值,两侧同时成立(true),结果才为true
		System.out.println(true & true);//true
		System.out.println(false & true);//false
		System.out.println(true & false);//false
		System.out.println(false & false);//false
		
		//&&短路与:前后两侧都接boolean值,两侧同时成立(true),结果才为true
		System.out.println(true && true);//true
		System.out.println(false && true);//false
		System.out.println(true && false);//false
		System.out.println(false && false);//false
		
		//&与:判断前者为false后,还会判断后者
		//&&短路与:判断前者为false后,不会判断后者,效率更高
		//ArithmeticException -- 算数异常
		System.out.println(false && 10/0>5);
		
		//|或:前后两侧都接boolean值,两侧有一侧成立(true),结果就为true
		System.out.println(true | true);//true
		System.out.println(false | true);//true 
		System.out.println(true | false);//true
		System.out.println(false | false);//false
		
		//||短路或:前后两侧都接boolean值,两侧有一侧成立(true),结果就为true
		System.out.println(true || true);//true
		System.out.println(false || true);//true 
		System.out.println(true || false);//true
		System.out.println(false || false);//false
		
		//|或:判断前者为true后,还会判断后者
		//||短路或:判断前者为true后,不会判断后者,效率更高
		System.out.println(true || 10/0>5);
		
		//^异或:前后两侧都接boolean值,两侧不同为true,相同为false
		System.out.println(true ^ true);//false
		System.out.println(false ^ true);//true
		System.out.println(true ^ false);//true
		System.out.println(false ^ false);//false
		
		//!非:置反,true变为false,false变为true
		boolean bool1 = true;
		System.out.println(!bool1);//false
		boolean bool2 = false;
		System.out.println(!bool2);//true
		
		需求:在控制台输入一个int类型的数字,判断是否在50~100的区间内
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入int类型的数字:");
		int num = scan.nextInt();
		
		boolean bool = num>50 && num<100;
		System.out.println("该数字是否在50~100的区间内:" + bool);
		
	}
}

6.三元运算符

语法

变量 = (条件) ? 值1 : 值2;

返回值类型规则

  1. 类型相同:直接返回该类型。

  2. 基本类型兼容:自动类型提升。

  3. 混合类型(基本与包装类):自动拆箱/装箱。

  4. 常量与变量:按兼容性决定类型。

    常量的值是否在变量所属类型的取值范围里

    在 - 按照变量的类型返回数据

    不在 - 按照常量的类型返回数据  

import java.util.Scanner;
public class Test06{
	/**
		知识点:表达式
			5 + 6 -- 算数表达式
			5 > 6 -- 关系表达式
	
		知识点:三目运算符/三元运算符
		
		语法规则:变量 = (表达式)?值1:值2;
		理解:表达式的结果必须是boolean
			  true - 将值1赋值给变量
			  false- 将值2赋值给变量
		做实验:

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

			int num = (false)?10:20;
			System.out.println(num);
			
		需求1:在控制台输入2个int类型的数字,比较大小,输出最大值
			Scanner scan = new Scanner(System.in);
			System.out.println("请输入第一个数字:");
			int a = scan.nextInt();
			System.out.println("请输入第二个数字:");
			int b = scan.nextInt();
			
			int max = (a>b)?a:b;
			System.out.println("最大值为:" + max);
			
		需求2:在控制台输入2个int类型的数字,比较大小,输出最小值
			Scanner scan = new Scanner(System.in);
			System.out.println("请输入第一个数字:");
			int a = scan.nextInt();
			System.out.println("请输入第二个数字:");
			int b = scan.nextInt();
			
			int min = (a<b)?a:b;
			System.out.println("最小值为:" + min);
			
		需求3:在控制台输入3个int类型的数字,比较大小,输出最大值
			Scanner scan = new Scanner(System.in);
			System.out.println("请输入第一个数字:");
			int a = scan.nextInt();
			System.out.println("请输入第二个数字:");
			int b = scan.nextInt();
			System.out.println("请输入第三个数字:");
			int c = scan.nextInt();
			
			int max = (a>b)?a:b;
			max = (max>c)?max:c;
			System.out.println("最大值为:" + max);
			
		需求4:在控制台输入3个int类型的数字,比较大小,由小到大输出(10<20<30)
			Scanner scan = new Scanner(System.in);
			System.out.println("请输入第一个数字:");
			int a = scan.nextInt();
			System.out.println("请输入第二个数字:");
			int b = scan.nextInt();
			System.out.println("请输入第三个数字:");
			int c = scan.nextInt();
			
			//最大值
			int max = (a>b)?a:b;
			max = (max>c)?max:c;
			
			//最小值
			int min = (a<b)?a:b;
			min = (min<c)?min:c;
			
			//中间值
			int mid = a+b+c-max-min;
			
			System.out.println(min + "<" + mid + "<" + max);
			
			
		扩展面试题1:
			int a = 5;
			System.out.println((a<5)?10.9:9);//9.0
			
		扩展面试题2:
			char x = 'x';//码值 - 120
			int i = 10;
			System.out.println(false?i:x);//120
			
		扩展面试题3:
			char x = 'x';//码值 - 120
			System.out.println(false?100:x);//x
			System.out.println(false?100000:x);//120
			
		扩展 -- 常量的概念:程序执行过程中不可发生改变的量
		注意:数字字面量是常量之一
			
		返回值规则:
			值1和值2都是常量时,按照取值范围大的类型返回数据
			值1和值2都是变量时,按照取值范围大的类型返回数据
			值1和值2一个是常量一个是变量,判断常量的值是否在变量所属类型的取值范围里
				在 - 按照变量的类型返回数据
				不在 - 按照常量的类型返回数据
		
	}
}

扩展面试题 ::注意这里的char类型的常量为规则变量跟常量,暂时把'X'看做是个变量

System.out.println(false ? 100 : 'x');   // 输出 'x'(char 类型)
System.out.println(false ? 100000 : 'x');// 输出 120(char 提升为 int)

7.位运算符

符号与功能

运算符名称功能
&位与两位为 1 则结果为 1
|位或任意一位为 1 则结果为 1
^异或两位不同为 1
<<左移低位补 0,相当于乘以 2
>>右移高位补符号位,相当于除以 2
>>>无符号右移高位补 0

示例

int a = 19; // 0001,0011
int b = 25; // 0001,1001
System.out.println(a & b);  // 17 (0001,0001)
System.out.println(a << 3); // 8192 (左移 3 位)
System.out.println(-1024 >> 3);  // -128
System.out.println(-1024 >>> 3); // 536870784
import java.util.Scanner;
public class Test07{
	/**
		知识点:位运算符
		理解:将十进制的数据转换为二进制做运算
		符号:&、|、^、<<、>>、>>>
		
		
	*/
	public static void main(String[] args){

		//&与:同位比较,两位为1,结果才为1
		byte a = 19;//0001,0011
		byte b = 25;//0001,1001
					//0001,0001
		
		//a - byte:0001,0011
		//	 (int):0000,0000,0000,0000,0000,0000,0001,0011
		//b - byte:0001,1001
		//	 (int):0000,0000,0000,0000,0000,0000,0001,1001
		//    结果:0000,0000,0000,0000,0000,0000,0001,0001
		//  (byte):0001,0001
		byte result = (byte)(a & b);
		
		System.out.println(result);//17 - 0001,0001
		
		//|或:同位比较,两者有1,结果就为1
		int a = 19;//0000,0000,0000,0000,0000,0000,0001,0011
		int b = 25;//0000,0000,0000,0000,0000,0000,0001,1001
				   //0000,0000,0000,0000,0000,0000,0001,1011
		System.out.println(a | b);//27
		
		//^异或:同位比较,两者不同为1,相同为0
		int a = 19;//0000,0000,0000,0000,0000,0000,0001,0011
		int b = 25;//0000,0000,0000,0000,0000,0000,0001,1001
				   //0000,0000,0000,0000,0000,0000,0000,1010
		System.out.println(a ^ b);//10
		
		注意:
			&、|、^:前后两侧为数值,该符号为位运算符
			&、|、^:前后两侧为boolean,该符号为逻辑运算符
			
		//<<左移:整体向左移动n位,就用n个0补位,补到最低位
		//经验:向左移动1位,相当于乘以2
		int a = 1024;//0000,0000,0000,0000,0000,0100,0000,0000
					 //0000,0000,0000,0000,0010,0000,0000,0000
		System.out.println(a << 3);//8192
			
			
		//>>右移:整体向右移动n位,就用n个最高位补位(符号位),补到最高位
		//注意:正数右移用0补位,负数右移用1补位
		//经验:向右移动1位,相当于除以2
		int a = 1024;//0000,0000,0000,0000,0000,0100,0000,0000
					 //0000,0000,0000,0000,0000,0000,1000,0000
		System.out.println(a >> 3);//128
		
		int b = -1024;//1111,1111,1111,1111,1111,1100,0000,0000
					  //1111,1111,1111,1111,1111,1111,1000,0000
		
		System.out.println(b >> 3);//-128
		
		//>>>无符号位右移:整体向右移动n位,就用n个0补位,补到最高位
		//注意:无符号位右移和右移处理正数都是一样的,都用0补位
		int a = 1024;//0000,0000,0000,0000,0000,0100,0000,0000
					 //0000,0000,0000,0000,0000,0000,1000,0000
		System.out.println(a >>> 3);//128
		
		int b = -1024;//1111,1111,1111,1111,1111,1100,0000,0000
				     //0001,1111,1111,1111,1111,1111,1000,0000
		
		System.out.println(b >>> 3);//536870784
	}
}

8.扩展知识点

1. 三元运算符的特殊场景

  • null 处理:若一个表达式为 null,返回值类型由另一个表达式决定。

    Object result = (true) ? "Hello" : null; // 类型为 String
  • 自动拆箱陷阱:包装类为 null 时可能抛出 NullPointerException

    Integer b = null;
    int result = (false) ? 10 : b; // 运行时异常

2. 位运算符应用

  • 交换两个数(无需临时变量):

    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
  • 快速计算:左移/右移实现乘除 2 的幂次。

3. 常量与变量混合运算

  • 若常量值在变量类型范围内,按变量类型返回;否则按常量类型返回。

示例

int a = 5;
System.out.println((a < 5) ? 10.9 : 9); // 输出 9.0(int 提升为 double)

总结: 运算符的优先级和类型转换规则是 Java 基础中的核心内容,理解这些规则可避免常见的编译错误和逻辑问题。建议通过实际编码验证不同场景下的行为,加深记忆。

五. 流程控制

Java 基础知识点总结

1. 转义字符

1.1 概念

在 Java 中,转义字符用于表示一些特殊的字符,例如双引号、单引号、反斜杠等。通过转义字符,可以在字符串中使用这些特殊字符而不产生语法错误。

1.2 常见转义字符及示例

转义字符含义示例代码输出结果
\"表示一个双引号字符System.out.println("老师说:\"好好学习\"");老师说:"好好学习"
\'表示一个单引号字符System.out.println("老师说:\'好好学习\'");老师说:' 好好学习'
\\表示一个反斜杠字符System.out.println("老师说:\\好好学习\\");老师说:\ 好好学习 \
\n表示换行System.out.print("好好学习\n");好好学习(换行)
\t表示水平制表符System.out.println("3*3=9\t3*4=12\t3*5=15");33=9 34=12 3*5=15

1.3 打印方法区别

println():打印内容后换行。

print():只打印内容,不换行。

示例代码:

java

System.out.print("好好学习\n");
System.out.print("天天向上");

输出结果:

好好学习 
天天向上

2. 常量

2.1 数字字面量

  • 整数默认类型为 int

  • 小数默认类型为 double

2.2 字面值常量

  • 双引号括起来的内容

2.3 final 修饰的常量

使用 final 关键字修饰的变量为常量,一旦赋值后不能再修改。

示例代码:

final int num = 100;
System.out.println(num++);//报错 无法为 final 变量 num 分配值

3. Java 执行流程

3.1 顺序结构

程序按照代码的书写顺序依次执行。

3.2 选择结构

3.2.1 if 语句
  • 语法结构:

if(条件表达式){
    // 语句块
}
  • 执行流程:条件表达式的结果为 boolean 类型,如果为 true,则执行语句块;如果为 false,则跳过 if 语句,继续执行后面的代码。

示例代码:

Scanner scan = new Scanner(System.in);
System.out.println("请输入成绩:");
double score = scan.nextDouble();
if(score > 98){
    System.out.println("恭喜你,一个奖励大娃娃");
}

3.3 循环结构

包括 for 循环、while 循环、do-while 循环。

3.4 跳转语句

包括 breakreturncontinuelable

4. 命名规范(Test04.java)

4.1 大驼峰命名法

用于类名,首字母大写,后续每个单词首字母也大写。例如:HelloWorld

4.2 小驼峰命名法(推荐)

用于变量名和方法名,第一个单词首字母小写,后续每个单词首字母大写。例如:javaScore

5. if...else... 语句

5.1 语法结构

if(条件表达式){
    // 语句块 1
} else {
    // 语句块 2
}

5.2 执行流程

条件表达式的结果必须为 boolean 类型,如果为 true,则执行语句块 1;如果为 false,则执行语句块 2。

示例代码:

Scanner scan = new Scanner(System.in);
System.out.println("请输入成绩:");
double score = scan.nextDouble();
if(score > 98){
    System.out.println("恭喜你,奖励一个大娃娃");
} else {
    System.out.println("很遗憾,继续努力");
}

6. 多重 if 语句

6.1 语法结构

if(条件表达式 1){
    // 语句块 1
} else if(条件表达式 2){
    // 语句块 2
} else if(条件表达式 n){
    // 语句块 n
} else {
    // 语句块 else
}

6.2 执行流程

依次判断条件表达式,如果某个条件表达式为 true,则执行对应的语句块,然后跳出多重 if 语句;如果所有条件表达式都为 false,则执行 else 语句块(如果有)。

示例代码:

Scanner scan = new Scanner(System.in);
System.out.println("请输入成绩:");
double score = scan.nextDouble();
if(score >= 90 && score <= 100){
    System.out.println("A");
} else if(score >= 80 && score < 90){
    System.out.println("B");
} else if(score >= 70 && score < 80){
    System.out.println("C");
} else if(score >= 60 && score < 70){
    System.out.println("D");
} else if(score >= 0 && score < 60){
    System.out.println("E");
} else {
    System.out.println("成绩错误");
}

7. 嵌套 if 语句

在一个 if 语句中可以嵌套另一个 if 语句,用于处理更复杂的条件判断。

小结:if可以无限层嵌套 

经验:if嵌套最好不要超过3层(考虑到可读性)

示例代码:

Scanner scan = new Scanner(System.in);
System.out.println("请输入考试成绩:");
double score = scan.nextDouble();
if(score >= 0 && score < 16){
    System.out.println("可以报名");
    String sex = scan.next();
    if(sex.equals("男")){
        System.out.println("欢迎来到男子组");
    } else if(sex.equals("女")){
        System.out.println("欢迎来到女子组");
    } else {
        System.out.println("报名错误");
    }
} else if(score >= 16){
    System.out.println("很遗憾,你不能参加...");
} else {
    System.out.println("成绩错误");
}
 

8. switch 语句

8.1 语法结构

switch(表达式){
    case 值 1:
        // 语句块 1
        break;
    case 值 2:
        // 语句块 2
        break;
    case 值 n:
        // 语句块 n
        break;
    default:
        // 语句块 default
        break;
}

8.2 执行流程

表达式的值与各个 case 后面的值进行比较,如果相等,则执行对应的语句块,直到遇到 break 语句跳出 switch 语句;如果所有 case 值都不匹配,则执行 default 语句块(如果有)。

8.3 注意事项

  • case 后面的值不能重复。

  • default 语句可以省略。

  • break 语句可以省略,如果省略,会继续执行下一个 case 语句块,直到遇到 breakswitch 语句结束。

  • 表达式的值可以是 byteshortintcharString(JDK1.7 及以上)、枚举(JDK1.5 及以上)。

  • switch底层逻辑是什么?

    • 将表达式的值转化为int类型

    输入类型转化类型方式
    byteint自动转型
    shortint自动转型
    intint直接使用
    charint获取码值
    Stringint获取hash值
    枚举int获取枚举对象的编号
    • 获取hash值:

      • (String的hash值就是获取的字符的码值 + 散列算法,算出来的一个int值)

示例代码

Scanner scan = new Scanner(System.in);
System.out.println("请输入抽奖序号:");
String str = scan.next();
switch(str){
    case "一等奖":
        System.out.println("获得一台华为电脑");
        break;
    case "二等奖":
        System.out.println("获得一部苹果手机");
        break;
    case "三等奖":
        System.out.println("获得一个移动硬盘");
        break;
    default:
        System.out.println("老师会详细讲解抽奖规则");
        break;
}

案例

  • 需求:输入年和月,输出当月的天数

import java.util.Scanner;
public class Test09{
	public static void main(String[] args){
					Scanner scan = new Scanner(System.in);
			System.out.println("请输入年:");
			int year = scan.nextInt();
			System.out.println("请输入月:");
			int month = scan.nextInt();
		
			int day = 0;
			switch(month){
				case 1:case 3:case 5:case 7:case 8:case 10:case 12:
					day = 31;
				break;
				case 4:case 6:case 9:case 11:
					day = 30;
				break;
				case 2:
					if(year%4==0 && year%100!=0 || year%400==0){
						day = 29;
					}else{
						day = 28;
					}
				break;
			}
			System.out.println(year + "年" + month + "月当月的天数为:" + day + "天");
	}
}

switch判断区间

int num = 3;
switch (num) {
    case 1:
    case 2:
    case 3:
        System.out.println("1-3");
        break;
    case 4:
    case 5:
        System.out.println("4-5");
        break;
    default:
        System.out.println("其他");
}

8.4 if 与 switch 的比较

  • 表达式类型

    • if 的条件表达式为 boolean 类型;

    • switch 的表达式可以是 byteshortintcharString、枚举。

  • 应用场景

    • if 适用于复杂的条件判断;

    • switch 适用于判断值的情况。

六.循环语句

1. for 循环

1.1 语法结构

for(表达式 1; 表达式 2; 表达式 3){
    // 语句块
}

理解: 

表达式1 -- 初始化变量 ​

表达式2 -- 判断条件 ​

表达式3 -- 更新变量

1.2 执行流程

  1. 执行表达式 1,进行初始化操作。

  2. 执行表达式 2,进行条件判断,结果为boolean类型。

    • 如果为 true,则执行语句块,然后执行表达式 3,再回到步骤 2 继续判断。

    • 如果为 false,则跳出循环。

示例代码:

for(int i = 1; i <= 10; i++){
    System.out.println(i);
}

 

1.3 常见应用场景

  • 打印一定范围内的数字。

  • 循环输入数据并进行求和、求平均值、找最大值等操作。

示例代码(求 5 个整数的和):

Scanner scan = new Scanner(System.in);
int sum = 0;
for(int i = 1; i <= 5; i++){
    System.out.println("请输入第" + i + "个数字:");
    int num = scan.nextInt();
    sum += num;
}
System.out.println("总和为:" + sum);
知识点
  • 用于已知循环次数的情况。

  • 语法结构:for(初始化语句; 判断条件; 迭代语句){ 循环体 }

示例代码
// 打印矩形图案
for(int i = 0;i<3;i++){
    for(int j = 0;j<4;j++){
        System.out.print("*");
    }
    System.out.println();
}
代码解释
  • 外层循环控制行数,内层循环控制每行的列数。通过嵌套循环可以打印出各种图案。

2. while 循环

知识点
  • 用于循环次数不确定,但有明确判断条件的情况。

  • 语法结构:while(判断条件){ 循环体 }

示例代码
int i = 0;
while(i<5){
    System.out.println("循环执行中");
    i++;
}
代码解释
  • 先判断条件,条件为true则执行循环体,执行完后再次判断条件,直到条件为false

3. do - while 循环

知识点
  • 先执行一次循环体,再判断条件。保证循环体至少执行一次。

  • 语法结构:do{ 循环体 }while(判断条件);

示例代码
Scanner scan = new Scanner(System.in);
String str;
do{
    System.out.println("请输入内容");
    str = scan.next();
}while(str.equals("继续"));
代码解释
  • 无论条件是否成立,循环体都会先执行一次,然后再根据条件决定是否继续循环。

4. 循环控制语句

4.1 break

知识点
  • 循环中使用,用于终止当前循环。

示例代码
Scanner scan = new Scanner(System.in);
boolean flag = true;
double sum = 0;
for(int i = 1;i<=5;i++){
    System.out.println("请输入第" + i + "个成绩");
    double score = scan.nextDouble();
    if(score < 0){
        flag = false;
        break;
    }
    sum += score;
}
代码解释
  • 当输入的成绩为负数时,使用break语句终止循环。

4.2 continue

Scanner scan = new Scanner(System.in);
int count = 0;
for(int i = 1;i<=5;i++){
    System.out.println("请输入第" + i + "个学生的成绩");
    double score = scan.nextDouble();
    if(score < 80){
        continue;
    }
    count++;
}
知识点
  • 在循环中使用,用于跳过本次循环,直接进入下一次循环。

代码解释
  • 当输入的成绩小于 80 分时,使用continue语句跳过本次循环,不执行count++

4.3 return

知识点
  • 在方法中使用,用于返回方法的结果,并终止当前方法的执行。

示例代码
public static void main(String[] args) {
    System.out.println("111");
    System.out.println("222");
    if(true){
        return;
    }
    System.out.println("333");
}
代码解释
  • 当条件为true时,使用return语句终止方法的执行,后面的System.out.println("333");不会执行。

4.4 label

知识点
  • 用于标记循环,可配合breakcontinue语句跳出指定的循环。

示例代码
a: for(int i = 1;i<=5;i++){
    for(int j = 1;j<=3;j++){
        if(i == 3){
            break a;
        }
        System.out.println(i + " -- " + j);
    }
}
代码解释
  • i等于 3 时,使用break a;语句跳出标记为a的外层循环。

5. 静态方法

知识点
  • static关键字修饰的方法,可通过类名直接调用。

  • 语法结构:public static 返回值类型 方法名(参数列表){ 方法体 }

方法的调用

  •   在需要调用方法的位置直接书写方法名()即可调用。
示例代码
public static void printStar(){
    for(int i = 0;i<5;i++){
        for(int j = 0;j<=i;j++){
            System.out.print("*");
        }
        System.out.println();
    }
}
代码解释
  • printStar方法是一个静态方法,可通过Test10.printStar();调用。

6. 日期计算与日历打印

知识点
  • 涉及日期计算,判断闰年,计算指定年月的第一天是星期几,以及打印日历。

示例代码
Scanner scan = new Scanner(System.in);
System.out.println("请输入年份:");
int year = scan.nextInt();
System.out.println("请输入月份:");
int month = scan.nextInt();
// 计算指定年份前的总天数
int allDayOfYear = 0;
for(int i = 1900;i<year;i++){
    if(i%4==0 && i%100!=0 || i%400==0){
        allDayOfYear += 366;
    } else {
        allDayOfYear += 365;
    }
}
代码解释
  • 首先获取用户输入的年份和月份,然后计算从 1900 年到指定年份前一年的总天数,根据闰年规则判断每年的天数。

七.方法的重载递归

方法的重载

知识点
  • 条件

    • 同一类中,方法名相同,参数列表不同(类型或数量或顺序)。

    • 与返回值无关以及访问权限修饰符无关 。

  • 优点:根据实参类型自动匹配方法。

代码示例

public class Test03 {
    public static void main(String[] args) {
        System.out.println(getMax(10, 20, 30.3));
    }
​
    // 重载示例
    public static int getMax(int a, int b) { /*...*/ }
    public static int getMax(int a, int b, int c) { /*...*/ }
    public static double getMax(double a, double b) { /*...*/ }
    public static double getMax(double a, double b, double c) { /*...*/ }
}

4. 方法的递归(错误示例)

知识点
  • 递归错误:死循环导致栈溢出(StackOverflowError)。

  • 原因:每次递归调用都会在栈中开辟新空间,无限调用导致内存耗尽。

代码示例

public class Test04 {
    public static void main(String[] args) {
        method(); // 错误示例
    }
​
    public static void method() {
        method(); // 无限递归
    }
}

总结

  • 方法:注重参数传递、返回值、重载与递归的合理使用。

  • 数组:掌握静态/动态初始化、遍历方式及常见操作(如求最值)。

  • 递归:必须定义出口,避免栈溢出。

  • 代码规范:方法功能单一,变量命名清晰,逻辑分层明确。


5. 递归实现阶乘

知识点
  • 递归要点

    • 规律n! = (n-1)! * n

    • 出口1! = 1

代码示例

public class Test05 {
    public static void main(String[] args) {
        System.out.println(method(5)); // 输出120
    }
​
    public static int method(int n) {
        return (n == 1) ? 1 : method(n - 1) * n;
    }
}
 

6. 方法版本的万年历

知识点
  • 功能分解

    • 计算总天数、判断闰年、获取当月天数、打印日历。

  • 关键方法

    • getAllDay:计算从基准年(1900)到目标年的总天数。

    • getWeek:计算某月第一天的星期。

代码结构

//封装方法万历表
import java.util.Scanner;
public class Test06{
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入年:");
        int year = scan.nextInt();
        System.out.println("请输入月:");
        int month = scan.nextInt();
        
        //获取星期
        int week = getWeek(year,month);
        
        //获取当月的天数
        int day = getDay(year,month);
        
        //打印日历
        printCalendar(year,month,day,week);
        
        
    }
    //打印日历
    public static void printCalendar(int year,int month,int day,int week){
        System.out.println(year + "年" + month + "月");
        System.out.println("一\t二\t三\t四\t五\t六\t日");
        
        int count = 0;
        
        for(int i = 1;i<week;i++){
            System.out.print("\t");
            count++;
        }
        
        for(int i = 1;i<=day;i++){
            System.out.print(i + "\t");
            count++;
            if(count % 7 == 0){
                System.out.println();//换行
            }
        }
    }
    //获取星期
    public static int getWeek(int year,int month){
        int week = getAllDay(year,month)%7;
        if(week == 0){
            week = 7;
        }
        return week;
    }   
    
    //获取总天数
    public static int getAllDay(int year,int month){
        int allDay = getAllDayOfMonth(year,month) + getAllDayOfYear(year)+1;
        return allDay;
    }
    
    //获取月的总天数
    public static int getAllDayOfMonth(int year,int endMonth){
        int AllDayOfMonth = 0;
        for(int i = 1;i < endMonth;i++){
            AllDayOfMonth += getDay(year,i);
        }
        return AllDayOfMonth;
    }
    
    //获取当月的天数
    public static int getDay(int year,int month){
        int day = 0;
        switch(month){
            case 1:case 3:case 5:case 7:case 8:case 10:case 12:
                day = 31;
            break;
            case 4:case 6:case 9:case 11:
                day = 30;
            break;
            case 2:
                if(isLeapYear(year)){
                    day = 29;
                }else{
                    day = 28;
                }
            break;
        }
        return day;
    }
​
    //获取年的总天数
    public static int getAllDayOfYear(int year){
        int allDayOfYear =0;
        for(int i = 1900;i < year; i++){
            if(isLeapYear(i)){
                allDayOfYear += 366;
            }else{
                allDayOfYear += 365;
            }
        }
        return allDayOfYear;
    }
    
    //判断是否是闰年
    public static boolean isLeapYear(int year){
        if(year % 4 == 0 && year % 100 !=0 || year % 400 == 0){
            return true;
        }else{
            return false;
        }
    }
}

八.数组

1.数组的概念:

                     一组`连续`的存储空间,存储多个`相同`数据类型的值,长度是`固定`的。

2. 数组的定义

先声明、再分配空间: 数据类型[] 数组名; 数组名 = new 数据类型[长度];

声明并分配空间: 数据类型[] 数组名 = new 数据类型[长度];

声明并赋值(繁): 数据类型[] 数组名 = new 数据类型[]{value1,value2,value3,...};

声明并赋值(简): 数据类型[] 数组名 = {value1,value2,value3,...};

3. 数组的使用

数组的元素:数组中的每个数据称之为数组中的元素

数组的访问:对数组中的元素赋值以及取值的操作 统称为数组的访问

下标、索引、角标、index : 下标自动生成 从0开始 往后依次+1

访问数组通过下标访问:

赋值 数组名[下标] = 值;

取值 System.out.println(数组名[下标]);

访问不存在的下标 将会导致数组下标越界异常 ArrayIndexOutOfBoundsException

一维数组

知识点
  • 静态初始化String[] names = {"A", "B", "C"};

  • 遍历方式

    • for循环(需下标时使用)。

    • foreach循环(无需下标时使用)。

代码示例

public class Test07 {
    public static void main(String[] args) {
        String[] names = {"麻生希", "椎名空", "王舟毅"};
        for (String name : names) {
            System.out.println(name);
        }
    }
}

4. 一维数组(动态初始化)

知识点
  • 动态初始化String[] names = new String[5];

  • 默认值

    • int:0,double:0.0,boolean:false,引用类型:null

代码示例

public class Test08 {
    public static void main(String[] args) {
        String[] names = new String[5];
        names[0] = "白鸽";
    }
}

//{白鸽,null,null,null,null}

5. 数组应用:最大值查找

知识点
  • 步骤

    • 动态初始化数组并录入数据。

    • 遍历比较求最大值。

代码示例

public class Test09 {
    public static void main(String[] args) {
        int[] arr = new int[5];
        // 录入数据...
        int max = arr[0];
        for (int num : arr) {
            if (num > max) max = num;
        }
        System.out.println("最大值:" + max);
    }
}

6.数组的扩容

数组的扩容:

实现步骤:

1.创建比原数组更长的新数组

2.将原数组中的元素依次复制到新数组中

3.将新数组的地址赋值给原数组

数组作为引用数据类型 其数组名中保存的是指向堆中的地址 所以 当我们把一个数组 赋值 给 另外一个数组 赋值的是地址

 

package com.atguigu.test4;


import java.util.Arrays;

/**
 *  数组的扩容:
 *  实现步骤:
 *      1.创建比原数组更长的新数组
 *      2.将原数组中的元素依次复制到新数组中
 *      3.将新数组的地址赋值给原数组
 */
public class TestArrayGrow {
    public static void main(String[] args) {
        int [] oldArr = {1,2,3,4,5};

        int [] newArr = new int[oldArr.length * 2];

        for(int i = 0;i < oldArr.length ;i++){
            newArr[i] = oldArr[i];
        }

        System.out.println(Arrays.toString(newArr));
        // 数组作为引用数据类型 其数组名中保存的是指向堆中的地址
        // 所以 当我们把一个数组 赋值 给 另外一个数组
        // 赋值的是地址

        System.out.println(oldArr);
        System.out.println(newArr);

        oldArr = newArr;
        System.out.println("==================地址赋值以后===================");

        System.out.println(oldArr);
        System.out.println(newArr);

        System.out.println(oldArr.length);

        System.out.println(Arrays.toString(oldArr));

        System.out.println("------------------------------------------------------------------");

        newArr[9] = 666;

        System.out.println(oldArr[9]); // 0? 666?
    }
}

 

 7.数组的复制

复制数组的三种方式:

循环将原数组中所有元素逐一赋值给新数组。

System.arraycopy(原数组,原数组起始,新数组,新数组起始,长度);

java.util.Arrays.copyOf(原数组, 新长度);//返回带有原值的新数组。

 

package com.atguigu.test4;

import java.sql.SQLOutput;
import java.util.Arrays;

/**
 * @author WHD
 * @description TODO
 * @date 2023/8/2 14:23
 *  复制数组的三种方式:
 *      循环将原数组中所有元素逐一赋值给新数组。
 *      System.arraycopy(原数组,原数组起始,新数组,新数组起始,长度);
 *      java.util.Arrays.copyOf(原数组, 新长度);//返回带有原值的新数组。
 */
public class TestArrayCopy {
    public static void main(String[] args) {
        int [] oldArr = {1,2,3,4,5};

        int [] newArr = new int[10];

        System.arraycopy(oldArr, 1, newArr, 2, 2);

        System.out.println(Arrays.toString(newArr));

        System.out.println("-------------------------------------------------");

        int [] nums = {11,22,33,44,55};

        // 第一个参数 原数组
        // 第二个参数 新长度 新长度可以小于等于或者大于原数组的长度
        int [] newNums = Arrays.copyOf(nums, 5);

        System.out.println(Arrays.toString(newNums));
    }
}

8.面试题

值传递和引用传递的区别?

Java官方明确指出 Java中只有值传递

基本数据类型属于'值传递',传递的就是值的副本,值的拷贝,在方法中对参数的修改不会影响原变量

引用数据类型属于'引用传递' 传递的是地址,也就是引用,在方法中对参数的修改会影响原变量

String类型是特殊的引用数据类型 作为参数不会影响原变量 因为String是不可变

 

9.可变长参数

可变长参数:可接收多个同类型实参,个数不限,使用方式与数组相同。

要求:

1.整个形参列表中只能有一个可变长参数

2.必须书写在形参列表的末尾

格式:数据类型...参数名

package com.atguigu.test6;

/**
 *  可变长参数:可接收多个同类型实参,个数不限,使用方式与数组相同。
 *  要求:
 *      1.整个形参列表中只能有一个可变长参数
 *      2.必须书写在形参列表的末尾
 *  格式:数据类型...参数名
 */
public class TestChangedParam {
    public static void m1(int ... args){
        System.out.println("m1方法开始执行");
        for(int i =0;i < args.length;i++){
            System.out.println(args[i]);
        }
        System.out.println("m1方法执行完毕");
    }
    public static void m2(int [] args){
        System.out.println("m2方法开始执行");
        for(int i =0;i < args.length;i++){
            System.out.println(args[i]);
        }
        System.out.println("m2方法执行完毕");
    }
    public static void main(String[] args) {
        m1(1,2,3,4,5,6);

        int [] nums = new int[4];
        m2(nums);

    }


}

10. Arrays工具类

java.util.Arrays 是JDK提供的一个用于操作数组的工具类

toString(数组名) : 将数组中的元素转换为字符串

copyOf(数组名,新长度) : 复制数组

sort(数组名) : 将数组按照升序排序 属于快速排序 实现原理为 递归

fill(数组名,填充元素) : 将数组按照指定元素进行填充

binarySearch(数组名,元素) : 使用二分查找法查找某个元素在数组中的下标

核心方法

方法功能说明注意事项
Arrays.sort(arr)数组排序(升序)修改原数组
Arrays.binarySearch(arr, key)二分查找元素下标必须已排序
Arrays.copyOf(arr, newLength)拷贝数组并指定新长度新长度可大于原数组长度
Arrays.fill(arr, value)用指定值填充数组可指定填充区间 (from, to)
Arrays.toString(arr)将数组转换为字符串输出格式:[e1, e2, e3]

代码示例

int[] arr = {67,81,37,72,41,18,88,22,44,66,11};
Arrays.sort(arr); // 排序后:[11, 18, 22, 37, 41, 44, 66, 67, 72, 81, 88]
int index = Arrays.binarySearch(arr, 37); // 返回3
int[] copy = Arrays.copyOf(arr, 15); // 新数组长度15,超出部分补默认值

package com.atguigu.test3;
​
import java.util.Arrays;
​
/**
 * @author WHD
 * @description TODO
 * @date 2023/8/4 14:05
 *  toString(数组名) : 将数组中的元素转换为字符串
 *  copyOf(数组名,新长度) : 复制数组
 *  sort(数组名) : 将数组按照升序排序
 *  fill(数组名,填充元素) : 将数组按照指定元素进行填充
 *  binarySearch(数组名,元素) : 使用二分查找法查找某个元素在数组中的下标
 */
public class TestArrays {
    public static void main(String[] args) {
        int [] nums = {56,12,22,41,85,99};
​
        Arrays.sort(nums);
​
        System.out.println(Arrays.toString(nums));
​
        int [] newArr = new int[nums.length];
​
        for(int i = 0,j = nums.length -1;i < nums.length;i++,j--){
            newArr[i] = nums[j];
        }
​
        System.out.println(Arrays.toString(newArr));
​
        System.out.println("--------------------------------------------");
​
        Arrays.fill(newArr, 666);
​
        System.out.println(Arrays.toString(newArr));
​
        System.out.println("--------------------------------------------");
​
        int index = Arrays.binarySearch(nums, 999);
​
        System.out.println("index = " + index);
​
    }
}

11. 数组插入元素

编写方法实现在数组中插入元素

扩展:可以使用System.arraycopy方法 实现插入效果

package com.atguigu.test3;
​
import java.util.Arrays;
​
/**
 * @author WHD
 * @description TODO
 * @date 2023/8/4 14:16
 *  编写方法实现在数组中插入元素
 *  扩展:可以使用System.arraycopy方法 实现插入效果
 */
public class TestArrayInsert {
    public static void main(String[] args) {
        int [] nums = {1,2,3,4,5};
        int[] newArray = insert(nums, -8, 666);
        System.out.println(Arrays.toString(newArray));
    }
    /**
     *
     * @param oldArray 操作的数据
     * @param index 插入元素的位置
     * @param num 插入的元素
     * @return 新的数组
     */
    public static int[] insert(int [] oldArray,int index,int num){
        // 下标不能小于0 或者 不能大于数组的长度
        if(index < 0 || index > oldArray.length){
            System.out.println("下标不合法");
            // 如果下标不合法 则将传入的数组 直接返回 表示没有做任何操作
            return oldArray;
        }
​
        // 代码执行到这里 表示下标没问题
        // 准备一个长度+1的数组 用于插入元素
        int [] newArray = new  int[oldArray.length + 1];
​
        // 遍历开始移动元素
        for(int i = 0;i < oldArray.length;i++){
            // 情况1 小于插入下标 则直接复制到新数组中
            if(i < index){
                newArray[i] = oldArray[i];
            }else{ // 情况2  大于或者等于插入下标 则移动到新数组的+1位置
                newArray[i + 1] = oldArray[i];
            }
        }
        // 空缺位插入指定的元素
        newArray[index] = num;
        return newArray; // 将新数组返回
    }
}

12.数组删除元素

编写方法实现删除数组中的元素

扩展:可以使用System.arraycopy方法 实现删除效果

package com.atguigu.test3;
​
import java.util.Arrays;
​
/**
 * @author WHD
 * @description TODO
 * @date 2023/8/4 14:31
 *  编写方法实现删除数组中的元素
 *  扩展:可以使用System.arraycopy方法 实现删除效果
 */
public class TestArrayDelete {
    public static int[] delete(int [] oldArray,int index){
        // 判断下标 如果小于0 或者 大于等于数组长度 表示不合法 因为删除 只能删除有效范围以内的
        if(index < 0 || index >= oldArray.length){
            System.out.println("下标不合法");
            return oldArray; // 直接将传入的原数组返回 表示没有做任何操作
        }
​
        // 准备一个长度-1的数组 用于删除之后复制元素
        int [] newArray = new int[oldArray.length - 1];
        // 循环遍历开始复制元素
        for(int i = 0;i < newArray.length;i++){
            if(i < index){ // 情况1 小于删除的下标 直接复制
                newArray[i] = oldArray[i];
            }else{ // 情况2 大于等于删除下标 则直接将原数组的+1位置 移动到新数组的后续位置 属于向左移动覆盖
                newArray[i] = oldArray[i +1];
            }
        }
        return newArray; // 将新数组返回
    }
​
    public static void main(String[] args) {
        int [] nums = {1,2,3,4,5};
        int[] delete = delete(nums, -5);
        System.out.println(Arrays.toString(delete));
    }
​
}

13.二维数组

二维数组:数组中的元素还是数组

package com.atguigu.test3;
​
/**
 * @author WHD
 * @description TODO
 * @date 2023/8/4 15:30
 *  二维数组:数组中的元素还是数组
 */
public class Test2DArray {
    public static void main(String[] args) {
        int [] arr1 = {1,2,3,4,5};
        int [] [] arr2 = { {1,2,4} ,  {55,88,66}  , {666} , {999,888,777}};
​
        System.out.println(arr2[0]);
        System.out.println(arr2[0][0]);
        System.out.println(arr2[0][1]);
        System.out.println(arr2[0][2]);
        System.out.println("----------------------------------");
        System.out.println(arr2[1][0]);
        System.out.println(arr2[1][1]);
        System.out.println(arr2[1][2]);
        System.out.println("----------------------------------");
        System.out.println(arr2[2][0]);
        System.out.println("----------------------------------");
        System.out.println(arr2[3][0]);
        System.out.println(arr2[3][1]);
        System.out.println(arr2[3][2]);
​
        System.out.println("----------------------------------");
​
        for(int i = 0;i < arr2.length;i++){
            System.out.println(arr2[i]);
            for(int j = 0;j < arr2[i].length;j++){
                System.out.print(arr2[i][j] + "\t");
            }
            System.out.println();
        }
​
​
    }
}

二维数组定义:和一维数组定义方式大致相同

二维开辟空间 高维度(第一个中括号)长度必须指定 低维度(第二个中括号)长度可以后续单独指定

package com.atguigu.test3;
​
/**
 * @author WHD
 * @description TODO
 * @date 2023/8/4 15:38
 *  二维数组定义:和一维数组定义方式大致相同
 *  二维开辟空间 高维度(第一个中括号)长度必须指定 低维度(第二个中括号)长度可以后续单独指定
 */
public class Test2DArrayDefine {
    public static void main(String[] args) {
        // 方式1
        int [][] arr1;
        arr1 = new int[3][4];
​
        // 方式2
        // 数组的默认值 二维数组每个元素为一维数组 属于引用数据类型 其默认值为null
        // 当我们创建一个长度为2的二维数组 表示在内存中 有两个一维数组 都指向为null
        int [][] arr2 = new int[2][];
​
        System.out.println(arr2[0]);
        System.out.println(arr2[1]);
​
​
        arr2[0] = new int[3];
        arr2[0][0] = 11;
        arr2[0][1] = 11;
        arr2[0][2] = 11;
​
        arr2[1] = new int[2];
        arr2[1][0] = 34;
        arr2[1][1] = 56;
​
​
        // 方式3
        int [][] arr3 = new int[][]{{1},{22,33,44},{55,55,666}};
​
        // 方式4
        int [][] arr4 = {{1},{22,33,44},{55,55,666}};
​
​
​
​
​
​
    }
}

二维数组实现:杨辉三角

package com.atguigu.test3;
​
/**
 * @author WHD
 * @description TODO
 * @date 2023/8/4 15:47
 *  杨辉三角
 *  1
 *  1   1
 *  1   2   1
 *  1   3   3   1
 *  1   4   6   4   1
 *  1   5   10  10  5   1
 */
public class TestYangHuiTriangle {
    public static void main(String[] args) {
        int [][] yh = new int[6][6];
        for(int i = 0;i < yh.length;i++){
            yh[i][0] = 1; // 每一行的第一列为1
            yh[i][i] = 1;
​
            if(i > 1){ // 表示从第3行开始 赋值有具体的计算
                for(int j = 1;j < i;j++){ // 因为每一行的第一列 和 最后一列都有值了 为0  所以 我们只需要赋值中间的元素
                    yh[i][j] = yh[i -1][j] + yh[i -1][j -1];
                }
            }
        }
        for(int i = 0;i < yh.length;i++){
            for(int j = 6;j >= i;j--){
                System.out.print(" ");
            }
            for(int j = 0;j <= i;j++){
                System.out.print(yh[i][j] + " ");
            }
            System.out.println();
        }
    }
}

九.面相对象

一、类与对象基础

1.1 类定义规范

//文档1基础类
public class Person {
    //成员变量(未封装)
    String name;
    char sex;
    int age;
    
    //成员方法
    public void eat(){...}
}

//文档4改进类
public class Person {
    //成员变量(封装改进)
    String name;
    char sex;
    int age;
    
    //使用this的成员方法
    public void eat(){
        System.out.println(this.name + " eating"); 
    }
}

核心知识点:​

  1. 类包含成员变量和成员方法
  2. 默认访问修饰符为包级私有(未显式声明时)
  3. this关键字用于明确访问当前对象成员
  4. 成员变量未初始化时系统默认赋值(String->null, int->0等)

1.2 对象创建与使用

//文档2测试类
Person p = new Person();
p.name = "张三";
p.eat();

//文档3多对象测试
Person p1 = new Person();
Person p2 = new Person();
p1.age = 23;
p2.age = 18;

对象特性:​

  • new关键字触发堆内存分配
  • 每个对象独立存储成员变量副本
  • 对象引用存储的是堆内存地址
  • 垃圾回收机制自动管理内存

二、封装与访问控制

2.1 private封装

//文档5私有化示例
public class A {
    private String str = "";
    private void method01(){...}
    
    public void method02(){
        method01(); //内部调用私有方法
    }
}

//文档6测试类
A a = new A();
a.method02(); //通过公有方法间接访问私有方法

封装原则:​

  1. 私有化字段(private修饰)
  2. 提供公有访问方法(getter/setter)
  3. 方法内部可添加业务逻辑控制

2.2 标准封装实现

//文档7完整封装类
public class User {
    private String username;
    private double money;
    
    //带验证的setter
    public void setMoney(double money) {
        System.out.println(LocalDateTime.now() + " 修改金额");
        this.money = money;
    }
    
    //只读属性
    public double getMoney() { return money; }
}

封装优势:​

  • 数据访问可控
  • 支持数据验证
  • 方便添加日志/通知等横切关注点
  • 保持接口稳定性

三、构造方法与对象初始化

3.1 构造方法类型

//文档10构造方法示例
public class Person {
    //无参构造
    public Person() {
        System.out.println("默认构造");
    }
    
    //全参构造
    public Person(String name, char sex, int age) {
        System.out.println("全参构造");
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
}

构造方法特点:​

  • 方法名必须与类名相同
  • 无返回类型声明
  • 支持方法重载
  • 默认提供无参构造(当无自定义构造时)
  • this()可调用同类其他构造方法

3.2 对象初始化顺序

//文档9构造方法测试
Person p = new Person("李四", 'M', 25); 
// 输出顺序:
// 1. 父类构造(如果有)
// 2. 成员变量初始化
// 3. 构造方法体执行

初始化顺序:​

  1. 静态初始化块(类加载时)
  2. 实例初始化块(每次new时)
  3. 构造方法执行
  4. 父类构造优先于子类

四、高级特性补充

4.1 静态成员

public class Person {
    //静态计数器
    private static int count = 0;
    
    public Person() {
        count++;
    }
    
    public static int getCount() {
        return count;
    }
}

静态特性:​

  • 类级别共享数据
  • 通过类名直接访问
  • 静态方法不能访问非静态成员
  • 静态初始化块用于复杂初始化

4.2 继承与多态

//补充继承示例
public class Student extends Person {
    private String school;
    
    @Override
    public void eat() {
        System.out.println("学生在食堂吃饭");
    }
}

继承要点:​

  • extends实现继承
  • super调用父类成员
  • 方法重写规则(@Override)
  • 里氏替换原则

4.3 接口与实现

//补充接口示例
public interface Walkable {
    void walk(int speed);
}

public class Athlete extends Person implements Walkable {
    @Override
    public void walk(int speed) {
        System.out.println("运动员竞走速度:" + speed);
    }
}

接口特性:​

  • 完全抽象(JDK8前)
  • 多实现机制
  • 默认方法(default)
  • 静态接口方法

五、面向对象设计原则

5.1 SOLID原则

  1. 单一职责:User类不应包含支付逻辑
  2. 开闭原则:通过继承扩展功能而非修改类
  3. 里氏替换:子类可完全替代父类
  4. 接口隔离:多个专用接口优于单一总接口
  5. 依赖倒置:高层模块不应依赖低层细节

5.2 设计模式示例

//简单工厂模式
public class PersonFactory {
    public static Person createPerson(String type) {
        switch(type) {
            case "student": return new Student();
            case "teacher": return new Teacher();
            default: return new Person();
        }
    }
}

六、异常处理补充

//封装中的异常处理
public void setAge(int age) throws IllegalArgumentException {
    if(age < 0 || age > 150) {
        throw new IllegalArgumentException("无效年龄");
    }
    this.age = age;
}

最佳实践:​

  • 在setter中进行参数校验
  • 使用自定义异常类型
  • 保持对象状态有效性

十、this 关键字相关

一. this 的三大核心作用

public class Person {
    public Person(String name, char sex, int age) {
        this.name = name;       // 1. 区分成员变量与局部变量
        this.sex = sex;
        this.age = age;
    }

    public void study() {
        this.eat();             // 2. 调用同类其他方法
        this.writerCode();
    }
}
public class User {
    public User() {
        this("default", "000000"); // 3. 调用其他构造方法(必须首行)
    }
}
核心知识点
  • 成员变量遮蔽:当形参与成员变量同名时,用 this.变量名 明确指向对象属性
  • 方法间调用:在实例方法中,this 可调用本类其他方法(非必须但增强可读性)
  • 构造方法链:通过 this(参数) 重用构造逻辑,需在构造方法首行使用

二、static 关键字相关

1. 静态变量 vs 实例变量

描述局部变量实例变量
定义位置方法或方法内的结构当中类的内部,方法的外部
默认值无默认值有默认值(与数组相同)
使用范围从定义行到包含其结构结束本类有效
命名冲突不允许重名可与局部变量重名,局部变量优先
存储位置基本数据类型存在栈中,引用数据类型名字在栈,值在堆因为实例属性保存在对象中,而对象存在堆中,全部存储在堆中
生命周期随着方法的入栈而生效,随着方法的出栈而死亡随着对象的创建而存在 随着对象被垃圾回收(GC)而死亡
public class A {
    String attr01;          // 实例变量(对象级)
    static String attr02;   // 静态变量(类级)
}
核心知识点
  • 存储位置:静态变量在方法区,实例变量在堆内存
  • 生命周期:静态变量随类加载存在,实例变量随对象创建/销毁
  • 访问方式
    A.attr02 = "value";      // 推荐类名访问
    new A().attr01 = "val";  // 必须通过对象

2. 类加载与初始化顺序

// 文档6:static A a = new A() 先执行
static A a = new A();     // 触发构造方法执行
static int value1;
static int value2 = 0;

// 构造方法中对静态变量自增
public A() {
    value1++;  // 结果:value1=1
    value2++;  // 先变成1,后被显式初始化为0
}
执行顺序解析
  1. 准备阶段:静态变量默认初始化(a=nullvalue1=0value2=0
  2. 初始化阶段:
    • 按代码顺序执行:
      • new A() → 构造方法使 value1=1value2=1
      • value2=0 覆盖为0
  3. 最终结果:value1=1value2=0

三、代码块执行顺序

1. 代码块类型与特性

public class A {
    static { // 静态代码块(类加载时执行一次)
        attr02 = "CCC"; 
    }
    
    { // 实例代码块(每次new对象时执行,先于构造方法)
        attr01 = "bbb";
    }

    public A() { // 构造方法最后执行
        attr01 = "aaa";
    }
}
执行顺序验证
new A(); // 输出顺序:
// 1. 静态代码块输出 → "CCC"
// 2. 实例代码块输出 → "bbb -- BBB"
// 3. 构造方法输出 → "aaa -- AAA"

四、工具类设计模式

1. 工具类最佳实践

public class MyArrays {
    private MyArrays() {} // 禁止实例化

    public static int[] copyOf(int[] arr, int newLength) {
        // 实现数组复制逻辑
    }

    public static String toString(int[] arr) {
        // 实现数组转字符串
    }
}
设计要点
  • 私有构造方法:防止通过 new 创建实例
  • 全静态方法:通过类名直接调用(如 MyArrays.copyOf()
  • 功能完整性
    • 处理不同长度需求(扩容/截断)
    • 格式规范化输出(模仿 Arrays.toString()

五、补充关键知识点

1. 类加载机制

  • 加载 → ​验证 → ​准备 → ​解析 → ​初始化
  • 静态变量准备阶段赋默认值,初始化阶段赋真实值

2. 单例模式与静态变量

class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton() {}
}

3. 方法设计建议

  • 参数校验:工具方法应添加 if (arr == null) throw...
  • 异常处理:考虑添加 IllegalArgumentException

六、易错点总结

场景常见错误正确做法
构造方法链this() 不在首行必须作为构造方法第一条语句
静态变量访问通过对象访问静态变量使用类名访问
代码块顺序混淆静态/实例代码块执行顺序记住静态→父类→实例→构造方法

 

十一、继承基础

1.1 继承结构

// 文档1:Person基类
public class Person {
    String name;
    char sex;
    int age;
    
    public Person() {
        System.out.println("Person构造");
    }
    
    public void eat(){}
    public void sleep(){}
}

// 文档3:Chinese子类
public class Chinese extends Person{
    String id;
    
    public Chinese() {
        System.out.println("Chinese构造");
    }
    
    public void playTaiJi(){}
}

1.2 核心知识点

  1. 继承机制:子类继承父类非私有成员(字段+方法)
  2. 构造方法执行顺序
    • 父类构造方法先于子类执行
    • 默认调用super()(隐式调用父类无参构造)
  3. 继承链
    Person构造 -> Chinese构造

二、构造方法链

2.1 构造方法示例

// 文档10:带参数的构造方法
public Chinese(String name, char sex, int age, String id) {
    super(name, sex, age); // 显式调用父类构造
    this.id = id;
}

2.2 关键要点

  1. super()规则
    • 必须作为子类构造方法的第一条语句
    • 父类若无无参构造,必须显式调用其他构造
  2. 构造方法执行顺序
    • 父类字段初始化 -> 父类构造方法体 -> 子类字段初始化 -> 子类构造方法体

三、访问权限控制

3.1 权限修饰符对比

修饰符同类同包子类其他包
private✔️✖️✖️✖️
default✔️✔️✖️✖️
protected✔️✔️✔️✖️
public✔️✔️✔️✔️

3.2 典型示例

// 文档6:A类
public class A {
    private String attr = "A属性";
    protected void method02(){}
}

// 文档7:B类(子类)
public class B extends A {
    public void test() {
        // super.attr; // 错误!不能访问父类私有成员
        super.method02(); // 允许访问protected方法
    }
}

四、方法重写(Override)

4.1 重写规则

  1. 方法签名相同
  2. 访问权限不能更严格
  3. 返回类型相同
  4. 异常不能扩大

4.2 注解使用

// 文档15:eat方法重写
@Override
public void eat() {
    System.out.println(super.getName() + "吃中餐");
}

4.3 特殊方法重写

  1. equals()
    // 文档24:User类重写
    @Override
    public boolean equals(Object obj) {
        if(this == obj) return true;
        if(obj instanceof User){
            return this.username.equals(((User)obj).username);
        }
        return false;
    }
  2. toString()
    @Override
    public String toString() {
        return username + "--" + password;
    }

五、Object类核心方法

5.1 重要方法解析

方法说明
equals()默认比较对象地址,需重写实现内容比较
hashCode()返回对象哈希码,重写equals时必须同时重写
toString()返回对象字符串表示,默认格式:类名@十六进制哈希码
getClass()返回运行时类对象
clone()创建并返回对象副本(需实现Cloneable接口)

5.2 典型应用

// 文档27:自定义字符串比较
public class MyString {
    @Override
    public boolean equals(Object obj) {
        // 内容比较逻辑
    }
}

六、封装与多态

6.1 封装实现

// 文档8:Person类封装
public class Person {
    private String name;
    // 通过getter/setter访问
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

6.2 多态应用

// 文档12:方法重写实现多态
public class Japanese extends Person {
    @Override
    public void eat() {
        System.out.println("吃日料");
    }
}

七、特殊语法特性

7.1 super关键字

  1. 访问父类成员
    super.getName();
  2. 调用父类构造
    super(name, sex, age);

7.2 final关键字

  1. 修饰类:不可继承
  2. 修饰方法:不可重写
  3. 修饰变量:常量

八、字符串处理

8.1 String特殊性

  1. 不可变性:任何修改都会创建新对象
  2. 字符串池:字面量共享机制
  3. 比较方法
    String s1 = new String("abc");
    String s2 = "abc";
    System.out.println(s1 == s2); // false
    System.out.println(s1.equals(s2)); // true

九、综合案例解析

9.1 用户系统实现

// 文档24-25:用户类及测试
public class User {
    // 字段封装
    // equals/toStirng重写
}

public class Test01 {
    public static void main(String[] args) {
        User u1 = new User("user1", "123", "张三", 5000);
        User u2 = new User("user1", "456", "李四", 3000);
        System.out.println(u1.equals(u2)); // true(用户名相同)
    }
}

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

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

相关文章

wsl2的centos7安装jdk17、maven

JDK安装 查询系统中的jdk rpm -qa | grep java按照查询的结果&#xff0c;删除对应版本 yum -y remove java-1.7.0-openjdk*检查是否删除 java -version 下载JDK17 JDK17&#xff0c;下载之后存到wsl目录下&#xff08;看你自己&#xff09;然后一键安装 sudo rpm -ivh jd…

乐鑫ESP-Mesh-Lite方案,启明云端乐鑫代理商,创新组网拓展智能应用边界

在当今智能化浪潮的背景下&#xff0c;智能家居、智能农业、能源管理等领域对设备组网的需求日益增长。然而&#xff0c;传统的Wi-Fi组网方式常常受限于设备数量、路由器位置以及网络覆盖范围等因素&#xff0c;难以满足复杂场景下的多样化需求。 一方面&#xff0c;需要支持更…

ISIS【路由协议讲解】-通俗易懂!

IS-IS的背景 IS-IS最初是国际标准化组织ISO为它的无连接网络协议CLNP&#xff08;ConnectionLess Network Protocol&#xff09;设计的一种动态路由协议。随着TCP/IP协议的流行&#xff0c;为了提供对IP路由的支持&#xff0c;IETF在相关标准中对IS-IS进行了扩充和修改&#xf…

Vitis HLS 学习笔记--块级控制(IDE 2024.1 + 执行模式 + 默认接口实现)

目录 1. 简介 2. 默认接口实现 2.1 执行模式 2.2 接口范式 2.2.1 存储器 2.2.2 串流 2.3.3 寄存器 2.3 Vitis Kernel Flow 2.3.1 默认的协议 2.3.2 vadd 代码 2.3.3 查看报告 2.4 Vivado IP Flow 2.4.1 默认的协议 2.4.2 vadd 代码 2.4.3 查看报告 3. 测试与波…

红宝书第二十一讲:详解JavaScript的模块化(CommonJS与ES Modules)

红宝书第二十一讲&#xff1a;详解JavaScript的模块化&#xff08;CommonJS与ES Modules&#xff09; 资料取自《JavaScript高级程序设计&#xff08;第5版&#xff09;》。 查看总目录&#xff1a;红宝书学习大纲 一、模块化的意义&#xff1a;分而治之 模块化解决代码依赖混…

github 页面超时解决方法

github 页面超时解决方法 每次好不容易找到github项目代码之后&#xff0c;满心欢喜打开却是个无法访问&#xff0c;心顿时又凉了半截&#xff0c;现在有方法可以访问github啦 快来学习 打开浏览器插件&#xff08;Edge浏览器&#xff09; 搜索iLink插件 并安装 打开插件 填…

前端 vue 项目上线前操作

目录 一、打包分析 二、CDN加速 三、项目部署 1. 打包部署 2. nginx 解决 history 刷新 404 问题 3. nginx配置代理解决生产环境跨域问题 一、打包分析 项目编写完成后&#xff0c;就需要部署到服务器上供他人访问。但是在此之前&#xff0c;我们可以先预览项目的体积大…

vue: easy-cron扩展-更友好地显示表达式

我们一个批处理调度系统里要用到cron表达式&#xff0c;于是就在网上找到一个现成的组件easy-cron&#xff0c;采用后发现&#xff0c;它的配置界面还是很直观的&#xff0c;但显示时直接显示cron表达式&#xff0c;这对业务人员很不友好&#xff0c;所以&#xff0c;我们就扩展…

移动零+复写零+快乐数+盛最多水的容器+有效三角形的个数

前言 2025.3.31&#xff0c;今天开始每日五道算法题&#xff0c;今天的算法题如标题&#xff01; 双指针算法 在做今天的算法题之前&#xff0c;先来介绍一下今天会用到的算法&#xff01; 双指针算法分为了两种常见的形式&#xff1a;对撞指针和快慢指针&#xff01; 对撞…

Linux中常用的文件管理命令

一、文件和目录的建立 文件 touch命令 单一文件的创建 当按下回车后我们就可以在桌面获得一个名字叫file的文件 [rootlocalhost Desktop]# touch file 同步文件访问时间和文件修改时间 由上两图可知touch file这个命令还可以把文件访问时间和文件修改时间变成touch file命…

Root Cause Analysis in Microservice Using Neural Granger Causal Discovery

Root Cause Analysis in Microservice Using Neural Granger Causal Discovery 出处:AAAI 24 摘要 近年来,微服务因其可扩展性、可维护性和灵活性而在 IT 运营中得到广泛采用。然而,由于微服务中的复杂关系,当面临系统故障时,站点可靠性工程师 (SRE) 很难查明根本原…

学习笔记—数据结构—二叉树(链式)

目录 二叉树&#xff08;链式&#xff09; 概念 结构 初始化 遍历 前序遍历 中序遍历 后序遍历 层序遍历 结点个数 叶子结点个数 第k层结点个数 深度/高度 查找值为x的结点 销毁 判断是否为完整二叉树 总结 头文件Tree.h Tree.c 测试文件test.c 补充文件Qu…

深入理解指针5

sizeof和strlen的对比 sizeof的功能 **sizeof是**** 操作符****&#xff0c;用来**** 计算****变量或类型或数组所占**** 内存空间大小****&#xff0c;**** 单位是字节&#xff0c;****他不管内存里是什么数据** int main() {printf("%zd\n", sizeof(char));p…

一文详解QT环境搭建:Windows使用CLion配置QT开发环境

在当今的软件开发领域&#xff0c;跨平台应用的需求日益增长&#xff0c;Qt作为一款流行的C图形用户界面库&#xff0c;因其强大的功能和易用性而备受开发者青睐。与此同时&#xff0c;CLion作为一款专为C/C打造的强大IDE&#xff0c;提供了丰富的特性和高效的编码体验。本文将…

NE 综合实验3:基于 IP 配置、链路聚合、VLAN 管理、路由协议及安全认证的企业网络互联与外网访问技术实现(H3C)

综合实验3 实验拓扑 设备名称接口IP地址R1Ser_1/0与Ser_2/0做捆绑MP202.100.1.1/24G0/0202.100.2.1/24R2Ser_1/0与Ser_2/0做捆绑MP202.100.1.2/24G0/0172.16.2.1/24G0/1172.16.1.1/24G0/2172.16.5.1/24R3G5/0202.100.2.2/24G0/0172.16.2.2/24G0/1172.16.3.1/24G0/2172.16.7.1/…

多段圆弧拟合离散点实现切线连续

使用多段圆弧来拟合一个由离散点组成的曲线,并且保证切线连续。也就是说&#xff0c;生成的每一段圆弧之间在连接点处必须有一阶导数连续&#xff0c;也就是切线方向相同。 点集分割 确保每个段的终点是下一段的起点&#xff0c;相邻段共享连接点&#xff0c;避免连接点位于数…

【蓝桥杯】第十四届C++B组省赛

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;蓝桥杯 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 试题A&#xff1a;日期统计试题B&#xff1a;01串的熵试题C&#xff1a;冶炼金属试题D&#xff1a;飞机降落试题E&#xff1a;接…

企业级海外网络专线行业应用案例及服务商推荐

在全球化业务快速发展的今天&#xff0c;传统网络技术已难以满足企业需求。越来越多企业开始选择新型海外专线解决方案&#xff0c;其中基于SD-WAN技术的企业级海外网络专线备受关注。这类服务不仅能保障跨国数据传输&#xff0c;还能根据业务需求灵活调整网络配置。接下来我们…

阿里云服务器安装docker以及mysql数据库

(1) 官方下载路径 官方下载地址: Index of linux/static/stable/x86_64/阿里云镜像地址: https://mirrors.aliyun.com/docker-ce/下载最新的 Docker 二进制文件&#xff1a;wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.23.tgz登录到阿里云服务…

深入解析:HarmonyOS Design设计语言的核心理念

深入解析&#xff1a;HarmonyOS Design设计语言的核心理念 在当今数字化迅速发展的时代&#xff0c;用户对操作系统的体验要求越来越高。华为的HarmonyOS&#xff08;鸿蒙操作系统&#xff09;应运而生&#xff0c;旨在为用户提供全场景、全设备的智慧体验。其背后的设计语言—…