JAVA快速入门到精通牛客零基础刷题指南:35~37 手把手带刷:常用API,日期工具

JAVA快速入门到精通牛客零基础刷题指南:35~37 手把手带刷:常用API,日期工具

常用API

日期工具

Date

Date类用来处理日期和时间,但是该类的大部分构造器、方法均以过时。

- 常用的构造方法
// 创建代表当前时间的Date对象,底层调用System类获取当前时间毫秒数。 public Date() { } // 根据指定的时间毫秒数创建Date对象,参数为时间的毫秒数。 public Date(long date) { }
- 常用的成员方法
// 判断该时间是否在指定时间之后 public boolean after(Date when) { } // 判断该时间是否在指定时间之前 public boolean before(Date when) { } // 返回该时间的毫秒数 public long getTime() { } // 以毫秒数的形式,设置该Date对象所代表的时间。 public void setTime(long time) { }

Calendar

  • 相比于Date类,Calendar类可以更好地处理日期和时间。
  • Calendar是一个抽象类,所以不能通过构造器创建Calendar对象。
  • Calendar类提供了静态方法getInstance(),用以创建实例。
- Calendar类提供了与Date互转的方法
// 返回Date public final Date getTime() { } // 将Date转为Calendar public final void setTime(Date date) { }
- Calendar类常用的成员方法
// 返回指定字段的值 public int get(int field) {} // 给指定的字段设置一个值 public void set(int field, int amount) {} // 设置年月日的值 public void set(int year, int month, int date) {} // 设置年月日时分秒的值 public void set(int year, int month, int date, int hourOfDay, int minute, int second) {}
- Calendar类常用的静态变量
YEAR, MONTH, DATE, HOUR, MINITE, SECOND, MILLISECOND

DateFormat

DateFormat用于实现日期的格式化,它是一个抽象类,提供了如下静态方法以创建实例:

// 返回日期格式器 public final static DateFormat getDateInstance() {} // 返回时间格式器 public final static DateFormat getTimeInstance() {} // 返回日期时间格式器 public final static DateFormat getDateTimeInstance() {}

同时,DateFormat提供了如下常用的成员方法:

// 将传入的日期格式化为字符串 public final String format(Date date) {} // 将传入的格式字符串解析为日期 public Date parse(String source) throws ParseException {}

SimpleDateFormat

SimpleDateFormat是DateFormat的子类,提供了更简单的格式化方案,该类提供了如下常用的构造器,常用的成员方法则与DateFormat一致。

// pattern是一个日期模板字符串,如“yyyy-MM-dd HH:mm:ss” public SimpleDateFormat(String pattern) {}

JAVA35 输出某一年的各个月份的天数

Calendar calendar=Calendar.getInstance(); for(int month=1;month<=12;month++){ calendar.set(year,month,0); System.out.println(year+"年"+month+"月:"+calendar.get(calendar.DAY_OF_MONTH)+"天"); }

DAY_OF_MONTHjava.util.Calendar 类的静态常量(int 类型)

Calendar 的月份是 0 基索引:0 代表 1 月,1 代表 2 月,……,11 代表 12 月,这是 Calendar 最经典的 “坑”

日期传入 0 的特殊规则:Calendar 的set方法中,日期字段传入0,代表取「上一个月的最后一天」

举个例子帮你理解:

  • month=1时,set(year, 1, 0) → 月份 1 对应日历的 2 月,日期 0 → 自动回退到 2 月的上一个月(1 月)的最后一天。
  • 此时调用get(Calendar.DAY_OF_MONTH),拿到的就是 1 月最后一天的数值,也就是 1 月的总天数。
  • 同理,month=12时,set(year,12,0) → 月份 12 对应次年 1 月,日期 0 → 回退到当年 12 月的最后一天,拿到 12 月的总天数。

JAVA36 日期换算

//将输入的日期用空格分割成字符串数组 String[] arr=str1.split(" "); //如果不是6位长度,则输入不正常 if(arr.length!=6){ System.out.println("您输入的数据不合理"); } else{ //将日期调整成"yyyy-MM-dd HH:mm:ss"的格式 String str=arr[0]+"-"+arr[1]+"-"+arr[2]+" "+arr[3]+":"+arr[4]+":"+arr[5]; //解析日期 Date date=sdf.parse(str); //输出北京时间 System.out.println("北京时间为:"+sdf.format(date.getTime())); //输出纽约时间 System.out.println("纽约时间为:"+sdf.format(date.getTime()-(long)12*60*60*1000)); }

parseSimpleDateFormat类的核心方法,作用是把符合指定格式的「日期时间字符串」,解析转换为java.util.Date日期对象,是「字符串→日期对象」的转换方法。

formatparse的反向操作,作用是Date对象 /long类型的时间戳,按照sdf指定的格式模板,转换为人类可读的日期时间字符串

强转long的 2 个核心原因
原因 1:从根源上规避整数溢出,是行业通用安全规范

如果不加强转,12*60*60*1000的所有操作数都是int,运算结果也是int。虽然 12 小时的毫秒数 43200000,刚好在int范围内,但这是非常脆弱的写法

  • 若后续修改数值(比如计算 30 天、100 天的毫秒数),30*24*60*60*1000=2592000000,已经超出int最大值,会直接溢出变成负数-1702967296,导致时间计算完全错误。

而把第一个数强转为(long)12后:

  • 第一个操作数变成long类型,后续所有乘法运算都会自动触发类型提升,全程以long类型运算,无论数值多大,都不会发生溢出。
  • 这是 Java 处理时间毫秒数的通用最佳实践,因为时间戳本身就是long类型,加减的数值也必须保证是long类型,从根源上避免 bug。
原因 2:和date.getTime()long类型匹配,避免隐式转换风险

date.getTime()返回的是long类型(64 位整数),如果减数是int类型,Java 会自动把int提升为long再做减法。

异常处理

  • Java语言具有如下的异常处理机制:当程序运行出现意外情形时,系统会自动生成一个异常对象来通知程序。
  • 在程序中,我们可以使用特定的语句来捕获异常对象,读取对象中的信息,进而做出处理。
  • 也可以使用特定的语句抛出异常对象,将这个异常对象交给程序的调用者处理。

异常的继承体系

- 所有的非正常情况被分为两类:

错误(Error)和异常(Exception),其中Error代表虚拟机相关问题,一般无法处理,也无需处理。

- 所有的 Exception 被分为两类
  • RuntimeException,代表运行时异常,程序可以显式处理这种异常,也可以不处理,而是交给顶层调用者统一处理。
  • 非运行时异常(Checked异常),程序必须显式地处理这种异常,否则在编译阶段会发生错误,导致程序无法通过编译。

捕获异常

语法:
try { 业务逻辑代码 } catch (AException e) { A异常的处理代码 } catch (BException e) { B异常的处理代码 } ... finally { 回收资源代码 }
说明:
1. 无论哪行代码发生异常,系统都会生成一个异常对象,这与try...catch...语句没有关系;

2. 若程序没有对这个异常对象做任何处理,则程序在此退出;

3. 创建异常对象后,JVM会寻找可以处理它的catch块,并将异常对象交给这个catch块去处理;

4. 程序应该先处理小异常、再处理大异常,即将处理父类异常的catch块放在处理子类异常的catch块之后;

5. finally块中代码总是会被执行,它必须位于try、catch之后,通常用来释放资源;

6. try是必须的,catch、finally是可选的,但catch、finally二者之中至少要出现一个。

声明抛出异常

语法:
throws ExceptionClass1, ExceptionClass2, ...
说明:
1. throws语句用于标识某方法可能抛出的异常,它必须位于方法签名之后;

2. throws语句声明抛出异常后,程序中旧无需使用try语句捕获该异常了;

3. 在重写时,子类方法声明抛出的异常类型不能比父类方法声明抛出的异常类型大。

抛出异常

语法:
throw ExceptionInstance;
说明:
1. throw语句用于在程序中主动抛出一个异常;

2. throw语句抛出的不是异常类型,而是一个异常实例;

3. 对于主动抛出的异常,也可以采用try块捕获,或者采用throws语句向外抛出。

异常的处理原则

1. 不要多度的使用异常:

不要用异常处理代替错误处理代码,不要用异常处理代替流程控制语句;

2. 不要忽略捕获的异常:

对于捕获到的异常,要进行合适的修复,对于不能处理的部分,应该抛出新的异常;

3. 不要直接捕获所有的异常:

应对不同的异常做出有针对性的处理,而捕获所有的异常,容易压制(丢失)异常;

4. 不要使用过于庞大的try块:

庞大的try块会导致业务过于复杂,不利于分析异常的原因,也不利于程序的阅读及维护。

JAVA37 判断学生成绩

import java.util.*; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int score = scanner.nextInt(); try{ //如果考试成绩在0-100之间,直接输出 if(score>=0&&score<=100){ System.out.println(score); } //否则抛异常 else{ throw new ScoreException("分数不合法"); } } //捕获到异常,输出错误信息 catch(ScoreException e){ System.out.println(e.getMessage()); } } } class ScoreException extends Exception{ //利用父类构造方法,初始化信息 ScoreException(String message){ super(message); } } 

getMessage():获取异常对象中携带的、自定义的异常详细描述文本

  • 当分数不合法时,new ScoreException("分数不合法") 会创建一个异常对象,把"分数不合法"通过构造方法,最终存到detailMessage里。
  • catch块捕获到这个异常对象,赋值给变量str
  • str.getMessage() 会读取异常对象里存储的detailMessage,也就是传入的"分数不合法",最终打印输出。
super(message) 的核心作用:“让父类帮忙初始化数据”

super 在这里的意思是 “父类的”,super(message) 就是 “调用父类中接收一个 String 参数的构造方法”。

public ScoreException(String message){ super(message); // 等价于:调用 Exception(String message) 这个构造方法 }
为什么必须写 super(message)?(不写会怎样?)

父类数据的封装性Throwable 里的 detailMessage 是一个 private(私有)变量。子类 ScoreException无权直接修改它。所以必须通过父类提供的 “构造方法入口”(即 super(message))来间接赋值。

如果不写,信息就丢了如果你只写 super()(不传参数),或者干脆不写 super(编译器会自动补一个无参的 super()),那么父类里的 detailMessage 就会是 null

super 关键字的两种常见用法

用法

示例

含义

1. 调用父类构造方法

super(message);

在子类构造方法的第一行调用,用于初始化父类的成员变量。

2. 调用父类的普通方法/变量

super.someMethod();

在子类方法中调用父类被重写(Override)的方法,或者访问父类的成员变量。

Read more

C++之动态数组vector

C++之动态数组vector

Vector * 一、什么是 `std::vector`? * 二、`std::vector` 的基本特性 * (一)动态扩展 * (二)随机访问 * (三)内存管理 * 三、`std::vector` 的基本操作 * (一)定义和初始化 * (二)添加和删除元素 * (三)访问元素 * (四)遍历 * (五)大小和容量 * 四、`std::vector` 的应用场景 * (一)动态数组 * (二)随机访问 * (三)内存管理 * 五、注意事项 * (一)性能优化 * (二)内存释放 * (三)异常安全 * 六、总结 在

By Ne0inhk
【收藏】15年Java老炮儿All in AI应用开发:2026年,会用AI的Java程序员才不会被淘汰

【收藏】15年Java老炮儿All in AI应用开发:2026年,会用AI的Java程序员才不会被淘汰

从2011年敲下第一行Java代码,到在微服务、高并发、分布式系统的战场里摸爬滚打整整15年,我曾笃定自己会沿着“稳扎稳打”的路线走到头——直到2025年底,我下定了一个绝不回头的决心:All in AI应用开发。 不是跟风转行做算法研究员,也不是追着AI风口炒概念、做表面功夫,而是把15年沉淀的工程化落地能力、系统架构思维,以及对接上千个业务场景的实战经验,全部锚定在AI大模型的应用层开发上。 为什么非要做这个选择?2026年的行业现实已经敲醒了所有人: AI不会取代程序员,但会用AI提效、用AI落地业务的程序员,正在快速取代只会写传统代码的程序员。 一、Java没死,只是要给它套上“AI新皮肤” 最近总能听到同行吐槽:Java不行了,岗位越来越少、薪资涨不动、新人都不愿学了…… 但拨开表象看本质:传统CRUD型Java开发岗位确实在萎缩,可“Java + AI”的复合型岗位正在呈爆发式增长——这一点,打开招聘平台搜“Java+AI”“大模型应用开发”就能直观感受到。 分享几个我近期接触到的真实大厂需求,更能说明问题: * 高德地图“扫街榜”

By Ne0inhk

c++调用OCR服务:使用libcurl发送POST请求获取识别结果

C++调用OCR服务:使用libcurl发送POST请求获取识别结果 📖 技术背景与问题提出 在现代信息处理系统中,光学字符识别(OCR) 已成为连接物理世界与数字世界的桥梁。无论是文档数字化、发票识别,还是智能客服中的图像理解,OCR 都扮演着关键角色。然而,许多轻量级 OCR 模型在面对复杂背景、模糊字体或中文手写体时表现不佳,导致识别准确率下降。 为解决这一问题,基于 CRNN(Convolutional Recurrent Neural Network) 的通用 OCR 服务应运而生。该服务采用经典的卷积+循环网络结构,在保持 CPU 可运行的前提下,显著提升了对中文文本的识别能力。同时,服务通过 Flask 提供了 RESTful API 接口,使得外部程序如 C++ 应用可以轻松集成。 本文将重点讲解如何在 C++ 环境下,利用 libcurl

By Ne0inhk
C++ 函数重载:规则、实现与实战案例

C++ 函数重载:规则、实现与实战案例

C++ 函数重载:规则、实现与实战案例 💡 学习目标:掌握函数重载的核心规则,能够熟练实现重载函数,并解决实际开发中重载相关的常见问题。 💡 学习重点:函数重载的匹配原则、与默认参数的冲突处理、实战场景中的重载应用。 一、函数重载的定义与核心价值 ✅ 结论:函数重载是 C++ 多态性的基础体现,允许同一作用域内定义多个同名函数,通过参数列表的差异区分调用。 函数重载的核心价值在于: 1. 简化函数命名,避免为功能相似的函数创建不同名称,提升代码可读性 2. 适配不同类型或数量的参数输入,让函数调用更灵活 ⚠️ 注意事项:函数返回值不能作为区分重载函数的依据。 例如以下代码是非法的: #include<iostream>usingnamespace std;// 非法重载:仅返回值不同intadd(int a,int b){return a + b;}doubleadd(int a,int

By Ne0inhk