Java基础:基本语法(一)

news2024/7/6 18:50:18

Java基础:基本语法(一)


文章目录

  • Java基础:基本语法(一)
    • 1. 前言
    • 2. 开发环境搭建
      • 2.1 Java开发工具包下载
      • 2.2 环境变量配置
      • 2.3 Java程序的运行过程
    • 3. 数据类型
      • 3.1 基本数据类型
      • 3.2 引用数据类型
    • 4. 常量与变量
      • 4.1 常量
        • 4.1.1 常量的概念
        • 4.1.2 常量的使用
      • 4.2 变量
        • 4.2.1 变量的概念
        • 4.2.2 变量的使用
    • 5. 运算符
      • 5.1 算术运算符
      • 5.2 关系运算符(比较运算符)
      • 5.3 位运算符
      • 5.4 逻辑运算符
      • 5.5 赋值运算符
      • 5.6 条件运算符(三元运算符)
      • 5.7 类型转换运算符
      • 5.8 其他运算符
    • 6. 流量控制
      • 6.1 顺序结构
      • 6.2 分支结构(选择结构)
        • 6.2.1 if语句
        • 6.2.2 if-else语句
        • 6.2.3 if-else if-else语句
        • 6.2.4 嵌套使用
        • 6.2.5 switch语句
      • 6.3 循环结构
        • 6.3.1 while循环
        • 6.3.2 do-while循环
        • 6.3.3 for循环
        • 6.3.4 循环嵌套
        • 6.3.5 continue与break
    • 7. 数组
      • 7.1 数组的概念
      • 7.2 数组的声明
      • 7.3 数组的创建
        • 7.3.1 静态创建数组
        • 7.3.2 动态创建数组
      • 7.4 数组的打印
      • 7.5 数组的排序
        • 7.5.1 选择排序
        • 7.5.2 冒泡排序
        • 7.5.3 快速排序
      • 7.6 Arrays工具
        • 7.6.1 排序方法
        • 7.6.2 toString方法
        • 7.6.3 fill方法
        • 7.6.4 binarySearch二分查找
        • 7.6.5 copyOf和copyOfRange方法
        • 7.6.6 equals和compare方法
        • 7.6.7 数组的数组(二维数组)
    • 8. 方法
      • 8.1 方法的好处
      • 8.2 方法的定义
      • 8.3 方法的调用
      • 8.4 方法返回值
      • 8.5 方法调用和内存结构
      • 8.7 方法参数传递
      • 8.8 方法的重载
      • 8.9 可变参数(不定长参数)
      • 8.10 return的用法
    • 9. 命名规范


1. 前言

  • Java SE是Java平台标准版(Java Platform, Standard Edition)的简称,用于开发和部署桌面、服务器以及嵌入设备和实时环境中的Java应用程序。
  • Java SE包括用于开发Java Web服务的类库,同时,Java SE为Java EEJava Platform, Enterprise Edition)企业版和Java MEJava Platform, Micro Edition)微型版提供了基础。
  • Java SE就是基于JDKJava开发工具包,Java Development Kit)和JREJava运行环境,Java Runtime Environment),包含支持Java Web服务开发的类,并为Java 企业级开发提供基础。

2. 开发环境搭建

2.1 Java开发工具包下载

JDK官网下载

2.2 环境变量配置

  1. 新建一个环境变量JAVA_HOME
变量名:JAVA_HOME
变量值:D:\Program Files\Java\jdk-11

JDK环境配置

  1. 修改Path,加入JAVA_HOME下的bin目录。
变量名:Path
变量值:%JAVA_HOME%\bin

JDK环境配置2

  1. win+R打开cmd(命令提示符,Command Prompt),查看安装的JDK版本。
 java -version

JDK版本信息

2.3 Java程序的运行过程

Java程序的运行过程通常包括编译和执行两个主要阶段。

  1. 编译阶段javac是Java编译器的命令行工具,它用于将Java源代码文件(.java)编译成Java字节码文件(.class)。
javac HelloWorld.java // 编译源代码
  1. 执行阶段:JVM加载字节码文件,解释执行或者将其编译成机器码,并执行。这个阶段需要JVM处于运行状态。
java HelloWorld // 运行程序

代码运行

📌

  1. 设置Java文件编码格式为ANSI,解决中文乱码问题。
  2. Java虚拟机(JVM)是运行Java字节码的虚拟机。JVM的运行流程可以分为几个阶段:加载Loading)、验证Verification)、准备Preparation)、解析Resolution)、初始化Initialization)、使用Using)和卸载Unloading)。JVM类加载机制
  3. JVM运行时,主要通过类加载器Class Loader)、执行引擎Execution Engine)、运行时数据区Runtime Data Area)以及本地库接口Native Interface)协同工作来完成任务。JVM运行流程

3. 数据类型

Java中的数据类型总体可以分为两大类,分别是基本数据类型引用数据类型

3.1 基本数据类型

Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byteshortintlongfloatdouble。数值类型又可以分为整数类型byteshortintlong和浮点数类型floatdouble
Java中的数值类型不存在无符号的,它们的取值范围是固定的,不会随着机器硬件环境或者操作系统的改变而改变。Java中还存在另外一种基本类型void,它也有对应的包装类 java.lang.Void,用于声明方法不返回任何值。八种基本类型表示范围如下:

大类类型说明长度最小值最大值备注
整数类型byte字节型8位(1字节)-128(-2^7)127(2^7-1)最大数据存储量是255
short短整型16位(2字节)-32768(-2^15)32767(2^15-1)最大数据存储量是65536
int整型32位(4字节)-2,147,483,648(-2^31)2,147,483,647(2^31-1)最大数据存储量是2^32-1
long长整型64位(8字节)-9,223,372,036,854,775,808(-2^63)9,223,372,036,854,775,807(2^63 -1)最大数据存储量是2^64-1,通常以Ll作为后缀来表示长整型字面量,如123L
浮点数类型float单精度32位(4字节)1.4e-453.4028235e38通常以Ff作为后缀来表示浮点数字面量,如3.14F
double双精度64位(8字节)4.9e-3241.7976931348623157e308双精度是默认的浮点数类型,所以通常不需要添加后缀,但如果需要明确指定,可以使用Dd作为后缀,如3.14D
布尔类型boolean布尔型8位(1字节)falsetrue表示逻辑值,只有truefalse两种取值
字符类型char字符型16位(2字节)'\u0000'(即0)'\uffff'(即65,535)存储Unicode码,字符字面量通常用单引号括起来,如'a'

📌

  1. 自动类型转换(隐式转换):小的数据类型向大的数据类型转换(byte—>short—>int—>longchar—>int),或者整数类型转换成浮点数类型,都可以实现自动转换的。
  2. 强制类型转换(显式转换):大的数据类型向小的数据类型转换,或者浮点数类型转换成整数类型,需要使用强制转换。要在转换类型加括号,如果是浮点数转整数,直接去掉小数点,只保留整数(不考虑四舍五入情况)。

3.2 引用数据类型

引用数据类型是Java中的非基本数据类型,它们在内存中通过引用来访问实际的对象。引用数据类型包括类(Class)、接口(Interface)、数组(Array)、枚举(Enum)和注解(Annotation)。

  • :是一种面向对象编程的基本概念,它是具有相同属性和行为的实体的集合或模板。类定义了对象的数据结构,包括对象的属性(变量)和方法(行为)。
  • 接口:接口定义了一个类必须实现的方法,但接口本身不提供这些方法的实现,一个类可以实现多个接口。
  • 数组:数组是一种引用数据类型,用于存储多个相同类型的元素。
  • 枚举:枚举是一种特殊的引用数据类型,用于表示一组命名的常量。
  • 注解:注解是一种用于为程序提供元数据信息的引用数据类型。

对象引用的强度或可达性级别被分为四种,它们由高到低依次为:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)。

  • 强引用:这是最常见的引用类型。当创建一个对象并将其赋值给一个变量时,就创建了一个强引用。只要强引用存在,垃圾回收器(GC)就永远不会回收掉被引用的对象。
  • 软引用:需要通过SoftReference类来实现,对于只有软引用的对象来说,当系统内存足够时,它不会被回收,当系统内存空间不足时,它会被回收。软引用通常用于对内存敏感的程序中,如缓存数据。
  • 弱引用:弱引用需要用WeakReference类来实现,它比软引用生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管JVM内存空间是否足够,总会回收该对象占用的内存。
  • 虚引用:虚引用需要PhantomReference类来实现,它不能单独使用,必须和引用队列(ReferenceQueue)联合使用。虚引用的主要作用是跟踪对象被垃圾回收的状态,无法通过虚引用获取对象实例(get方法总是返回null),存在的唯一目的就是能在这个对象被回收时收到一个系统通知。
级别例子回收时机用途生存时间
强引用Object obj = new Object();从来不会强引用用于表示程序正在使用的对象,如局部变量、实例变量等JVM停止运行时终止
软引用SoftReference a = new SoftReference(new A());在内存不足时联合ReferenceQueue构造有效期短/占内存大/生命周期长的对象的二级高速缓冲器(内存不足时才清空)内存不足时终止
弱引用WeakReference a = new WeakReference(new A());在垃圾回收时联合ReferenceQueue构造有效期短/占内存大/生命周期长的对象的二级高速缓冲器(系统发生GC则清空)GC运行后终止
虚引用PhantomReference a = new PhantomReference(new A(), referenceQueue);在垃圾回收时联合ReferenceQueue来跟踪对象被垃圾回收器回收的活动GC运行后终止

4. 常量与变量

4.1 常量

4.1.1 常量的概念
  • 不可变性:常量的值在初始化后不能被修改。
  • 命名规范:常量名通常使用大写字母,单词之间使用下划线_分隔,以区别变量名,例如PIMAX_VALUE
  • 声明方式:使用final关键字来声明一个常量,并且如果它是静态的(即属于类而不是实例),则还会使用static关键字。
4.1.2 常量的使用
  • 使用final关键字声明常量,并在声明时初始化其值。
  • 对于静态常量,可以通过类名直接访问;对于非静态常量,需要通过对象实例来访问;但由于常量通常设计为不可变的,并且与具体的对象实例无关,因此大多数常量都是静态的。
  • 常量可以是任何数据类型,包括基本数据类型常量、引用类型常量、枚举常量、自定义常量。
  • 在Java接口中,所有字段(即常量)都隐式地是staticfinal的,因此不需要显式声明这两个关键字。
  • 枚举类型enum在Java中经常用做常量,因为它们提供了一种类型安全的方式来表示一组固定的常量值。

4.2 变量

4.2.1 变量的概念

变量是程序里最基本的存储单元,它由数据类型变量名变量值组成。从本质上来说,变量其实就是内存里的一小块存储区域,该区域只能存储声明变量时指定类型的数据。我们创建使用每个变量前,必须先声明,在内存中申请空间,然后对其进行初始化赋值,接着就可以通过变量名来访问和使用这块内存区域了。语法格式如下:

// 先声明,再赋值
数据类型 变量名;
变量名 = 变量值;
// 声明的同时并赋值
数据类型 变量名 = 变量值;
// 同时定义多个类型相同的变量
数据类型 变量名1 = 变量值1,变量名2 = 变量值2,变量名3……;
4.2.2 变量的使用

在使用变量的过程中,还有一些事项需要我们注意:

  • 变量必须要先声明,才能使用;
  • 声明变量时,要指定变量的类型(基本数据类型、引用数据类型);
  • 变量的作用域:其定义所在的一对{}内;
  • 变量只有在其作用域内才有效;
  • 同一个作用域(代码块)中,变量名不能相同;
  • 变量在声明时可以没有值,使用时必须要有值的;
  • JDK 10可以使用var作为局部变量类型推断标识符(Local-Variable Type Inference),仅适用于局部变量,使用var声明时,必须要赋初始值。

5. 运算符

Java运算符主要分为以下几类:算术运算符、关系运算符(比较运算符)、位运算符、逻辑运算符、赋值运算符、条件运算符(三元运算符)、类型转换运算符等。

5.1 算术运算符

  • +:加法(当操作数是字符串时,用作连接符)
  • -:减法
  • *:乘法
  • /:除法
  • %:取余(模运算)
  • ++:自增(自身加1)
  • --:自减(自身减1)

5.2 关系运算符(比较运算符)

所有计算的结果,会返回boolean类型的值。

  • ==:等于
  • !=:不等于
  • >:大于
  • <:小于
  • >=:大于等于
  • <=:小于等于
  • instanceof:判断其左边对象是否为其右边类的实例

5.3 位运算符

  • <<:左移(右边用0填充,即低位补0)
  • >>:右移(有符号,左边用符号位填充,即高位补符号位)
  • >>>:无符号右移(无符号,左边用0填充,即高位补0)
  • &:按位与(两边同是1,才为1,不然为0)
  • |:按位或(两边有一边为1,则结果为1,否则为0)
  • ^:按位异或(两边相同,则结果为0,两边不同,则结果为1)
  • ~:按位非(取反,如果是0,则取值为1,如果是1,则取值为0)

5.4 逻辑运算符

  • &&:逻辑与(短路与)
  • ||:逻辑或(短路或)
  • !:逻辑非

5.5 赋值运算符

  • =:赋值
  • +=:加法赋值
  • -=:减法赋值
  • *=:乘法赋值
  • /=:除法赋值
  • %=:取余赋值
  • <<=:左移赋值
  • >>=:右移赋值
  • >>>=:无符号右移赋值
  • &=:按位与赋值
  • |=:按位或赋值
  • ^=:按位异或赋值

5.6 条件运算符(三元运算符)

  • ?::该运算符有3个操作符,并且需要判断布尔表达式的值,主要是决定哪个值应该赋值给变量。例如:var c = (a > b) ? a : b;

5.7 类型转换运算符

  • (type):强制类型转换,用于显式地将一种类型的值转换为另一种类型。例如:int a = (int) 3.14;

5.8 其他运算符

  • .:成员运算符,用于访问对象的成员(属性和方法)。
  • []:索引运算符,用于访问数组或集合的元素。
  • ():方法调用运算符,用于调用方法。
  • new:实例化运算符,用于创建对象的实例。
  • instanceof:用于测试对象是否是一个类的实例。
  • ->:Lambda运算符(箭头运算符),是Java 8引入的的一个新特性,它分隔了参数列表和Lambda体,用于定义Lambda表达式。
  • :::方法引用运算符,是Java 8引入的一个新特性,用于引用现有方法或构造函数,通常与Lambda表达式一起使用。

6. 流量控制

在Java中,流程控制主要包括顺序、分支(选择)、循环三大结构。

6.1 顺序结构

代码自上而下顺序执行。

6.2 分支结构(选择结构)

使用if-else语句和switch语句实现条件分支。

6.2.1 if语句

语法格式如下:

if (condition) {
    // 条件成立true,执行这里的代码
    // 如果只有一行或一组代码,大括号可以省略
}
6.2.2 if-else语句

语法格式如下:

if (condition) {
    // 条件成立true,执行这里的代码
} else {
    // 必须和对应的if一起出现,不能单独出现
    // 条件不成立false,执行这里的代码
}
6.2.3 if-else if-else语句

语法格式如下:

if (condition1) {  
    // 如果condition1为true,执行这里的代码  
} else if (condition2) {  
    // 如果condition1为false但condition2为true,执行这里的代码  
} else if (condition3) {  
    // 如果前两个条件都为false但condition3为true,执行这里的代码  
    // 可以继续添加更多的else if子句  
} else {  
    // 如果所有条件都为false,执行这里的代码  
}
6.2.4 嵌套使用

if-else语句可以嵌套使用,即一个ifelse语句块内部可以包含另一个完整的if-else语句。这样可以根据多个条件进行更复杂的判断。

6.2.5 switch语句

语法格式如下:

switch (variable) {  
    case value1:  
        // 当variable的值等于value1时执行  
        break;  
    case value2:  
        // 当variable的值等于value2时执行  
        break;  
    // 可以添加更多的case  
    default:  
        // 当variable的值不匹配任何case时执行  
        break;  
}

6.3 循环结构

使用whiledo-whilefor循环。

6.3.1 while循环

当型循环,语法格式如下:

while (condition) {
    // 当条件成立,反复执行这段代码(循环体)
}
6.3.2 do-while循环

直到型循环,先执行一次循环体,后面根据while条件是否为真,如果为真继续执行。语法格式如下:

do {
    // 循环体
} while (condition); // 后面有分号
6.3.3 for循环

语法格式如下:

for (表达式1; 表达式2; 表达式3) {
    // 循环体
}

for循环执行的过程:

  1. 执行表达式1,赋初始值;
  2. 执行表达式2,条件判定(boolean类型值),如果条件不成立,退出循环;
  3. 如果表达式2条件成立,执行循环体;
  4. 执行表达式3,让循环条件变动;
  5. 从第2步开始循环。

for循环的特殊用法:

  • 增强的for循环(for-each循环),用于遍历数组或集合中的元素,而不需要通过索引来访问每个元素。
int[] numbers = {1, 2, 3, 4, 5};  
for (int number : numbers) {  
    System.out.println(number);  
}  
  
List<String> list = Arrays.asList("a", "b", "c");  
for (String item : list) {  
    System.out.println(item);  
}
  • 无限循环,通常用于需要一直运行直到某个条件被外部触发的场景(如服务器监听)。
for (;;) {  
    // 循环体内的代码将无限执行,直到遇到break语句或程序被终止  
}
  • 可以在for循环的初始化部分声明多个变量。
for (int i = 0, j = 10; i < j; i++, j--) { // 如果控制两种不同类型的变量,需要在外面做声明处理
    System.out.println("i: " + i + ", j: " + j);  
}
  • for循环中声明并初始化数组。
int[] numbers = new int[5];  
for (int i = 0; i < numbers.length; i++) {  
    numbers[i] = i * 2;  
}
  • for循环中嵌套switch语句。
for (int i = 0; i < 5; i++) {  
    switch (i) {  
        case 0:  
            System.out.println("Zero");  
            break;  
        case 1:  
            System.out.println("One");  
            break;  
        // ... 其他case  
        default:  
            System.out.println("Default");  
    }  
}
  • for循环中使用Lambda表达式。
List<String> list = Arrays.asList("a", "b", "c", "a", "b");  
list.stream()  
    .filter(item -> !item.equals("a")) // 过滤掉所有"a"  
    .forEach(System.out::println); // 打印剩下的元素
  • 使用for循环进行字符串迭代。
String str = "Hello";  
for (char c : str.toCharArray()) { // toCharArray()方法将字符串转换为字符数组
    System.out.print(c + " ");  
}

快速生成for循环的处理方式:

  • fori从0到指定值循环。
  • 100.fori从0-100循环。
  • 100.forr从100-0循环。

📌

  1. for循环变量的初值,最好在for循环中声明,因为它有助于减少变量的作用域并提高代码的可读性。
  2. 迪米特法则(Law of Demeter,LOD),也称为最少知识原则(Least Knowledge Principle,LKP),是一种面向对象编程(OOP)和面向对象设计(OOD)的原则。通过降低类之间的耦合度、提高内聚性和简化依赖关系,可以创建出更加可维护、可扩展和可复用的软件系统。
6.3.4 循环嵌套

我国传统数学名著《九章算术》记载:今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?使用循环解决计算鸡兔同笼问题。代码示例如下:

public class ChiRabCage {
    public static void main(String[] args) {
        for (int i = 0; i <= 35; i++) { // 鸡的数量
            for (int j = 1; j <= 35 - i; j++) { // 兔的数量
                if (i * 2 + j * 4 == 94 && i + j == 35) {
                    System.out.println("鸡的数量:" + i + ",兔的数量:" + j);
                }
            }
        }
    }
}

🆚🆚运行结果:

鸡的数量:23,兔的数量:12
6.3.5 continue与break
  • break:退出当前循环,break后面的语句都不执行。
  • continue:结束本次循环,continue后的语句本次不再执行,从循环的下一次开始执行。

7. 数组

7.1 数组的概念

数组(Array)是一种引用数据类型,用于存储相同类型数据的有序集合。数组中的每个元素都有一个唯一的索引,该索引用于访问和修改数组中的元素。数组在内存中占用一段连续的存储空间,因此通过索引访问数组元素的速度非常快。

7.2 数组的声明

数组的声明用于定义数组的类型和名称,但并不会为数组分配内存空间。数组声明的基本语法如下:

int[] array; // 推荐使用
int array[];

7.3 数组的创建

7.3.1 静态创建数组

在声明数组的同时直接指定数组的元素值,也称为字面量初始化。

int[] intArray = {1, 2, 3, 4, 5}; // 静态初始化整数数组  
double[] doubleArray  = {1.2, 3.4, 5.6, 7.8}; // 静态初始化双精度浮点数数组
String[] stringArray = {"apple", "banana", "cherry"}; // 静态初始化字符串数组
7.3.2 动态创建数组

先声明数组变量,然后为其分配内存空间并指定长度,但不立即为数组元素赋值。

// 数组类型[] 数组名 = new 数组类型[长度(数组中存储元素的个数)]
int[] x = new int[3]; // 动态初始化,指定长度为3
x[0] = 1; // 为数组的元素赋值
x[1] = 2;
x[2] = 3;
System.out.println(x[0]);
System.out.println(x[1]);
System.out.println(x[2]);

📌

  1. 数组一旦创建,其长度就不能改变。
  2. 在声明数组变量后,必须对其进行初始化(即分配内存空间)才能使用。
  3. 数组在内存中占用连续的空间,可以通过索引来访问数组中的元素。
  4. 访问数组元素时,索引从0开始,到数组长度减1结束。如果越界访问数组元素,将会抛出ArrayIndexOutOfBoundsException异常。

7.4 数组的打印

可以使用循环来遍历数组并逐个打印元素。代码示例如下:

public class TestPrint {
    public static void main(String[] args) {
        int[] a = {1, 3, 5, 7, 9};
        // 使用增强的for循环(for-each循环)
        for (int i : a) { // a.for
            System.out.print(i + "\t");
        }
        System.out.println();
        // 使用基本for循环
        for (int i = 0; i < a.length; i++) { // 正序
            int x = a[i]; // a.fori
            System.out.print(x + "\t");
        }
        System.out.println();
        for (int i = a.length - 1; i >= 0; i--) { // 倒序
            int x = a[i]; // a.forr
            System.out.print(x + "\t");
        }
    }
}

🆚🆚运行结果:

1	3	5	7	9	
1	3	5	7	9	
9	7	5	3	1

📌

  1. 使用Arrays类的toString方法(适用于所有类型的数组);
  2. 对于更复杂的数组处理或函数式编程风格,可以使用Java 8的Stream API(java.util.stream);
  3. 对于大型数组或需要频繁拼接字符串的情况,使用StringBuilder可以提高性能。

7.5 数组的排序

7.5.1 选择排序

选择排序(Selection Sort)是一种简单直观的排序算法,其基本思想是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。选择排序的主要步骤如下:

  1. 初始化:首先,在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置。
  2. 继续选择:然后,再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。
  3. 重复执行:重复步骤2,直到所有元素均排序完毕。

选择排序的特点:时间复杂度O(n^2) ,空间复杂度O(1) ,原地排序算法,不需要额外的存储空间,不稳定排序。代码示例如下:

/* 选择排序 */
public class SelectionSort {
    public static void main(String[] args) {
        int[] x = {56, 12, 78, 90, 34};
        for (int i = 0; i < x.length - 1; i++) { // 控制外层循环
            int minIndex = i; // 假设当前位置是最小的
            for (int j = i + 1; j < x.length; j++) { // 在剩余未排序的元素中找最小元素
                if (x[j] < x[minIndex]) { // 如果找到更小的元素,更新最小元素的索引
                    minIndex = j;
                }
            }
            if (minIndex != i) { // 将找到的最小元素与第一个未排序的元素交换位置
                int tmp = x[i];
                x[i] = x[minIndex];
                x[minIndex] = tmp;
            }
            System.out.println("第" + (i + 1) + "轮:");
            for (int a : x) {
                System.out.print(a + "\t");
            }
            System.out.println();
        }
    }
}

🆚🆚运行结果:

1轮:
12	56	78	90	342轮:
12	34	78	90	563轮:
12	34	56	90	784轮:
12	34	56	78	90
7.5.2 冒泡排序

冒泡排序(Bubble Sort)是一种交换排序的算法,其基本思想是两两比较,进行交换位置,得到一个有序的序列。冒泡排序的主要步骤如下:

  1. 比较相邻元素:从列表的第一个元素开始,比较每对相邻的项,如果它们的顺序错误就交换它们。
  2. 遍历数组:在列表的剩余部分(即未排序的部分)中,重复步骤1。
  3. 重复过程:在每次遍历后,数组中最大的元素就像气泡一样“浮”到数组的末尾。然后减少遍历的范围(因为最后一个元素已经是最大的,不需要再比较),并重复步骤1和2,直到没有元素需要交换为止。

冒泡排序的特点:时间复杂度O(n^2) ,空间复杂度O(1) ,原地排序算法,不需要额外的存储空间,稳定排序。代码示例如下:

/* 冒泡排序 */
public class BubbleSort {
    public static void main(String[] args) {
        int[] x = {56, 12, 78, 90, 34};
        for (int i = 0; i < x.length - 1; i++) { // 外循环
            for (int j = 0; j < x.length - i - 1; j++) { // 内循环
                if (x[j] > x[j + 1]) { // 交换值
                    int t = x[j];
                    x[j] = x[j + 1];
                    x[j + 1] = t;
                }
            }
            System.out.println("第" + (i + 1) + "轮:");
            for (int a : x) {
                System.out.print(a + "\t");
            }
            System.out.println();
        }
    }
}

🆚🆚运行结果:

1轮:
12	56	78	34	902轮:
12	56	34	78	903轮:
12	34	56	78	904轮:
12	34	56	78	90
7.5.3 快速排序

快速排序(Quick Sort)是一种非常高效的排序算法,它采用了分治(Divide and Conquer)的策略。快速排序的主要步骤如下:

  1. 选择基准(Pivot):从待排序序列中选取一个元素作为基准,通常选择序列的第一个或最后一个元素。
  2. 分区操作(Partition):将序列分成两个子序列,左边子序列的元素都小于或等于基准,右边子序列的元素都大于基准。
  3. 递归排序(Recursion):递归地对基准元素左右两边的子序列进行快速排序。

快速排序的特点:平均时间复杂度O(n log n) ,最坏时间复杂度O(n^2),平均空间复杂度O(log n) ,最坏空间复杂度O(n),原地排序算法,除了递归栈外不需要额外的存储空间,不稳定排序。代码示例如下:

public class QuickSort1 {
    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            // 获取分区后的枢纽位置
            int pivotIndex = partition(arr, low, high);
            // 分别对枢纽左右两边的子数组进行递归排序
            quickSort(arr, low, pivotIndex - 1);
            quickSort(arr, pivotIndex + 1, high);
        }
    }

    private static int partition(int[] arr, int low, int high) {
        // 选择数组的最后一个元素作为枢纽值
        int pivot = arr[high];
        int i = (low - 1);
        // 遍历数组,将小于枢纽值的元素放到左边,大于枢纽值的元素放到右边
        for (int j = low; j < high; j++) {
            if (arr[j] < pivot) {
                i++;
                // 交换 arr[i] 和 arr[j]
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        swap(arr, i + 1, high);
        return i + 1;
    }

    // 将基准元素交换到其最终位置
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    // 返回枢纽位置
    public static void main(String[] args) {
        int[] arr = {56, 12, 78, 90, 34};
        quickSort(arr, 0, arr.length - 1);
        // 输出排序后的数组
        System.out.println(java.util.Arrays.toString(arr));
    }
}
public class QuickSort2 {
    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            // 获取分区后基准元素的位置
            int pivotIndex = partition(arr, low, high);
            // 分别对基准元素左右两边的子数组进行快速排序
            quickSort(arr, low, pivotIndex - 1);
            quickSort(arr, pivotIndex + 1, high);
        }
    }

    private static int partition(int[] arr, int low, int high) {
        // 选择数组的第一个元素作为基准元素
        int pivot = arr[low];
        int i = low + 1;
        int j = high;
        // 进行迭代,直到i和j指向同一个位置
        while (i <= j) {
            // 从右向左找到第一个小于等于基准元素的元素
            while (i <= j && arr[j] > pivot) {
                j--;
            }
            // 从左向右找到第一个大于等于基准元素的元素
            while (i <= j && arr[i] <= pivot) {
                i++;
            }
            // 交换i和j指向的元素
            if (i < j) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        // 将基准元素放到正确的位置
        arr[low] = arr[j];
        arr[j] = pivot;
        // 返回基准元素的位置
        return j;
    }

    public static void main(String[] args) {
        int[] arr = {56, 12, 78, 90, 34};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(java.util.Arrays.toString(arr));
    }
}

🆚🆚运行结果:

[12, 34, 56, 78, 90]

📌
效率:快速排序>选择排序>冒泡排序(冒泡排序在内循环交换,选择排序在外循环交换)

7.6 Arrays工具

7.6.1 排序方法

Arrays.sort()是Java中的数组排序,它是对一个数组的所有元素进行排序,并且是按从小到大的顺序。代码示例如下:

public class QuickSort3 { // 快速排序
    public static void main(String[] args) {
        int[] arr = {56, 12, 78, 90, 34};
        long t1 = System.currentTimeMillis(); // 返回当前时间的毫秒数
        Arrays.sort(arr); // 数组进行排序
        long t2 = System.currentTimeMillis(); // 返回当前时间的毫秒数
        System.out.println(Arrays.toString(arr));
        long t = t2 - t1;
        System.out.println("执行时间:" + t + "毫秒");
    }
}

🆚🆚运行结果:

[12, 34, 56, 78, 90]
执行时间:0毫秒
7.6.2 toString方法

Arrays.toString()用于将数组转换为字符串,可以快速的输出数组的内容。

7.6.3 fill方法

Arrays.fill()对数组元素进行填充。代码示例如下:

public class ArrayTest {
    public static void main(String[] args) {
        int x[] = new int[5];
        x[0] = 29;
        x[3] = 89;
        //起始位包含,结束位置不包含,对数组进行填充
        Arrays.fill(x, 1, 3, 100);
        System.out.println(Arrays.toString(x));
    }
}

🆚🆚运行结果:

[29, 100, 100, 89, 0]
7.6.4 binarySearch二分查找

数组必须经过排序再进行二分查找,返回数组中元素所在的下标位置,如果找不到,返回负值。

public class ArraysBinarySearch {
    public static void main(String[] args) {
        int[] y = {12, 56, 34, 88, 66};
        Arrays.sort(y);
        System.out.println(Arrays.toString(y));
        int n = Arrays.binarySearch(y, 66);
        System.out.println(n);
    }
}

🆚🆚运行结果:

[12, 34, 56, 66, 88]
3
7.6.5 copyOf和copyOfRange方法
public class ArraysTest {
    public static void main(String[] args) {
        int[] x = {66, 33, 44, 55, 11, 22};
        System.out.println(Arrays.toString(x));
        int[] y = Arrays.copyOf(x, 4);
        System.out.println(Arrays.toString(y));
        int[] z = Arrays.copyOfRange(x, 1, 3);
        System.out.println(Arrays.toString(z));
    }
}

🆚🆚运行结果:

[66, 33, 44, 55, 11, 22]
[66, 33, 44, 55]
[33, 44]
7.6.6 equals和compare方法
public class ArraysTest2 {
    public static void main(String[] args) {
        int[] x = {66, 33, 44, 55, 11, 22};
        int[] y = Arrays.copyOf(x, 4);
        System.out.println("x:" + Arrays.toString(x));
        System.out.println("y:" + Arrays.toString(y));
        int[] m = new int[5];
        // 参数1:源数组              参数2:从源数组哪个下标开始复制
        // 参数3:复制到的目标数组      参数4:从目标数组的哪个下标位置开始放入
        // 参数5:复制源数组多长
        System.arraycopy(x, 1, m, 0, 5);
        System.out.println("m:" + Arrays.toString(m));
        boolean b = Arrays.equals(x, y);
        System.out.println("两数组的值是否相同(相同为true,不同为false):" + b);
        int i = Arrays.compare(x, y);
        System.out.println("两数组按字典顺序比较(相同为0,前者大为正,后者大为负):" + i);
    }
}

🆚🆚运行结果:

x:[66, 33, 44, 55, 11, 22]
y:[66, 33, 44, 55]
m:[33, 44, 55, 11, 22]
两数组的值是否相同(相同为true,不同为false):false
两数组按字典顺序比较(相同为0,前者大为正,后者大为负):2
7.6.7 数组的数组(二维数组)

在Java中,二维数组被看作数组的数组,即二维数组为一个特殊的一维数组,其每个元素又是一个一维数组。Java并不直接支持二维数组,但是允许定义数组元素是一维数组的一维数组,以达到同样的效果。代码示例如下:

public class ArraysTest3 {
    public static void main(String[] args) {
        // 静态创建二维数组 数组的长度和元素都有
        int[][] a = {{12, 34}, {21, 43, 54}, {12, 53, 76}, {21, 54}};
        int[][] b = {{16, 34, 34}, {87, 96, 66}};
        // 动态创建二维数组
        int[][] c = new int[3][];
        int[] arr0 = {12, 34};
        int[] arr1 = {21, 43, 54};
        int[] arr2 = {12, 53, 76};
        c[0] = arr0;
        c[1] = arr1;
        c[2] = arr2;
        for (int[] x : c) {
            for (int y : x) {
                System.out.print(y + "\t");
            }
            System.out.println();
        }
        for (int i = 0; i < c.length; i++) {
            for (int j = 0; j < c[i].length; j++) {
                System.out.print(c[i][j] + "\t");
            }
        }
    }
}

🆚🆚运行结果:

12	34	
21	43	54	
12	53	76	
12	34	21	43	54	12	53	76

8. 方法

在Java中,方法(函数)是代码组织的基本单位,方法封装了一段特定的代码,这段代码执行某个特定的任务或操作。

8.1 方法的好处

  • 实现对相同代码的复用
    • 将重复的代码段封装成方法,就可以在整个程序中的任何位置调用它,而无需重复编写相同的代码。可以提高代码的复用性、可维护性和可读性。
  • 使程序逻辑清晰
    • 通过将程序逻辑分解为多个小方法,我们可以更容易地理解每个部分的职责和工作原理,从而使整个程序的结构更加清晰。
  • 实现细粒度设计
    • 细粒度设计是一种将程序拆分成多个小模块或组件的方法,每个模块或组件都具有明确的功能和接口。方法是实现细粒度设计的基本单元之一。
    • 细粒度设计还有助于提高代码的可测试性。由于每个方法都具有明确的输入和输出,我们可以更容易地为它们编写单元测试,以确保它们按预期工作。这有助于我们在开发过程中发现并修复错误,提高代码的质量和可靠性。

8.2 方法的定义

方法头(方法签名或方法声明)由五个部分组成。方法定义的语法格式如下:

[访问修饰符] <返回值类型> <方法名>([参数列表]) [异常列表] {
    // 方法体
    [return 语句(如果返回值类型不是void)];]
}
// 使用中括号[]包括的部分是可选项,使用尖角号<>包括的部分是必填项。

8.3 方法的调用

定义了一个方法之后,这个方法本身不会自动运行。它必须被另一个方法(通常是main方法或其他非静态方法)显式地调用才能执行。方法调用的基本语法如下:

方法名(参数1, 参数2, ..., 参数N);

调用一个方法时,需要遵循以下规则:

  • 方法名:必须使用定义该方法时所用的确切名称来调用它。
  • 参数列表:如果方法需要参数,必须在调用时提供与定义时相匹配的参数。这包括参数的个数、类型和顺序。如果参数类型不匹配,或者参数的个数不正确,编译器将报错。
  • 实参(Actual Parameters):当调用一个方法并传递参数时,提供的具体值被称为实参。这些实参将被用于方法内部的计算或操作。

8.4 方法返回值

  • 返回值类型不是void:对于返回值类型不是void的方法,必须确保方法体内有一个与返回值类型相匹配的return语句来返回一个值。
  • 返回值类型是void:对于返回值类型是void的方法,return语句后面不需要跟任何表达式,但可以用来提前结束方法的执行。

8.5 方法调用和内存结构

  • 方法的存放位置
    • 在Java程序的源代码中,方法被定义在类中。
    • 当Java程序被编译后,方法的字节码被存储在.class文件中。
    • 当Java虚拟机(JVM)加载.class文件时,它会把类的信息(包括方法)加载到方法区(Method Area)中,也被称为永久代(PermGen,在Java 8之前)或元空间(Metaspace,在Java 8及以后)。方法区方法的调用和执行存储了类的元数据,包括方法信息、常量池等。
  • 方法的调用和执行
    • 当一个方法被调用时(无论是从主方法、其他方法还是通过事件等),JVM会在Java栈(Java Stack)中为该方法的执行创建一个新的栈帧(Stack Frame)。
    • 栈帧包含了方法的局部变量、操作数栈、指向当前方法所属类的常量池的引用等信息。
    • 方法在栈帧中执行,执行过程中可能会涉及到操作局部变量、调用其他方法等操作。
    • 如果方法A调用了方法B,而方法B又调用了方法A(没有合适的终止条件),这会导致无限递归,最终会因为栈空间耗尽而抛出StackOverflowError
  • 栈溢出和递归
    • 栈溢出(StackOverflowError)通常是由于递归调用过深、方法调用过多导致栈空间耗尽而引发的。
    • 在编写递归方法时,需要特别注意递归的终止条件,以确保递归调用能够正常结束。

8.7 方法参数传递

在Java中,方法参数的传递是通过值传递(pass-by-value)进行的。

  1. 基本数据类型传递:传递的是参数值的副本,在方法内部对参数值的修改不会影响原始变量。
  2. 引用数据类型传递:传递的是该对象在内存中的引用地址的副本,而不是对象本身。

8.8 方法的重载

方法的重载(Overloading)是指在同一个类中,使用相同的方法名,定义多个不同方法的机制。方法的重载有以下几个要点:

  1. 方法名必须相同。
  2. 参数列表必须不同(参数的类型、参数的个数或参数的顺序不同)。
  3. 返回类型可以相同,也可以不相同(返回类型不参与重载)。
  4. 访问修饰符和异常类型可以相同,也可以不相同(访问修饰符和异常类型不参与重载)。

8.9 可变参数(不定长参数)

可变参数(Varargs,即Variable-length Arguments)是一个允许在调用方法时传入任意数量参数的特性。这种特性使得方法可以接受可变数量的参数,而不需要为每种可能的参数数量重载方法。以下是可变参数定义的语法格式:

returnType methodName(type... parameters) {  
    // 方法体  
}

可变参数的规则如下:

  1. 如果方法中,有可变参数,还有其他参数,可变参数必须是最后出现,并且只能有一个可变参数。
  2. 可变参数是兼容数组类型参数的,但是数组类型参数不兼容可变参数。
  3. 能匹配定长的方法时,优先匹配定长方法,不定参数的方法是最后被选择的。
  4. 可变参数方法和数组方法不能重载。

8.10 return的用法

return语句的两种主要用法:

  • 在有返回值的方法中,返回方法指定类型的值,同时结束方法执行。
  • 在返回值为void的方法中,用来结束当前方法,回到主调方法,后面的语句都不会再执行。

9. 命名规范

Java中的命名规则主要包括以下几点:

  • 包名:全部小写,用点分隔符.来分隔各级目录,通常为反域名命名法,例如com.example.mypackage
  • 类和接口名:每个单词的首字母都大写(大驼峰式命名法,又称Pascal命名法),例如MyClassIMyInterface
  • 对象名:首字母小写,遇到单词就大写(小驼峰式命名法,又称camelCase命名法),例如objectmyObjectName
  • 方法名:首字母小写,遇到单词就大写(小驼峰),例如myMethod()getNumber()
  • 变量名:首字母小写,遇到单词就大写(小驼峰),例如summyVariable
  • 常量名:全部大写,单词间用下划线_分隔,例如PIMAX_VALUE

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

以上内容是关于Java基本语法的基础知识,希望对初学者或再次学习者有所帮助,基础打扎实,不怕风吹雨打!如果以上内容有错误或者内容不全,望大家提出!我也会继续写好每一篇博文!
👍👍👍

待续未完
🙊🙊🙊

欢迎观看和提问!!!
👏👏👏

下一篇:Java基础:面向对象(二)
赞

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

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

相关文章

深度学习中文笔记.pdf

深度学习和机器学习应该如何入门呢&#xff1f;这是很多初学者经常提的问题&#xff0c;针对这个问题&#xff0c;相信很多过来人都会推荐吴恩达的在线课程。不过&#xff0c;由于是英文版本&#xff0c;就将很多人挡在了门外。 于是&#xff0c;在国内&#xff0c;以黄海广博士…

发现一个可以白嫖GPU的平台

网址 https://platform.virtaicloud.com/gemini_web/auth/register?inviteCodeb0322161368ead7f49716688486796dd 驱动云注册有100点的算力点&#xff0c;目前最便宜的机器大概是0.49算力点每小时&#xff0c;安装个sd或者简单学习训练数据的话&#xff0c;应该能用挺久的。…

K8s 小白入门|从电影配乐谈起,聊聊容器编排和 K8s

来听听音乐 电影&#xff0c;是我们生活中的重要调味剂。 配乐&#xff0c;是电影中不可或缺的一部分。 有的时候&#xff0c;配乐可以跟剧情共振&#xff0c;让你按捺不住自己的情绪&#xff0c;或眼含热泪、或慷慨激昂、或人仰马翻、或怅然若失&#xff1b; 有的时候&…

探索研究大语言在生物识别技术——使用ChatGP-4从完成从人脸识别到年龄估计

0.引言 论文提出以下几要点&#xff1a; &#xff08;1&#xff09;. 人脸识别、性别检测和年龄估计的性能评估&#xff1a; 进行了一项研究&#xff0c;使用GPT-4这样的大型语言模型来处理人脸识别、性别检测和年龄估计等任务。这些任务是生物识别技术中的常见应用&#xff…

深入分析 Android Activity (十)

文章目录 深入分析 Android Activity (十)1. Activity 的资源管理1.1 使用资源 ID 访问资源1.2 Drawable 资源1.3 使用 TypedArray 管理资源1.4 使用资源配置 2. Activity 的数据存储2.1 SharedPreferences2.2 文件存储2.3 SQLite 数据库2.4 ContentProvider 3. Activity 的性能…

生产者延迟消息和重试机制

messageDelayLevel1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h 延迟消息级别public PutMessageResult putMessage(final MessageExtBrokerInner msg) {//事务消息处理if (tranType MessageSysFlag.TRANSACTION_NOT_TYPE|| tranType MessageSysFlag.TRANSACT…

基于高光谱数据集的创新点实现-高斯核函数卷积神经网络

一、高光谱数据集简介 1.1 数据集简介 数据集链接在这:高光谱数据集(.mat.csv)-科研学术 数据集包含下面三个文件&#xff1a; 文件中包含.mat与.csv,145x145x220, 其实主要使用avirissub.csv文件&#xff0c;在代码上只是将mat文件转成了csv文件。具体avirissub.csv如下&am…

算法学习笔记(7.1)-贪心算法(分数背包问题)

##问题描述 给定 &#x1d45b; 个物品&#xff0c;第 &#x1d456; 个物品的重量为 &#x1d464;&#x1d454;&#x1d461;[&#x1d456;−1]、价值为 &#x1d463;&#x1d44e;&#x1d459;[&#x1d456;−1] &#xff0c;和一个容量为 &#x1d450;&#x1d44e;&…

【kubernetes】关于k8s集群如何将pod调度到指定node节点(亲和与反亲和等)

目录 一、调度约束 1.1K8S的 List-Watch 机制 ⭐⭐⭐⭐⭐ 1.1.1Pod 启动典型创建过程 二、调度过程 2.1Predicate&#xff08;预选策略&#xff09; 常见的算法 2.2priorities&#xff08;优选策略&#xff09;常见的算法 三、k8s将pod调度到指定node的方法 3.1指定…

白酒:传统产区的创新之路与品牌重塑

云仓酒庄豪迈白酒作为传统产区的品牌&#xff0c;面临着市场需求的不断变化和消费者口味的多样化。为了保持品牌竞争力和市场地位&#xff0c;传统产区需要不断创新和重塑品牌形象&#xff0c;以满足消费者的需求和期望。 首先&#xff0c;传统产区需要注重产品的品质和口感。品…

Owinps静态IP代理:跨境电商的优选解决方案

在快速发展的电子商务领域&#xff0c;尤其是跨境电商行业&#xff0c;网络的稳定性和安全性是成功经营的关键因素之一。在这背后&#xff0c;少不得一个重要的跨境电商工具——代理IP&#xff0c;而这其中&#xff0c;静态IP因其独特的稳定性和安全性&#xff0c;正逐渐成为众…

IC开发——Ubuntu安装VCS2018

1. 简介 VCS是一种常用的Verilog仿真和综合工具&#xff0c;由Synopsys公司开发。它提供了一个完整的设计验证环境&#xff0c;用于验证硬件设计的正确性和性能。以下是VCS工具的一些主要特点和功能&#xff1a; 仿真功能&#xff1a;VCS支持基于事件驱动的数字电路级仿真&am…

MySQL学习——连接服务器和输入查询

MySQL是一个流行的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;由瑞典的MySQL AB公司开发&#xff0c;后来被Oracle公司收购。它使用SQL&#xff08;结构化查询语言&#xff09;作为访问和操作数据库的标准语言。 要查看 mysql 客户端程序提供的选项列表&a…

合约的值类型

基本数据类型&#xff1a;整数、枚举、布尔&#xff08;类似java的数据类型&#xff09;Address、Contract&#xff08;这两种是solidity特有的数据类型&#xff09;Fixed byte array&#xff08;定长字节数组&#xff09; Integer(int/uint) int/uint 以8位字节递增&#xf…

硬盘有EFI分区格式化不了,也删不了怎么办,不能读取磁盘

问题&#xff1a;EFI为系统引导分区表明这是一块系统盘&#xff0c;常规操作无法格式化也无法删除&#xff0c;也不能读取 解决&#xff1a; 1.管理员运行cmd 2.输入diskpart 3.输入list disk 查看系统磁盘&#xff0c;并找到你格式化不了的那块磁盘 4.select disk 编号 选择…

【Go专家编程——并发控制——三剑客】

并发控制 我们考虑这么一种场景&#xff0c;协程在A执行过程中需要创建子协程A1、A2、A3…An&#xff0c;协程创建完子协程后就等待子协程退出。 针对这种场景&#xff0c;Go提供了三种解决方案&#xff1a; Channel&#xff1a;使用channel控制子协程 优点&#xff1a;实现…

【稳定检索】2024年核能科学与材料、物理应用国际会议(NESMPA 2024)

2024年核能科学与材料、物理应用国际会议 2024 International Conference on Nuclear Energy Science and Materials, Physical Applications 【1】会议简介 2024年核能科学与材料、物理应用国际会议即将拉开帷幕&#xff0c;这是一场汇聚全球核能科学、材料研究及物理应用领域…

全志T527 适配双目tp2815_mipi

一、硬件信息 TP2815&#xff1a; 确认硬件信息&#xff1a; 1、通信接口&#xff1a;TWI2总线&#xff0c;引脚组为PE1 、PE2 2、RESET脚&#xff1a; 二、软件配置 1、设备树 t527 dtsi: bsp/configs/linux-5.15/sun55iw3p1.dtsi t527 uboot-board.dts device/config/chi…

必看丨SSL证书是什么?怎么免费申请一张?

SSL证书是一种网络安全证书&#xff0c;它能帮助网站实现数据加密传输&#xff0c;保障用户信息在浏览器和网站服务器之间的安全交流。想象一下SSL证书就像一封密信的封蜡&#xff0c;确保信件内容在途中不会被他人偷看或篡改。 SSL证书的作用主要有两点&#xff1a; 1. 身份验…

gin框架精通篇(二)

原生数据库使用 导入模块&#xff1a;go get -u github.com/go-sql-driver/mysql 安装 mysql 数据库 安装数据库可能遇到的问题&#xff1a;&#xff08;网上的方法基本可以解决&#xff09; ERROR 1045 (28000): Access denied for user ‘-root’‘localhost’ (using passwo…