Java SE “异常处理 + IO + 序列化”面试清单(含超通俗生活案例与深度理解)

一、异常处理

一、请详细说说 Java 异常处理体系的结构,并用生活中常见的场景举例,让各部分的区别更清晰?

• 核心体系逻辑:Java 中所有与"错误""异常"相关的内容,都源于顶层基类 Throwable。这个基类就像"所有问题的总集合",往下又分为两大分支------Error 和 Exception,二者最本质的区别是"程序是否有能力处理":

◦ Error 属于系统级别的错误,比如 JVM 崩溃、内存溢出等,这类问题并非程序代码逻辑错误导致,而是底层系统出现故障,程序自身没有修复能力,只能依赖外部干预(比如重启服务器、扩容内存);

◦ Exception 是程序运行中因逻辑疏漏或操作不当引发的异常,属于程序可处理的范畴,它又细分为两类:CheckedException(受检异常,编译器会强制要求处理,不处理则程序无法运行)和 RuntimeException(运行时异常,编译器不强制处理,仅在程序运行时才可能突发)。

• 生活场景类比,帮你秒懂区别:

◦ 用"家庭电器故障"类比:

◦ Error 就像夏天高温时,家里冰箱的压缩机突然烧坏------这不是你"使用冰箱时没关紧门"这类操作问题导致的,而是冰箱核心部件故障,你自己没法维修(程序处理不了),只能联系维修师傅上门(外部干预),否则冰箱里的食物会变质;

◦ CheckedException 就像用洗衣机洗衣服时,你忘记打开进水龙头------洗衣机启动前会自动检查"水源是否通畅"(编译器强制检查),发现水龙头没开就会报警(编译报错),你必须先打开水龙头(处理异常),洗衣机才能正常注水运转;

◦ RuntimeException 就像你用微波炉热牛奶时,没撕掉牛奶盒的密封膜------微波炉启动前不会检查"膜是否撕掉"(编译器不强制处理),但加热过程中牛奶盒会因内部气压升高炸开(程序运行时报错),这种问题是操作时的细节疏忽,虽不用提前强制预防,但发生后需要调整操作(修复代码)才能避免下次出错。

二、Java 中处理异常的方式主要有哪两种?throw 和 throws 这两个关键字有什么本质区别?finally 块的核心特点是什么?请结合生活场景逐一说明。

• 核心处理逻辑与区别:

  1. 异常处理的两种核心方式:一是"自身不处理,抛给调用者解决"(借助 throw/throws 关键字),二是"主动捕获异常并处理"(借助 try-catch-finally 语句块);

  2. throw 和 throws 的区别:

◦ 位置不同:throws 只能写在方法声明处(比如 public void readFile() throws IOException),throw 只能写在方法内部(比如方法中写 throw new IOException("找不到指定文件"));

◦ 内容不同:throws 后面跟的是"异常类的名称"(可同时跟多个,用逗号分隔,比如 throws IOException, SQLException),表示"该方法可能出现这些类型的异常,我不负责处理,需调用者处理";throw 后面跟的是"具体的异常对象"(比如 new IOException()),表示"此刻主动抛出这个明确的异常";

  1. finally 块的特点:无论 try 块代码是否出现异常、catch 块是否捕获到异常、try/catch 块中是否有 return 语句,finally 块中的代码都一定会执行(唯一例外是程序在执行 finally 前强行退出,比如调用 System.exit(0))。

• 生活场景类比,让区别更直观:

◦ 用"外卖配送"场景类比两种处理方式:

◦ "抛给调用者处理"(throw/throws):外卖员接单时,看到订单备注"收货地址在老旧小区,无门牌号,可能找不到具体单元"(throws 在方法声明处,提前告知平台/用户"可能出现地址找不到异常"),这是外卖员将"解决地址问题"的责任交给了调用者(平台或用户);如果外卖员到小区后,确实找不到备注中的单元楼,就打电话给用户说"我到小区门口了,但没找到3号楼,无法继续配送"(throw 在方法内部,主动抛出具体异常),明确告知当前遇到的问题;

◦ "自己捕获处理"(try-catch):外卖员配送时,担心"高峰期堵车导致迟到"(可能出现的异常),提前规划了两条路线------主路线走主干道,备选路线走小巷(try 块写"按主路线配送",catch 块写"若堵车则切换到备选路线"),这样即使遇到堵车,也能自己解决问题,不用麻烦用户或平台;

◦ 用"外卖员下班流程"类比 finally 块:无论外卖员当天送了多少单、是否遇到用户投诉(对应 try/catch 中的异常)、是否提前完成配送任务(对应 try/catch 中的 return),下班前都必须完成两件事------把外卖箱内的垃圾清理干净、给电动车充满电(对应 finally 块中的代码),这两件事是"无论如何都要执行"的,不会因其他情况省略。

三、如果 try 块里有 return 语句,finally 块里分别出现"输出内容""return 语句""修改变量"这三种情况,最终的执行结果会不一样,请分别用生活场景解释这三种情况的逻辑,让结果更易理解?

• 三种场景的核心结论(先明确结果,再用例子解释):

  1. try 块 return + finally 块输出内容:程序会先执行 finally 块的输出操作,再执行 try 块的 return,最终返回 try 块的结果;

  2. try 块 return + finally 块 return:finally 块的 return 会"覆盖"try 块的 return,程序不会执行 try 块的 return,直接返回 finally 块的结果(实际开发中绝对禁止这样写,会破坏代码正常逻辑,还可能导致异常无法正常捕获);

  3. try 块 return 变量 + finally 块修改变量:程序在执行 finally 块前,会先把 try 块中变量的值"暂存"起来,即便 finally 块修改了变量的值,最终返回的仍是之前暂存的结果,变量修改不会影响返回值。

• 生活场景类比(每个场景都用"日常办事"举例,贴近生活):

  1. try return + finally 输出:你去政务大厅办理社保卡(try 块的核心任务),提交完身份证、照片等材料后,工作人员说"资料没问题,社保卡制作完成后会短信通知你领取(try 块的 return,准备返回'办理成功'的结果)"------但无论你的社保卡最终能否顺利制作(是否出现异常),工作人员都会先给你一张"受理回执单"(finally 块的输出),所以你会先拿到回执单,之后才收到领卡短信,最终的"执行结果"就是"先有回执单,再有办理成功的反馈";

  2. try return + finally return:你去超市买东西,选了一袋大米(try 块的代码,准备结账后带走大米,对应 return"大米"),到收银台付款时,收银员说"你会员卡里有一张满50减10的券,必须买满50元才能用(finally 块的逻辑),要不你再拿一瓶食用油?"你同意后,最终买了大米和食用油(finally 块的 return"大米+食用油")------此时,你最初"只买大米"的需求(try 块的 return)被覆盖,实际拿到的是两种商品,对应程序中"finally 的 return 覆盖 try 的 return";

  3. try return 变量 + finally 修改变量:你让同事帮你带一份午餐,明确说"要一份番茄炒蛋盖饭+一杯可乐(try 块里给变量赋值'番茄炒蛋盖饭+可乐',准备 return 这个变量)",同事去餐厅的路上,突然想"你平时爱吃辣,要不加一份辣椒小菜?(finally 块里修改变量为'番茄炒蛋盖饭+可乐+辣椒小菜')"------但同事忘了,你最初已经明确说了"不要额外小菜",他虽然加了小菜,最终还是按你原需求带了盖饭和可乐(对应程序中"暂存变量值,修改不影响返回结果")。这里的关键是"同事记住了你的原始需求(JVM 暂存变量值)",后续的临时修改不会改变原始需求。

二、IO 流

一、Java 中的 IO 流有哪些常见的分类方式?每种分类的核心逻辑是什么?IO 流的顶层基类有哪些?另外,IO 流体系用到了什么设计模式?请用生活中"快递收发"的场景类比这些概念,让分类和设计模式更易理解。

• 核心分类方式、基类与设计模式:

  1. 按"数据流向"分类:输入流和输出流------输入流是"数据从外部(如文件、网络、U盘)进入程序",相当于"程序在'接收'数据";输出流是"数据从程序发送到外部",相当于"程序在'发送'数据";

  2. 按"操作单元"分类:字节流和字符流------字节流以"单个字节"为操作单位(1字节=8位),能处理所有类型的数据(如图片、音频、视频、压缩包);字符流以"单个字符"为操作单位(1字符=2字节,针对 Unicode 编码),仅适合处理文本数据(如 .txt 文档、Java 代码文件、Excel 中的文字内容);

  3. 按"流的角色"分类:节点流和处理流------节点流是"直接与数据源打交道的流",比如直接读取本地 .txt 文件的流、直接从网络接收数据的流;处理流是"基于节点流做加工的流",比如给节点流增加"缓冲加速""编码转换""数据压缩"等功能,不直接操作数据源;

  4. 顶层基类:输入流的基类是 InputStream(字节输入流)和 Reader(字符输入流),输出流的基类是 OutputStream(字节输出流)和 Writer(字符输出流)------所有具体的 IO 流类,均从这四个基类派生而来;

  5. 设计模式:装饰器模式------核心是"在不改变原有流(被装饰者)核心功能的前提下,为其增加新功能",就像给手机贴保护膜、装手机壳,手机本身的通话、上网功能不变,但多了"防刮花""防摔"的附加能力。

• 用"快递收发站"场景类比,让所有概念落地:

◦ 输入流 vs 输出流:快递站接收快递公司送来的包裹(输入流------外部的包裹进入快递站,对应"外部数据进入程序");快递站把用户要寄的衣服、书籍等物品装进包裹,交给快递公司(输出流------快递站的物品发送到外部,对应"程序数据发送到外部");

◦ 字节流 vs 字符流:快递站处理"零散的小零件"(字节流------单个小零件相当于1个字节,能处理各种类型的物品,比如螺丝、纽扣);快递站处理"整页的信件"(字符流------1页信件相当于1个字符,仅适合处理文本类物品,比如家书、通知);

◦ 节点流 vs 处理流:快递站的"收件窗口"直接接收用户拿来的包裹(节点流------直接操作"用户包裹"这个数据源);快递站的"打包区"给用户的包裹套上防水袋、贴好运单、缠上缓冲气泡膜(处理流------基于"收件窗口"接收的包裹,做"防水""标记""防压"的加工,不直接与用户接触);

◦ 装饰器模式:快递站的"打包区"就是"装饰者"------用户拿来的包裹(被装饰的节点流)本身具备"可运输"的核心功能(能被快递公司运送),但经过打包区处理后,多了"防水""防压"的附加功能(对应处理流给节点流增加缓冲、编码转换功能),且没有改变包裹"可运输"的核心属性。

二、既然字节流能处理所有类型的数据(包括文本),为什么 Java 还要专门设计字符流?请用生活中"处理文档"的场景类比,说明字符流的优势。

• 核心原因:字节流处理文本数据时,存在"编码转换"的痛点------文本数据的本质是"字符"(如"你好""abc"),而字节流只能处理"字节",因此需要将字符拆分为字节(写入文本时)或把字节拼接回字符(读取文本时)。这个过程中,若不清楚文本的编码格式(如 UTF-8、GBK、ISO-8859-1),就会出现"乱码";而且频繁的拆拼操作会消耗额外的系统资源,处理效率较低。字符流的设计初衷就是"跳过字节拆拼步骤,直接操作字符",专门解决文本处理的痛点。

• 生活场景类比(用"处理手写文档"举例,贴近文本处理的核心需求):

假设你有一份手写的会议纪要(文本数据),需要完成两件事:一是把纪要内容录入电脑(程序读取文本),二是把电脑里的内容打印出来(程序写入文本):

◦ 用字节流处理:相当于你把会议纪要的每个字都拆成"笔画"(字符拆成字节),录入电脑时,先逐个输入每个字的笔画(比如"你"拆成"撇、竖、撇、横钩、竖钩、横"),再让电脑把笔画拼回成字;打印时,又要把字拆成笔画,传输到打印机,再让打印机拼回成字。这个过程中,一旦某个字的笔画顺序记错(比如把"你"的"横钩"写成"横"),电脑就会拼出"错字"(乱码);而且拆拼笔画需要反复核对,很费时间(效率低);

◦ 用字符流处理:相当于你直接把会议纪要的每个字完整录入电脑(直接操作字符,不拆笔画),电脑直接存储"完整的字",无需拆拼;打印时,直接把"完整的字"传输到打印机,打印机直接打印"字"。这个过程中,没有"笔画拆拼"的步骤,不会因"笔画顺序错误"导致错字(避免乱码),而且录入和打印的速度更快(效率高)。

简单说,字节流处理文本就像"用笔画拼字",字符流处理文本就像"直接写字"------后者更贴合文本处理的需求,不用绕弯子,还能避免不必要的问题。

三、Java 中的 BIO、NIO、AIO 分别是什么?它们的核心区别是"同步/异步"和"阻塞/非阻塞",请用生活中"餐厅服务"的场景类比,说明三者的差异,以及各自适合的场景。

• 核心概念与区别:

  1. BIO(Blocking IO,同步阻塞 IO):"同步"指程序需自行等待 IO 操作完成(比如读取文件时,程序要等文件全部读完才能做其他事);"阻塞"指线程在等待 IO 操作时,无法做其他任务,只能闲置。BIO 的核心是"一个连接对应一个线程"------每个 IO 连接都需要一个独立线程处理,线程随连接创建而启动,随连接关闭而销毁。

  2. NIO(Non-blocking IO,同步非阻塞 IO):"同步"指程序仍需自行关注 IO 操作的状态(比如读取文件时,程序要时不时检查"文件是否已读完");"非阻塞"指线程在等待 IO 操作时,不用闲置,可去处理其他任务。NIO 的核心是"一个线程处理多个连接"------通过"多路复用器"(Selector)管理所有连接,线程仅在连接有 IO 需求(如数据到达、请求发送)时才处理,无需求时则处理其他任务。

  3. AIO(Asynchronous IO,异步非阻塞 IO):"异步"指程序无需关注 IO 操作的过程,只需发起 IO 请求,待 IO 操作完成后,系统会主动通知程序(比如读取文件时,程序发起请求后就去做其他事,文件读完后系统会告知"可获取数据");"非阻塞"指线程在整个过程中都无需等待,完全不被 IO 操作占用。AIO 的核心是"IO 操作完成后通知程序"------线程不用参与 IO 过程,仅需处理"IO 完成后的通知"。

• 生活场景类比(用"餐厅服务"举例,线程=服务员,连接=客人,IO 操作=客人点单、用餐、结账):

◦ BIO(同步阻塞):小区门口的小餐馆只有2个服务员,每个服务员只负责1桌客人(一个连接对应一个线程)。客人坐下后,服务员就站在桌旁等待客人点单(线程阻塞等待 IO 操作),哪怕客人在纠结菜单、玩手机,服务员也不能去帮其他桌(无法做其他事)。如果同时来了3桌客人,第3桌就没人接待,必须等其中一个服务员的客人用餐结束(连接关闭),才能过来服务。这种模式适合"客人少且固定"的场景(比如小餐馆,每天就几桌熟客),对应程序中"连接数少且固定"的架构(如公司内部的员工管理系统,用户数不多,且同时在线人数稳定)。

◦ NIO(同步非阻塞):商场里的中型快餐店有1个服务员,负责4桌客人(一个线程处理多个连接)。客人坐下后,服务员给每桌发了菜单,然后去擦桌子、补充餐具、整理收银台(线程非阻塞,处理其他任务),每隔2分钟过来问一句"您想好点什么了吗?"(程序检查 IO 状态)。如果有客人举手说"我要下单"(连接有 IO 需求),服务员就过来记录订单、下单到厨房(处理 IO 操作),处理完再去做其他事。这种模式适合"客人多但 IO 操作频率低"的场景(比如下午茶餐厅,客人多但大多在聊天,点单、结账频率低),对应程序中"连接数多但 IO 操作不频繁"的架构(如电商网站的商品浏览页面,用户多但点击购买、提交评论的频率低)。

◦ AIO(异步非阻塞):市中心的大型连锁餐厅采用"扫码点单"系统,只有1个服务员负责处理"订单通知"(线程处理 IO 完成后的通知)。客人坐下后,直接用手机扫码点单(客人发起 IO 请求),不用等服务员过来(程序不用等待),点完单后,系统会给服务员的平板发通知"2号桌下单了,需要送餐具和饮品"(IO 完成后系统通知程序),服务员收到通知后,再去执行对应操作(处理通知)。整个过程中,服务员不用盯着任何一桌客人(线程不阻塞),可以一直在后厨帮忙打包、准备餐具,直到收到通知再去服务。这种模式适合"客人多且 IO 操作频繁"的场景(比如商场里的网红餐厅,客流大且客人点单、加菜频率高),对应程序中"连接数多且 IO 操作频繁"的架构(如即时通讯软件,用户多且发送消息、接收文件的频率高)。

三、序列化

一、什么是序列化?什么是反序列化?Java 中的 Serializable 接口、serialVersionUID 常量、transient 关键字分别有什么作用?请用生活中"家具搬家"的场景类比,让这些概念更易理解。

• 核心概念与作用:

  1. 序列化与反序列化:序列化是"将 Java 对象转换成二进制流"的过程,目的是方便存储(如存入本地文件、数据库)或传输(如通过网络发送给其他服务);反序列化是"将二进制流恢复成 Java 对象"的过程,目的是让对象能重新被程序调用、使用。简单说,序列化是"拆家具",反序列化是"装家具"。

  2. Serializable 接口:这是一个"标记接口"------接口内部没有任何方法,仅起到"标记"作用,告诉 JVM"该类的对象允许被序列化"。若一个类未实现这个接口,尝试序列化它的对象时,JVM 会直接抛出异常,就像家具上没贴"可拆装"标签,搬家公司拒绝帮忙拆解一样。

  3. serialVersionUID 常量:这是一个"版本标识号",常见格式为 private static final long serialVersionUID = 1L;。序列化时,JVM 会将这个版本号与对象数据一起存入二进制流;反序列化时,JVM 会对比"二进制流中的版本号"和"当前类的版本号"------若一致,可正常反序列化;若不一致,则抛出异常。它的作用是"确保序列化和反序列化的对象属于同一个类的同一版本"。

  4. transient 关键字:用于修饰"不需要被序列化的变量"。被 transient 修饰的变量,在序列化时会被"跳过",不存入二进制流;反序列化时,该变量会恢复成"默认值"(如 int 类型默认 0,String 类型默认 null),就像家具上的小零件(如抽屉拉手、柜门合页)不想跟着家具一起搬,贴了"不拆装"标签,搬家时不拆,到新家后也不会有这个零件。

• 生活场景类比(用"家具搬家"举例,Java 对象=家具,二进制流=拆装后的家具零件,序列化=拆家具,反序列化=装家具):

◦ 序列化 vs 反序列化:你要搬新家,家里的衣柜(Java 对象)太大,没法直接塞进搬家车,于是请搬家公司把衣柜拆成木板、螺丝、隔板(转换成二进制流),方便装车运输(存储/传输)------这是序列化;到新家后,搬家公司再把木板、螺丝、隔板重新组装成完整的衣柜(恢复成 Java 对象),能继续用来放衣服------这是反序列化;

◦ Serializable 接口:衣柜的侧面贴了一张"可拆装"标签(实现 Serializable 接口),搬家公司看到标签才会同意帮你拆解(JVM 允许序列化);如果衣柜上没贴标签,搬家公司会说"这个衣柜不能拆,我们没法搬"(JVM 抛出异常);

◦ serialVersionUID:衣柜的说明书上写着"版本号:20240510"(serialVersionUID = 20240510L),搬家公司拆衣柜时,会把版本号写在零件箱的标签上(序列化时存入二进制流);到新家组装时,搬家公司会核对"零件箱标签上的版本号"和"说明书上的版本号"(反序列化时对比版本号)------若都是 20240510,就按说明书正常组装;若零件箱标签上是 20231201,说明书上是 20240510,就会说"版本不匹配,零件可能对不上,没法组装"(反序列化抛出异常);

◦ transient 关键字:衣柜的抽屉拉手上贴了"不拆装"标签(transient 修饰),搬家公司拆衣柜时,不会把拉手拆下来(不序列化);到新家组装时,衣柜能正常装起来,但抽屉没有拉手(反序列化后变量为默认值)------你需要自己买新的拉手装上去。

二、Java 中常见的序列化方式有三种:Java 对象流序列化、Json 序列化、ProtoBuff 序列化,请分别说明它们的核心特点、适用场景,并用生活中"文件传输"的场景类比,让三种方式的差异更清晰。

• 核心特点与适用场景:

  1. Java 对象流序列化(原生序列化):

◦ 特点:基于 Java 原生的 ObjectOutputStream 和 ObjectInputStream 实现,仅能序列化实现了 Serializable 接口的对象;序列化后的二进制流"仅能被 Java 程序反序列化",不支持跨语言(如 Python、Go 程序无法解析 Java 原生序列化的流);优点是"无需额外依赖包,Java 自带",缺点是"跨语言兼容性差、序列化后的数据体积大、解析速度较慢"。

◦ 适用场景:仅在 Java 程序之间传输数据,且对数据体积、解析速度要求不高的场景(如 Java 后端系统之间的内部数据同步,比如订单系统向库存系统同步订单信息)。

  1. Json 序列化:

◦ 特点:将对象转换成 Json 字符串(如 {"username":"张三","age":25,"gender":"男"}),Json 是跨语言的通用格式(Java、Python、Go、JavaScript 等语言均能解析);优点是"易读性强(人能直接看懂字符串内容)、跨语言兼容性好、使用简单(常用 Jackson、FastJson 等工具包)",缺点是"序列化后的数据体积比二进制流大、解析速度比二进制慢"。

◦ 适用场景:需要跨语言传输数据,或需要"人能直接读取数据内容"的场景(如前后端交互------前端用 JavaScript 解析 Json 渲染页面,后端用 Java 生成 Json 数据;或接口调试------直接查看 Json 字符串就能快速定位数据问题)。

  1. ProtoBuff 序列化(Protocol Buffers):

◦ 特点:由 Google 开发,将对象转换成"压缩后的二进制流";优点是"数据压缩率高(比 Json 小 30%-50%)、解析速度快(比 Json 快 2-10 倍)、跨语言兼容性好(支持多种主流语言)",缺点是"需要定义 .proto 文件描述对象结构(学习成本稍高)、序列化后的二进制流不可读(人无法直接看懂内容)"。

◦ 适用场景:对数据传输速度、数据体积要求高的场景(如分布式系统之间的高频数据传输,比如微服务之间的实时数据同步;或移动端与服务器的交互------移动端流量有限,需要小体积数据减少流量消耗)。

• 生活场景类比(用"文件传输"举例,序列化方式=传输工具,对象=文件,二进制流/Json 字符串=传输的文件格式):

  1. Java 对象流序列化:就像用"专属 U 盘"传输文件------这个 U 盘只能在 Windows 电脑之间使用(仅 Java 程序间可反序列化),无法在 Mac 或 Linux 电脑上读取(不跨语言);优点是"无需安装额外软件,插电脑就能用"(Java 自带),缺点是"U 盘存储容量有限,相同文件存在 U 盘里占用空间比其他格式大"(数据体积大)。适合"只在 Windows 电脑之间传文件,且文件不大"的场景(仅 Java 程序间传数据,数据量小)。

  2. Json 序列化:就像用"微信文件传输助手"传文件------不管是 Windows 电脑、Mac 电脑还是手机(跨语言),都能打开微信接收文件;而且文件是"明文格式"(如 Word 文档、TXT 文本,人能直接看懂内容),接收后不用额外工具就能查看(易读);缺点是"传大文件时速度慢"(解析速度慢),"相同文件比压缩格式占用空间大"(数据体积大)。适合"需要在不同设备之间传文件,且要快速查看文件内容"的场景(跨语言传输、接口调试)。

  3. ProtoBuff 序列化:就像用"压缩包+高速网盘"传文件------先把文件压缩成 ZIP 包(数据压缩,体积小),再用高速网盘(如百度网盘超级会员)传输(解析速度快);不管是电脑还是手机(跨语言),安装解压软件就能打开压缩包;缺点是"需要安装解压软件才能查看内容"(需要定义 .proto 文件,学习成本高),"压缩包不解压的话,看不到里面的内容"(二进制流不可读)。适合"传大文件、且对传输速度要求高"的场景(分布式系统高频传输、移动端交互)。

相关推荐
九皇叔叔31 分钟前
Java循环结构全解析:从基础用法到性能优化
java·开发语言·性能优化
流星52112239 分钟前
GC 如何判断对象该回收?从可达性分析到回收时机的关键逻辑
java·jvm·笔记·学习·算法
csdn_aspnet39 分钟前
Java 圆台体积和表面积计算程序(Program for Volume and Surface area of Frustum of Cone)
java
杯莫停丶1 小时前
设计模式之:外观模式
java·设计模式·外观模式
乐之者v1 小时前
Mac常用软件
java·1024程序员节
新子y1 小时前
【小白笔记】「while」在程序语言中的角色
笔记·python
TDengine (老段)1 小时前
TDengine 数据函数 ROUND 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·1024程序员节
TDengine (老段)1 小时前
TDengine 数学函数 RAND 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
從南走到北1 小时前
JAVA无人自助共享系统台球室源码自助开台约球交友系统源码小程序
java·微信·微信小程序·小程序·1024程序员节
烟袅1 小时前
告别 var!深入理解 JavaScript 中 var、let 和 const 的差异与最佳实践
javascript·面试