我学习到的Java类完整结构

基础认识

  • 每个 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 类元素:

  1. 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 没有)
  1. 类型安全 :方法参数限定OrderStatus,不能传数字 / 字符串,前端传错值运行时才报错;Java 编译期直接拦截错误。

    typescript 复制代码
    // 限定只能传枚举,传数字编译器直接报错
    public void changeOrderStatus(OrderStatus status) {}
  2. 自带工具方法:values()遍历全部状态、valueOf()根据名称匹配;

  3. 可扩展业务逻辑:在枚举内部写方法(校验、状态流转判断);

  4. 统一管理常量:所有状态集中在一个文件,修改文案只改一处,不用全局搜硬编码。

开发避坑

禁止在代码里写 if(status == 0) 这种魔法数字,全部替换枚举,大幅降低线上 bug。

相关推荐
什巳14 小时前
JAVA练习309- 二叉树的层序遍历
java·数据结构·算法·leetcode
宠友信息15 小时前
消息序号如何保证即时通讯源码聊天记录稳定加载
java·spring boot·redis·python·mysql·uni-app
圣光SG15 小时前
Java Web入门基础知识笔记
java·前端·笔记
Csvn15 小时前
📊 SQL 入门 Day 6:多表查询 — JOIN 的四种姿势
后端·sql
行思理15 小时前
微信支付“商家转账用户确认模式”,新手教程
java·开发语言·微信
空中湖16 小时前
Spring AI RAG 完整实战:从零搭建企业知识库问答系统
java·人工智能·spring
Ai拆代码的曹操16 小时前
K8s Pod Pending 逐层排查:从 FailedScheduling 到 PVC StorageClass 不存在的实战记录
java·linux·kubernetes
hold?fish:palm17 小时前
RDB全量快照备份
c++·redis·后端
LucianaiB17 小时前
我把刘备一生做成了可播放的高德地图,还把整套方法封装成了 Skill
后端