基础认识
- 每个 Java 程序都必须包含至少一个类。在 Java 中,可以使用
class关键字声明类。 - Java 程序是由一个或多个类组成的集合,其中一个类包含 main方法。
- 要执行Java程序,我们需要编写一个main方法。当JVM执行 字节码时, 它会查找 main 方法并从该行开始执行。
- 从控制台窗口(命令提示符)读取用户数据称为 标准输入 ,向控制台打印/写入数据称为 标准输出。
- System.out.println:使用 println 方法向控制台打印内容,该方法由PrintStream类的 out 对象 提供 ,而out对象由 System类提供访问 。
完整.java文件的固定书写层级
外层顺序强制,类内部元素顺序自由
1. Package statement 包声明【可选】
规则:
- 如果写,必须是代码第一行;唯一例外:文件最顶部可以放注释。
- 作用:给类划分命名空间,解决类名重名冲突,对应项目目录文件夹。
go
package com.company.demo.controller;
前端类比:等同于 TS 里的文件目录分层,用来区分不同模块,避免同名组件冲突。
2. Import statement (s) 导入语句【可选】
写在 package 之后、类定义之前;用来导入其他包下的类,不用写完整长路径。
java
import java.util.List;
import com.company.demo.entity.User;
前端类比:和 JS/TS import xxx from 'xxx' 作用完全一致。
3. Comments 注释【可选】
无位置限制,文件任意地方都能写,不参与编译。Java 三种注释:单行//、多行/* */、文档注释/** */。
4. Class declaration 类声明(核心主体,必写)
整个文件的核心,用{}包裹所有类内部内容;一个.java最多一个public class,类名和文件名必须一致。
kotlin
public class User {
// 内部所有元素写在这里
}
前端类比:对应 TS 里 class User {},但 Java 类是文件核心载体,JS 可以无 class 直接写逻辑。
大括号 {} 内部:所有元素顺序任意、全部可选
规范推荐:属性→构造器→方法
内部包含 7 类元素:
- Variable declarations 变量声明
类的属性(成员变量),分为静态变量、实例变量,对应业务实体字段。
vbnet
private Long id;
private String username;
- Comments 注释
类内部任意位置添加注释。
- Constructors 构造方法(构造器)
和类同名、无返回值,new 创建对象时自动执行,用来初始化对象数据;不写会默认生成空参构造。
arduino
public class User {
// 构造器
public User(String name) {
this.username = name;
}
}
Methods 普通方法
业务逻辑载体,接口、工具逻辑都写在方法里。
typescript
public String getUsername() {
return this.username;
}
- Nested Classes 内部类
在当前类{}中再定义 class,封装强关联逻辑。
分两类:静态内部类、成员内部类
场景 1:静态内部类(业务高频:分页返回、复合 VO)
后台接口统一分页返回,外层是分页包装,内层放列表数据,强耦合、不会单独使用,用静态内部类最合适。
java
// 外层通用分页工具类
public class PageResult {
private Long total;
private Integer pageNum;
private Integer pageSize;
private List<User> records;
// 静态内部类:分页里的用户详情,只属于PageResult,不会单独new
public static class User {
private Long id;
private String username;
private String phone;
// getter/setter
}
// 对外静态构建方法
public static PageResult build(Long total, List<User> list) {
PageResult res = new PageResult();
res.total = total;
res.records = list;
return res;
}
}
// 业务使用(Controller 返回分页)
// 调用静态内部类,外层类.内部类
PageResult.User user = new PageResult.User();
PageResult page = PageResult.build(100, List.of(user));
场景 2:成员内部类(绑定外部实例,业务:订单明细依附订单)
订单Order是外层类,订单明细OrderItem只能依附订单存在,不存在脱离订单的明细,用成员内部类。
csharp
public class Order {
private String orderNo;
private BigDecimal amount;
// 成员内部类:明细必须依附一个订单实例
public class OrderItem {
private Long productId;
private Integer num;
// 内部类可直接访问外部类私有字段 orderNo
public void printOrderInfo() {
System.out.println("所属订单号:" + orderNo);
}
}
// 外部类提供创建明细的入口
public OrderItem createItem() {
return new OrderItem();
}
}
// 使用方式(必须先 new 外层订单,才能创建明细)
Order order = new Order();
Order.OrderItem item = order.createItem();
item.printOrderInfo(); // 能拿到订单号
- Nested Interfaces 内部接口
类内部定义接口,多用于回调、规范内部行为。
实战场景 1:回调函数(后台异步通知、消息回调,对标前端回调)
模拟订单支付完成回调,回调逻辑只属于订单服务,把回调接口写在OrderService内部。
typescript
public class OrderService {
// 内部回调接口:只给OrderService自己用,外部无需感知
// 作用域隔离:`PayCallback`只属于订单模块,不会和全局接口重名;不用新建独立`.java`文件,简化项目结构。
public interface PayCallback {
// 支付完成执行回调
void onPaySuccess(String orderNo, BigDecimal payAmount);
void onPayFail(String orderNo, String errMsg);
}
// 支付方法,接收内部回调接口
public void pay(String orderNo, PayCallback callback) {
boolean paySuccess = true;
if (paySuccess) {
callback.onPaySuccess(orderNo, new BigDecimal("99"));
} else {
callback.onPayFail(orderNo, "余额不足");
}
}
}
// 业务调用(Controller 层)
OrderService orderService = new OrderService();
orderService.pay("ORD20260719", new OrderService.PayCallback() {
@Override
public void onPaySuccess(String orderNo, BigDecimal payAmount) {
System.out.println("订单" + orderNo + "支付成功,金额:" + payAmount);
// 执行业务:发通知、扣库存
}
@Override
public void onPayFail(String orderNo, String errMsg) {
System.out.println("支付失败:" + errMsg);
}
});
实战场景 2:内部策略规范(权限校验内置规则)
arduino
public class UserAuth {
// 内部接口:登录校验规则
public interface LoginRule {
boolean checkUsername(String username);
boolean checkPassword(String password);
}
// 登录方法,传入自定义校验规则
public boolean login(String username, String pwd, LoginRule rule) {
return rule.checkUsername(username) && rule.checkPassword(pwd);
}
}
- Enums 枚举
枚举是固定、不可修改的常量集合,专门描述有限、不变的业务状态 / 类型,替代硬编码数字、字符串(杜绝魔法值)。
场景 1:订单状态(后台 CRUD 必用,最经典)
订单只有 4 种固定状态:待支付、已支付、已发货、已完成,禁止随便传其他值。
typescript
// 订单状态枚举
public enum OrderStatus {
// 固定枚举实例:括号内是数据库存储值、前端展示文案
WAIT_PAY(0, "待支付"),
PAID(1, "已支付"),
DELIVERED(2, "已发货"),
FINISHED(3, "已完成");
// 成员变量
private final Integer code;
private final String desc;
// 私有构造器(枚举构造器强制private,不能手动new)
OrderStatus(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
// getter
public Integer getCode() { return code; }
public String getDesc() { return desc; }
// 业务工具方法:根据数据库code反向匹配枚举
public static OrderStatus getByCode(Integer code) {
for (OrderStatus status : values()) {
if (status.getCode().equals(code)) {
return status;
}
}
throw new RuntimeException("无效订单状态");
}
}
// 业务使用(Service 逻辑判断)
// 从数据库取出code=0
Integer dbCode = 0;
OrderStatus status = OrderStatus.getByCode(dbCode);
if (status == OrderStatus.WAIT_PAY) {
System.out.println("订单待支付,等待用户付款");
}
场景 2:用户性别、操作类型、支付渠道
arduino
// 性别枚举
public enum Gender {
MALE(1, "男"), FEMALE(2, "女");
private Integer code;
private String desc;
// 构造+getter省略
}
Java 枚举独有优势(前端 TS 没有)
-
类型安全 :方法参数限定
OrderStatus,不能传数字 / 字符串,前端传错值运行时才报错;Java 编译期直接拦截错误。typescript// 限定只能传枚举,传数字编译器直接报错 public void changeOrderStatus(OrderStatus status) {} -
自带工具方法:
values()遍历全部状态、valueOf()根据名称匹配; -
可扩展业务逻辑:在枚举内部写方法(校验、状态流转判断);
-
统一管理常量:所有状态集中在一个文件,修改文案只改一处,不用全局搜硬编码。
开发避坑
禁止在代码里写 if(status == 0) 这种魔法数字,全部替换枚举,大幅降低线上 bug。