Appearance
环境安装
java环境
java 的 jdk 类似于前端的浏览器或 node 运行环境
1.https://www.oracle.com/cn/java/technologies/downloads/ 官网下载 jdk
2.配置环境变量
1.新建环境变量 变量名:JAVA_HOME 变量值:D:\JDK 2.添加 path 环境变量 变量值:%JAVA_HOME%\bin
验证
bash
java -versionMaven安装
maven 是用来管理 java 项目依赖的,类似前端的 npm 包管理工具。
1.https://maven.apache.org/download.cgi 官网下载(如:apache-maven-3.9.16-bin.zip)
2.配置环境变量
1.新建环境变量 变量名:MAVEN_HOME 变量值:D:\sw\install\java\apache-maven-3.9.7 2.添加 path 环境变量 变量值:%MAVEN_HOME%\bin
验证
bash
mvn -v设置镜像
为了解决下载依赖慢的问题,需要设置为国内镜像。
在
/conf/目录内settings.xml(maven 解压位置)配置文件中添加如下代码:
xml
<!-- 镜像所有仓库 -->
<!-- 在 settings.xml 的 <mirrors> 中添加,如果没有 <mirrors> 就新建一个 -->
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>aliyunmaven</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>xml
<!-- 只镜像 central 仓库 -->
<mirror>
<id>aliyun-central</id>
<!-- mirrorof 写 central:只替代中央仓库,不影响你公司私服 -->
<!-- 如果你还有公司私服,就不要写成*,避免把私服也镜像掉 -->
<mirrorOf>central</mirrorOf>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>默认情况下,安装的依赖目录为
win用户目录/.m2/repository,相当于是本地仓库一样
1.本地仓库
就是 settings.xml 中配置的目录,使用过的依赖会存储在这里,后续复用。
2.中央仓库
是 maven 社区提供的仓库,内置了中央仓库的地址,其中包含了流行的开源 java 构件
3.公共仓库(重点)
依赖包下载
4.私服
公司私有的共享仓库,不对外开放,可以通过 Nexus 来创建,管理
VScode配置
安装插件
安装
Extension Pack for Java插件。为了能够在
vscode中方便的使用java语言,Microsoft特意推出了java插件包
安装 SpringBoot 插件
搜索安装 Spring Boot Extension Pack
这个扩展包含了多个与 Spring Boot 相关的扩展
创建项目
创建普通项目
1.在 vscode 资源管理器区域,右键,创建 java 项目
2.在弹出的选项中,选择 No build tools,然后选择目录,在输入项目名称即可
创建的项目结构如下
tex
bin
lib // jar 包放置位置
src
-App.java // 入口main方法
README.md创建springBoot项目
1.在vscode资源管理器区域,右键,创建java项目,或直接点击
创建java项目2.在弹出的选项中,选择
Spring Boot,然后选择Maven Project,然后选择 boot 版本,再选择 java3.输入项目组id,一般为倒写域名,例如com.example,接着输入项目名称,例如demo
4.然后弹窗中选择jar,接着选择jdk版本,然后选需要的依赖,可以勾选 Spring Web、Spring Boot DevTools、Lombok ,勾选后接下来选择保存目录。
5.等待 VScode 下载依赖完成后即可。
创建的项目结构如下
tex
.mvn
.vscode
src
-main
--java // 项目代码目录
--resources
---application.properties // 项目boot配置,例如启动端口号
-test
target // 打包后输出文件夹
HELP.md
mvnw
mvnw.cmd
pom.xml // 项目依赖列表编写测试代码
properties
# 在 src\main\resources\application.properties 文件添加服务端口配置
spring.application.name=demo
# 添加服务端口
server.port=8080java
// 在 src\main\java\com\example\demo 下创建 controller 文件再在其下创建 Hello.java 文件
// 写入如下代码
package com.example.demo.controller; // 声明当前文件为一个包
import org.springframework.web.bind.annotation.*; // 引入模块
@RestController
public class Hello {
@RequestMapping("/hello") // 注解
public String handel(@RequestParam String name) { // 接口处理
return "Hello " + name + "!";
}
@PostMapping("/hello2")
public String handel2(@RequestParam String name) {
return "Hello22 " + name + "!";
}
}然后在 VScode 代码区右上角点击 Run Java 运行项目。
最后打开浏览器输入 127.0.0.1:8080/hello?name=zs 访问即可。
当然也可以直接使用命令行运行(以下均为 Windows 系统)
bash
# 在 spring-boot 项目根目录打开 cmd
# 使用 Maven 运行
mvnw.cmd spring-boot:run
# 使用 Gradle 运行
gradlew.bat bootRun构建
bash
# 这个命令会清理之前的构建结果,然后编译并打包你的应用。打包后的 jar 文件通常位于 target 目录下,文件名类似于 your-application-0.0.1-SNAPSHOT.jar。
# 打包为 jar 打包后会输出到 target 文件夹
mvn clean package
# 进入 target 文件夹后运行打包后的 jar 包
java -jar demo.jar基础
运行
新建 code 文件夹,再新建 HelloWorld.java 文件
java
// 这里必须要和文件夹名称一致
package code;
// 类名称必须与文件名一致
public class HelloWorld {
// 入口函数
public static void main() {
System.out.println("执行");
}
}运行
bash
javac HelloWorld.java之后会在同文件夹下生成一个 HelloWorld.class
bash
# 在 code 文件夹之外执行如下命令,即可执行上述代码
java code.HelloWorld变量
变量要先声明才能使用
变量是什么类型,就必须装什么类型的数据
变量是从定义开始到 "}" 截止的范围内有效
同一个范围内,变量的名称不能一样
变量定义的时候可以不赋初始值,但在使用时,变量里必须有值
java
// Java:必须先声明类型
String name = "张三"; // 字符串
final int age = 18; // final 类似 JS 的 const
boolean flag = true;
double num = 3.14;
// Java 10+ 也支持类型推断(但仍是静态类型)
var city = "北京"; // 编译器自动推断为 String数据类型
基础数据类型
java 中基础数据类型分为 4 种:整型、浮点型、字符型、布尔型
表达式的最终结果类型由表达式中的最高类型决定
表达式中 byte、short、char 是直接转换成 int 类型参与运算的
java
// 整型
byte b = 1; // 1字节(值范围:-128 到 127)
short s = 2; // 2字节(值范围:-32768 到 32767)
int i = 100; // 4字节,最常用(值范围:-2147483648 到 2147483647(10位数,大概21亿多))
long l = 100L; // 8字节,注意加 L,大写小写都行,一般用大写(值范围:19位数)
// 浮点型(小数)
float f = 1.5F; // 注意加 F ,大写小写都行,一般用大写
double d = 3.14; // 最常用的小数类型
// 字符型
char c = 'A'; // 单个字符,用单引号(值范围:0 到 65535)
// 布尔型
boolean flag = true;
// 类型转换(值范围小的可以赋值给值范围大的类型)
int a = 1;
byte b = 2;
a = b;
// 运算(当几个值范围不一样之间运算,必须使用值范围最大的那个类型接收)
byte b = 1;
short s = 2;
long l = 22L;
// 正确
long i = b + s + l;
// 错误
// int i = b + s + l;
// 正确
double d = b + s + l + 3.15;
// 错误
// float d = b + s + l + 3.15;
// 面试题
byte b = 1;
byte s = 2;
// 正确(表达式中 byte、short、char 是直接转换成 int 类型参与运算的)
int i = b + s;
// 错误
// byte i = b + s;
System.out.println("a" + 1); // 输出字符串的 "a1"
// 输出数字的 98,因为单引号表示 char 类型,加运算时会将其转换为 int 类型计算,小写 a 对应 ASCII 码为97
System.out.println('a' + 1);引用数据类型
java 中的引用数据类型分为**类(Class)、接口(Interface)、数组(Array)**三大类,变量存储的是堆内存对象的地址而非直接值。
字符串
尽管 String 使用频率极高且不可变,但其本质仍是类,非语言内置的基本类型。
java
// Java:String 是一个类,length() 是方法
String s = "hello";
int len = s.length();// 注意是方法,要括号
// 拼接
String str = "你好 " + name;
// Java 15+ 文本块(类似模板字符串的多行)
String json = """
{
"name": "张三"
}
""";
// 字符串格式化
String msg = String.format("你好 %s,今年 %d 岁", name, age);数组
数组就是一种容器,可以存储同种类型的多个值
java
int[] arr = new int[]{1,2,3}; // 完整格式
double[] arr2 = {1.2,3}; // 简易格式
// 打印的不是数组内容而是数组的十六进制内存地址
// @:分隔符 [:当前的空间是数组类型 I:数组中元素的类型 13c6f6d7:十六进制地址
System.out.println(arr); // [I@13c6f6d7
System.out.println(arr[1]); // 按照索引取值
arr[2] = 5; // 按照索引修改值动态初始化
初始化时只指定数组长度,由系统为数组分配初始值
java
int[] arr = new int[10]; // [] 内可直接指定数组长度
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]); // 0
}二维数组
java
// 二维数组创建简写方式(完整方式参考普通数组创建方式)
int[][] arr = { { 1, 2 }, { 3, 4 } };
for (int i = 0; i < arr.length; i++) {
for (int i2 = 0; i2 < arr[i].length; i2++) {
// 二维数组访问
System.out.println(arr[i][i2]);
}
}类
JS 也有 class,但 Java 的 OOP 更严格、更体系化
java
public class Person {
// 1. 成员变量(字段)需要声明类型
private String name;
private int age;
// 2. 构造方法(方法名 = 类名,无返回值)
public Person(String name, int age) {
// this 代表当前类对象的引用(地址),和 js 中类似
this.name = name;
this.age = age;
}
// 构造方法也是可以重载的
public Person() {
}
// 3. getter / setter(Java 习惯用私有字段 + 公开方法访问)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 4. 普通方法
public String sayHi() {
// 局部变量
int a = 10;
return "我是 " + name;
}
}
// 使用
Person p = new Person("张三", 18);
System.out.println(p.sayHi());成员变量和局部变量
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 类中位置不同 | 函数外 | 函数中 |
| 初始化值不同 | 有默认初始化值 | 没有,使用之前需要完成赋值 |
| 内存位置不同 | 堆内存 | 栈内存,因为存在函数中 |
| 生命周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着函数的调用而存在,随着函数的执行结束而消失 |
| 作用域 | 在自己所归属的大括号中 | 在自己所归属的大括号中 |
访问修饰符
| 修饰符 | 含义 |
|---|---|
| public | 任何地方都能访问 |
| private | 只能在本类访问(最常用于字段) |
| protected | 本类 + 子类访问 |
| 不写 | 同一个包(同一个目录下)内访问 + 同一个类中 |
static
static 是静态的意思,可以修饰成员变量,也可以修饰成员方法
被 static 修饰的变量或方法可以被所有的示例访问并使用。
static 中只能访问同样被 static 修饰的成员(直接访问)。
static 修饰的方法中没有 this 关键字。
java
public class Fu {
public Fu() {
// 可直接通过类名访问被 static 修饰的变量或方法
Hello.fn();
}
}
public class Hello {
static void fn() {}
}继承
让类与类之间产生关系(子父类关系),子类可以直接使用父类中非私有的成员。
当类与类之间,存在相同(共性)的内容,并且产生了 is a 的关系,就可以考虑使用继承,来优化代码。
Java 中的继承只允许单继承,不允许多继承(类 A 同时继承类 B 和类 C),允许多层继承(类 A 可以继承类 B ,类 B 又继承类 C)。
java
// extends 关键字(和 JS 一样)
public class Student extends Person {
private String school;
public Student(String name, int age, String school) {
super(name, age); // 调用父类构造,类似 JS 的 super()
this.school = school;
}
// @Override 注解表示重写父类方法
@Override
public String sayHi() {
return "我是学生 " + getName();
}
}重写
子类重写父类方法,需要保证方法声明完全一致(方法名,参数,返回值类型需要保持一致)
父类中私有方法不能被重写
子类重写父类方法时,访问权限必须大于等于父类
java
public class Fu {
public void fn() {
System.out.println("父类方法");
}
}
public class Zi extends Fu {
// 重写的标记注解,用于声明当前方法旨在重写(覆盖)父类或接口中的方法,若未真正重写则编译报错
@Override
public void fn() {
super.fn(); // 可通过 super 调用父类方法
System.out.println("重写");
}
}接口
接口:一套规范/契约,只定义"能做什么",不实现。
和 ts 的 interface 概念类似,但 Java 接口是运行时真实存在的
java
// 定义接口
public interface Animal {
void eat(); // 抽象方法,没有方法体
void sleep();
}
// 实现接口用 implements
public class Dog implements Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗睡觉");
}
}运算符
把多个条件放在一起运算,最终返回布尔类型的值:true、false
| 符号 | 叫法 | 例子 | 运算逻辑 |
|---|---|---|---|
| & | 逻辑与 | 2>1&3>2 | 多个条件必须都是true,结果才是true;有一个是false,结果就是false |
| | | 逻辑或 | 2>1|3<5 | 多个条件中只要有一个是true,结果就是true |
| ! | 逻辑非 | !(2>1) | 就是取反:你真我假,你假我真 |
| ^ | 逻辑异或 | 2>1^3>1 | 前后条件的结果相同,就直接返回false,前后条件的结果不同,返回true |
| && | 短路与 | 2 >10 &&3>2 | 判断结果与 & 一样,过程不同:左边为fase,右边则不执行。 |
| || | 短路或 | 2>1||3<5 | 判断结果与 | 一样,过程不同:左边为true,右边则不执行。 |
其他
自增自减(如 ++a)、三元运算符、运算符优先级(括号内优先级最高,&& 优先级比 || 优先级高)等和 js 基本一致
控制流
和 js 中基本一样
java
// if-else 一致
if (age >= 18) {
System.out.println("成年");
} else {
System.out.println("未成年");
}
// for 循环一致
// 循环中 () 中定义的变量,在整个循环结束后,都会从内存中释放
for (int i = 0; i < 10; i++) {
// 循环中 {} 中定文的变量,在每一轮循环结束后,都会从内存中释放
int a = 10;
System.out.println(i);
}
// while 循环(先判断后执行)
int i = 1;
while (i <= 5) {
i++;
System.out.println("执行");
}
// do while 循环(先执行后判断)
int i = 1;
do {
i++;
System.out.println("执行");
} while (i <= 5);
// 增强 for(类似 JS 的 for...of)
int[] arr = {1, 2, 3};
for (int item : arr) {
System.out.println(item);
}
// 注意这里的 i 只支持 byte、short、int、char 类型,JDK5开始支持枚举,JDK7开始支持 String
int i = 1;
switch (i) {
// case 给出的值不允许重复,且只能是字面量,不能是变量
case 1:
System.out.println("等于1");
// 正常使用 switch 的时候,不要忘记写 break,否则会出现穿透现象
break;
case 2:
System.out.println("等于2");
break;
default:
System.out.println("等于10");
}
// switch(Java 14+ 新写法很好用)
String result = switch (age) {
case 18 -> "成年了";
case 1, 2, 3 -> "小孩";
default -> "其他";
};
// break 终止循环体内容的执行,也就是说结束当前的整个循环
// continue 跳过某次循环体内容的执行,继续下一次的执行函数
Java 中方法必须写在类里,且要声明返回类型和参数类型
注意事项:
1.函数在类中的位置放前放后无所谓,但一个函数不能定义在另一个函数里面。
2.函数的返回值类型写 void(无返回申明)时,函数内不能使用 return 返回数据,如果函数的返回值类型写了具体类型,函数内部则必须使用 return 返回对应类型的数据。
3.return 语句的下面,不能编写代码,属于无效的代码,执行不到这儿
4.函数不调用就不会执行,调用函数时,传给函数的数据,必须严格匹配函数的参数情况。
5.调用有返回值的函数,有3种方式:可以定义变量接收结果、或者直接输出调用、甚至直接调用。
6.调用无返回值的函数,只有1种方式:1、只能直接调用,因为它无返回值所以不能接收其返回值。
java
public int add(int a, int b) {
return a + b;
}
// 无返回值用 void
public void printName(String name) {
System.out.println(name);
}
// 修饰符说明:
// public = 访问权限(公开)
// int = 返回值类型
// add = 方法名函数执行原理
函数没有被调用的时候,在函数区中的字节码文件中存放。
函数被调用的时候,是进入到栈(先进后出)内存中运行。这么做有两个原因:
1..确保函数调用其他函数后可以回来(在一个函数 A 中调用函数 B,B 执行完后可以返回 A 函数继续执行 A 函数的剩余代码)。
2.确保函数执行完毕后可以释放栈内存
参数传递机制
参数传递机制是值传递:指的是在传输实参给方法的形参的时候传输的是实参变量中存储的值的副本。
java
// 这点和 js 基本一致
public static void main() {
int a = 10;
fun(a);
System.out.println(a); // 10
}
static void fun(int c) {
c = c + 1;
System.out.println("函数内:" + c); // 11
}重载
函数重载必须在同一个类中。
函数名必须一致。
参数列表必须不同(个数、类型、顺序)。
返回值、修饰符(public、private 等)不同不算重载。
java
public static void main(String[] args) {
fn(); // 无参数 fn
fn(2); // 有参数 fn2
}
static void fn() {
System.out.println("无参数 fn");
}
static void fn(int i) {
System.out.println("有参数 fn" + i);
}集合框架
java
import java.util.*;
// List:有序可重复,类似 JS 数组
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
String first = list.get(0);
int size = list.size();
// Map:键值对,类似 JS 对象/Map
Map<String, Integer> map = new HashMap<>();
map.put("张三", 18);
Integer age = map.get("张三");
// Set:不重复集合
Set<String> set = new HashSet<>();
set.add("a");
set.add("a"); // 重复无效
// 遍历 Map
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}泛型
类型参数化,让代码复用且类型安全
java
// 1. 泛型方法
public <T> T identity(T arg) {
return arg;
}
// 2. 泛型在集合中(最常见)
List<String> names = new ArrayList<>(); // 只能放 String
// 3. 自定义泛型类
public class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}
// 使用
Box<String> box = new Box<>();
box.set("hello");
String s = box.get();异常处理
java
// Java 异常是分类型的
try {
int result = 10 / 0;
} catch (ArithmeticException e) { // 捕获特定异常
System.out.println("除零错误:" + e.getMessage());
} catch (Exception e) { // 兜底
System.out.println("其他错误");
} finally {
System.out.println("结束");
}
// 主动抛异常
throw new RuntimeException("自定义错误");构建工具
构建工具 Maven(类似 npm)
pom.xml 相当于 package.json
xml
<project>
<groupId>com.example</groupId> <!-- 组织名 -->
<artifactId>demo</artifactId> <!-- 项目名 -->
<version>1.0.0</version>
<!-- 依赖,类似 dependencies -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>| Maven 命令 | npm 类比 |
|---|---|
| mvn install | npm install |
| mvn package | npm run build |
| mvn test | npm test |
Maven 会从中央仓库下载 jar 包到本地
.m2目录(类似 node_modules,但全局共享)。
配置数据库
application.yml 或者 application.properties
yaml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver