Showing preview only (625K chars total). Download the full file or copy to clipboard to get everything.
Repository: joeljhou/geekyspace
Branch: master
Commit: 0e92c932f72c
Files: 107
Total size: 410.9 KB
Directory structure:
gitextract_4cg6voya/
├── .github/
│ └── workflows/
│ └── deploy-docs.yml
├── .gitignore
├── DirectoryV3.xml
├── README.md
├── package.json
└── src/
├── .vuepress/
│ ├── client.ts
│ ├── config/
│ │ └── docSearchLocales.ts
│ ├── config.ts
│ ├── path/
│ │ ├── navbar.ts
│ │ └── sidebar/
│ │ ├── index.ts
│ │ ├── installation-guide.ts
│ │ ├── java-datetime.ts
│ │ ├── java-features.ts
│ │ ├── java.ts
│ │ ├── jvm.ts
│ │ └── spring-framework.ts
│ ├── public/
│ │ ├── CNAME
│ │ └── special/
│ │ └── wedding-chenzhuo.html
│ ├── styles/
│ │ ├── config.scss
│ │ ├── index.scss
│ │ └── palette.scss
│ └── theme.ts
├── README.md
├── about-me.md
├── article.md
└── md/
├── blockchain/
│ └── README.md
├── database/
│ └── mysql/
│ ├── README.md
│ └── overview/
│ └── what-is-database.md
├── docker/
│ ├── install.md
│ ├── mirror-acceleration.md
│ ├── overview.md
│ └── top20-commands.md
├── flutter/
│ └── flutter-guide.md
├── idea-tips/
│ └── activation.md
├── installation-guide/
│ ├── README.md
│ ├── base-tools/
│ │ └── Homebrew.md
│ ├── dev-env/
│ │ ├── java/
│ │ │ └── SDKMAN.md
│ │ └── nodejs/
│ │ ├── Corepack.md
│ │ ├── nrm.md
│ │ └── nvm.md
│ └── os/
│ └── windows-office-activation.md
├── java/
│ ├── basic/
│ │ ├── java-basic-oop.md
│ │ ├── java-common-classes.md
│ │ └── java-from-scratch.md
│ ├── datetime/
│ │ ├── README.md
│ │ ├── api.md
│ │ ├── compare-dates.md
│ │ ├── convert-dates.md
│ │ ├── date-diff.md
│ │ ├── datetime.md
│ │ ├── locale.md
│ │ ├── timestamp.md
│ │ └── zoneddatetime-vs-offsetdatetime.md
│ ├── features/
│ │ ├── Java10/
│ │ │ └── jep286-local-variable-type-inference.md
│ │ ├── Java11/
│ │ │ └── jep320-remove-JavaEE-CORBA.md
│ │ ├── Java14/
│ │ │ └── jep361-switch-expressions.md
│ │ ├── Java15/
│ │ │ ├── jep371-hidden-classes.md
│ │ │ └── jep378-text-blocks.md
│ │ ├── Java16/
│ │ │ ├── jep394-pattern-matching-for-instanceof.md
│ │ │ └── jep395-records.md
│ │ ├── Java17/
│ │ │ ├── jep406-pattern-matching-for-switch-preview.md
│ │ │ └── jep409-sealed-classes.md
│ │ ├── Java18/
│ │ │ ├── jep400-utf8-by-default.md
│ │ │ ├── jep408-simple-web-server.md
│ │ │ └── jep413-code-snippets-in-api-documentation.md
│ │ ├── Java19/
│ │ │ └── java19-new-features-summary.md
│ │ ├── Java20/
│ │ │ └── java20-new-features-summary.md
│ │ ├── Java21/
│ │ │ ├── jep430-string-templates.md
│ │ │ ├── jep431-sequenced-collections.md
│ │ │ ├── jep439-generational-zgc.md
│ │ │ ├── jep440-record-partterns.md
│ │ │ ├── jep441-pattern-matching-for-switch.md
│ │ │ └── jep444-virtual-threads.md
│ │ ├── Java9/
│ │ │ ├── jep222-jshell.md
│ │ │ └── jep269-convenience-factory-methods-for-collections.md
│ │ └── README.md
│ ├── jvm/
│ │ ├── README.md
│ │ ├── part1/
│ │ │ ├── compile_jdk.md
│ │ │ └── overview.md
│ │ ├── part2/
│ │ │ ├── heap-object-flow.md
│ │ │ ├── runtime-data-areas.md
│ │ │ └── visual-tools/
│ │ │ └── visualvm.md
│ │ └── part3/
│ │ ├── bytecode-instructions-set.md
│ │ ├── class-file-structure.md
│ │ └── class-loading-mechanism.md
│ ├── kotlin/
│ │ └── kotlin-quick-for-java.md
│ └── thread/
│ └── thread-concurrency.md
├── spring-boot/
│ ├── README.md
│ └── quickstart.md
├── spring-data-jpa/
│ ├── README.md
│ └── jetbrains/
│ └── getting-started.md
├── spring-framework/
│ ├── core/
│ │ ├── README.md
│ │ ├── beans-definition.md
│ │ ├── beans-lifecycle.md
│ │ ├── beans-scope.md
│ │ ├── child-bean-definitions.md
│ │ ├── dependencies/
│ │ │ ├── README.md
│ │ │ ├── factory-autowire.md
│ │ │ ├── factory-collaborators.md
│ │ │ ├── factory-dependson.md
│ │ │ ├── factory-lazy-init.md
│ │ │ ├── factory-method-injection.md
│ │ │ └── factory-properties-detailed.md
│ │ └── ioc-container.md
│ └── overview/
│ ├── README.md
│ └── quickstart.md
└── template/
└── blog template.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/deploy-docs.yml
================================================
# 全局配置参考:https://vuejs.press/zh/guide/deployment.html
name: docs
on:
# push 到 master 分支时自动部署
push:
branches: [master]
# 允许手动触发
workflow_dispatch:
permissions:
contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# “最近更新时间” 等 git 日志相关信息,需要拉取全部提交记录
fetch-depth: 0
- name: 设置 pnpm
uses: pnpm/action-setup@v4
- name: 设置 Node.js
uses: actions/setup-node@v4
with:
# 选择要使用的 node 版本
node-version: 22
# 缓存 pnpm 依赖
cache: pnpm
- name: 安装依赖
run: pnpm install --frozen-lockfile
# 运行构建脚本
- name: 构建 VuePress 站点
env:
NODE_OPTIONS: --max_old_space_size=8192
run: |
pnpm docs:build
touch src/.vuepress/dist/.nojekyll
# 查看 workflow 的文档来获取更多信息
# @see https://github.com/crazy-max/ghaction-github-pages
- name: 部署到 GitHub Pages
uses: crazy-max/ghaction-github-pages@v4
with:
# 部署到 gh-pages 分支
target_branch: gh-pages
# 部署目录为 VuePress 的默认输出目录
build_dir: src/.vuepress/dist
env:
# @see https://docs.github.com/cn/actions/reference/authentication-in-a-workflow#about-the-github_token-secret
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .gitignore
================================================
/.idea/
/**/.obsidian/
node_modules/
src/.vuepress/.cache/
src/.vuepress/.temp/
src/.vuepress/dist/
.DS_Store
================================================
FILE: DirectoryV3.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<trees>
<tree path="/src/md/jvm/part2/basic-tools" title="基础故障处理工具"/>
<tree path="/src/md/jvm/part2/visual-tools" title="可视化故障处理工具"/>
</trees>
================================================
FILE: README.md
================================================
## 在线访问地址
https://www.geekyspace.cn/
## 博客效果图展示:
<img width="1440" alt="image" src="https://github.com/joeljhou/geekyspace/assets/45135095/ea9b9d85-28e6-425c-80a6-1b21643c8b9f">
<img width="1680" alt="image" src="https://github.com/joeljhou/geekyspace/assets/45135095/4156eefa-737b-4968-aadd-e93dfb2201f2">
<img width="1680" alt="image" src="https://github.com/joeljhou/geekyspace/assets/45135095/3f318c5d-b689-4546-8914-c3c97d57180f">
<img width="1680" alt="image" src="https://github.com/joeljhou/geekyspace/assets/45135095/5466e458-615b-4bac-9ff3-0daf28fad76b">
<img width="1680" alt="image" src="https://github.com/joeljhou/geekyspace/assets/45135095/b1fc78ed-eb7d-4744-a50d-cfa24b338b0f">
<img width="1680" alt="image" src="https://github.com/joeljhou/geekyspace/assets/45135095/da2646f8-4ea3-4908-a322-4a8ade7f69a4">
## 项目介绍
本项目是一个基于VuePress的个人博客项目,主要用于记录个人的学习和工作经验,以及一些技术分享。
## 代码仓库地址
https://github.com/joeljhou/geekyspace/
================================================
FILE: package.json
================================================
{
"name": "vuepress-theme-hope-template",
"version": "2.0.0",
"description": "A project of vuepress-theme-hope",
"license": "MIT",
"type": "module",
"scripts": {
"docs:build": "vuepress-vite build src",
"docs:clean-dev": "vuepress-vite dev src --clean-cache",
"docs:dev": "vuepress-vite dev src",
"docs:dedupe": "pnpm dedupe",
"docs:update-package": "pnpm dlx vp-update"
},
"devDependencies": {
"@vuepress/bundler-vite": "2.0.0-rc.9",
"@vuepress/plugin-copyright": "2.0.0-rc.21",
"@vuepress/plugin-docsearch": "2.0.0-rc.21",
"@vuepress/plugin-feed": "2.0.0-rc.21",
"@vuepress/plugin-google-analytics": "2.0.0-rc.21",
"@vuepress/plugin-redirect": "2.0.0-rc.21",
"mermaid": "^11.4.1",
"vue": "^3.4.27",
"vuepress": "2.0.0-rc.9",
"vuepress-plugin-comment2": "2.0.0-rc.30",
"vuepress-theme-hope": "2.0.0-rc.32"
},
"packageManager": "pnpm@10.6.3+sha512.bb45e34d50a9a76e858a95837301bfb6bd6d35aea2c5d52094fa497a467c43f5c440103ce2511e9e0a2f89c3d6071baac3358fc68ac6fb75e2ceb3d2736065e6"
}
================================================
FILE: src/.vuepress/client.ts
================================================
// client.ts ---> 客户端配置文件
// @ts-ignore
import {defineGiscusConfig} from 'vuepress-plugin-comment2/client'
// @ts-ignore
import {defineClientConfig} from "vuepress/client";
/**
* // 设置评论插件Giscus客户端选项:https://giscus.app/zh-CN
*/
defineGiscusConfig({
repo: 'joeljhou/geekyspace',
repoId: 'R_kgDOK4fo4g',
category: 'Announcements',
categoryId: 'DIC_kwDOK4fo4s4Cd4Y9',
mapping: 'title'
})
export default defineClientConfig({
// 解决百度统计单页面应用无法统计的问题
enhance({app, router, siteData}) {
router.beforeEach((to, from, next) => {
// @ts-ignore
if (typeof _hmt != "undefined") {
if (to.path && to.fullPath !== from.fullPath) {
// @ts-ignore
_hmt.push(["_trackPageview", to.fullPath]);
}
}
next();
});
},
setup() {
},
rootComponents: [],
})
================================================
FILE: src/.vuepress/config/docSearchLocales.ts
================================================
export const docSearchLocales = {
placeholder: "搜索geekyspace.cn的文档",
translations: {
button: {
buttonText: "",
buttonAriaLabel: "",
},
modal: {
searchBox: {
resetButtonTitle: "清除查询条件",
resetButtonAriaLabel: "清除查询条件",
cancelButtonText: "取消",
cancelButtonAriaLabel: "取消",
},
startScreen: {
recentSearchesTitle: "搜索历史",
noRecentSearchesText: "最近没有搜索",
saveRecentSearchButtonTitle: "保存至搜索历史",
removeRecentSearchButtonTitle: "从搜索历史中移除",
favoriteSearchesTitle: "收藏",
removeFavoriteSearchButtonTitle: "从收藏中移除",
},
errorScreen: {
titleText: "无法获取结果",
helpText: "你可能需要检查你的网络连接",
},
footer: {
selectText: "选择",
navigateText: "导航",
closeText: "关闭",
searchByText: "搜索",
},
noResultsScreen: {
noResultsText: "无法找到相关结果",
suggestedQueryText: "你可以尝试查询",
reportMissingResultsText: "你认为该查询应该有结果?",
reportMissingResultsLinkText: "点击反馈",
},
},
},
};
================================================
FILE: src/.vuepress/config.ts
================================================
// config.ts ---> 配置文件
import {defineUserConfig} from "vuepress";
import {redirectPlugin} from '@vuepress/plugin-redirect';
import {docsearchPlugin} from "@vuepress/plugin-docsearch";
import {googleAnalyticsPlugin} from '@vuepress/plugin-google-analytics';
import {commentPlugin} from "vuepress-plugin-comment2";
import {docSearchLocales} from "./config/docSearchLocales";
import theme from "./theme.js";
export default defineUserConfig({
base: "/",
lang: "zh-CN",
theme,
plugins: [
// 设置重定向
redirectPlugin({
config: {},
}),
// 搜索插件
docsearchPlugin({
appId: "PTKSWUU4JQ",
apiKey: "8cf4dc036ad5f140f40d1d97e178b0b4",
indexName: "geekyspace",
locales: {"/": docSearchLocales},
injectStyles: true
}),
// 设置谷歌分析
googleAnalyticsPlugin({
id: "G-3L19EZ1HH8",
debug: false,
}),
// 设置评论插件
commentPlugin({
// 插件选项:Artalk | Giscus | Waline | Twikoo
provider: "Giscus",
}),
],
// Enable it with pwa
// shouldPrefetch: false,
head: [
// 添加百度统计代码
[
"script",
{},
`
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?c3b455c45c9c9b349e7d28e7e13e950f";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
`
],
// 添加Google AdSense广告位
[
"script",
{
async: true,
src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3218450089809357",
crossorigin: "anonymous"
}
]
],
});
================================================
FILE: src/.vuepress/path/navbar.ts
================================================
import {navbar} from "vuepress-theme-hope";
export default navbar([
{text: "首页", icon: "home", link: "/"},
{text: "时间轴", icon: "list", link: "timeline/"},
{
text: "Java", icon: "java", children: [
{
text: "Java 基础", children:[
{text: "快速入门", icon: "java", link: "md/java/basic/java-from-scratch"},
{text: "面向对象编程(OOP)", icon: "java", link: "md/java/basic/java-basic-oop"},
],
},
{
text: "文章", children:[
{text: "Java 多线程与并发", icon: "thread", link: "md/java/thread/thread-concurrency"},
{text: "Java 程序员快速掌握 Kotlin", icon: "kotlin", link: "md/java/kotlin/kotlin-quick-for-java"},
],
},
{
text: "专栏", children:[
{text: "Java日期时间", icon: "java", link: "md/java/datetime/"},
{text: "Java新版本特性", icon: "java", link: "md/java/features/"},
{text: "深入理解Java虚拟机", icon: "jvm-xx", link: "md/java/jvm/"},
],
},
]
},
{
text: "DataBase", icon: "database", children: [
{
text: "专栏", children:[
{text: "MySQL必知必会", icon: "mysql", link: "md/database/mysql/"},
],
},
]
},
{
text: "Spring", icon: "spring", children: [
{text: "Spring 框架", icon: "spring", link: "md/spring-framework/core/"},
// {text: "Spring Boot 教程", icon: "spring", link: "md/spring-boot/"},
{text: "Spring Data JPA", icon: "spring", link: "md/spring-data-jpa/jetbrains/getting-started"},
]
},
{text: "安装大全", icon: "launch", link: "md/installation-guide/"},
{
text: "玩转IDEA", icon: "intellij-idea", prefix: "md/idea-tips/", children: [
{
text: "IDEA 教程",
icon: "intellij-idea",
link: "https://www.jetbrains.com/help/idea/getting-started.html"
},
{text: "正版激活码", icon: "intellij-idea", link: "activation"},
]
},
{text: "文库汇总", icon: "article", link: "article.html"},
]);
================================================
FILE: src/.vuepress/path/sidebar/index.ts
================================================
import {sidebar} from "vuepress-theme-hope";
import {java} from "./java.js";
import {springFramework} from "./spring-framework"
import {installationGuide} from "./installation-guide";
// 专栏
import {javaDatetime} from "./java-datetime";
import {javaFeatures} from "./java-features.js";
import {jvm} from "./jvm.js";
export default sidebar({
"/md/java/": java, // 1.Java
"/md/java/datetime/": javaDatetime, // 专栏:Java日期时间
"/md/java/features/": javaFeatures, // 专栏:Java新特性
"/md/java/jvm/": jvm, // 专栏:深入理解Java虚拟机
"/md/database/mysql/": [
{text: "总目录", prefix: "/md/database/mysql/", link: "/md/database/mysql/",},
{
text: "概述", prefix: "overview/", link: "overview/",
children: [
{text: "什么是数据库?", link: "what-is-database"},
],
},
],
"/md/spring-framework/": springFramework, // Spring框架
// "/md/spring-boot/": [ // SpringBoot框架
// {text: "总目录", prefix: "/md/spring-boot/", link: "/md/spring-boot/"},
// {
// text: "快速入门", children: [
// {text: "Spring Boot 入门", link: "quickstart"}
// ]
// },
// ],
"/md/spring-data-jpa/": [
{text: "总目录", prefix: "/md/spring-data-jpa/", link: "/md/spring-data-jpa/"},
{text: "快速入门", prefix: "/md/jetbrains/", link: "jetbrains/getting-started"},
],
"/md/installation-guide/": installationGuide,
"/md/docker/": [
{text: "概述", prefix: "/md/docker/overview", link: "/md/docker/overview"},
{text: "安装指南", prefix: "/md/docker/install", link: "/md/docker/install"},
{text: "镜像加速器", prefix: "/md/docker/mirror-acceleration", link: "/md/docker/mirror-acceleration"},
{text: "Top20常用命令", prefix: "/md/docker/top20-commands", link: "/md/docker/top20-commands"},
],
});
================================================
FILE: src/.vuepress/path/sidebar/installation-guide.ts
================================================
import {arraySidebar} from "vuepress-theme-hope";
export const installationGuide = arraySidebar([
{text: "开发者安装大全", prefix: "/md/installation-guide/", link: "/md/installation-guide/"},
{
text: "操作系统", prefix: "os/", children: [
{text: "Windows、Office激活", link: "windows-office-activation"},
],
},
{
text: "常用工具", prefix: "base-tools/", children: [
{text: "Homebrew", link: "Homebrew"},
],
},
{
text: "开发环境", prefix: "dev-env/", children: [
{
text: "Java", prefix: "java/", link: "java/",
collapsible: false,
children: [
{text: "SDKMAN", link: "SDKMAN"},
]
},
{
text: "Nodejs", prefix: "nodejs/", link: "nodejs/",
collapsible: false,
children: [
{text: "nvm", link: "nvm"},
{text: "nrm", link: "nrm"},
{text: "Corepack", link: "Corepack"},
]
},
],
},
]);
================================================
FILE: src/.vuepress/path/sidebar/java-datetime.ts
================================================
import {arraySidebar} from "vuepress-theme-hope";
export const javaDatetime = arraySidebar([
{text: "总目录", prefix: "/md/java/datetime/", link: "/md/java/datetime/",},
{text: "API", prefix: "/md/java/datetime/api", link: "/md/java/datetime/api",},
{
text: "1.获取当前日期和时间",
children: [
{text: "当前日期和时间", link: "datetime"},
{text: "当前时间戳", link: "timestamp"},
{text: "当前区域设置/国际化", link: "locale"},
],
},
{
text: "2.比较日期和时间",
children: [
{text: "日期比较", link: "compare-dates"},
{text: "时区与偏移量的区别", link: "zoneddatetime-vs-offsetdatetime"},
],
},
{
text: "3.转换日期和时间",
children: [
{text: "转换日期时间实例", link: "convert-dates"},
],
},
{
text: "6.日期和时间提取与处理",
children: [
{text: "日期时间差", link: "date-diff"},
],
},
]
);
================================================
FILE: src/.vuepress/path/sidebar/java-features.ts
================================================
import {arraySidebar} from "vuepress-theme-hope";
export const javaFeatures = arraySidebar([
{text: "总目录", prefix: "/md/java/features/", link: "/md/java/features/",},
{
text: "Java 21", prefix: "Java21/", link: "Java21/",
children: [
{text: "字符串模版(Preview)", link: "jep430-string-templates"},
{text: "有序集合", link: "jep431-sequenced-collections"},
{text: "分代ZGC", link: "jep439-generational-zgc"},
{text: "记录模式", link: "jep440-record-partterns"},
{text: "switch模式匹配", link: "jep441-pattern-matching-for-switch"},
{text: "虚拟线程", link: "jep444-virtual-threads"},
],
},
{
text: "Java 20", prefix: "Java20/", link: "Java20/",
children: [
{text: "新特性总结", link: "java20-new-features-summary"},
],
},
{
text: "Java 19", prefix: "Java19/", link: "Java19/",
children: [
{text: "新特性总结", link: "java19-new-features-summary"},
],
},
{
text: "Java 18", prefix: "Java18/", link: "Java18/",
children: [
{text: "指定UTF-8为默认字符集", link: "jep400-utf8-by-default"},
{text: "简单Web服务器", link: "jep408-simple-web-server"},
{text: "新增@snipppet标签", link: "jep413-code-snippets-in-api-documentation"},
],
},
{
text: "Java 17", prefix: "Java17/", link: "Java17/",
children: [
{text: "switch模式匹配(Preview)", link: "jep406-pattern-matching-for-switch-preview"},
{text: "sealed类", link: "jep409-sealed-classes"},
],
},
{
text: "Java 16", prefix: "Java16/", link: "Java16/",
children: [
{text: "instanceof模式匹配", link: "jep394-pattern-matching-for-instanceof"},
{text: "record类", link: "jep395-records"},
],
},
{
text: "Java 15", prefix: "Java15/", link: "Java15/",
children: [
{text: "隐藏类(Hidden Classes)", link: "jep371-hidden-classes"},
{text: "文本块(Text Blocks)", link: "jep378-text-blocks"},
],
},
{
text: "Java 14", prefix: "Java14/", link: "Java14/",
children: [
{text: "switch表达式增强", link: "jep361-switch-expressions"},
],
},
{
text: "Java 11", prefix: "Java11/", link: "Java11/",
children: [
{text: "移除JavaEE和CORBA模块", link: "jep320-remove-JavaEE-CORBA"},
],
},
{
text: "Java 10", prefix: "Java10/", link: "Java10/",
children: [
{text: "局部变量类型推断", link: "jep286-local-variable-type-inference"},
],
},
{
text: "Java 9", prefix: "Java9/", link: "Java9/",
children: [
{text: "交互式编程环境JShell", link: "jep222-jshell"},
{text: "不可变集合的快捷创建方法", link: "jep269-convenience-factory-methods-for-collections"},
],
}
]
);
================================================
FILE: src/.vuepress/path/sidebar/java.ts
================================================
import {arraySidebar} from "vuepress-theme-hope";
export const java = arraySidebar([
{
text: "Java 基础", prefix: "basic/", /*link: "basic/",*/
children: [
{text: "快速入门", link: "java-from-scratch"},
{text: "面向对象编程(OOP)", link: "java-basic-oop"},
{text: "常用类与工具", link: "java-common-classes"},
],
},
{
text: "文章",
children: [
{text: "Java 多线程与并发", icon: "thread", link: "thread/thread-concurrency"},
{text: "Java 程序员快速掌握 Kotlin", icon: "kotlin", link: "kotlin/kotlin-quick-for-java"},
],
},
{
text: "专栏",
children: [
{text: "Java 日期时间", icon: "java", link: "datetime/"},
{text: "Java 新版本特性", icon: "java", link: "features/"},
{text: "深入理解Java虚拟机", icon: "jvm-xx", link: "jvm/"},
],
},
]
);
================================================
FILE: src/.vuepress/path/sidebar/jvm.ts
================================================
import {arraySidebar} from "vuepress-theme-hope";
export const jvm = arraySidebar([
{text: "总目录", prefix: "/md/java/jvm/", link: "/md/java/jvm/",},
{
text: "走近Java", prefix: "part1/", link: "part1/",
children: [
{text: "JVM概述", link: "overview"},
{text: "编译JDK", link: "compile_jdk"},
],
},
{
text: "自动内存管理", prefix: "part2/", link: "part2/",
children: [
{text: "运行时数据区", link: "runtime-data-areas"},
{text: "对象分配过程", link: "heap-object-flow"},
{
text: "基础故障处理工具", prefix: "basic-tools/", link: "basic-tools/",
collapsible: true,
children: [
// {text: "依赖注入", link: "factory-collaborators"}
]
},
{
text: "可视化故障处理工具", prefix: "visual-tools/", link: "visual-tools/",
collapsible: true,
children: [
{text: "VisualVM介绍", link: "visualvm"}
]
},
],
},
{
text: "虚拟机执行子系统", prefix: "part3/", link: "part3/",
children: [
{text: "类文件结构", link: "class-file-structure"},
{text: "字节码指令集", link: "bytecode-instructions-set"},
{text: "类加载机制", link: "class-loading-mechanism"},
],
},
{
text: "程序编译与代码优化", prefix: "part4/", link: "part4/",
children: [],
},
{
text: "高效并发", prefix: "part5/", link: "part5/",
children: [],
},
]
);
================================================
FILE: src/.vuepress/path/sidebar/spring-framework.ts
================================================
import {arraySidebar} from "vuepress-theme-hope";
export const springFramework = arraySidebar([
{
text: "概述", collapsible: true, prefix: "overview/", link: "overview/",
children: [{text: "快速开始", link: "quickstart"}]
},
{
text: "核心技术", collapsible: true, prefix: "core/", link: "core/",
children: [
{text: "IoC容器", link: "ioc-container"},
{text: "Bean定义", link: "beans-definition"},
{
text: "依赖", prefix: "dependencies/", link: "dependencies/",
collapsible: true,
children: [
{text: "依赖注入", link: "factory-collaborators"},
{text: "依赖和配置详解", link: "factory-properties-detailed"},
{text: "使用depends-on", link: "factory-dependson"},
{text: "懒加载Bean", link: "factory-lazy-init"},
{text: "自动装配协作者", link: "factory-autowire"},
{text: "方法注入", link: "factory-method-injection"},
]
},
{text: "Bean作用域", link: "beans-scope"},
{text: "Bean生命周期", link: "beans-lifecycle"},
{text: "Bean定义继承", link: "child-bean-definitions"},
]
},
]
);
================================================
FILE: src/.vuepress/public/CNAME
================================================
www.geekyspace.cn
================================================
FILE: src/.vuepress/public/special/wedding-chenzhuo.html
================================================
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新婚快乐</title>
<style>
body {
font-family: "Arial", sans-serif;
text-align: center;
background: #fff7f0;
padding: 20px;
}
.card {
background: #fffbf5;
border-radius: 12px;
padding: 30px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
display: inline-block;
max-width: 500px;
}
h1 {
color: #d81e06;
font-size: 28px;
}
.heart {
color: #ff4d4f;
font-size: 24px;
}
p {
font-size: 18px;
color: #444;
line-height: 1.8;
}
.highlight {
color: #d81e06;
font-weight: bold;
}
.footer {
margin-top: 20px;
font-size: 16px;
color: #888;
}
</style>
</head>
<body>
<div class="card">
<h1>🎉🎊 囍 新婚快乐 囍 🎊🎉</h1>
<p>亲爱的 <span class="highlight">卓哥</span>,</p>
<p>今天是你人生中最重要的日子之一,<br>从懵懂少年到如今的新郎官,<br>见证你的成长,真的由衷替你高兴!🎉</p>
<p>愿你与 <span class="highlight">伟娜</span> 携手同行,相知相守,<br>往后余生,岁月温柔,爱情长存 💕💕</p>
<p class="heart">💖 祝你们百年好合,白头偕老!💖</p>
<p class="footer">—— 来自最好兄弟的祝福 ✨</p>
</div>
</body>
</html>
================================================
FILE: src/.vuepress/styles/config.scss
================================================
// 你可以在这里更改配置 https://theme-hope.vuejs.press/zh/config/style.html
/* Content Class */
$content-class: ".theme-hope-content";
/* responsive breakpoints */
// wide screen
$pc: 1440px !default;
// desktop
$laptop: 1280px !default;
// narrow desktop / iPad
$pad: 959px !default;
// wide mobile
$tablet: 719px !default;
// narrow mobile
$mobile: 419px !default;
/* Color list */
$colors: #cf1322, #fa541c, #f39c12, #2ecc71, #25a55b, #10a5a5, #096dd9, #aa6fe9,
#eb2f96 !default;
/* Code Block */
// only available with shiki highlighter
$code-color: (
light: #383a42,
dark: #abb2bf,
) !default;
$code-bg-color: (
light: #ecf4fa,
dark: #282c34,
) !default;
================================================
FILE: src/.vuepress/styles/index.scss
================================================
// fix:解决新版Chrome字体加粗
body {
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-size: 16px;
}
// 导航栏
#navbar {
border-bottom: 1px solid var(--border-color);
// 去掉父级标题“文本转换为大写字母”
.dropdown-subtitle {
text-transform: none;
}
}
// 侧边栏
#sidebar {
border-right: 1px solid var(--border-color);
font-size: 0.86em;
scrollbar-color: var(--border-color);
//padding-inline-start: 0;
// 父级目录字体加粗
.vp-sidebar-title {
font-weight: 700;
}
}
// 设置博客上边距
.blog-page-wrapper {
margin-top: 20px;
}
/**
* ========== Markdown 样式 ==========
*/
// 修改 > 块引用 样式
html[data-theme] blockquote {
border-left: 4px solid var(--theme-color-dark);
padding: 10px 15px;
color: var(--text-color);
background-color: var(--theme-color-mask);
}
// 修改 `标记` 样式
html[data-theme] mark {
border-radius: 2px;
padding: 2px 4px;
margin: 0 2px;
font-weight: 500;
color: var(--text-color);
background-color: var(--theme-color-mask);
}
// 修改 “表格” 样式
table {
// 默认情况下,“表格” 宽度不会占满整个屏幕,这里设置为 100%
display: inline-table;
//width: 100%;
border-radius: 1px;
margin: 0;
th {
text-align: left;
color: #fff;
background-color: var(--theme-color-dark);
}
tr:nth-child(odd) {
background-color: var(--theme-color-mask);
}
// 鼠标悬停时改变行颜色
tr:hover {
color: var(--theme-color);
html[data-theme=light] & {
background-color: #ebebeb;
}
html[data-theme=dark] & {
background-color: #30363d;
}
}
// 去除“表格”的边框,看起来更加美观
thead, tbody, tfoot, tr, td, th {
border-width: 0 0 1px 0;
}
}
// 视觉优化 “夜间模式”
html[data-theme=dark] {
--bg-color: #22272e; /*页面背景颜色*/
--navbar-bg-color: #22272e; /*导航栏背景颜色*/
--sidebar-bg-color: #22272e; /*侧边栏背景颜色*/
--bg-color-back: #22272e; /*首页页背景颜色*/
--bg-color-float: #2b313a; /*首页卡片背景颜色*/
--text-color: #e6edf3; /*页面字体颜色*/
--grey3: #e6edf3; /*首页项目卡片字体颜色*/
--dark-grey: #e6edf3; /*图标文字颜色*/
--light-grey: #e6edf3; /*图标文字颜色*/
}
html[data-theme=light] {
//--dark-grey: #2c3e50; /*图标文字颜色*/
--light-grey: #2c3e50; /*图标文字颜色*/
}
// 夜间模式下降低图片亮度
html[data-theme="dark"] img {
filter: brightness(0.7); /* 适当降低亮度 */
transition: filter 0.3s ease-in-out;
}
// 将博主信息移动至文章列表的左侧
@import "vuepress-theme-hope/presets/left-blog-info.scss";
================================================
FILE: src/.vuepress/styles/palette.scss
================================================
// 设置默认主题色
$theme-color: #3eaf7c;
// 主题色选择器
$theme-colors: #2196f3, #a266f3, #e04c8a, #fb9b5f;
================================================
FILE: src/.vuepress/theme.ts
================================================
import {hopeTheme} from "vuepress-theme-hope";
import navbar from "./path/navbar.js";
import sidebar from "./path/sidebar";
export default hopeTheme({
/**
* 信息选项
*/
// 站点图标
favicon: "/images/system/geeky.png",
// 全局默认作者
author: {
name: "流浪码客",
url: "https://github.com/joeljhou",
email: "joeljhou336@gmail.com"
},
// 全局默认协议
license: "MIT",
// 网站部署域名
hostname: "https://www.geekyspace.cn",
/**
* 外观选项
*/
// 深色模式支持选项 (switch:默认)
darkmode: "toggle",
/**
* 导航栏本地选项
*/
navbar,
// 导航栏标题
// navTitle: "极客空间",
// 导航栏图标
logo: "/images/system/geeky.png",
// logoDark: "/images/system/geeky_zh.png",
// 全屏按钮
fullscreen: false,
// 字体图标资源链接(阿里巴巴iconfont矢量图标:https://www.iconfont.cn/)
iconAssets: "//at.alicdn.com/t/c/font_4370612_ke2l7xy0pf.css",
// 页面显示信息:作者、原创、分类、日期、标签、阅读时间、字数、阅读量
// "Author", "Original", "Category", "Date", "Tag", "ReadingTime", "Word", "PageView"
pageInfo: ["Author", "Original", "Date", "Category", "Tag", "ReadingTime"],
// 是否在向下滚动时自动隐藏导航栏 "always" | "mobile" | "none"
navbarAutoHide: "mobile",
// 导航栏布局设置
navbarLayout: {
start: ["Brand"],
center: ["Links"],
end: ["Repo", "Outlook", "Search"],
},
// 是否在移动视图下隐藏站点名称
hideSiteNameOnMobile: false,
/**
* 侧边栏本地选项
*/
sidebar,
// 是否在侧边栏显示图标
sidebarIcon: true,
// 侧边栏和页面目录的标题深度, 默认值为 2
headerDepth: 2,
/**
* 页脚选项
*/
footer: "© 2023 - 至今 <a href=\"https://www.geekyspace.cn\" target=\"_blank\">www.geekyspace.cn</a> 保留所有权利",
// 默认的版权信息,设置为 false 来默认禁用它
copyright: "Copyright © 2026 流浪码客",
// 是否默认显示页脚
displayFooter: true,
/**
* 功能区域设置选项
*/
// 博客功能配置
blog: {
avatar: "/images/personal/geekyspace.png",
description: "流浪码客,分享技术,品味人生",
intro: "/about-me.html",
medias: {
GitHub: "https://github.com/joeljhou",
Gitee: "https://gitee.com/joeljhou",
BiliBili: "https://space.bilibili.com/3546587190004175",
CSDN: [
"https://blog.csdn.net/qq_40174960?type=blog",
"<svg t=\"1659342659217\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"2038\" width=\"200\" height=\"200\"><path d=\"M512 1024C229.2224 1024 0 794.7776 0 512 0 229.2224 229.2224 0 512 0c282.7776 0 512 229.2224 512 512 0 282.7776-229.2224 512-512 512z m17.066667-413.525333c34.850133 4.352 68.778667 5.12 102.741333 2.0992 23.04-2.048 44.817067-8.362667 64.170667-21.9136 38.212267-26.794667 49.783467-85.1968 24.251733-123.050667-14.626133-21.7088-36.8128-30.344533-60.757333-35.498667-35.054933-7.543467-70.4512-5.751467-105.847467-3.413333-5.666133 0.3584-6.7584 3.072-7.236267 8.209067-3.072 32.682667-6.536533 65.314133-9.813333 97.962666-2.5088 24.814933-4.932267 49.629867-7.509333 75.605334z m53.4016-33.928534c1.962667-20.906667 3.6352-39.338667 5.4272-57.770666 1.553067-15.906133 3.413333-31.778133 4.727466-47.701334 0.3584-4.283733 1.553067-6.656 5.956267-6.382933 15.616 1.041067 31.709867 0.034133 46.728533 3.652267 36.488533 8.823467 48.725333 54.306133 23.3472 83.029333-15.8208 17.902933-36.7616 23.586133-59.255466 25.088-8.465067 0.546133-17.015467 0.085333-26.9312 0.085333zM512 434.295467c-2.184533-0.648533-3.5328-1.1776-4.932267-1.4336-37.717333-6.877867-75.690667-8.328533-113.646933-2.816-20.974933 3.037867-41.0112 9.489067-57.480533 23.330133-22.9888 19.319467-21.640533 46.848 4.4032 62.0032 13.056 7.594667 28.023467 12.509867 42.5984 17.288533 14.08 4.608 28.996267 6.826667 43.144533 11.264 12.5952 3.925333 14.011733 14.318933 3.584 22.306134-3.345067 2.56-7.441067 5.085867-11.537067 5.751466-11.195733 1.826133-22.698667 4.386133-33.826133 3.566934-24.098133-1.774933-48.042667-5.461333-72.5504-8.430934-1.365333 10.615467-2.935467 23.0912-4.5568 35.9424 4.181333 1.365333 7.68 2.730667 11.264 3.618134 33.9456 8.4992 68.386133 9.608533 102.912 5.12 20.087467-2.6112 39.4752-7.901867 56.695467-19.029334 28.603733-18.4832 36.693333-57.1904-4.676267-75.383466-14.506667-6.382933-30.190933-10.410667-45.482667-15.086934-11.4176-3.4816-23.313067-5.614933-34.525866-9.5232-9.7792-3.413333-11.144533-12.202667-3.037867-18.397866 4.6592-3.549867 10.717867-6.997333 16.384-7.3728a480.853333 480.853333 0 0 1 53.384533-0.853334c15.377067 0.699733 30.651733 3.549867 46.4896 5.5296L512 434.295467z m257.143467 2.048L750.933333 614.2976h54.152534c4.778667-45.636267 9.710933-90.7264 14.062933-135.8848 0.6144-6.365867 2.3552-8.840533 8.686933-9.0112 11.434667-0.273067 22.8864-1.979733 34.286934-1.570133 23.722667 0.853333 42.3936 9.728 38.4 43.264-2.901333 24.2688-5.597867 48.571733-8.2432 72.874666-1.092267 10.069333-1.826133 20.189867-2.730667 30.4128h55.330133c3.584-35.259733 7.9872-70.058667 10.496-104.994133 3.413333-47.4624-17.7664-73.3184-64.682666-80.213333-40.96-6.007467-81.339733-0.341333-121.5488 7.133866z m-483.498667 134.6048c-8.738133 1.297067-16.384 2.798933-24.098133 3.4816-25.6512 2.235733-51.319467 3.9424-76.305067-4.266667-13.909333-4.590933-24.6784-12.578133-29.7984-25.9584-7.901867-20.701867 0.887467-47.104 19.831467-60.3136 17.373867-12.117333 37.717333-15.9232 58.453333-15.9232 22.545067-0.017067 45.090133 2.423467 68.232533 3.84L307.2 432.298667c-15.069867-1.723733-29.4912-3.925333-43.997867-4.9152-41.0112-2.798933-80.64 2.6112-117.469866 20.462933-30.020267 14.557867-52.053333 36.010667-58.6752 68.130133-7.850667 38.144 11.537067 69.495467 51.7632 85.845334 19.1488 7.765333 39.287467 12.509867 60.0064 12.5952 24.746667 0.1024 49.493333-1.570133 74.205866-2.952534 3.106133-0.170667 8.311467-2.901333 8.669867-5.034666 1.979733-11.554133 2.730667-23.278933 3.9424-35.464534z\" fill=\"#DD1700\" p-id=\"2039\"></path></svg>"
],
Bokeyuan: [
"https://www.cnblogs.com/geekyspace",
"<svg t=\"1659342381548\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"1786\" width=\"200\" height=\"200\"><path d=\"M475.129328 466.27877 466.135508 466.27877l0 106.727553-23.384547 0L442.750961 466.27877l-10.193133 0 0-4.79725 10.193133 0 0-31.179054L466.135508 430.302466l0 31.179054 8.99382 0L475.129328 466.27877zM576.460999 536.430363 565.068553 536.430363l0 17.98764c0 12.386073-6.800879 18.587297-20.386265 18.587297-15.196067 0-28.180773-3.803622-38.973562-11.392445-2.398625-1.601471-3.597937-2.604309-3.597937-2.998281 0.393972-0.80534 1.995443-0.599656 4.79725 0.599656 6.389511 1.199312 14.184019 1.798969 23.384547 1.798969 7.194852 0.393972 10.587105-3.597937 10.193133-11.992101l0-12.591758-70.152616 0 0-5.395883 70.152616 0 0-8.99382 7.794508 0 0-13.79107-11.392445 0 0 17.387984-23.384547 0 0-17.387984-11.392445 0 0 17.387984-22.78489 0 0-65.955023 22.78489 0 0 6.595195c1.199312-3.990886 4.993724-6.193037 11.392445-6.595195l0-8.394164-38.373906 0 0-5.395883 38.373906 0 0-15.589015 23.384547 0 0 15.589015 13.191414 0c-4.79725-0.796131-7.794508-4.79725-8.99382-11.992101l18.587297 0c2.792597 6.398721 5.593381 10.398817 8.394164 11.992101l8.394164 0 0 5.395883-39.573218 0 0 8.394164 14.989359 0c13.584363-0.393972 20.180581 4.79725 19.786609 15.589015l0 50.366007-6.595195 0 0 5.395883 11.392445 0L576.460999 536.430363zM484.722804 538.828988l27.581117 0c4.394068 8.000192 10.792789 13.593572 19.186953 16.788328-15.196067 0.403182-24.986018 0-29.380086-1.199312-4.79725-0.393972-8.19769-2.192941-10.193133-5.395883-1.199312-1.199312-2.398625-2.792597-3.597937-4.79725C486.718248 542.229428 485.518935 540.431483 484.722804 538.828988zM502.110789 468.676372l0 13.191414 11.392445 0 0-17.387984-2.998281 0C506.908039 464.479802 504.106232 465.884798 502.110789 468.676372zM502.110789 487.263669l0 14.989359 11.392445 0 0-14.989359L502.110789 487.263669zM539.285382 464.479802l-2.398625 0 0 17.387984 11.392445 0 0-8.99382C548.673174 466.878427 545.675916 464.08583 539.285382 464.479802zM536.88778 487.263669l0 14.989359 11.392445 0 0-14.989359L536.88778 487.263669zM613.635592 474.073278l-23.984203 0 0-30.579398 23.984203 0 0 13.191414c1.995443-8.788136 9.593476-12.984706 22.78489-12.591758l7.794508 0 0-13.79107 28.180773 0 0 13.79107 28.780429 0c18.381613-0.393972 26.981461 4.403278 25.782148 14.390726l0 4.79725c0 4.000096-0.599656 7.598033-1.798969 10.792789l-16.788328 0c-0.403182 3.203965-1.601471 5.60259-3.597937 7.194852-8.000192 5.995539-16.788328 11.598129-26.381804 16.788328 3.194756 2.004653 8.18848 4.403278 14.989359 7.194852 1.199312 0.80534 2.192941 1.199312 2.998281 1.199312 10.389607 4.403278 22.381708 8.394164 35.975281 11.992101-23.984203 4.403278-42.177527 3.40044-54.562577-2.998281-5.60259-2.398625-10.998473-5.190199-16.188672-8.394164-2.398625 1.199312-5.395883 2.800783-8.99382 4.79725-3.597937 2.004653-6.398721 3.40044-8.394164 4.197594-9.996658 5.199408-28.986113 6.800879-56.961202 4.79725 16.386169-3.597937 30.97337-8.99382 43.769789-16.188672 4.394068-2.792597 8.788136-4.993724 13.191414-6.595195-5.995539-3.597937-11.992101-6.989167-17.98764-10.193133-5.199408 5.995539-15.992197 8.394164-32.378367 7.194852 8.788136-4.79725 19.786609-17.781956 32.978023-38.973562l22.78489 0c-0.80534 1.199312-1.601471 2.398625-2.398625 3.597937-0.80534 1.601471-2.604309 4.197594-5.395883 7.794508 3.194756-2.792597 7.194852-4.197594 11.992101-4.197594l35.375625 0c5.995539 0.403182 10.792789 1.199312 14.390726 2.398625 0.393972-0.796131 0.599656-1.798969 0.599656-2.998281l0-3.597937c0-5.995539-3.803622-8.99382-11.392445-8.99382L635.819803 450.091122c-11.194947 0-18.587297 3.203965-22.185234 9.593476L613.634568 474.073278zM628.624951 570.008043l-26.981461 0 0-45.568757 26.981461 0 0 10.792789c1.199312-7.194852 6.389511-10.792789 15.589015-10.792789l49.166695 0c15.589015 0.403182 23.581021 6.595195 23.984203 18.587297l0 10.792789c0.393972 11.186761-7.194852 16.582644-22.78489 16.188672l-50.366007 0c-9.996658 0-15.196067-3.803622-15.589015-11.392445L628.624951 570.008043zM628.624951 540.028301l0 16.188672c1.593285 5.190199 6.193037 7.794508 13.79107 7.794508l37.77425 0c6.792693 0 10.193133-2.604309 10.193133-7.794508l0-14.390726c0-7.588824-4.197594-11.392445-12.591758-11.392445l-35.375625 0C635.220146 530.434824 630.620394 533.63879 628.624951 540.028301zM674.793365 469.276028l-23.384547 0c-6.398721-0.393972-11.598129 2.004653-15.589015 7.194852l-3.597937 4.197594 11.992101 0c2.792597 2.004653 6.792693 4.197594 11.992101 6.595195 1.995443 0.80534 3.597937 1.404997 4.79725 1.798969 1.593285-0.796131 3.194756-1.798969 4.79725-2.998281 3.597937-1.995443 6.389511-3.794412 8.394164-5.395883 6.389511-3.597937 9.387792-6.389511 8.99382-8.394164C683.187528 470.278866 680.386745 469.276028 674.793365 469.276028zM766.531559 570.607699l-23.384547 0 0-134.30867 23.384547 0 0 8.99382c2.398625-5.190199 7.588824-7.992005 15.589015-8.394164l70.752272 0c18.381613 0 27.375433 6.800879 26.981461 20.386265l0 93.536139c0.393972 13.584363-6.998377 20.180581-22.185234 19.786609l-76.747811 0c-8.000192 0-12.797442-2.998281-14.390726-8.99382L766.530535 570.607699zM766.531559 450.089075 766.531559 556.216972c1.199312 5.593381 4.394068 8.18848 9.593476 7.794508l67.753991 0c8.788136 0 13.191414-4.79725 13.191414-14.390726l0-93.536139c0-8.788136-4.403278-13.191414-13.191414-13.191414l-64.156054 0C772.92107 443.297406 768.527002 445.695007 766.531559 450.089075zM815.098597 531.634137l0-38.973562-11.392445 0c-0.403182 13.996754-1.601471 27.786801-3.597937 41.372187-0.403182 13.593572-11.194947 19.392637-32.378367 17.387984 6.792693-5.995539 10.389607-13.191414 10.792789-21.585578 0.393972-4.79725 1.199312-12.788232 2.398625-23.984203 0-4.394068 0.393972-8.788136 1.199312-13.191414l-12.591758 0 0-5.995539 83.343007 0 0 5.995539-16.188672 0 0 37.174593c-0.403182 6.398721 1.395787 9.199504 5.395883 8.394164 3.990886 1.601471 7.194852-4.993724 9.593476-19.786609 2.398625 21.585578-1.798969 31.77871-12.591758 30.579398l-5.995539 0C820.288796 549.827461 814.293257 544.028397 815.098597 531.634137zM844.478682 465.679114l-67.154335 0 0-5.995539 67.154335 0L844.478682 465.679114z\" p-id=\"1787\" fill=\"#1296db\"></path><path d=\"M348.423808 426.689179c-45.993428-45.993428-120.541136-45.987289-166.529448 0-45.987289 45.987289-45.992405 120.537043-0.001023 166.527401 45.992405 45.993428 120.542159 45.987289 166.529448 0C394.410073 547.229292 394.41519 472.681585 348.423808 426.689179zM234.574058 562.965663c-4.513795 4.513795-11.82121 4.525051-16.344214 0.002047-4.502538-4.502538-4.513795-11.831443 0-16.345237 4.512771-4.512771 11.826326-4.506631 16.338074 0.005117C239.092969 551.151617 239.086829 558.454939 234.574058 562.965663zM284.993277 563.30847c-0.289595 1.936091-1.183963 3.805668-2.677987 5.299692-3.714594 3.715617-9.731622 3.714594-13.442123 0.005117-2.215453-2.215453-3.105728-5.24955-2.67901-8.135268l-0.010233-0.004093c-0.007163 0.051165-0.010233 0.082888-0.010233 0.084934l0.004093-0.086981 0.00614 0.002047c0.071631-0.648775 0.492209-5.086845-0.731662-11.044522-1.718128-8.345045-5.73255-15.713859-11.922517-21.903825-6.188944-6.188944-13.512731-10.169597-21.781029-11.841676-5.04182-1.015118-8.975401-0.842179-10.419283-0.721429-3.03819 0.640588-6.326066-0.218987-8.683759-2.57668-3.709478-3.710501-3.710501-9.727529 0.004093-13.443147 1.462302-1.463325 3.287876-2.352576 5.183036-2.662637l-0.005117-0.056282c1.098005-0.182148 27.270032-4.034888 49.154415 17.847448C288.826574 535.913595 285.167238 562.199209 284.993277 563.30847zM327.976144 565.168837c-0.81762 5.187129-5.696734 8.723668-10.88591 7.895815-2.057865-0.320294-3.85581-1.286293-5.228061-2.658544-2.073214-2.072191-3.354391-5.142103-2.850925-8.268298 0.020466-0.080841 1.245361-9.192341-1.250478-21.820938-3.26127-16.537618-11.104897-31.138122-23.290403-43.405492-12.269417-12.186529-26.867874-20.029132-43.406516-23.292449-12.628597-2.494816-21.74112-1.270944-21.831171-1.259687l0.045025-0.004093c-0.01228 0.002047-0.014326 0.004093-0.013303 0.00614-3.128241 0.484023-6.219643-0.770548-8.301043-2.852972-1.371228-1.371228-2.337227-3.170196-2.658544-5.228061-0.81762-5.177919 2.719942-10.057033 7.896838-10.884886 0.477883-0.072655 11.741392-1.799992 27.306871 1.071399 9.046009 1.666962 17.811632 4.547564 26.060487 8.579382 10.280114 5.006004 19.748747 11.79972 28.123468 20.176488 0.081864 0.080841 0.157589 0.166799 0.22922 0.23843 0.071631 0.070608 0.156566 0.146332 0.228197 0.217964 8.385978 8.384954 15.179694 17.853588 20.185698 28.133701 4.021585 8.238622 6.902187 17.004245 8.579382 26.060487C329.775113 553.429492 328.058009 564.700164 327.976144 565.168837z\" p-id=\"1788\" fill=\"#1296db\"></path></svg>"
],
Zhihu: "https://www.zhihu.com/people/joeljhou",
Juejin: [
"https://juejin.cn/user/2911162523717640",
"<svg t=\"1659342177327\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"1573\" width=\"200\" height=\"200\"><path d=\"M465.189 161.792c-22.967 18.14-44.325 35.109-47.397 37.742l-5.851 4.68 10.971 8.632c5.998 4.827 11.85 9.508 13.02 10.532 1.17 1.024 17.993 14.336 37.156 29.696l34.962 27.795 5.267-3.95c2.925-2.194 23.259-18.432 45.348-35.986 21.943-17.555 41.253-32.768 42.716-33.646 1.609-1.024 2.779-2.194 2.779-2.78 0-0.438-9.655-8.63-21.504-17.846-11.995-9.363-22.674-17.847-23.845-18.871-15.945-13.02-49.737-39.059-50.76-39.059-0.586 0.147-19.896 14.922-42.862 33.061z m233.325 180.37C507.465 493.275 508.928 492.105 505.417 489.911c-3.072-1.902-11.556-8.485-64.073-50.03-9.07-7.168-18.578-14.775-21.358-16.823-2.78-2.194-8.777-6.875-13.312-10.532-4.68-3.657-10.679-8.339-13.312-10.533-13.165-10.24-71.095-56.027-102.107-80.457-5.852-4.681-11.41-8.485-12.142-8.485-0.731 0-10.971 7.754-22.674 17.116-11.703 9.508-22.674 18.286-24.284 19.456-1.755 1.17-5.12 3.95-7.46 6.144-2.34 2.34-4.828 4.096-5.413 4.096-3.072 0-0.731 3.072 6.437 8.777 4.096 3.218 8.777 6.875 10.094 8.046 1.316 1.024 10.24 8.045 19.748 15.506s23.26 18.286 30.428 23.99c19.31 15.215 31.89 25.308 127.853 101.084 47.836 37.742 88.796 69.779 90.844 71.095 3.657 2.487 3.95 2.487 7.46-0.292a1041.42 1041.42 0 0 0 16.092-12.727c6.875-5.413 14.775-11.703 17.554-13.897 30.135-23.699 80.018-63.05 81.774-64.512 1.17-1.024 12.434-9.802 24.868-19.603s37.888-29.696 56.32-44.324c18.579-14.629 46.227-36.425 61.733-48.567 15.506-12.142 27.794-22.528 27.502-23.26-0.878-1.17-57.637-47.104-59.978-48.274-0.731-0.439-18.578 12.727-39.497 29.257z\" fill=\"#006CFF\" p-id=\"1574\"></path><path d=\"M57.93 489.326c-15.215 12.288-28.527 23.405-29.697 24.576-2.34 2.194-5.412-0.44 80.018 66.852 33.207 26.185 32.622 25.747 57.637 45.495 10.386 8.192 36.279 28.672 57.783 45.495 38.18 30.135 44.91 35.401 52.663 41.545 2.048 1.756 22.967 18.14 46.372 36.572 23.26 18.432 74.167 58.514 112.933 89.088 38.912 30.573 71.095 55.734 71.826 56.027 0.732 0.293 7.46-4.389 14.921-10.386 21.797-16.97 90.259-70.949 101.523-79.872 5.705-4.535 12.873-10.24 15.945-12.58 3.072-2.488 6.436-5.12 7.314-5.852 0.878-0.878 11.85-9.509 24.283-19.31 20.773-16.091 59.1-46.226 64.366-50.615 1.17-1.024 5.12-4.096 8.777-6.875 3.657-2.78 7.9-6.29 9.509-7.607 1.609-1.317 14.775-11.703 29.257-23.113 29.11-22.82 42.277-33.207 88.503-69.632 17.262-13.605 32.475-25.454 33.646-26.478 2.486-2.048 31.451-24.869 44.617-35.255 4.827-3.657 9.07-7.168 9.508-7.607 0.44-0.585 5.998-4.827 12.435-9.8 6.436-4.828 13.165-10.24 15.067-11.85l3.365-2.926-9.948-7.753c-5.412-4.388-10.24-8.192-10.679-8.63-1.17-1.317-22.381-18.433-30.135-24.284-3.95-3.072-7.314-5.998-7.606-6.73-1.317-3.071-6.73 0.147-29.258 17.994-13.458 10.532-25.746 20.187-27.355 21.504-1.61 1.463-10.533 8.338-19.749 15.652-9.216 7.168-17.115 13.459-17.554 13.898-0.439 0.438-6.583 5.412-13.897 10.971-7.168 5.559-15.214 11.703-17.7 13.75-4.974 4.097-5.413 4.39-20.334 16.239-5.56 4.388-11.264 8.777-12.435 9.8-1.17 1.025-20.333 16.092-42.422 33.354-22.09 17.408-41.546 32.768-43.155 34.084-1.609 1.463-14.482 11.557-28.525 22.528s-40.814 32.037-59.539 46.812c-18.578 14.775-42.276 33.353-52.516 41.399s-23.26 18.285-28.965 22.82l-10.386 8.339-4.389-3.072c-2.34-1.756-4.68-3.511-5.12-3.95-0.439-0.439-4.973-4.096-10.24-8.046-11.849-9.216-14.482-11.264-16.676-13.166-0.878-0.877-4.243-3.51-7.46-5.851-3.22-2.487-6.145-4.681-6.584-5.12-0.439-0.439-6.875-5.705-14.482-11.703-7.607-5.851-14.921-11.556-16.091-12.58-1.317-1.17-17.116-13.605-35.255-27.795-17.993-14.19-35.109-27.648-38.035-29.842-5.705-4.681-33.499-26.624-125.074-98.743-34.523-27.209-72.704-57.344-84.846-66.852-49.737-39.498-55.15-43.594-56.905-43.447-0.877 0-14.043 10.24-29.257 22.528z\" fill=\"#006CFF\" p-id=\"1575\"></path></svg>"
],
XiaoHongShu: "https://www.xiaohongshu.com/user/profile/5dd53e0c0000000001009bf1",
WechatMP: "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzI4MTMwMDg4MA==",
Tieba: "https://tieba.baidu.com/home/main?un=%E6%9E%81%E5%AE%A2%E8%8B%B1%E9%9B%84",
Weibo: "https://weibo.com/u/7788864199",
Twitter: "https://twitter.com/joeljhou336",
Rss: "./rss.xml",
},
},
/*
* 文章目录加密:
* https://theme-hope.vuejs.press/zh/guide/feature/encrypt.html
*/
encrypt: {
config: {
// 这会加密整个 demo 目录,并且两个密码都是可用的
// "/idea-tips/activation.html": ["52ff"],
},
},
// 是否展示编辑此页链接
editLink: true,
// 编辑此页链接地址
docsRepo: "https://github.com/joeljhou/joeljhou.github.io",
docsDir: "src",
docsBranch: "master",
// page meta
metaLocales: {
editLink: "编辑此页",
},
plugins: {
blog: true,
// 开启git实现编辑此页面-最后更新时间-贡献者功能
git: true,
/*
* 版权信息在复制时自动附加-vuepress-plugin-copyright2
*/
copyright: {
global: false,
triggerLength: 100,
author: "GeekySpace",
license: "MIT",
},
// 代码复制功能-vuepress-plugin-copy-code2
copyCode: {
showInMobile: true,
},
// Feed生成器-vuepress-plugin-feed2
feed: {
rss: true,
},
// install @waline/client before enabling it
// WARNING: This is a test server for demo only.
// You should create and use your own comment service in production.
// comment: {
// provider: "Waline",
// serverURL: "https://waline-comment.vuejs.press",
// },
// MarkDown文件增强-vuepress-plugin-md-enhance
mdEnhance: {
align: true,
attrs: true,
// install chart.js before enabling it
// chart: true,
codetabs: true,
// insert component easily
// component: true,
demo: true,
// install echarts before enabling it
// echarts: true,
figure: true,
// install flowchart.ts before enabling it
// flowchart: true,
// gfm requires mathjax-full to provide tex support
// gfm: true,
imgLazyload: true,
imgSize: true,
include: true,
// install katex before enabling it
// katex: true,
// install mathjax-full before enabling it
// mathjax: true,
mark: true,
// install mermaid before enabling it
mermaid: true,
playground: {
presets: ["ts", "vue"],
},
// install reveal.js before enabling it
// revealJs: {
// plugins: ["highlight", "math", "search", "notes", "zoom"],
// },
stylize: [
{
matcher: "Recommended",
replacer: ({tag}) => {
if (tag === "em")
return {
tag: "Badge",
attrs: {type: "tip"},
content: "Recommended",
};
},
},
],
// 启用剧透,目前版本不支持
// spoiler: true,
// 启用下角标
sub: true,
// 启用上角标
sup: true,
tabs: true,
vPre: true,
// install @vue/repl before enabling it
// vuePlayground: true,
},
// MarkDown启用组件-vuepress-plugin-components
components: {
components: [
// 为站点提供了在MD文档中自定义颜色的徽章
"Badge",
// 为站点提供了在MD文档中加载B站视频的功能,但是不建议使用
"BiliBili",
// 为站点提供了在MD文档中加载PDF阅读器的功能,但是不建议使用
// 原因一:PDF书籍较大,上传到码云后会大量占用码云空间
// 原因二:当PDF阅读器较多的时候,将MD文档渲染成HTML页面比较耗费性能,使页面加载速度变慢
"PDF",
]
},
// uncomment these if you want a PWA
// pwa: {
// favicon: "/favicon.ico",
// cacheHTML: true,
// cachePic: true,
// appendBase: true,
// apple: {
// icon: "/assets/icon/apple-icon-152.png",
// statusBarColor: "black",
// },
// msTile: {
// image: "/assets/icon/ms-icon-144.png",
// color: "#ffffff",
// },
// manifest: {
// icons: [
// {
// src: "/assets/icon/chrome-mask-512.png",
// sizes: "512x512",
// purpose: "maskable",
// type: "image/png",
// },
// {
// src: "/assets/icon/chrome-mask-192.png",
// sizes: "192x192",
// purpose: "maskable",
// type: "image/png",
// },
// {
// src: "/assets/icon/chrome-512.png",
// sizes: "512x512",
// type: "image/png",
// },
// {
// src: "/assets/icon/chrome-192.png",
// sizes: "192x192",
// type: "image/png",
// },
// ],
// shortcuts: [
// {
// name: "Demo",
// short_name: "Demo",
// url: "/demo/",
// icons: [
// {
// src: "/assets/icon/guide-maskable.png",
// sizes: "192x192",
// purpose: "maskable",
// type: "image/png",
// },
// ],
// },
// ],
// },
// },
},
}, {custom: true});
================================================
FILE: src/README.md
================================================
---
# 博客主页配置:https://theme-hope.vuejs.press/zh/config/frontmatter/blog-home.html
home: true
layout: BlogHome
hero: false
title: 最新发布
icon: home
projects:
- icon: launch
name: 开发者安装大全
desc: 好用工具、开发环境、中间件配置等安装指南
link: /md/installation-guide/
- icon: java
name: Java新特性
desc: 从Java 8开始所有新特性解读
link: /md/java-features/
- icon: intellij-idea
name: IDEA激活
desc: 了解IDEA更多牛x功能、推荐很有意思的主题和插件
link: /md/idea-tips/activation
- icon: spring
name: Spring实战
desc: 深入理解Spring框架
link: /md/spring-framework/core/
- icon: mysql
name: MySQL教程
desc: MySQL必知必会、高性能架构、排错指南
link: /mysql/
- icon: aigc
name: AIGC新时代
desc: 提供生成式人工智能的入门和进阶教程
link: /aigc/
- icon: cloud-service
name: 云原生技术
desc: 分享云原生架构的最佳实践和使用指南
link: /cloud-native/
- icon: smart-contracts
name: 区块链智能合约
desc: 提供区块链技术和智能合约开发的指南
link: /md/blockchain/
footer: © 2023 - 至今 <a href="https://www.geekyspace.cn/" target="_blank">www.geekyspace.cn</a> 保留所有权利
copyright: Copyright © 2026 流浪码客
---
================================================
FILE: src/about-me.md
================================================
---
# 信息 Frontmatter 配置
title: 个人简介
description: 一个专注于技术分享的博客网站
icon: circle-info
# cover: /assets/images/cover3.jpg
author: 流浪码客
isOriginal: false # 是否原创文章
date: 1998-12-14
category: 程序人生
tag: 程序人生
# 布局 Frontmatter 配置
sidebar: false # 禁用侧边栏
---
# 个人简介 | 一个专注于技术分享的博客网站
欢迎访问我的博客网站 [www.geekyspace.cn](www.geekyspace.cn),与我一起探索科技的未来!
本博客维护人周宇,在Java和相关技术领域拥有多年的专业经验。
此前,我在深圳南山 [Liquido](https://www.liquido.com/) 工作,这是一家专注于金融领域,
提供拉美地区[支付解决方案](https://mp.weixin.qq.com/s/UzPsaVvXqrvW8T8PDPnhZw)的公司。
**贴上“程序员”标签**
1. 个人兴趣:我从小就对工科方向的工作非常感兴趣,喜欢倒腾电子产品,研究它们的原理,拆了又装。
2. 家庭影响:我有一个“伢伢”,比我大10多岁,他学的就是计算机,赚钱也多。
他毕业后在一家电商公司工作,后来被京东收购,之后去了高德,又被阿里收购。在它的影响下,我最终成为了一名程序员。
**程序员的价值体现**
做程序员是幸运的,世界的本质是价值交换。
作为程序员,我最大的成就感在于能否真正给别人带来价值。如果可以,那泰裤辣。
大环境没有那么差(给自己信心),这是程序员的时代!!!
* 人生没有白走的路,每一步都算数(我要坚持坚持坚持)
**我的程序员格言**
1. 编码原则:🥇 代码简洁高效,优雅永不过时 ✨
2. 架构核心:🔧 掌握系统控制权,确保可扩展性和灵活性
3. 技术理念:🌐 技术广度是技术深度的副产品
4. 职业信仰:🚀 当坚持成为一种热爱,极致成为一种精神,那么成功就是一种必然
5. 长期主义:⏳ 注重长远发展,坚持不懈地追求卓越
================================================
FILE: src/article.md
================================================
---
home: true
icon: home
title: 文库汇总
# 指定首页背景头像
heroImage: /images/personal/geekyspace.png
heroImageDark: /images/personal/geekyspace.png
# 指定首页背景图片
#bgImage: /assets/bg/wallhaven-8586my.png
#bgImageDark: /assets/bg/wallhaven-o5762l.png
bgImageStyle:
background-attachment: fixed
heroText: 文库汇总
tagline: 极客空间,一个专注于技术分享的博客网站✨
actions:
- text: 首页
icon: home
link: /
type: primary
- text: 文章
icon: article
link: /article/
features:
- title: RabbitMQ
icon: rabbitmq
# icon: https://avatars.githubusercontent.com/u/96669?s=48&v=4
details: 高并发实战-RabbitMQ消息队列
link: https://github.com/joeljhou/RabbitMQ
- title: JVM
icon: javaJvm-xx
details: 深入理解Java虚拟机
link: /md/java/jvm/
- title: Docker
icon: docker
details: Docker容器化最佳实践
link: /md/docker/overview
- title: K8S
icon: k8s
details: Kubernetes云原生时代
- title: MySQL
icon: mysql
# icon: https://labs.mysql.com/common/logos/mysql-logo.svg
details: MySQL原理与SQL调优
- title: Redis
icon: redis
#icon: https://redis.io/wp-content/uploads/2024/04/Logotype.svg
details: Redis缓存高可用实战
- title: Elasticsearch
icon: elasticsearch
#icon: https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt36f2da8d650732a0/5d0823c3d8ff351753cbc99f/logo-elasticsearch-32-color.svg
details: Elasticsearch搜索引擎
- title: Google Istio
icon: istio_bypass_mode_s
details: Google Istio服务网格
copyright: false
footer: "© 2023 - 至今 <a href=\"https://www.geekyspace.cn\" target=\"_blank\">www.geekyspace.cn</a> 保留所有权利"
---
================================================
FILE: src/md/blockchain/README.md
================================================
---
title: 区块链基础
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-11-06
category: blockchain
tags:
- blockchain
---
# 区块链基础
## 注册美国/新加坡AppleID
参考:[B站视频](https://www.bilibili.com/video/BV1Tg1MBmEk4)
**注册成功后**
- 闲鱼/淘宝购买礼品卡,防止被封
- 礼品卡金额可用来购买小火箭(Shadowrocket)软件,$2.99
## 交易所实操1
1. 选择交易所
- [Binance(币安)](https://www.binance.com/zh-CN) - 新加坡、香港
- [OKX(欧易)](https://www.okx.com/zh-hans)
2. 身份认证
3. 充值(资金)
- 法币充值,得到数字货币。其中法币是指国家发行的货币。
- [Binance(币安)- C2C 快捷区](https://p2p.binance.com/zh-CN/express/buy/USDT/CNY)
- [OKX(欧易)- C2C 快捷交易](https://www.okx.com/zh-hans/p2p/express/cny/buy-usdt)
4. 划转
- 将**资产账户**的资金划转到**现货账户**,以便进行现货交易。
- 资金账户:存放充值的法币或数字资产
- 现货账户:用于现货交易(买卖币种)
- 合约账户:用于合约交易(U本位/币本位合约),如`BTC-USDT` 永续合约。
- `BTC-USDT` 是一个**交易对**,表示用 USDT 买 BTC,或卖 BTC 换 USDT。
- [Binance(币安)- 钱包总览下划转](https://www.binance.com/zh-CN/my/wallet/account/overview)
- [OKX(欧易)- 资金划转](https://www.okx.com/zh-hans/balance/transfer)
5. 买币
* 现货:购买`BNB/USDT`,可抵扣平台20%手续费
* 合约:
* **U本位合约**,使用稳定币 USDT结算保证金和盈亏。
* **币本位合约**,使用加密货币本身(比如 BTC、ETH)结算保证金和盈亏。
* 买币一定要委托**止盈/止损**策略,一定要止损!!!
6. 卖币
7. 提币
* **从币安提币(withdraw) → 到欧易充币(deposit)地址**
* 选择币种(USDT)
* 选择网络(**重要!** 需与币安提币网络一致)
* 不同网络手续费不一样,`APT(Aptos)`收费费低,欧易能看到具体费用标准
================================================
FILE: src/md/database/mysql/README.md
================================================
---
title: MySQL 必知必会
shortTitle:
description:
icon: mysql
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-09-18
category: DataBase
tags:
- DataBase
---
# MySQL 必知必会
开启一个新的专栏,介绍 MySQL 的一些必知必会的内容。
================================================
FILE: src/md/database/mysql/overview/what-is-database.md
================================================
---
title: 什么是数据库?
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-09-18
category: DataBase
tags:
- DataBase
---
# 什么是数据库?
## 数据库的定义
> 这个术语的用法很多,对于程序员来说,数据库是一个**有组织的数据集合**,由 [数据库管理系统 (DBMS)](https://www.oracle.com/cn/database/what-is-database/#WhatIsDBMS) 来管理。在计算机系统中,<u>数据、DBMS 和相关应用程序</u>统称为**数据库系统**,简称数据库。
- 理解数据库的一种最简单的办法是将其想象为一个**文件柜**。
- 此文件柜是一个存放数据的物理位置,不管数据是什么以及如何组织的。
## 什么是SQL?
> **SQL**(Structured Query Language,**结构化查询语言**)是一种专门**与[关系数据库](https://www.oracle.com/cn/database/what-is-database/#relational)通信的编程语言**。 可以使用 SQL 语句从数据库中<u>存储、更新、删除、搜索和检索信息</u>。您还可以使用 SQL 来维护和优化数据库性能。
**历史背景**
1. SQL 最初由 IBM 在 20 世纪 70 年代开发,用于关系数据库操作。
2. Oracle 是主要贡献者之一,推动了 SQL 的 ANSI 标准化。
3. 随着 SQL 的广泛应用,IBM、Oracle、Microsoft 等公司相继扩张其数据库业务。
4. 时至今日,SQL 仍是主流数据库的标准语言,但新兴语言和技术也逐渐出现。
## 数据库的类型
1. 关系数据库
2. 非关系型数据库
## 序
* [什么是数据库? | Oracle 中国](https://www.oracle.com/cn/database/what-is-database)
* [什么是数据库?- 云数据库简介 - AWS](https://aws.amazon.com/cn/what-is/database)
================================================
FILE: src/md/docker/install.md
================================================
---
title: Docker安装
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-11-15
category: Docker
tag:
- docker
---
# Docker安装&配置
您可以在多个平台上下载并安装 Docker。请参阅以下部分并选择最适合您的安装路径。
> [适用于Mac的Docker桌面](https://docs.docker.com/desktop/setup/install/mac-install/)
> [适用于Windows的Docker桌面](https://docs.docker.com/desktop/setup/install/windows-install/)
> [适用于Linux的Docker桌面](https://docs.docker.com/desktop/setup/install/linux/)
**验证是否安装成功:**
```shell
$ docker version # 查看版本
$ docker info # 查看信息
```
**运行测试镜像**
```shell
$ docker run hello-world
$ docker run -it ubuntu bash
```
可能会遇到如下网络错误,这个时候就需要配置[镜像源加速器](/md/docker/mirror-acceleration.html)
`docker: error pulling image configuration: download failed after attempts=6: EOF.`
================================================
FILE: src/md/docker/mirror-acceleration.md
================================================
---
title: Docker镜像加速器
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-11-16
category: Docker
tag:
- docker
---
# Docker镜像加速器
国内从`Docker Hub`拉取镜像有时会遇到困难,此时可以配置镜像加速器。
## 阿里云镜像加速器
> [阿里云镜像加速器](https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors),有针对`Ubuntu`,`CentOS`,`Mac`,`Windows`的操作文档

## Linux
对于使用`Ubuntu`或`CentOS`的系统,请在`/etc/docker/daemon.json`文件中写入如下内容(如果文件不存
在请新建该文件)
```shell
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://onnxqmp4.mirror.aliyuncs.com"]
}
EOF
# 之后重新启动服务
sudo systemctl daemon-reload
sudo systemctl restart docker
```
## Windows
对于使用Windows的系统,在`docker desktop`右上角**齿轮**图标,打开配置窗口后选择`Docker Engine`。<br/>
编辑JSON串,填写加速器地址:
Windows: `%USERPROFILE%\.docker\daemon.json`

**完整的`daemon.json`配置示例:**
```shell
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"registry-mirrors": [
"https://onnxqmp4.mirror.aliyuncs.com",
"https://docker.hpcloud.cloud",
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"http://mirrors.ustc.edu.cn",
"https://docker.chenby.cn",
"https://docker.ckyl.me",
"http://mirror.azure.cn",
"https://hub.rat.dev"
]
}
```
## MacOS

================================================
FILE: src/md/docker/overview.md
================================================
---
title: Docker概述
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-11-15
category: Docker
tag:
- docker
---
# Docker概述
## 什么是Docker?
`Docker`是`dotCloud`团队在2013年发布的开源项目。 使用`Go`语言开发,是一个轻量级的虚拟机容器解决方案。
## 为什么使用Docker?
Docker跟传统虚拟机相比,具有以下优势:
* 更高效的利用系统资源
* 更快速的启动速度
* 一致的运行环境
* 持续交付和部署
* 更轻松的迁移
* 更轻松的维护和扩展
**`Docker` VS `传统虚拟机`**
| 特性 | 容器 | 虚拟机 |
|-------|-----------|--------|
| 启动 | 秒级 | 分钟级 |
| 硬盘使用 | 一般为 MB | 一般为 GB |
| 性能 | 接近原生 | 弱于 |
| 系统支持量 | 单机支持上千个容器 | 一般几十个 |
## 基本概念
* **镜像(Image)**:Docker镜像是一个只读的模板,包含了运行容器所需的所有文件。
* 本质是==文件系统==
* 基于`Union FS`设计,**分层存储**,可以叠加
* **容器(Container)**:Docker容器是可独立运行的一个或一组应用,是Docker镜像的运行实例。
* 实质是==进程==
* 拥有自己的`root`文件系统,网络配置,进程空间等
* 最佳实践:文件写入操作使用**数据卷(Volume)**,避免文件写入到容器中
* **仓库(Repository)**:Docker Registry是一个集中存储、分发镜像服务。
* [Docker Hub](https://hub.docker.com/) 官方镜像仓库
* [Google Container Registry](https://cloud.google.com/artifact-registry/docs?hl=zh-cn) K8s 镜像仓库
* [Amazon ECR](https://aws.amazon.com/cn/ecr/) AWS 镜像仓库
* [VMWare Harbor](https://github.com/goharbor/harbor) 和 [Sonatype Nexus](https://www.sonatype.com/docker)
三方软件实现了Docker Registry API
## Docker执行流程
* 客户端发指令 → 守护进程接收指令 → 检查镜像(本地/Docker Hub) → 创建容器 → 启动并运行。

## Docker架构
Docker 的架构设计基于 **客户端-服务器模型**,主要包含以下核心组件:

1. **Client(客户端)** :用户与Docker交互的界面,通过命令行或API发送指令给Docker daemon。
* `docker run`:创建并启动一个容器。
* `docker build`:根据Dockerfile构建一个新的镜像。
* `docker pull`:从注册中心拉取一个镜像。
* `docker push`:将本地镜像推送到注册中心。
2. **Docker daemon(守护进程)** :Docker引擎的核心,负责监听、处理客户端的指令,并管理Docker对象(镜像、容器等)。
* `镜像管理`:管理本地镜像,包括存储、加载和删除。
* `容器管理`:创建、启动、停止、删除容器。
* `网络管理`:为容器提供网络接口。
* `存储管理`:管理容器的数据卷。
3. **Images(镜像)** :Docker镜像是一个只读的模板,包含了运行容器所需的所有文件
* `分层结构`:镜像由多层组成,每一层代表一个构建步骤。
* `只读`:镜像是只读的,保证了镜像内容的不可变性。
4. **Containers(容器)** :Docker容器是镜像的运行实例,是应用程序的运行环境。
* `隔离性`:每个容器都有独立的文件系统、网络配置和进程空间。
* `可复用性`:基于同一个镜像可以创建多个容器实例。
5. **Registry(注册中心)** :用于存储和分发Docker镜像的仓库。
* `集中存储`:将镜像存储在集中式的仓库中,方便管理和共享。
* `版本控制`:支持镜像的版本管理。
================================================
FILE: src/md/docker/top20-commands.md
================================================
---
title: Top20常用命令
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-11-23
category: Docker
tag:
- docker
---
# Top20常用命令
作为一款领先的容器化工具,Docker 提供了强大的功能,让开发者和运维人员能够快速构建、部署和管理应用。
在这篇文章中,我们将介绍 20 条最常用的 Docker 命令,并结合详细说明,帮助大家轻松掌握 Docker 的基本操作。
* [1. Docker version](#docker-version)
* [2. Docker search](#docker-search)
* [3. Docker pull](#docker-pull)
* [4. Docker run](#docker-run)
* [5. Docker ps](#docker-ps)
* [6. Docker stop](#docker-stop)
* [7. Docker restart](#docker-restart)
* [8. Docker kill](#docker-kill)
* [9. Docker exec](#docker-exec)
* [10. Docker login](#docker-login)
* [11. Docker commit](#docker-commit)
* [12. Docker push](#docker-push)
* [13. Docker network](#docker-network)
* [14. Docker history](#docker-history)
* [15. Docker rmi](#docker-rmi)
* [16. Docker ps -a](#docker-ps--a)
* [17. Docker copy](#docker-copy)
* [18. Docker logs](#docker-logs)
* [19. Docker volume](#docker-volume)
* [20. Docker logout](#docker-logout)
**相关文档**
* [Docker 命令参考文档](https://docs.docker.com/engine/reference/commandline/cli/)
* [Dockerfile 镜像构建参考文档](https://docs.docker.com/engine/reference/builder/?spm=5176.8351553.0.0.4ef81991wFvDZm)
## Docker version
用途:显示 Docker 的版本信息。
```bash
docker version
```

## Docker search
用途: 用于搜索 Docker Hub 上的镜像。
```shell
docker search nginx
```

## Docker pull
用途:从 Docker Hub 下载镜像。
```shell
docker pull nginx
```

## Docker run
用途:运行一个镜像,并创建一个容器。
```shell
docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD=root -p 3307:3306 mysql:8.0
```
参数解释:
* `-d`:后台运行容器,并返回 Shell。
* `-e MYSQL_ROOT_PASSWORD=root`:设置环境变量,用于设置 MySQL 的 root 用户密码。
* `-p 3306:3306`:将主机的端口 3306 映射到容器的端口 3306。
* `mysql:8.0`:要下载的镜像的名称。

## Docker ps
用途:列出当前正在运行的容器。
```shell
docker ps
```
## Docker stop
用途:停止一个正在运行的容器。
```shell
docker stop <container_id>
```
## Docker restart
用途:重启一个容器。
```shell
docker restart <container_id>
```
## Docker kill
用途:强制停止一个容器。
```shell
docker kill <container_id>
```
## Docker exec
用途:在运行中的容器中执行命令。
```shell
docker exec -it <container_id> bash
```
参数解释:
* `-it`:保持 STDIN 打开并允许使用键盘输入。
* `<container_id>`:要进入的容器的ID。
* `bash`:要执行的命令。

## Docker login
用途:登录 Docker Hub,用于推送私有镜像。
```shell
docker login
```

## Docker commit
用途:创建一个镜像,该镜像包含一个容器的当前状态。
```shell
docker commit <container_id> <image_name>
```
参数解释:
* `<container_id>`:要提交为镜像的容器的ID。
* `<image_name>`:新镜像的名称。
## Docker push
用途:将镜像推送到 Docker Hub。
```shell
docker push <image_name>
```
## Docker network
用途:管理 Docker 网络。
```shell
docker network create <network_name>
docker network inspect <network_name>
docker network rm <network_name>
docker network connect <network_name> <container_id>
docker network disconnect <network_name> <container_id>
```
参数解释:
* `<network_name>`:要创建、查看、删除或连接的 Docker 网络的名称。
* `<container_id>`:要连接到或断开连接的网络的容器的ID。
## Docker history
用途:显示镜像的创建历史。
```shell
docker history <image_name>
```
参数解释:
* `<image_name>`:要查看其创建历史的镜像的名称。
## Docker rmi
用途:删除镜像。
```shell
docker rmi <image_id>
```
## Docker ps -a
用途:列出所有容器,包括已停止的容器。
```shell
docker ps -a
```

## Docker copy
用途:复制文件或文件夹到容器。
```shell
docker cp <host_path> <container_id>:<container_path>
```
参数解释:
* `<host_path>`:主机上的文件或文件夹的路径。
* `<container_id>`:要复制文件的容器的ID。
* `<container_path>`:容器内的目标路径。
## Docker logs
用途:查看容器的日志。
```shell
docker logs <container_id>
```
参数解释:
* `<container_id>`:要查看其日志的容器的ID。
## Docker volume
用途:管理 Docker 卷。
```shell
docker volume create <volume_name>
docker volume inspect <volume_name>
docker volume rm <volume_name>
docker run -v <volume_name>:/data nginx
```
参数解释:
* `<volume_name>`:要创建、查看或删除的卷的名称。
* `nginx`:要运行的镜像名称。
* `/data`:要挂载到容器内的卷的挂载点。
## Docker logout
用途:注销 Docker Hub。
```shell
docker logout
```
================================================
FILE: src/md/flutter/flutter-guide.md
================================================
---
title: Flutter入门指南
shortTitle:
description: Flutter是一个跨端的平台开发框架
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-09-26
category: Flutter
tags:
- Flutter
---
# Flutter入门
> Flutter 是 Google 推出的跨平台 UI 框架,使用 **Dart** 语言,可一次开发同时运行在 **Android / iOS / Web / 桌面端**。
- 核心理念:**一切皆为组件(Widget)**。
## 环境搭建
### 安装 Flutter SDK
- [SDK 归档列表](https://docs.flutter.cn/release/archive?tab=macos)
- [国内镜像加速配置](https://docs.flutter.cn/community/china/)
**解压与环境变量配置**
```shell
# 假设解压路径为 ~/Development/sdk/flutter
export PATH="$HOME/Development/sdk/flutter/bin:$PATH"
# 国内镜像
export PUB_HOSTED_URL="https://pub.flutter-io.cn"
export FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"
# 配置生效
source ~/.zshrc
```
**检查安装是否成功**
```shell
flutter --version
dart --version
```
**环境诊断命令:`flutter doctor`**
```shell
$ flutter doctor
Doctor summary (查看详细信息,请运行 flutter doctor -v):
[✓] Flutter (稳定通道, 版本 3.35.4, 运行于 macOS 15.6.1 24G90 darwin-arm64, 语言环境 zh-Hans-CN)
[✗] Android 工具链 - 用于开发 Android 设备
✗ 无法找到 Android SDK。
请从 https://developer.android.com/studio/index.html 安装 Android Studio
首次启动会协助你安装 Android SDK 组件。
(或者访问 https://flutter.dev/to/macos-android-setup 获取详细说明)。
如果 Android SDK 已安装在自定义路径,请使用
`flutter config --android-sdk` 更新该路径。
[✗] Xcode - 用于开发 iOS 和 macOS
✗ Xcode 安装不完整;iOS 和 macOS 开发需要完整安装。
下载地址: https://developer.apple.com/xcode/
或通过 App Store 安装 Xcode。
安装完成后运行:
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -runFirstLaunch
✗ 未安装 CocoaPods。
CocoaPods 是 iOS 或 macOS 平台的包管理工具。
没有 CocoaPods,插件无法在 iOS 或 macOS 上正常工作。
更多信息请见 https://flutter.dev/to/platform-plugins
安装说明请见 https://guides.cocoapods.org/using/getting-started.html#installation
[✓] Chrome - 用于 Web 开发
[!] Android Studio (未安装)
[✓] IntelliJ IDEA Ultimate 版本 (2025.1.3)
[✓] VS Code 版本 (1.104.2)
[✓] 已连接设备 (2 个可用)
[✓] 网络资源
! Doctor 在 3 个类别中发现问题。
```
### 安装 Android Studio
==搭建<u>安卓</u>环境==
1. [下载 Android Studio](https://developer.android.com/studio?hl=zh-cn)
2. 安装 Dart 和 Flutter 插件
3. 安装 SDK Command-line Tools

4. 接受 Android SDK 许可证
```shell
$ flutter doctor --android-licenses
# 根据提示逐条输入 y 接受许可证
```
### 安装 XCode
==搭建<u>iOS/macOS</u>环境==
- 通过 [App Store安装 Xcode](https://developer.apple.com/xcode/)
- 安装完成后,在终端执行:
```shell
# 指定 Xcode 路径(支持安装多个)
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
# 首次启动初始化(确保命令行工具可用)
sudo xcodebuild -runFirstLaunch
```
### 安装 CocoaPods
CocoaPods 是 iOS/macOS 平台的依赖管理工具,用于管理 Flutter 插件的本地依赖。
```shell
# 1. 安装 ruby(Mac系统自带,但建议使用 brew 安装新版)
brew install ruby
# 配置 ruby 环境变量
echo 'export PATH="/opt/homebrew/opt/ruby/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
# 验证 ruby 是否安装成功
ruby --version
# 2. 安装 CocoaPods
gem install cocoapods
# 配置 gems 环境变量
export PATH="/opt/homebrew/lib/ruby/gems/3.4.0/bin:$PATH"
source ~/.zshrc
```
## 常用命令
```shell
# 🌟 检查环境
flutter doctor # 检查 SDK、IDE、工具链
flutter doctor -v # 显示详细信息
# 🌟 设备管理
flutter devices # 列出已连接设备/模拟器
flutter emulators # 查看可用模拟器
flutter emulators --launch <id> # 启动指定模拟器
# 🌟 运行项目
flutter run # 在默认设备运行
flutter run -d <device_id> # 指定设备运行
flutter run -d all # 所有设备同时运行
# 🌟 管理依赖
flutter pub get # 下载依赖(pubspec.yaml 中的包)
flutter pub upgrade # 升级依赖
# 🌟 清理与构建
flutter clean # 清理缓存和临时文件
flutter build apk # 构建 Android APK
flutter build apk --debug # 构建调试 APK
flutter build apk --split-per-abi # 按 CPU 架构分包,减小 APK 大小
# 🌟 代码检查与格式化
flutter analyze # 静态分析代码
flutter format . # 格式化项目代码
# 🌟 iOS 模拟器(仅 macOS)
open -a Simulator # 启动 Xcode iOS 模拟器
flutter run -d ios # 在 iOS 模拟器运行
```
## 组件(Widget)
### 理解 Flutter 应用
* [🐟代码小抄-理解 Flutter 应用](https://codecopy.cn/post/19cdjq)
- 1️⃣ StatelessWidget —— 无状态组件
- 2️⃣ StatefulWidget —— 有状态组件
- [joeljhou/hello_flutter: 一个面向初学者的 Flutter 示例项目,展示基础控件、布局和样式。适合学习 Flutter 基础知识并快速上手开发简单应用。](https://github.com/joeljhou/hello_flutter)
### StatefulWidget 生命周期

StatefulWidget 的生命周期可分为 **4 个阶段**:
1. **初始化阶段**:`createState()` → `initState()`
2. **依赖变化与首次构建阶段**:`didChangeDependencies()` → `build()`
3. **状态更新阶段**:`setState()`、`didUpdateWidget()`、`reassemble()`
4. **销毁阶段**:`deactivate()` → `dispose()`
**🧩 各阶段方法说明**
1. `createState()`
- 当 StatefulWidget 第一次被创建时调用
- 用于创建对应的 `State` 实例
2. `initState()`
- State 初始化时调用(仅执行一次)
- 常用于:
- 初始化变量
- 发起网络请求 / 初始化数据
- ⚠️ 不要在此直接调用 `BuildContext` 相关操作(如 `Provider.of`)
3. `didChangeDependencies()`
- 当依赖的对象(如 `InheritedWidget`)发生变化时调用
- 在 `initState()` 之后 **会被调用一次**
- 通常用于依赖外部数据的初始化
4. `build()`
- 返回要渲染的界面
- 可能会被调用多次(如 `setState()`、父组件重建)
- ⚠️ 避免在此执行耗时或带副作用的操作
5. `reassemble()`
- **仅在 Debug 模式下热重载(Hot Reload)** 时调用
- 用于调试时更新状态
6. `didUpdateWidget()`
- 当父组件重建并传入新的配置时调用
- Flutter 通过 `Widget.canUpdate` 判断是否需要调用此方法
- 调用后一定会触发 `build()` 重新渲染
7. `setState()`
- 用于触发状态更新并重新调用 `build()`
- 只更新当前组件,不影响父组件
8. `deactivate()`
- 当组件从 Widget 树中**暂时移除**时调用
- 有可能会再次被插入(如路由切换)
9. `dispose()`
- 当组件 **永久从树中移除** 时调用
- 用于:
- 释放资源(如 `Controller`、`Stream`、`Timer`)
- 取消订阅、关闭动画等
### Widget/UI布局/交互

## 页面跳转(Navigator)

## 网络请求和序列化数据

## 参考:
* [Flutter 开发文档](https://docs.flutter.dev/) | [Flutter 中文开发文档](https://docs.flutter.cn/)
* [手动安装Flutter](https://docs.flutter.cn/install/manual) | [安装常见问题](https://docs.flutter.cn/install/troubleshoot#cmdline-tools-component-is-missing)
* [在 Android Studio 或 IntelliJ 里开发 Flutter 应用](https://docs.flutter.cn/tools/android-studio)
* [女程序猿带你从0开始学Flutter:认识Flutter](https://www.bilibili.com/video/BV1p14y1T79R/)
* [一个面向初学者的 Flutter 示例项目](https://github.com/joeljhou/hello_flutter)
================================================
FILE: src/md/idea-tips/activation.md
================================================
---
title: 2025最新IntelliJ IDEA专业版稳定正版激活码
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: true
date: 2024-04-17
category: 开发工具
tag:
- IDEA
---
# 2025最新IntelliJ IDEA专业版稳定正版激活码
## 适用于Mac系统
> 仅支持官网专业版2020-2024的激活。不支持社区版 toolbox下载的IDEA。
### 1️⃣ 第一步:下载激活文件
[激活文件获取](https://h5.m.goofish.com/item?id=785250929165)
### 2️⃣ 第二步:打开激活文件 `macjihuo.zip`,解压缩
### 3️⃣ 第三步:"macjihuo"文件夹上右键,新建终端窗口

### 4️⃣ 第三步:运行脚本,输入对应软件的命令-回车(看下图)
==运行命令前:先打开你要激活的软件。然后关闭软件,最后输入命令激活软件哦。==
```shell
如果你要激活idea: 则输入 sh idea.sh
如果你要激活pycharm: 则输入 sh pycharm.sh
如果你要激活datagrip: 则输入 sh datagrip.sh
如果你要激活clion: 则输入 sh clion.sh
如果你要激活goland: 则输入 sh goland.sh
如果你要激活webstorm: 则输入 sh webstorm.sh
如果你要激活phpstorm: 则输入 sh phpstorm.sh
如果你要激活dataspell:则输入 sh dataspell.sh
如果你要激活rider: 则输入 sh rider.sh
```

## 适用于Windows系统
> 仅支持官网专业版2020-2024的激活。不支持社区版 toolbox下载的
### 1️⃣ 第一步:下载激活文件
[激活文件获取](https://h5.m.goofish.com/item?id=785250929165)
### 2️⃣ 第二步:解压下载的压缩包
### 3️⃣ 第三步:打开解压的“`激活码-Win系统`”文件夹,
双击要激活软件的vbs

**♦♦比如:**
* 要激活pycharm,就运行 pycharm激活.vbs
* 要激活IDEA,就运行 IDEA激活.vbs
等待出现 如下 `Success` 提示,再次打开软件即可正常使用!

================================================
FILE: src/md/installation-guide/README.md
================================================
---
title: 开发者安装大全
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-04-23
category: 软件安装
tag:
---
# 开发者安装大全
该专栏主要整理与汇总开发者常用的编程环境、中间件等工具的安装,以指导开发者快速搭建自己的需要的开发环境。
================================================
FILE: src/md/installation-guide/base-tools/Homebrew.md
================================================
---
title: macOS必备包管理工具—Homebrew
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-03-15
category: 包管理器
tags:
- Homebrew
---
# macOS必备包管理工具—Homebrew
主要官方来源:[Homebrew官网](https://brew.sh/zh-cn/) | [Github](https://github.com/homebrew)
> Homebrew 是 macOS 和 Linux 上的包管理器,可以帮助用户轻松安装和管理各种软件包。
## 安装Homebrew
### 官网脚本

**安装 Homebrew**
将以下命令粘贴至终端:
```shell
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
运行此命令将安装最新版本的Homebrew,自动处理MacOS环境中`Xcode Command Tools`的安装。
- **`git`**(用于版本控制,拉取 Homebrew 软件包)
- **`gcc` / `clang`**(用于编译部分软件包)
- **`make`**(用于构建和安装依赖)
安装完成后,按照终端提示,添加 Homebrew 环境环境变量到 `.zprofile` 或 `.bash_profile`。
```shell
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
source ~/.zprofile
```
**卸载 Homebrew**
```shell
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"
```
**验证 Homebrew 安装**
安装完成后,可以运行以下命令来检查 Homebrew 是否正确安装:
```shell
brew --version
```
### 国内脚本
由于国内网络访问 GitHub 可能较慢,可以使用国内的 Homebrew 安装脚本,加快安装速度。
**安装步骤**
1. 访问 [HomebrewCN](https://gitee.com/cunkai/HomebrewCN)。
2. 按照说明执行相应的安装命令。
### .pkg包(macOS)
如果您使用的是 macOS,并希望通过图形化方式安装 Homebrew,可以使用官方提供的 `.pkg` 安装器。
**安装步骤:**
1. 访问 [Homebrew 最新 GitHub 发行版](https://github.com/Homebrew/brew/releases/latest)。
2. 下载 `.pkg` 文件。
3. 双击安装并按照提示完成安装。
## 使用指南
以下是一些常见的 Homebrew 命令:
| 操作 | 命令 |
| ---------------- | ----------------------------------- |
| 安装命令行软件包 | `brew install <soft-name>` |
| 安装图形界面软件 | `brew install --cask <soft-name>` |
| 搜索软件 | `brew search <soft-name>` |
| 卸载命令行软件包 | `brew uninstall <soft-name>` |
| 卸载图形界面软件 | `brew uninstall --cask <soft-name>` |
| 更新 Homebrew 本身 | `brew update` |
| 更新所有已安装软件 | `brew upgrade` |
| 更新具体软件 | `brew upgrade <soft-name>` |
| 显示已安装的软件 | `brew list` |
| 查看软件信息 | `brew info <soft-name>` |
| 查看需要更新的软件 | `brew outdated` |
| 清理不再使用的旧版本 | `brew cleanup` |
| 显示软件安装路径 | `brew --prefix <soft-name>` |
| 测试软件是否正常运行 | `brew test <soft-name>` |
| 检查 Homebrew 运行状态 | `brew doctor` |
| 列出所有可用的 cask | `brew list --cask` |
| 列出所有依赖项 | `brew deps <soft-name>` |
| 显示详细依赖树 | `brew deps --tree <soft-name>` |
| 查看软件安装日志 | `brew log <soft-name>` |
## 默认安装路径
在 Apple M1 (M4) 芯片的 Mac 上,Homebrew 默认安装路径有所不同。对于 M1 芯片,Homebrew 会安装在 `/opt/homebrew` 目录下,而不是像 Intel 芯片那样安装在 `/usr/local`。
- **Homebrew** 安装路径:`/opt/homebrew`
- **Homebrew 安装的软件** 默认路径:`/opt/homebrew/Cellar/`
- **软链接** 默认路径:`/opt/homebrew/bin`(软链接会创建在这个目录中,以便更方便地在命令行中调用安装的软件)
通过以下命令确认安装路径:
```shell
which brew
```
检查某个软件包的安装路径,可以使用 `brew list <软件名>`。
================================================
FILE: src/md/installation-guide/dev-env/java/SDKMAN.md
================================================
---
title: Java生态版本管理神器—SDKMAN
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: true
date: 2025-03-15
category: 包管理器
tags:
- SDKMAN
---
# Java生态版本管理神器—SDKMAN
主要官方来源:[SDKMAN官网](https://sdkman.io/) | [Github](https://github.com/sdkman)
> SDKMAN! 是一个轻量级、支持多平台,开源的,用于管理多个 SDK(如 `Java`、`Kotlin`、`Gradle`、`Maven` 等)的工具。
## 安装SDKMAN
**安装 SDKMAN!**
* 只需启动一个新终端并输入:
```shell
curl -s "https://get.sdkman.io" | bash
```
**初始化并配置环境变量**
* 按照屏幕上的说明完成安装。然后,打开一个新终端或在同一 shell 中运行以下命令:
```shell
source "$HOME/.sdkman/bin/sdkman-init.sh"
```
最后,运行以下代码片段来确认安装成功:
```shell
sdk version
```
您应该看到包含最新脚本和本机版本的输出:
```shell
SDKMAN!
script: 5.19.0
native: 0.6.0 (macos aarch64)
```
## 使用指南
以下是基于 SDKMAN! 文档整理的 **Java SDK 管理命令及详细解释**,按照使用流程排列:
### 查看Java版本
```shell
sdk list java
```
查看所有 [Java 发行版](https://sdkman.io/jdks)(如 Zulu、AdoptOpenJDK、Amazon Corretto 等)及版本列表。

* **关键字段**:`Identifier` 是安装时使用的唯一标识符(如 `21.0.6-tem`)。
### JDK的安装与卸载
**安装指定版本的 Java**
```shell
sdk install java $Identifier
```
* 如果不输入`$Identifier`的话,会自动安装最新的稳定版本。
* Eclipse Temurin 作为默认 JDK,因为它被广泛认为是 OpenJDK 发行版的事实标准。
**卸载已安装的 Java 版本**
```shell
sdk uninstall java $Identifier
```
### JDK版本管理
**切换 Java 版本(当前会话有效)**
```shell
sdk use java $Identifier
```
**设置全局默认 Java 版本**
```shell
sdk default java $Identifier
```
**查看当前 Java 版本**
```shell
sdk current java
```
================================================
FILE: src/md/installation-guide/dev-env/nodejs/Corepack.md
================================================
---
title: Corepack核心包管理工具
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-03-15
category: 包管理器
tag:
- npm
- pnpm
- yarn
---
# Corepack核心包管理工具
主要官方来源:[Nodejs官网文档](https://nodejs.org/api/corepack.html) | [Github](https://github.com/nodejs/corepack)
> Corepack 作为一个内置于 Node.js 工具,为开发者解决了包管理器(`Yarn`、`npm` 和 `pnpm` )版本不一致和兼容性问题。
## 安装Corepack
从 Node.js 16.x 开始,Corepack 已经内置在 Node.js 中,所以只要安装 Node.js,就可以直接使用 Corepack。如果需要手动安装,可以参考 [Github 官方文档](https://github.com/nodejs/corepack?tab=readme-ov-file#manual-installs)。
**验证安装**
```shell
corepack -v
```
**Corepack更新**
* 用于解决 [Corepack 中的签名过时](https://github.com/nodejs/corepack/issues/612) 问题
```shell
npm install --global corepack@latest
```
## 启用/禁用 Corepack
* [Corepack](https://github.com/nodejs/corepack) 默认是实验性工具,需要手动启用。
```shell
# 启用
corepack enable
```
启用后,它会自动为你管理所需的包管理器版本。
```shell
# 禁用
corepack disable
```
## 管理包管理器的版本
Corepack 使得你能够轻松管理不同版本的包管理器。比如你可以为项目指定特定版本的 `npm`、`Yarn` 或 `pnpm`。
### 安装[pnpm](https://pnpm.io/zh/)
> 快速的,节省磁盘空间的包管理工具。pnpm 比 npm 快 2 倍。
**安装并启用:**
```shell
corepack prepare pnpm@latest --activate
```
**验证安装:**
```shell
pnpm --version
```
**固定项目使用的版本:**
```shell
corepack use pnpm@latest-10
```
这会将 `pnpm` 的版本信息添加到 `package.json` 中的 `packageManager` 字段。
### 安装[Yarn](https://yarnpkg.com/)
[Github](https://github.com/yarnpkg/yarn)
> Yarn 是 Facebook 开发的一个快速、安全、稳定的包管理器,特别适用于大型项目。
**安装并启用:**
* 稳定版本:1.22.22
```shell
corepack prepare yarn@1.22.22 --activate
```
**验证安装:**
```shell
yarn --version
```
**固定项目使用的版本:**
```shell
corepack use yarn@1.22.22
```
在 `package.json` 中,会看到类似以下内容:
```shell
{
"packageManager": "yarn@1.22.22"
}
```
这样,Corepack 会根据该配置自动管理 Yarn 的版本。
================================================
FILE: src/md/installation-guide/dev-env/nodejs/nrm.md
================================================
---
title: npm源切换加速利器—nrm
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-03-17
category: 包管理器
tags:
- nrm
- 镜像
---
# npm源切换加速利器—nrm
主要官方来源:[npmjs-nrm](https://www.npmjs.com/package/nrm)
> `nrm`可以帮助您轻松快速地切换不同的 npm 注册表。它支持 `npm` 、 `cnpm` 、 `taobao` 、 `yarn` 、 `tencent` 、 `npmMirror`和`huawei` 。
## 安装nrm
```shell
# npm 安装
npm install -g nrm
```
安装成功后,使用`nrm --version`查看命令,验证是否安装正常。
## 使用指南
### nrm ls
查看源列表
```shell
$ nrm ls
* npm ---------- https://registry.npmjs.org/
yarn --------- https://registry.yarnpkg.com/
tencent ------ https://mirrors.tencent.com/npm/
cnpm --------- https://r.cnpmjs.org/
taobao ------- https://registry.npmmirror.com/
npmMirror ---- https://skimdb.npmjs.com/registry/
huawei ------- https://repo.huaweicloud.com/repository/npm/
```
### nrm use
切换镜像
```shell
$ nrm use taobao
SUCCESS The registry has been changed to 'taobao'.
```
### nrm current
查看当前源
```shell
$ nrm current
You are using taobao registry.
```
### nrm test
测试所有源的响应时间
```shell
$ nrm test
npm ---------- 823 ms
yarn --------- 799 ms
tencent ------ 964 ms
cnpm --------- 1882 ms
* taobao ------- 184 ms
npmMirror ---- 871 ms
huawei ------- 845 ms
```
### nrm add
添加镜像源
```shell
$ nrm add <源名> <源URL>
```
### nrm del
删除镜像源
```shell
nrm del <源名>
```
## 统一切换npm,pnpm,yarn镜像源
使用 `nrm` 切换镜像源时,通常会修改 `.npmrc` 配置文件,这会同时影响 `npm` 和 `pnpm`。
```
nrm use huawei
```
* 验证 `npm` 镜像源:
```shell
npm config get registry
```
* 验证 `pnpm` 镜像源:
```shell
pnpm config get registry
```
为了确保`nrm use`命令, `yarn` 也同步更新镜像源,在 `~/.zshrc`中中添加以下内容:
```shell
nrm() {
if [ "$1" = "use" ] && [ -n "$2" ]; then
command nrm use "$2"
yarn config set registry $(npm config get registry)
echo "Yarn registry updated to $(yarn config get registry)"
else
command nrm "$@"
fi
}
```
执行`source ~/.zshrc`后,验证 `yarn` 镜像源:
```shell
yarn config get registry
```
================================================
FILE: src/md/installation-guide/dev-env/nodejs/nvm.md
================================================
---
title: Node.js版本管理神器—nvm
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-03-15
category: 包管理器
tags:
- nvm
---
# Node.js版本管理神器—nvm
主要官方来源:[nvm Github](https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating)
> `nvm`是 [node.js](https://nodejs.org/zh-cn) 的版本管理器,允许您通过命令行快速安装和使用不同版本的 node。
## 安装nvm
手动下载并运行 [安装脚本](https://github.com/nvm-sh/nvm/blob/v0.40.2/install.sh),或使用**命令行安装**(`cURL` 或 `Wget`):
```shell
# 使用 curl 安装
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
# 使用 wget 安装
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
```
脚本会自动**配置环境变量**(`~/.zshrc`下):
```shell
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # 加载 nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # 加载 nvm bash_completion
```
* 自行修改后,需执行 `source ~/.zshrc`
**验证安装**
```shell
nvm --version
```
> 注意:[nvm](https://github.com/nvm-sh/nvm) 的维护者明确表示 `brew` 不是官方推荐的安装方式。
## 使用指南
### 查看所有可用版本
```shell
nvm ls-remote --lts # 查看所有长期支持 (LTS) 版本
nvm ls-remote # 查看所有可用版本
```
### 安装
```shell
nvm install <version> # 安装指定版本(如 nvm install 20)
nvm install --lts # 安装最新的 LTS 版本
nvm install node # 安装最新的稳定版本
```
### 切换版本
```shell
nvm use <version> # 切换到指定版本(如 nvm use 16)
nvm use default # 切换到默认版本
```
### 设置默认版本
```shell
nvm alias default <version> # 设置默认版本(如 nvm alias default 18)
```
### 列出已安装的版本
```shell
nvm list # 列出本地已安装的 Node.js 版本
nvm ls # 同上,显示已安装的版本
```
### 当前版本
```shell
node -v # 显示当前 Node.js 版本
nvm current # 显示当前 NVM 管理的 Node.js 版本
```
### 卸载
```shell
nvm uninstall <version> # 卸载指定版本(如 nvm uninstall 16)
```
================================================
FILE: src/md/installation-guide/os/windows-office-activation.md
================================================
---
title: Windows、Office激活密钥,脚本,程序
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-04-23
category: 激活
tag:
- Windows
- Office
---
# Windows、Office激活密钥,脚本,程序
## ① 微软正版秘钥(官方)
### 01.Windows系统激活
1. `Win+R` 打开终端,输入命令
```shell
slui 3
```
2. 打开“系统激活”窗口,点击“更改”按钮

3. 输入“秘钥”,点击“下一页” 进行 “激活” !获取 [微软Windows官方正版秘钥](https://learn.microsoft.com/zh-cn/windows-server/get-started/kms-client-activation-keys)

4. “激活”成功

### 02.Office软件激活
1. **打开Office应用程序:** 启动`Word`、`Excel`或`PowerPoint`等
2. **访问文件菜单:** 在应用程序中,点击左上角的"文件"菜单
3. **点击账户:** 在文件菜单中,选择"账户"
4. **更改产品密钥:** 在账户页面,找到并点击"更改产品密钥"
5. **输入产品密钥:** 在弹出的对话框中输入你的25位密钥 !获取 [微软Office官方正版秘钥](https://learn.microsoft.com/zh-cn/deployoffice/vlactivation/gvlks)
6. **激活Office:** 输入密钥后,点击"继续"或"激活产品"
## ② 激活脚本(原理)
> 一键激活脚本:[https://wwi.lanzoup.com/b0foh27ne](https://wwi.lanzoup.com/b0foh27ne), 密码:`gkjb`

### 01.脚本激活命令
**将密钥写入系统,实现激活**
```shell
slmgr /ipk XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
```
如果你有新的零售产品密钥,将 `X` 替换为实际的密钥,运行以上命令即可激活
### 02.脚本激活网站推荐
[KMS一键激活windows/office网站](https://kms.cx/)

## ③ 激活程序(推荐)
> 获取 [一键激活程序](https://m.tb.cn/h.g0ZtnKz?tk=OoXyWIKR74J) ,提供多种激活方式

::: note 注意:使用一键激活程序,需先关闭电脑相关的杀毒程序
* [关闭 Windows 安全中心中的Defender 防病毒保护](https://support.microsoft.com/zh-cn/windows/%E5%85%B3%E9%97%AD-windows-%E5%AE%89%E5%85%A8%E4%B8%AD%E5%BF%83%E4%B8%AD%E7%9A%84defender-%E9%98%B2%E7%97%85%E6%AF%92%E4%BF%9D%E6%8A%A4-99e6004f-c54c-8509-773c-a4d776b77960)
* [360安全卫士设置白名单](http://www.fastaux.com/index.php?c=show&id=54)
* [360杀毒软件怎么添加文件白名单](https://www.eyunsou.com/360sd/gongnneg/bmd/)
:::
### 01.数字激活工具 HWID_KMS38_CN_62
**概述**
`HWID_KMS38_CN_62.exe` 是一种**数字激活工具**,主要用于激活 Microsoft Windows 操作系统。它采用 HWID 技术,生成硬件标识符并将其发送到
Microsoft 的激活服务器进行验证,实现系统长期激活。
**激活步骤**
1. 鼠标右键点击“打开”,进入程序中

2. 进入程序界面后,工作模式选择“==安装数字密钥==(HWID)”,点击“开始”

3. 完成后执行[一键激活脚本](#一键激活脚本)中的`06.查看是否永久激活.bat`验证激活状态

### 02.KMS激活工具 DragonKMS
互联网论坛上的知名激活工具,也是我个人常用的激活工具,常用于激活Windows和Office全家桶,通过联网KMS激活

### 03.开源激活工具 HEU_KMS_Activator
仅供研究激活原理使用,在“智能激活”中点击“开始”,即按照最佳激活方式"数字许可证/KMS38/OEM/KMS"依次激活,直到激活成功

等待一会,激活成功后提示

### 04.小马激活工具 KMS10
老牌激活工具,文件大小仅1M,我以前还用来激活Win7,可以想象年代的久远。支持离线激活,永久有效,无需考虑激活时限。office版本为retail的用户请自行转换版本到volume,即channel
switch。

### 05.大神制作 W10DigitalActivation
大神Ratiborus制作的,它还有开发激活Office的 **KMSAuto++** 工具,以及可定制化安装Office的 **Office2013-2021 C2R Install**
。可以关注它的[Twitter](https://twitter.com/ratiborus58)。


### 06.云萌激活工具 CMWTAT_Digital
云萌 Windows 10 激活工具,专门用于数字权利激活的软件。本软件是一款使用CSharp编写的 Windows 10 数字权利激活工具

================================================
FILE: src/md/java/basic/java-basic-oop.md
================================================
---
title: Java核心思想 - 面向对象编程(OOP)
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-09-13
category: Java
tags:
- JavaBasic
- OOP
---
# Java核心思想-面向对象编程(OOP)
## 什么是面向对象编程?
### 发展历史简述
- **1960 年**:类(Class)和对象(Object)的概念首次出现在 **Simula** 语言中。
- **1970 年代**:**Smalltalk** 引入了“面向对象编程(OOP)”的概念,被认为是第一个真正意义上的 OOP 语言。
- **1980 年左右**:**C++** 出现,推动了 OOP 的广泛流行。
- **今天**:大多数主流语言都支持 OOP(Java、C++、Python、C#、Ruby、JavaScript、Go、Scala、PHP 等)。
### 类和对象
面向对象编程中有两个非常重要、非常基础的概念,那就是**类(Cass)** 和**对象(Object)**。
* **类(Class)** 是指对某一类事物的抽象描述,包含属性和方法。
* **对象(Object)** 是类的实例,是在程序中具体存在的实体。
### 核心定义
* **面向对象编程(OOP, Object-Oriented Programming)** 是一种编程范式或编程风格。它以**类**或**对象**作为组织代码的基本单元,并将**封装**、**抽象**、**继承**、**多态**四个特性,作为代码设计和实现的基石 。
* **面向对象编程语言(OOPL, Object-Oriented Programming Language)** 是支持类或对象的语法机制,并有现成的语法机制,能方便地实现面向对象编程四大特性(封装、抽象、继承、多态)的编程语言。
## 四大特性
### 封装(Encapsulation)
- 核心思想:==<u>隐藏实现、保护数据、对外提供接口</u>==。
- **实现方式:** 通过 `private`、`protected`、`public` 等权限控制,把属性隐藏起来,通过方法来操作。
- **意义:**
- 防止数据被随意修改,提高代码的**安全性和可维护性**。
- 对外只暴露必要的接口,提高类的**易用性**。
- 👉 通俗理解:**“把属性藏起来,通过方法管起来”**。
### 抽象(Abstraction)
- 核心思想:==<u>提取共性,屏蔽细节</u>==。
- **实现方式:** 接口、抽象类,或者只提供方法定义而隐藏实现。
- **意义:**
- 使用者只需关心**做什么**,不必关心**怎么做**。
- 提高代码的**扩展性和维护性**,修改实现不影响对外接口。
- 👉 通俗理解:**“只告诉你功能,不告诉你原理”**。
⚠️ 有的教程会把**抽象** 视为 **封装的一部分**(抽象 ≈ “隐藏细节、暴露共性”)
### 继承(Inheritance)
- 核心思想:==<u>子类复用父类的属性和方法</u>==,体现 `is-a` 关系。
- **模式:**
- 单继承:一个子类只能继承一个父类(Java)。
- 多继承:一个子类可继承多个父类(C++ 支持,Java 通过接口间接实现)。
- **意义:**
- 解决**代码复用**问题。
- 为多态打下基础。
- 👉 通俗理解:**“子承父业”**。
### 多态(Polymorphism)
- 核心思想:==<u>同一接口,不同实现,表现出不同行为</u>==。
- **定义:** 多态是指子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现。
- **实现方式:** 继承 + 方法重写、接口实现、duck typing(动态语言)。
- **多态的三种类型:**
1. **编译时多态(静态多态)**
- 通过**方法重载(Overload)**实现。
- 编译阶段决定调用哪个方法。
- 示例:`print(int a)` 和 `print(String s)`。
2. **运行时多态(动态多态)**
- 通过**方法重写(Override)**和**向上转型**实现。
- 运行时根据实际对象类型决定调用哪个方法。
- 示例:父类 `Animal` 的 `speak()` 被子类 `Dog`、`Cat` 重写。
3. **参数化多态(泛型多态)**
- 通过**泛型(Generics)** 实现。
- 方法或类可以操作不同类型,而无需写多份代码。
- 示例:`List<String>`、`List<Integer>` 都能用同一个 `List<T>` 实现。
- **意义:**
- 提高代码的**扩展性**(新增子类无需修改原有逻辑)。
- 提升代码的**复用性**(相同代码可适配多种对象)。
- 是**设计模式与面向对象编程技巧**的核心基础。
- 👉 通俗理解:**“一个接口,多种形态”**。
================================================
FILE: src/md/java/basic/java-common-classes.md
================================================
---
title: Java 常用类与工具
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-09-13
category: Java
tags:
- JavaBasic
---
# Java 常用类与工具
## Object 通用方法
`Object` 类是Java编程语言中的根类(基类),具有以下特点:
- **继承关系**:所有类都直接或间接继承自 `Object` 类
- **默认父类**:如果一个类没有明确指定父类,它会自动继承 `Object` 类
- **核心方法**:提供了所有对象都具备的基本方法

## 对象包装器与自动装箱
Java 为每种基本数据类型提供了对应的**包装类(Wrapper Class)**,其特点如下:
- 所有包装类位于 `java.lang` 包中,均为 `final` 类
- 包装类是引用类型,可以像对象一样使用基本类型

从 Java 5 开始,JDK 支持了**自动装箱/拆箱(Autoboxing / Unboxing)**,简化了基本类型与包装类之间的转换:
```java
Integer i = 100; // 装箱:基本类型 → 包装类对象
int j = i; // 拆箱:包装类对象 → 基本类型
```
根据 Java 自动装箱规范,部分包装类在特定范围内使用**缓存池(CachePool)** 复用对象,提高性能,避免重复创建:
- Boolean:缓存 `true` / `false`
- Character:缓存 `\u0000 ~ \u007F`(0 ~ 127)
- Byte:缓存所有取值范围 `[-128, 127]`
- Short / Integer/Long:默认缓存 `[-128, 127]`,其中 `Integer` 上限可通过 JVM 参数调整(`-XX:AutoBoxCacheMax=<size>`)
- Float / Double:不使用缓存
## String
String 是 Java 中最常用的**引用类型**之一,使用`final`修饰,具有**不可变性**(`Immutable`)。
- 位于 `java.lang` 包中
- **线程安全**,可被多个线程共享
- JDK8 底层使用`char`数组实现,JDK9+ 改用`byte`数组+ `coder`编码标志
### String API
```java
1️⃣ 字符串创建
String s = "..." → 字面量创建(常量池复用)
new String(...) → 构造函数创建(堆中新建对象)
2️⃣ 长度与空值判断
length() → 获取字符串的长度
isEmpty() → 判断是否为空(即:length == 0)
isBlank() → 判断是否为空白
3️⃣ 字符串查找
indexOf(...) → 查找子字符串首次出现位置
lastIndexOf(...) → 查找子字符串最后出现位置
contains(...) → 判断是否包含某子串
4️⃣ 字符串截取
substring(begin) → 截取子字符串(从 begin 到 结尾)
substring(begin, end) → 截取子字符串(从 begin 到 end-1)
charAt(index) → 获取指定位置字符
5️⃣ 字符串拼接
+ → 最常用
concat(...) → 辅助拼接
String.join(delimiter, ...) → 多字符串拼接
6️⃣ 字符串替换
replace(old, new) → 替换字符或子串
replaceAll(regex, replacement) → 正则全局替换
7️⃣ 大小写转换
toUpperCase() → 转大写
toLowerCase() → 转小写
8️⃣ 字符串比较
equals(...) → 精确比较
equalsIgnoreCase(...) → 忽略大小写
compareTo(...) → 字典序比较(负数/0/正数表示小于/相等/大于)
9️⃣ 类型转换与格式化
String.valueOf(...) → 基本类型转字符串
String.format(...) → 模板格式化
toCharArray() → 字符串转字符数组(char[])
```
### JDK9+ Compact Strings
- [JEP 254: Compact Strings](https://openjdk.org/jeps/254)
- 前面提到:<u>JDK8 底层使用`char`数组实现,JDK9+ 改用`byte`数组+`coder`编码标志</u>。
- **背景**:JDK8 String 使用 `char[]`,每字符占 2 字节,存储 ASCII/Latin1 时存在内存浪费。
- **优化方案**:JDK9 起改为 `byte[] + coder`,根据字符串内容自动选择最优编码方式:
- `Latin1` 编码 → 每个字符占 1 字节
- `UTF-16` 编码 → 每个字符占 2 字节
- **效果**:减少内存占用,提高缓存命中率,且 API 保持兼容。
### [Java21 String Templates](/md/java/features/Java21/jep430-string-templates.html)
### 内存分配演进
1. 在 Java 中,String 是引用类型,其引用存放在**栈(Stack)** 中,对象内容存放在**堆(Heap)** 中。
2. 通过**字符串常量池(String Pool)** 缓存已创建的字面量,避免重复创建对象,提高内存利用率。
3. 利用`String.intern()`方法,将字符串对象**放入常量池**,并返回常量池中的对象引用。
**HotSpot中字符串常量池保存哪里?**
| JDK 版本 | 常量池位置 | 说明 |
|--------|--------------------------------|----------------------------------------------------------------------|
| ≤ JDK6 | **方法区(Method Area / PermGen)** | 字符串常量池在类加载阶段创建,固定大小,存储在永久代中 |
| JDK7 | **堆(Heap)** | 为了扩展灵活性,字符串常量池移到了堆,JVM 管理更方便 |
| ≥ JDK8 | **堆(Heap)** | 方法区被移除(PermGen 被 Metaspace 替代),字符串常量池仍在堆上,`String.intern()` 的对象存储在堆中 |
## Arrays
`Arrays` 类位于 `java.util` 包,是 Java 提供的**数组工具类**,特点如下:
* 方法均为 `static`,无需创建对象即可调用
* 提供对数组的排序、搜索、填充、复制、比较等操作
* 支持基础类型数组与对象数组
**Arrays API**
```java
1️⃣ 排序
Arrays.sort(arr); → 升序排序
Arrays.sort(arr, from, to); → 指定区间排序 [from, to)
Arrays.sort(arr, Collections.reverseOrder()); → 降序(对象数组)
Arrays.parallelSort(arr); → 并行排序(大数组更快)
2️⃣ 搜索
Arrays.binarySearch(arr, key); → 二分查找,数组需已排序
Arrays.binarySearch(arr, from, to, key); → 在 [from, to) 区间查找
3️⃣ 比较与哈希
Arrays.equals(arr1, arr2); → 数组内容是否相等
Arrays.deepEquals(arr1, arr2); → 多维数组内容是否相等
Arrays.hashCode(arr); → 一维数组哈希
Arrays.deepHashCode(arr); → 多维数组哈希
4️⃣ 填充与复制
Arrays.fill(arr, value); → 将数组元素全部填充为指定值
Arrays.fill(arr, from, to, value); → 填充区间 [from, to)
Arrays.copyOf(arr, newLength); → 复制并改变长度(扩容/缩容)
Arrays.copyOfRange(arr, from, to); → 复制区间 [from, to)
5️⃣ 转字符串/集合
Arrays.toString(arr); → 一维数组转字符串
Arrays.deepToString(arr); → 多维数组转字符串
Arrays.asList(arr); → 数组 → 固定大小 List 视图
6️⃣ 并行/批量操作(Java 8+)
Arrays.setAll(arr, i -> i * 2); → 顺序初始化数组
Arrays.parallelSetAll(arr, i -> i * 2); → 并行初始化数组
Arrays.parallelPrefix(arr, Integer::sum); → 前缀和计算
7️⃣ 流式 API(Java 8+)
Arrays.stream(arr); → 数组 → Stream
Arrays.stream(arr, from, to); → [from, to) 区间 → Stream
```
## Math
Math 类位于 `java.lang` 包,是 Java 提供的**数学工具类**。特点如下:
- 使用`final`修饰,具有**不可变性**(`Immutable`),线程安全
- 方法均为 `static`,无需创建对象即可调用
- 用途:支持基本运算(如加减乘除、取绝对值)、幂运算、三角函数、对数与指数运算、舍入操作,以及生成随机数等
**Math API**
```java
1️⃣ 基本数学运算
Math.abs(x) → 绝对值
Math.max(a, b) → 最大值
Math.min(a, b) → 最小值
Math.signum(x) → 符号函数 (-1/0/1)
2️⃣ 幂运算与开方
Math.pow(a, b) → a 的 b 次幂
Math.sqrt(x) → 平方根
Math.cbrt(x) → 立方根
Math.hypot(x, y) → √(x² + y²)
3️⃣ 指数与对数
Math.exp(x) → e 的 x 次幂
Math.expm1(x) → e^x - 1
Math.log(x) → 自然对数 ln(x)
Math.log10(x) → 以 10 为底的对数
Math.log1p(x) → ln(1+x),高精度
4️⃣ 三角函数
Math.sin(x) / Math.cos(x) / Math.tan(x) → 正弦/余弦/正切
Math.asin(x) / Math.acos(x) / Math.atan(x) → 反三角函数
Math.atan2(y, x) → y/x 的角度(弧度)
5️⃣ 舍入与取整
Math.ceil(x) → 向上取整
Math.floor(x) → 向下取整
Math.rint(x) → 返回最接近 x 的整数(double)
Math.round(x) → 四舍五入
Math.floorDiv(a, b) → 整数除法向下取整
Math.floorMod(a, b) → 向下取整取模
6️⃣ 随机数与常量
Math.random() → 返回 [0~1) 之间随机 double
Math.PI → π 常量
Math.E → e 常量
```
**常见用法**
```java
1️⃣ 分页计算
int pages = (int) Math.ceil(totalItems / (double) pageSize); → 向上取整
2️⃣ 随机数生成
int randInt = (int) (Math.random() * n); → 0 ~ n-1
double randDouble = Math.random() * (max - min) + min; → min ~ max
boolean flip = Math.random() < 0.5; → 随机布尔
3️⃣ 数值比较与约束
int value = Math.max(minValue, Math.min(maxValue, inputValue)); → 限定范围 [minValue, maxValue]
4️⃣ 取整与舍入
double d = 2.7;
double ceil = Math.ceil(d); → 3.0 向上取整
double floor = Math.floor(d); → 2.0 向下取整
long round = Math.round(d); → 3 四舍五入
5️⃣ 几何与距离计算
double distance = Math.hypot(x2 - x1, y2 - y1); → 两点间欧几里得距离
6️⃣ 幂运算
double area = Math.pow(radius, 2) * Math.PI; → 圆面积
```
## Random
`Random` 类位于 `java.util` 包,是 Java 提供的**伪随机数生成器**,基于 **线性同余算法(LCG)** 实现。特点如下:
- **伪随机**:由确定算法生成,种子相同会得到相同序列。
- **线程不安全**:每个 `Random` 实例在多线程中使用可能会有竞争问题。
- JDK 8 引入 `ThreadLocalRandom` 解决。
- **可复现性**:使用相同种子可生成相同随机序列。
- **多种数据类型支持**:可生成 `int`、`long`、`float`、`double`、`boolean` 等随机值。
**Random API**

**常见用法及扩展**
```java
// Random(单线程随机数)
Random random = new Random();
int min = 10, max = 20;
int randInt = random.nextInt(max - min) + min; // 区间随机整数 [min, max)
double randDouble = random.nextDouble() * (max - min) + min; // 区间随机浮点数 [min, max)
List<String> prizes = List.of("奖品A","奖品B","奖品C");
String winner = prizes.get(random.nextInt(prizes.size())); // List 随机选择
// Java 8+ 流式生成随机整数/双精度
random.ints(5, 50, 100).forEach(System.out::println);
random.doubles().limit(5).forEach(System.out::println);
// ThreadLocalRandom(多线程安全)
int tRand = ThreadLocalRandom.current().nextInt(0, 100); // 区间随机整数 [0, 100)
double tDouble = ThreadLocalRandom.current().nextDouble(); // 区间浮点数 [0.0, 1.0)
// SplittableRandom(高性能/并行流)
SplittableRandom sr = new SplittableRandom();
sr.ints(5, 50, 100).forEach(System.out::print);
sr.doubles().limit(5).forEach(System.out::println);
```
## 时间日期(Date、Calendar、LocalDateTime 等)
* [Java 日期时间API](https://www.yuque.com/yublog/nokuzy/xkk0xf)
## 序
* [lombok 使用及技巧](https://www.yuque.com/yublog/nokuzy/wmmc6g)
* [stream 使用及其技巧](https://www.yuque.com/yublog/nokuzy/dioi46)
* [lambda 使用及其技巧](https://www.yuque.com/yublog/nokuzy/mtonym)
* [自定义注解(元注解)](https://www.yuque.com/yublog/nokuzy/qb14q0)
* [反射专题-框架的灵魂](https://www.yuque.com/yublog/nokuzy/gff0zc)
================================================
FILE: src/md/java/basic/java-from-scratch.md
================================================
---
title: Java基础 - 从零开始学习Java
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2025-09-09
category: Java
tags:
- JavaBasic
---
# Java基础 - 从零开始学习Java
## 1.Java语言的发展历史
### Java特征
Java语言是美国Sun公司(Stanford University Network),在1995年推出的高级的编程语言。
**特征:**
- 面向对象(OOP)
- 跨平台性强(“一次编写,到处运行”)
- 安全性高、可移植性强
### Java之父

詹姆斯·高斯林 (James Gosling)是一名软件专家,1955年5月19日出生于加拿大,Java编程语言的共同创始人之一,一般公认他为“Java之父”。
1977年获得了加拿大卡尔加里大学计算机科学学士学位,1983年获得了美国卡内基梅隆大学计算机科学博士学位。
### 发展历史

* 2004年推出了Java 1.5版本
* 2009年Sun公司被Oracle甲骨文公司收购
* 2014年推出了Java 8.0版本
### 计算机语言发展历史
1. 第一代**机器语言** 打孔机 二进制010101
2. 第二代**汇编语言** 助记符
3. 第三代**高级编程语言** C、C++、Java、Python 、php、c#等

### Java跨平台原理
* **平台** = 操作系统(`Windows`,`Linux`,`Mac`)
* Java的程序可以在任意的操作系统上运行

## 2.下载安装使用JDK
### 下载JDK11
JDK11的下载官方网站:
[https://www.oracle.com/java/technologies/javase-jdk11-downloads.html](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html)
注意:需要注意下载对应不同操作系统版本的JDK

### 安装后目录介绍
傻瓜式安装,下一步


### 配置JDK环境变量
**1. 为什么需要配置JDK环境变量?**
不配置JDK环境变量的话,就需要每次到JDK安装路径下的Bin目录执行对应的exe文件;
在环境变量中加入软件的安装路径后,即使没有在该软件的安装目录下,我们在命令行输入软件的名称也可启动该软件。
**2.如何配置环境变量**
右键“此电脑”>>“属性”,在弹出的页面上点击高“高级系统设置”

在弹出的“系统属性”窗口中“高级”标签下点击“环境变量”按钮

在弹出的“环境变量”窗口中,点击下方的“新建”按钮,在弹出的“新建系统变量”窗口中,新建一个名为`JAVA_HOME`的环境变量,设置`Path`环境变量

验证是否配置成功,进入win+r输入cmd,输入指令`java -version`

JDK8之后的版本只需要配置`JAVA_HOME`,在PATH中添加`JAVA_HOME/bin`即可。
### JRE,JDK,JVM之间的关系

### JavaSE,JavaEE,JavaME之间的区别
Java总共有三个版本
1. **标准版Java SE**
* Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 包含了支持 Java Web 服务开发的类;
2. **企业版Java EE**
* JavaEE是在JavaSE的基础上构建的,用来开发B/S架构软件,也就是开发企业级应用,所以称为企业版帮助开发和部署可移植、健壮、可伸缩且安全的服务器端 Java 应用程序。Java EE 是在 Java SE 的基础上构建的,它提供 Web 服务、组件模型、管理和通信 API;
3. **微型Java ME**
* Java ME为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME包括灵活的用户界面、健壮的安全模式、许多内置的网络协议以及对于动态下载的连网和离线应用程序的丰富支持。基于Java ME规范的应用程序只需要编写一次,就可以用于许多设备,而且可以利用每个设备的本级功能。
**简而言之**
* JavaSE是Java的基础,主要针对桌面程序开发;
* JavaEE是针对企业级应用开发;
* JavaME是主要针对嵌入式设备软件开发。
### Dos常用命令

### 编译运行Java程序
开发java程序,需要三个步骤:**1.编写程序(源代码)>> 2.编译程序 >> 3.运行程序**
1. 新建文本文件,修改名称为`HelloWorld.java`
2. 用记事本打开,编写以下程序
```java
public class HelloWorld{
public static void main(String[] args){
System.out.println("HelloWorld!");
}
}
```
3. 打开命令提示窗口,进入`HelloWorld`所在目录,输入编译和执行命令
```shell
# 编译,生成 .class 字节码文件
javac -encoding UTF-8 HelloWorld.java
# 运行程序(执行字节码)
java HelloWorld
```

## 3.Java基础语法
### Java注释
注释是指在程序指定的位置添加的说明信息,不参与运行。**Java 支持三种注释方式:**
1. 单行:`// 注释内容`
2. 多行:`/* 注释内容 */`
3. 文档注释:`/** 注释内容 */`

### 什么是关键字
**Java关键字**是电脑语言里事先定义的,**有特别意义的标识符**,有时又叫保留字。
一律用**小写字母标志**,根据用途分为如下分组:
1. **数据类型**:`boolean`、`byte`、`char`、 `double`、 `false`、`float`、`int`、`long`、`new`、`short`、`true`、`void`、`instanceof`。
2. **语句控制**: `break`、`case`、 `catch`、 `continue`、 `default` 、`do`、 `else`、 `for`、 `if`、`return`、`switch`、`try`、 `while`、 `finally`、 `throw`、`this`、 `super`。
3. **修饰符**: `abstract`、`final`、`native`、`private`、 `protected`、`public`、`static`、`synchronized`、`transient`、 `volatile`。
4. **用于类,方法,包,接口和异常**:`class`、 `extends`、 `implements`、`interface`、 `package`、`import`、`throws`。
### 常量与变量
- **常量**:Java中使用`final` 修饰,表示运行中不可变化的量。
- **变量**:在程序运行过程中,可以取不同数值的量;可变,需先声明后使用。
- 语法:变量的数据类型 变量名称 = 变量的值(赋值操作);
- 为整数常量,浮点数常量,字符常量,字符串常量,布尔常量(true,false),NULL是常量
- 命名规则:字母、数字、下划线 `_`、$ 符号开头,不能以数字开头,遵循驼峰命名法
### Java变量命名规则
1. 不能使用Java中的关键字,比如public class void int char等等..
2. 变量名必须以 字母 下划线_ 或者 $ 符号开头
3. 变量名可以包含数字,但是不能够以数字开头
4. 变量名除了 下划线_ 或者 $ 符号以外不能包含其他任何特殊字符
**驼峰命名法**

### 存储单位与数据类型
**常见存储单位换算**
数据必须首先在计算机内被表示,然后才能被计算机处理。计算机表示数据的部件主要是存储设备;而存储数据的具体单位是**存储单元**;因此,了解存储单元的结构是十分必要的。
```shell
1 Byte(字节)= 8 bit(位)
1 KB = 1024 Byte
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB
1 PB = 1024 TB
1 EB = 1024 PB
1 ZB = 1024 EB
```
* 计算机中存储设备的最小单元叫”位(bit)”,又称为“比特位”,用小写字母b表示。
* 计算机中最小存储单元叫”字节(byte)”,用大写字母B表示,字节由8个位组成。
**Java中的数据类型**
Java语言是强类型语言,对于每一个数据都给出明确的数据类型,不同的数据类型也分配了不同的内存空间,所以它们表示的数据大小也是不一样的。

| **数据类型** | **类型** | **内存占用** | **取值范围** |
| -------- | -------------- | -------- | ---------------------------------------------------------------- |
| **整数** | **byte** | 1字节 | -128~127 |
| | **short** | 2字节 | -32768-32767 |
| | **int(默认)** | 4字节 | -2的31次方到2的31次方-1 |
| | **long** | 8字节 | -2的63次方到2的63次方-1 |
| **浮点数** | **float** | 4字节 | 负数:-3.402823E+38到-1.401298E-45<br>正数:-1.401298E-45到3.402823E+38 |
| | **double(默认)** | 8字节 | 负数:-1.797693E+308到-4.9000000E-324<br>正数:4.9000000E到1.797693E+308 |
| **字符** | **char** | 2字节 | 0-65535 |
| **布尔** | **boolean** | 1字节 | true,false |
说明:E+38表示是乘以10的38次方,同样,E-45表示乘以10的-45次方。
### 类型转换
在 java 程序中,不同的基本类型的值经常需要进行相互类型转换,类型转换分为**自动类型转换**和**强制类型转换**。

**自动类型转换**: <u>把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量。</u>
* 例如:`double a = 10;`
* **规律**
- 小的类型自动转化为大的类型
- 整数类型可以自动转化为浮点类型,可能会产生舍入误差
- 字符可以自动提升为整数
**强制类型转换**:<u>把一个表示数据范围大的数值或者变量赋值给另一个表示数据范围小的变量。</u>
* 例如:`int j = (int) 99.99;`
* 在要强制类型转换的前面加上括号,然后在括号里面加上你要转换的类型(强制转换需要程序员手动处理)
### 运算符
* **运算符**:对常量或者变量进行操作的符号
* **表达式**:用运算符吧常量或者变量连接起来的符号
#### 算术运算符
| **操作符** | **说明** | **举例** |
| ------- | ------ | --------------- |
| **+** | **加** | **加法** |
| **-** | **减** | **减法** |
| **\*** | **乘** | **乘法** |
| **/** | **除** | **除法** |
| **%** | **取余** | **得到两个数做除法的余数** |
| **++** | **自增** | **变量的值+1** |
| **--** | **自减** | **变量的值-1** |
**搞清楚`i++`,`++i`,`i--`,`--i`的区别?**
* `++i`,表示参与运算之前先自加1.
* `i++`,表示参与运算以后再加1.
* `--i`,`i--` 类似。
#### 关系运算符
| **操作符** | **说明** |
| ------- | ------------------------------------ |
| **==** | **检查如果两个操作数的值是否相等,如果相等则条件为真。** |
| **!=** | **检查如果两个操作数的值是否相等,如果值不相等则条件为真。** |
| **>** | **检查左操作数的值是否大于右操作数的值,如果是那么条件为真。** |
| **<** | **检查左操作数的值是否小于右操作数的值,如果是那么条件为真。** |
| **>=** | **检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。** |
| **<=** | **检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。** |
* 注意事项:关系运算符的结果都是boolean类型,要么是true,要么是false。
* 千万不要把“==”误写成“=”,“==”是判断是否相等的关系,“=”是赋值。
#### 位运算符
| **操作符** | **说明** |
| ------- | -------------------------------------- |
| **&** | 如果相对应位都是1,则结果为1,否则为0 |
| \| | 如果相对应位都是 0,则结果为 0,否则为 1 |
| **〜** | 按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 |
| **^** | 如果相对应位值相同,则结果为0,否则为1 |
| **<<** | 按位左移运算符。左操作数按位左移右操作数指定的位数。左移一位相当于将原数*2 |
| **>>** | 按位右移运算符。左操作数按位右移右操作数指定的位数。右移一位相当于将原数/2 |
#### 逻辑运算符
逻辑运算符把各个运算的关系表达式联系起来组成一个复杂的逻辑表达式,以判断程序中的表达式是否成立,判断结果是`true`或`false`。
| **操作符** | **说明** | **举例** |
| ------- | --------- | --------------------------------------- |
| **&&** | 逻辑与 运算符。 | 当且仅当两个操作数都为真,条件才为真。 |
| \|\| | 逻辑或 操作符。 | 如果任何两个操作数任何一个为真,条件为真。 |
| **^** | 逻辑异或 操作符。 | 如果任意两个操作数结构不相同,条件为真,否则条件假 |
| **!** | 逻辑非 运算符。 | 用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。 |
#### 短路运算符
| **操作符** | **说明** | **举例** |
| ------- | ------ | ----------------- |
| **&&** | 短路与 | 作用和 & 相同,但是有短路效果 |
| \|\| | 短路或 | 作用和 \| 相同,但是有短路效果 |
* 短路与 &&:如果左边为真,右边执行;如果左边为假,右边不执行。
* 短路或 ||:如果左边为假,右边执行;如果左边为真,右边不执行。
#### 三元运算符 ( ? : )
* **语法是:“条件表达式 ? 表达式1 : 表达式2”;**
* `?`前面的位置是判断的条件,判断结果为`boolean`型
* 为`true`时调用**表达式1**,为`false`时调用**表达式2**

### Scanner打印机用法
```java
import java.util.Scanner; // ① 导包
public class ScannerDemo {
public static void main(String[] args) {
// ② 创建对象
Scanner scan = new Scanner(System.in);
// ③ 接收数据
System.out.print("请输入你的名字:");
String name = scan.nextLine(); // 接收字符串
System.out.print("请输入你的年龄:");
int age = scan.nextInt(); // 接收整数
System.out.print("请输入你的身高(米):");
double height = scan.nextDouble(); // 接收小数
// 输出结果
System.out.println("------ 信息展示 ------");
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
System.out.println("身高:" + height + " 米");
// 关闭Scanner(养成好习惯)
scan.close();
}
}
```
### 流程控制语句
#### 顺序结构
是程序中最简单的流程控制,按照代码执行的先后顺序,依次执行,程序中的大多数代码都是这样执行的。

#### 分支结构(if,switch)
选择结构也被称为分支结构。选择结构有特定的语法规则,代码要执行具体的逻辑运算进行判断,逻辑运算的结果有两个,所以产生选择,按照不同的选择执行不同的代码。
##### if语句
```java
// 语法
if(布尔表达式){
语句体
}
```

##### if-else语句
```java
// 语法
f(关系表达式) {
语句体1;
} else {
语句体2;
}
```

##### 多重if-else语句
```java
// 语法
if (判断条件1) {
执行语句1
} else if (判断条件2) {
执行语句2
}
...
else if (判断条件n) {
执行语句n
} else {
执行语句n+1
}
```

##### switch语句
```java
// 语法
switch(表达式) {
case目标值1:
语句体1;
break;
case目标值2:
语句体2;
break;
…
default:
语句体n+1;
break;
}
```

#### 循环结构(for,while,do..while)
循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将一直执行下去,形成死循环。
##### for循环
```java
// 语法
for(初始化表达式;布尔表达式;步进表达式){
循环体
}
```

##### **while循环**
```java
// 语法
while(布尔表达式) {
循环体语句;
}
// 扩展格式
初始化表达式①
while(布尔表达式②){
循环体③
步进表达式④
}
```

##### **do while循环**
```java
// 语法
do{
循环体语句;
}while(布尔表达式);
// 扩展格式
初始化表达式①
do{
循环体③
步进表达式④
}while(布尔表达式②);
```

##### 三种不同循环的区别
* `do…while`循环至少会执行一次循环体。
* `for`循环和`while`循环只有在条件成立的时候才会去执行循环体
* `for`循环语句和while循环语句的小区别:
**使用区别:** 控制条件语句所控制的那个变量,在for循环结束后,就不能再被访问到了,而while循环结束还可以继续使用,如果你想继续使用,就用while,否则推荐使用for。原因是for循环结束,该变量就从内存中消失,能够提高内存的使用效率。
#### break和contiune区别
* `break`直接中断当前的整个循环,`continue`跳出本次的循环进入下一次。
* `continue`只能在循环中进行使用。
#### 嵌套for循环语句
可以通过带**标记**的`break`和`continue`结束或跳出多重循环。

## 4.Java 方法
### 什么是方法?
方法的本意是**功能块**,就是实现某个功能的语句块的集合。
### 方法的定义与调用
```java
// 语法
修饰符 返回类型 方法名(参数列表) {
// 方法体:具体执行的代码
return 返回值; // 如果有返回类型,必须返回相应类型的值
}
```
各部分解释:
1. 修饰符(modifier):如 `public`, `private`, `static`,控制方法的访问范围和行为
2. 返回类型(return type):方法执行后返回的数据类型,如果不返回值则写 `void`
3. 方法名(method name):方法的名字,命名规则和变量名类似
4. 参数列表(parameters):方法执行所需的外部数据,可以没有参数
5. 方法体(body):实际执行的操作
6. 返回值(return):方法执行后返回的结果,如果返回类型是 `void`,则无需 `return`
**方法的调用**
```java
public class MethodInvoke {
// 静态方法
public static void staticMethod() {
System.out.println("这是静态方法");
}
// 无参数、无返回值
public void sayHello() {
System.out.println("Hello, Java!");
}
// 有参数
public void greet(String name) {
System.out.println("Hello, " + name + "!");
}
// 有返回值
public int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
// 调用静态方法
MethodInvoke.staticMethod();
// 创建对象,调用非静态方法
MethodInvoke invoke = new MethodInvoke();
invoke.sayHello(); // 输出问候
invoke.greet("Alice"); // 输出个性化问候
System.out.println(invoke.add(5, 7)); // 输出 12
}
}
```
### 方法的重载
**定义:** 重载就是在一个类中,有相同的函数名称,但形参不同的函数。
* 返回类型可以相同,也可以不同
* **仅靠返回类型不同不能构成重载**
```java
public class OverloadDemo {
public void show() {
System.out.println("无参数方法");
}
public void show(String name) {
System.out.println("一个参数:" + name);
}
public void show(String name, int age) {
System.out.println("两个参数:" + name + ", " + age);
}
public static void main(String[] args) {
OverloadDemo demo = new OverloadDemo();
demo.show(); // 调用无参数方法
demo.show("Alice"); // 调用一个参数方法
demo.show("Bob", 25); // 调用两个参数方法
}
}
输出:
无参数方法
一个参数:Alice
两个参数:Bob, 25
```
### 命令行传参
有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给`main()`函数实现。
```java
public class CommandLine {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("args[" + i + "]: " + args[i]);
}
}
}
```
运行方式(文件名为 `CommandLine.java`):
```shell
javac CommandLine.java
java CommandLine hello world 123
输出结果:
args[0]: hello
args[1]: world
args[2]: 123
```
### 可变参数(...)
在 Java 里,**可变参数(varargs)** 用来让方法接收不定数量的参数。
```java
// 语法
返回类型 方法名(参数类型... 参数名) { }
```
**可变参数求最大值案例:**
```java
public class VarArgsMax {
// 使用可变参数求最大值
public static void printMax(double... numbers) {
if (numbers.length == 0) {
System.out.println("未传递参数");
return;
}
double result = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > result) {
result = numbers[i];
}
}
System.out.println("最大值是 " + result);
}
public static void main(String[] args) {
printMax(1.2, 3.4, 0.5); // 多个参数
printMax(10); // 单个参数
printMax(); // 没有参数
printMax(new double[]{7.7, 9.9, 8.8}); // 传数组
}
}
```
### 递归(recursion)
👉 递归本质就是就是:**方法自己调用自己**。
递归结构包含两个部分:
- **递归头**:终止条件(避免无限调用)
- **递归体**:继续调用自身(问题规模要缩小)
#### 阶乘(Factorial)
```java
public class RecursionDemo {
// 计算 n 的阶乘:n! = n * (n-1) * (n-2) * ... * 1
public static int factorial(int n) {
if (n == 1) return 1; // 递归头
return n * factorial(n - 1); // 递归体
}
public static void main(String[] args) {
System.out.println("5! = " + factorial(5)); // 输出 120
}
}
```
#### 斐波那契(Fibonacci Sequence)
```java
public class FibonacciDemo {
/**
* 斐波那契数列(Fibonacci Sequence)
* 特点:
* 1. 第1项 = 1,第2项 = 1(固定)
* 2. 从第3项开始,每一项 = 前两项之和
* 数学公式:
* F(1) = 1
* F(2) = 1
* F(n) = F(n-1) + F(n-2) (n >= 3)
*
* 示例:
* 第1项:1
* 第2项:1
* 第3项:2 (1+1)
* 第4项:3 (2+1)
* 第5项:5 (3+2)
* 数列:1, 1, 2, 3, 5, 8, 13, 21, 34, ...
*/
// 使用递归实现斐波那契
public static int fib(int n) {
// 递归出口:第1项或第2项,直接返回1
if (n == 1 || n == 2) return 1;
// 递归体:第n项 = 前两项之和
return fib(n - 1) + fib(n - 2);
}
public static void main(String[] args) {
// 输出前10项
for (int i = 1; i <= 10; i++) {
System.out.print(fib(i) + " ");
}
}
}
```
## 5.Java 数组(Array)
### 什么是数组?
定义:数组是**相同数据类型元素**的有序集合,具有以下特点:
- **连续存储**:数组在内存中占用连续的存储空间。
- **下标访问**:每个元素通过唯一索引访问,下标从0开始。
- **长度固定**:一旦创建,长度不可改变。
- **类型统一**:数组中的所有元素必须是相同类型,可以是基本类型或引用类型。
- **数组是对象**:在Java中,数组属于引用类型,存储在堆内存中,数组元素类似对象的成员变量。
### 数组声明与创建
**声明**
```java
// 声明,以 int 为例
int[] numbers; // ✅ 推荐写法
int numbers2[];
```
**创建**
```java
int[] numbers = new int[5]; // 创建一个长度为5的int数组
```
**访问元素**
* 数组索引从 0 开始,到 length - 1 结束。
* 使用 `数组名[索引]` 访问元素。
```java
numbers[0] = 10; // 修改第一个元素
int first = numbers[0]; // 访问第一个元素
System.out.println(numbers[0]);
```
注意:数组下标范围 `[0, length-1]`,越界会抛出 `ArrayIndexOutOfBoundsException`。
### 数组初始化方式
```java
① 静态初始化
int[] a = {1, 2, 3};
Man[] mans = {new Man(1,1),new Man(2,2)};
② 动态初始化
int[] a = new int[2];
a[0] = 1;
a[1] = 2;
③ 数组的默认初始化
当使用动态初始化时,数组元素会自动被赋予该类型的默认值
```
### 数组内存分析
**先了解Java 内存模型**

数组对象存储在**堆内存**中。
数组变量本身在栈内存中保存**堆地址引用**。
每个线程都有独立的程序计数器(PC),控制执行流程。

### 反转数组
```java
public void reverse(int[] nums) {
int left = 0, right = nums.length - 1;
while (left < right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
}
```
### java.util.Arrays 类
```java
import java.util.Arrays;
public class ArraysDemo {
public static void main(String[] args) {
// 初始化一个数组
int[] a = {1, 6, 8, 19, 1000, 999, 178, -1, 0, 5};
System.out.println("原始数组: " + Arrays.toString(a));
// 1. 排序(升序)
Arrays.sort(a);
System.out.println("排序后: " + Arrays.toString(a));
// 2. 二分查找(前提是数组已排序)
int index = Arrays.binarySearch(a, 19);
System.out.println("数字 19 的索引: " + index);
// 3. 填充数组
int[] b = new int[5];
Arrays.fill(b, 7);
System.out.println("填充后的数组: " + Arrays.toString(b));
// 4. 数组复制(扩容)
int[] c = Arrays.copyOf(a, 15);
System.out.println("扩容后的数组: " + Arrays.toString(c));
// 5. 部分复制
int[] d = Arrays.copyOfRange(a, 2, 6); // 下标 [2,6) System.out.println("部分复制: " + Arrays.toString(d));
// 6. 比较数组是否相等
int[] e = { -1, 0, 1, 5, 6, 8, 19, 178, 999, 1000 };
Arrays.sort(e); // 确保顺序一致
System.out.println("数组a与数组e是否相等: " + Arrays.equals(a, e));
// 7. 多维数组打印
int[][] f = {{1, 2}, {3, 4, 5}};
System.out.println("二维数组: " + Arrays.deepToString(f));
// 8. 并行排序(大数组时更快)
int[] g = {10, 9, 8, 7, 6, 5};
Arrays.parallelSort(g);
System.out.println("并行排序结果: " + Arrays.toString(g));
}
}
```
### 冒泡排序
冒泡的代码还是相当简单的。两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。
```java
import java.util.Arrays;
// 冒泡排序
public class BubbleSortDemo {
public static void main(String[] args) {
int[] a = {1, 6, 8, 19, 1000, 999, 178, -1, 0, 5};
bubbleSort(a);
System.out.println("冒泡排序后: " + Arrays.toString(a));
}
public static void bubbleSort(int[] array) {
// 外层循环控制轮数
for (int i = 0; i < array.length - 1; i++) {
boolean swapped = false; // 标记本轮是否发生过交换
// 内层循环控制比较和交换
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
swapped = true;
}
}
if (!swapped) break;
}
}
}
```
================================================
FILE: src/md/java/datetime/README.md
================================================
---
title: Java 日期时间
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2026-02-03
category: Java Dates
tags:
- date-time
---
# Java 日期时间
> 此文参考文献:[【howtodoinjava】-Java 日期时间教程](https://howtodoinjava.com/java/date-time/guides-java-date-time/)
长期以来,传统的 Java API 一直是 Java 开发人员的一大痛点。随着[Java 8](https://howtodoinjava.com/java-8-tutorial/)版本([JSR-310](https://jcp.org/en/jsr/detail?id=310)
)的发布,`java.time`包引入了新的[不可变](https://howtodoinjava.com/java/basics/how-to-make-a-java-class-immutable/)类,解决了原有类存在的问题。
以下文章旨在帮助您开始使用[新的日期时间 API ](/md/java/date-time/intro-to-date-time-api)的一些常见任务。
## 1. 获取当前日期和时间
- [获取当前日期和时间](/md/java/datetime/datetime)
- [获取当前时间戳](/md/java/datetime/timestamp)
- [获取当前用户区域设置、国际化](/md/java/datetime/locale)
## 2. 比较日期和时间
- [日期比较](/md/java/datetime/compare-dates)
- [ZonedDateTime 和 OffsetDateTime 的区别](/md/java/datetime/zoneddatetime-vs-offsetdatetime)
## 3. 转换日期和时间
- [转换日期时间实例](/md/java/datetime/convert-dates)
## 4. 将字符串解析为日期
- [Java 日期格式验证](https://howtodoinjava.com/java/date-time/date-validation/)
- [将字符串转换为 UTC 日期时间](https://howtodoinjava.com/java/date-time/parse-string-to-date-time-utc-gmt/)
- [将字符串转换为 ZonedDateTime](https://howtodoinjava.com/java/date-time/zoneddatetime-parse/)
- [将字符串转换为本地日期时间](https://howtodoinjava.com/java/date-time/localdatetime-parse/)
- [将字符串转换为本地日期](https://howtodoinjava.com/java/date-time/localdate-parse-string/)
- [将字符串解析为 java.util.Date](https://howtodoinjava.com/java/date-time/java-date-examples/)
- [Java 严格、智能和宽松的日期解析](https://howtodoinjava.com/java/date-time/resolverstyle-strict-date-parsing/)
- Spring Boot 日期格式验证注解(_待办事项_)
- 验证多种日期格式(_待办事项_)
## 5. 将日期格式化为字符串
- [在 Java 中将日期格式化为字符串](https://howtodoinjava.com/java/date-time/java-date-formatting/)
- [格式化分区日期时间](https://howtodoinjava.com/java/date-time/format-zoneddatetime/)
- [格式化本地日期时间](https://howtodoinjava.com/java/date-time/format-localdatetime-to-string/)
- [格式化本地日期](https://howtodoinjava.com/java/date-time/localdate-format-example/)
- [格式 XMLGregorianCalendar](https://howtodoinjava.com/java/date-time/format-xmlgregoriancalendar-to-date-pattern/)
- [基于位置的货币格式](https://howtodoinjava.com/java/date-time/location-based-currency-formatting-in-java/)
- [基于位置的日期时间格式](https://howtodoinjava.com/java/date-time/locale-based-date-formatting/)
- [以用户时区显示本地化时间戳](https://howtodoinjava.com/java/date-time/display-localized-timestamps/)
- [以 12 小时制格式格式化日期/时间戳](https://howtodoinjava.com/java/date-time/format-time-12-hours-pattern/)
- [将毫秒级持续时间格式化为小时、分钟和秒](https://howtodoinjava.com/java/date-time/format-millis-to-hh-mm-ss/)
## 6. 日期和时间提取与处理
- [测量经过时间](https://howtodoinjava.com/java/date-time/execution-elapsed-time/)
- [两个日期之间的差异](/md/java/datetime/date-diff)
- [计算两个日期之间的天数](https://howtodoinjava.com/java/date-time/calculate-days-between-dates/)
- [获取两个日期之间的所有日期](https://howtodoinjava.com/java/date-time/dates-between-two-dates/)
- [检查日期或本地日期是否为周末。](https://howtodoinjava.com/java/date-time/check-weekend/)
- [计算两个日期之间的工作日](https://howtodoinjava.com/java/date-time/calculate-business-days/)
- [增加或减少工作日](https://howtodoinjava.com/java/date-time/add-subtract-business-days/)
- [获取下一个和上一个日期](https://howtodoinjava.com/java/date-time/java8-next-previous-date/)
- [请检查给定年份是否为闰年?](https://howtodoinjava.com/java/date-time/check-leap-year/)
- [增加或减少天数、月份和年份](https://howtodoinjava.com/java/date-time/add-days-months-years/)
- [增加或减少小时、分钟和秒](https://howtodoinjava.com/java/date-time/add-subtract-hours-minutes-seconds/)
- [从日期中获取年、月和日](https://howtodoinjava.com/java/date-time/get-year-month-day-from-date/)
- [确定约会的星期几](https://howtodoinjava.com/java/date-time/finding-day-of-week/)
- [用于匹配日期模式的正则表达式](https://howtodoinjava.com/java/regex/java-regex-date-format-validation/)
- [如何设置 JVM 时区](https://howtodoinjava.com/java/date-time/setting-jvm-timezone/)
- [一天的开始和结束](https://howtodoinjava.com/java/date-time/start-and-end-of-day/)
## 7. 日期时间 API
- [Java 本地化类](https://howtodoinjava.com/java/date-time/java-locale-api-examples/)
- [Java 类 LocalTime](https://howtodoinjava.com/java/date-time/java-localtime/)
- [Java 类 LocalDate](https://howtodoinjava.com/java/date-time/java-time-localdate-class/)
- [Java 类 LocalDateTime](https://howtodoinjava.com/java/date-time/java-localdatetime-class/)
- [Java ZonedDateTime 类](https://howtodoinjava.com/java/date-time/zoneddatetime-class/)
- Java OffsetDateTime(_待办事项_)
- [Java XMLGregorianCalendar](https://howtodoinjava.com/java/date-time/xmlgregoriancalendar-date-string-example/)
- Java SimpleDateFormat (_TODO_)
- [Java DateTimeFormatter](https://howtodoinjava.com/java/date-time/java8-datetimeformatter-example/)
- [爪哇时期](https://howtodoinjava.com/java/date-time/java8-period/)
- Java 持续时间(_待办事项_)
- [Java 星期几](https://howtodoinjava.com/java/date-time/find-dayofweek/)
- [Java 时间调整器](https://howtodoinjava.com/java/date-time/java8-temporal-adjusters/)
- [Java TemporalQuery](https://howtodoinjava.com/java/date-time/temporalquery/)
- Java InstantSource(_待办事项_)
快乐学习!
================================================
FILE: src/md/java/datetime/api.md
================================================
---
title: Java 日期时间 API
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2026-02-03
category: Java Dates
tags:
- date-time
---
# Java 日期时间 API
> 此文参考文献:
>
> - [【菜鸟教程】-Java 日期时间](https://www.runoob.com/java/java-date-time.html)
> - [【howtodoinjava】- Java 8 日期时间 API](https://howtodoinjava.com/java/date-time/intro-to-date-time-api/)
Java 主要使用两个包`java.time`和`java.util`支持日期和时间特性。 `java.time`包是在 Java 8 [JSR-310](https://jcp.org/en/jsr/detail?id=310) 中新增的,解决了旧版
`java.util.Date`和`java.util.Calendar`类的不足之处。
## 遗留 API
Java 8 之前的日期时间处理主要依赖 `Date`、`Calendar`、`SimpleDateFormat` 和 `TimeZone` 等遗留 API,本质上围绕**毫秒时间戳**进行封装、计算、格式化及时区转换。
| 类/方法 | 用途 |
|-------------------------------------------------------------------------------------------------------------------------|-----------------------------------|
| [System.currentTimeMillis()](https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#currentTimeMillis%5C(%5C)) | 获取当前时间的 **毫秒时间戳** |
| [java.util.Date](https://docs.oracle.com/javase/7/docs/api/java/util/Date.html) | 对时间戳进行封装,表示一个具体的 **时间点** |
| [java.util.Calendar](https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html) | 提供按 **年、月、日、时、分、秒** 等字段进行计算和操作的能力 |
| [java.text.SimpleDateFormat](https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html) | 负责 **日期与字符串之间的格式化与解析**,受时区和区域设置影响 |
| [java.util.TimeZone](https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html) | 表示 **时区偏移量**,可计算夏令时 |
**核心缺陷**:
旧的日期时间 API 既易出错又不直观,难以安全、清晰地表示日期与时间。
1. _可变性_:`Date` 和 `Calendar` 类是可变的,这可能导致意外的副作用和**线程安全问题**。
2. _设计缺陷_:月份从 0 开始计数,年份从 1900 开始计数,这可能导致混淆。
3. _有限的功能_:这些类缺乏对日期和时间操作的丰富支持,例如处理时区、闰秒等。
因此,其他许多第三方库(例如 [Joda-Time](https://www.joda.org/joda-time/) 或 [Apache Commons](https://commons.apache.org/) 中的类)也更加受欢迎。
## Java 8 Time API
新的日期 API 尝试解决旧类的上述问题。 它主要包含以下类:
| 类/接口 | 用途 |
| ----------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| [java.time.LocalDate](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html) | 不带时间的**日期** |
| [java.time.LocalTime](https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html) | 不带日期的**时间** |
| [java.time.Instant](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html) | 时间线上的一个**瞬间点** |
| [java.time.LocalDateTime](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html) | **日期和时间** |
| [java.time.ZonedDateTime](https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html) | 包含**时区**的完整日期和时间 |
| [java.time.OffsetDateTime](https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html) | 包含**UTC 偏移量**的完整日期和时间 |
| [java.time.Duration](https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html) | **时间量**,两个时间点之间的**时间段** |
| [java.time.Period](https://docs.oracle.com/javase/8/docs/api/java/time/Period.html) | **时间量**,两个日期之间的**日期段** |
| [java.time.format.DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) | **格式化解析器** |
| [java.time.ZoneId](https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html) | **时区标识符**(如 `Asia/Shanghai`) |
| [java.time.ZoneOffset](https://docs.oracle.com/javase/8/docs/api/java/time/ZoneOffset.html) | **UTC 偏移量**(如 `+08:00`) |
## 执行常见任务
[🐟代码小抄-Java 日期、时间常用API](https://codecopy.cn/post/suloc9)
```java
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
/**
* Java8 日期时间API的通用操作
*/
public class Java8DateTimeCommonOperations {
public static void main(String[] args) throws InterruptedException {
// 获取当前日期和时间
// 所有日期时间类都有一个工厂方法 now() 这是在 Java 8 中获取当前日期和时间的首选方法。
LocalTime currentTime = LocalTime.now();
LocalDate currentDate = LocalDate.now();
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("当前时间 (LocalTime): " + currentTime);
System.out.println("当前日期 (LocalDate): " + currentDate);
System.out.println("当前日期时间 (LocalDateTime): " + currentDateTime);
// 解析日期和时间
// 日期解析是借助 DateTimeFormatter 类和日期时间类中的 parse() 方法完成的。
String dateString = "2026-02-04 12:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime parsedDateTime = LocalDateTime.parse(dateString, formatter);
System.out.println("解析后的日期时间: " + parsedDateTime);
// 格式化日期和时间
// 日期格式化是借助 DateTimeFormatter 类和日期时间类中的 format() 方法完成的。
LocalDateTime myDateObj = LocalDateTime.now();
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");
String formattedDate = myDateObj.format(myFormatObj);
System.out.println("格式化后的日期时间: " + formattedDate);
// 测量经过时间
// 要获取不同时间单位的执行时间,可以使用 java.time.Instant 和 java.time.Duration 类中的
// toDays() 、 toHours() 、 toMillis() 、 toMinutes() 、 toNanos() 和 getSeconds() 等方法。
Instant start = Instant.now();
Thread.sleep(1000); // 休眠1s
Instant finish = Instant.now();
long timeElapsed = Duration.between(start, finish).toMillis();
System.out.println("执行时间(毫秒): " + timeElapsed);
// 计算两个日期之间的天数
// 在 Java 8 中使用 ChronoUnit.DAYS.between() 和 LocalDate.until() 方法计算两个日期之间的天数 。
LocalDate date1 = LocalDate.now();
LocalDate date2 = date1.plusDays(99);
long diffInDays = ChronoUnit.DAYS.between(date1, date2);
System.out.println("两个日期之间的天数: " + diffInDays);
}
}
```
================================================
FILE: src/md/java/datetime/compare-dates.md
================================================
---
title: 比较两个日期
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2026-02-06
category: Java Dates
tags:
- date-time
---
# 比较两个日期
> 此文参考文献:
>
> - [【howtodoinjava】- 用 Java 比较两个日期](https://howtodoinjava.com/java/date-time/compare-dates/)
> - [比较 LocalDate](https://howtodoinjava.com/java/date-time/compare-localdates/)
> - [比较 LocalDateTime](https://howtodoinjava.com/java/date-time/compare-localdatetime/)
> - [比较 ZonedDateTime](https://howtodoinjava.com/java/date-time/zoneddatetime-comparison/)
| 方法 / API | 支持类 / 类型 | Java 版本 | 说明 |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ----------------- |
| `isBefore / isAfter / isEqual` | [LocalDate](https://howtodoinjava.com/java/date-time/java-time-localdate-class/), [LocalTime](https://howtodoinjava.com/java/date-time/java-localdatetime-class/), [LocalDateTime](https://howtodoinjava.com/java/date-time/zoneddatetime-class/), `ZonedDateTime`, `OffsetDateTime`, `Instant` | Java 8+ | 判断先后或相等,语义清晰、线程安全 |
| `compareTo` | `LocalDate`, `LocalTime`, `LocalDateTime`, `ZonedDateTime`, `OffsetDateTime`, `Instant`, `java.util.Date` | 通用 | 排序或比较大小 |
| `before / after` | [java.util.Date](https://howtodoinjava.com/java/date-time/java-date-examples/), `java.util.Calendar` | Java 7 以前 | 判断早于或晚于 |
| `equals` | `java.util.Date`, `java.util.Calendar` | 通用 | 判断相等 |
| `getTime / getTimeInMillis` | `java.util.Date`, `java.util.Calendar` | Java 7 以前 | 获取毫秒时间戳,可直接比较大小 |
**Date 日期比较**
```java
import java.util.Calendar;
import java.util.Date;
public class CompareDatePartOnly {
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date(date1.getTime() + 24 * 60 * 60 * 1000); // 次日
int diff = compareDatePartOnly(date1, date2);
if (diff > 0) {
System.out.println(date1 + " 大于 " + date2);
} else if (diff < 0) {
System.out.println(date1 + " 小于 " + date2);
} else {
System.out.println(date1 + " 等于 " + date2);
}
}
private static int compareDatePartOnly(final Date date1, final Date date2) {
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(date1);
cal2.setTime(date2);
int result = cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR);
if (result == 0) {
result = cal1.get(Calendar.DAY_OF_YEAR) - cal2.get(Calendar.DAY_OF_YEAR);
}
return result;
}
}
```
================================================
FILE: src/md/java/datetime/convert-dates.md
================================================
---
title: 转换日期时间实例
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2026-02-09
category: Java Dates
tags:
- date-time
---
# 转换日期时间实例
本文总结了 Java 中常见的日期时间类之间的转换方法,涵盖了 Java 8 引入的 `java.time` 包中的类(如 `LocalDate`, `LocalDateTime`, `ZonedDateTime`)以及旧版的 `java.util.Date` 和 `java.sql.Date` 等。
* [🐟代码小抄-Java日期转换工具类](https://codecopy.cn/post/q7kdjf)
## 1. LocalDateTime 与 ZonedDateTime 互转
`LocalDateTime` 表示不带时区的日期时间,而 `ZonedDateTime` 是带有时区的日期时间(`LocalDateTime` + `ZoneId`)。
### LocalDateTime -> ZonedDateTime
要将 `LocalDateTime` 转换为 `ZonedDateTime`,必须添加时区信息(Zone Offset)。
```java
LocalDateTime ldt = LocalDateTime.now(); // 本地日期时间
// 添加时区信息
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZonedDateTime zdtAtAsia = ldt.atZone(zoneId);
// 转换到另一个时区(保持时间瞬间一致)
ZonedDateTime zdtAtET = zdtAtAsia.withZoneSameInstant(ZoneId.of("America/New_York"));
```
### ZonedDateTime -> LocalDateTime
直接使用 `toLocalDateTime()` 方法,这将丢弃时区信息。
```java
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/New_York"));
LocalDateTime ldt = zdt.toLocalDateTime();
```
## 2. LocalDate 与 ZonedDateTime 互转
`LocalDate` 仅包含日期信息,转换为 `ZonedDateTime` 需要补充时间和时区。
### LocalDate -> ZonedDateTime
**方法一:使用 `atStartOfDay`(默认时间为 00:00)**
```java
LocalDate localDate = LocalDate.now();
// 默认当天开始时间 (00:00) + 指定时区
ZonedDateTime zdt = localDate.atStartOfDay(ZoneId.of("America/New_York"));
```
**方法二:先转 LocalDateTime 再转 ZonedDateTime**
```java
LocalDate localDate = LocalDate.now();
// 指定具体时间
LocalDateTime localDateTime = localDate.atTime(14, 30, 0);
// 添加时区
ZonedDateTime zdt = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
```
### ZonedDateTime -> LocalDate
直接使用 `toLocalDate()`。
```java
ZonedDateTime zdt = ZonedDateTime.now();
LocalDate localDate = zdt.toLocalDate();
```
## 3. LocalDate 与 LocalDateTime 互转
`LocalDateTime` = `LocalDate` + `LocalTime`。
### LocalDate -> LocalDateTime
需要补充时间部分。
```java
LocalDate date = LocalDate.now();
// 1. 当天开始时间 (00:00)
LocalDateTime startOfDay = date.atStartOfDay();
// 2. 当前时间
LocalDateTime withCurrentTime = date.atTime(LocalTime.now());
// 3. 指定时间
LocalDateTime specificTime = date.atTime(14, 30, 0);
```
### LocalDateTime -> LocalDate
直接使用 `toLocalDate()`。
```java
LocalDateTime dateTime = LocalDateTime.now();
LocalDate date = dateTime.toLocalDate();
```
## 4. LocalDate 与 java.sql.Date 互转
`java.sql.Date` 是旧版 JDBC API 使用的类,仅包含日期部分(时间设为 00:00:00)。
### java.sql.Date -> LocalDate
```java
java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());
LocalDate localDate = sqlDate.toLocalDate();
```
### LocalDate -> java.sql.Date
```java
LocalDate localDate = LocalDate.now();
java.sql.Date sqlDate = java.sql.Date.valueOf(localDate);
```
## 5. LocalTime 与 java.sql.Time 互转
### LocalTime -> java.sql.Time
注意:`java.sql.Time` 不包含纳秒精度。
```java
LocalTime localTime = LocalTime.now();
java.sql.Time sqlTime = java.sql.Time.valueOf(localTime);
```
### java.sql.Time -> LocalTime
```java
java.sql.Time sqlTime = new java.sql.Time(System.currentTimeMillis());
LocalTime localTime = sqlTime.toLocalTime();
```
## 6. LocalDate 与 java.util.Date 互转
`java.util.Date` 包含日期和时间,且基于 Epoch 毫秒数。转换时通常需要借助 `Instant` 和系统默认时区。
### java.util.Date -> LocalDate
```java
Date date = new Date();
LocalDate localDate = Instant.ofEpochMilli(date.getTime())
.atZone(ZoneId.systemDefault())
.toLocalDate();
```
### LocalDate -> java.util.Date
需要先转为当天开始时间的 `ZonedDateTime` 或 `Instant`。
```java
LocalDate localDate = LocalDate.now();
Date date = Date.from(localDate.atStartOfDay()
.atZone(ZoneId.systemDefault())
.toInstant());
```
## 7. LocalDateTime 与 java.util.Date 互转
### java.util.Date -> LocalDateTime
```java
Date date = new Date();
LocalDateTime ldt = Instant.ofEpochMilli(date.getTime())
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
```
### LocalDateTime -> java.util.Date
```java
LocalDateTime ldt = LocalDateTime.now();
Date date = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
```
## 8. 时区转换与 EST/EDT 处理
### ZonedDateTime 时区转换
使用 `withZoneSameInstant` 方法将同一时刻转换为另一时区的表达。
```java
ZonedDateTime now = ZonedDateTime.now(); // 当前时区
ZonedDateTime utc = now.withZoneSameInstant(ZoneId.of("UTC"));
ZonedDateTime ny = now.withZoneSameInstant(ZoneId.of("America/New_York"));
```
### OffsetDateTime 时区转换
类似地,使用 `withOffsetSameInstant`。
```java
OffsetDateTime now = OffsetDateTime.now();
OffsetDateTime utc = now.withOffsetSameInstant(ZoneOffset.UTC);
```
### java.util.Date 时区格式化
java.util.Date 表示一个时间点(UTC),但在格式化时会根据默认时区进行展示。可以通过设置 `SimpleDateFormat` 的时区来控制输出。
- [如何设置java.util.Date的时间区域? - Stack Overflow](https://stackoverflow.com/questions/2891361/how-to-set-time-zone-of-a-java-util-date/30403673#30403673).
```java
SimpleDateFormat FORMATTER = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mma z");
Date currentDate = new Date();
// 默认系统时区(东八区)
System.out.println(FORMATTER.format(currentDate)); //02/12/2026 at 02:08上午 CST
// 指定 UTC 时区
FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(FORMATTER.format(currentDate)); //02/11/2026 at 06:08下午 UTC
```
### EST, EDT 与 "America/New_York"
* **EST**: Eastern Standard Time (UTC-5),不包含夏令时。
* **EDT**: Eastern Daylight Time (UTC-4),夏令时。
* **EST5EDT**: 自动切换 EST 和 EDT。
* **America/New_York**: 推荐使用,涵盖了 1966 年以后的所有规则,自动处理夏令时。
转换示例:
```java
// 将 ZonedDateTime 转换为 ET 时区
ZonedDateTime ist = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime et = ist.withZoneSameInstant(ZoneId.of("America/New_York")); //推荐
```
## 9. Instant 与 LocalDateTime 互转
`Instant` 代表时间轴上的一个点(UTC)。
### Instant -> LocalDateTime
需要指定时区偏移。
```java
Instant instant = Instant.now();
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
LocalDate ld = LocalDate.ofInstant(instant, ZoneOffset.systemDefault());
LocalTime lt = LocalTime.ofInstant(instant, ZoneOffset.systemDefault());
// 或者
LocalDateTime ldt2 = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDate ld2 = instant.atZone(ZoneOffset.systemDefault()).toLocalDate();
LocalTime lt2 = instant.atZone(ZoneOffset.systemDefault()).toLocalTime();
```
### LocalDateTime -> Instant
需要指定时区偏移。
```java
LocalDateTime ldt = LocalDateTime.now();
Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
```
================================================
FILE: src/md/java/datetime/date-diff.md
================================================
---
title: 获取两个日期之间的时间差
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2026-02-05
category: Java Dates
tags:
- date-time
---
# 获取两个日期之间的时间差
## 1. Java 8 推荐
传统的 Java 类一直缺乏足够的支持来有效地表达日期和时间段。Java 8 首次尝试升级此日期/时间 API。
### 1.1 ChronoUnit
**用于计算所有时间单位之间的差值**
- 获取两个日期或时间之间的绝对差值(按**单位**),适用所有`Temporal`类型(如 `LocalDate`,`LocalDateTime`,`ZonedDateTime` 等)。
```java
// 日期级单位(仅依赖日期)
long years = ChronoUnit.YEARS.between(startDate, endDate);
long months = ChronoUnit.MONTHS.between(startDate, endDate);
long days = ChronoUnit.DAYS.between(startDate, endDate);
// 时间级单位(需包含时间部分,如 LocalDateTime)
long hours = ChronoUnit.HOURS.between(startDateTime, endDateTime);
long minutes = ChronoUnit.MINUTES.between(startDateTime, endDateTime);
long seconds = ChronoUnit.SECONDS.between(startDateTime, endDateTime);
long millis = ChronoUnit.MILLIS.between(startDateTime, endDateTime);
long micros = ChronoUnit.MICROS.between(startDateTime, endDateTime);
long nanos = ChronoUnit.NANOS.between(startDateTime, endDateTime);
```
### 1.2 Period-日期段
**用于计算天数、月数和年数的差值**
```java
// 包含开始日期,不包含结束日期
Period diff = Period.between(startDate, endDate);
int years = diff.getYears(); // 完整年数
int months = diff.getMonths(); // 剩余月数
int days = diff.getDays(); // 剩余天数
// ⚠️ 仅为近似值,不推荐用于精确计算
int totalDays = years * 365 + months * 30 + days;
```
⚠️ 注意事项
- `Period` 以 “x 年 y 月 z 日” 的形式表示时间差
- `getDays()` 返回的是剩余天数,并非两个日期之间的总天数
- 结果可能为负值(当结束日期早于开始日期)
### 1.3 Duration-时间段
**计算基于时间线的精确时间差**
**Duration**表示以小时、分钟、秒、纳秒等较小时间单位表示的时间差。
```java
Duration duration = Duration.between(dateTime, dateTime2);
long hours = duration.toHours(); // 总小时数
long minutes = duration.toMinutes(); // 总分钟数
long seconds = duration.getSeconds(); // 总秒数
long millis = duration.toMillis(); // 总毫秒数
long micros = duration.toNanos() / 1_000; // 总微秒数
int nanos = duration.getNano(); // 剩余纳秒(非总纳秒)
```
⚠️ 仅对包含时间部分的日期时间对象有效(如 `LocalDateTime`、`Instant`)。
## 2. Joda‑Time 库
对于Java8之前的旧项目,还可以用 [Joda‑Time](https://www.joda.org/joda-time/)。

由于我们都更喜欢可读性,我建议使用 Jodatime 库(它实际上启发了 Java 8 日期/时间 API)。
1. 导入依赖`joda-time`依赖
2. 演示代码
```java
DateTime dateOfBirth = new DateTime(1988, 7, 4, 0, 0, GregorianChronology.getInstance());
DateTime currentDate = new DateTime(); // 当前时间
Days diffInDays = Days.daysBetween(dateOfBirth, currentDate); // 计算天数差
Hours diffInHours = Hours.hoursBetween(dateOfBirth, currentDate); // 计算小时差
Minutes diffInMinutes = Minutes.minutesBetween(dateOfBirth, currentDate); // 计算分钟差
Seconds diffInSeconds = Seconds.secondsBetween(dateOfBirth, currentDate); // 计算秒数差
```
## 3. Legacy API 方法(不推荐)
为了便于参考,我们来看一个使用 `java.util.Date` 和 `TimeUnit` 类查找日期差的示例。
```java
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class DateDifference {
public static void main(final String[] args) {
// 第一个日期:今天
Date today = new Date();
// 第二个日期:下个月同一天
Date sameDayNextMonth = new Date();
sameDayNextMonth.setMonth(today.getMonth() + 1); // 注意:月份从0开始
// 计算两个日期的时间差
long days = getDateDiff(today, sameDayNextMonth, TimeUnit.DAYS);
long hours = getDateDiff(today, sameDayNextMonth, TimeUnit.HOURS);
long minutes = getDateDiff(today, sameDayNextMonth, TimeUnit.MINUTES);
long seconds = getDateDiff(today, sameDayNextMonth, TimeUnit.SECONDS);
long mills = getDateDiff(today, sameDayNextMonth, TimeUnit.MILLISECONDS);
}
/**
* 计算两个日期之间的差值,并以指定的时间单位返回
*
* @param date1 起始日期
* @param date2 结束日期
* @param timeUnit 返回的时间单位(天、小时、分钟等)
* @return 两个日期之间的差值
*/
public static long getDateDiff(final Date date1, final Date date2,
final TimeUnit timeUnit) {
long diffInMillies = date2.getTime() - date1.getTime(); // 毫秒差
// 将毫秒差转换成指定时间单位
return timeUnit.convert(diffInMillies, TimeUnit.MILLISECONDS);
}
}
```
================================================
FILE: src/md/java/datetime/datetime.md
================================================
---
title: 获取当前日期和时间
shortTitle:
description: Java 提供了许多有用的方法来获取当前日期或当前时间,可以使用 `Date`、`Calendar` 以及 Java 8 Date/Time API 类中新引入的 `LocalDate`、`LocalDateTime` 和 `ZonedDateTime` 类。
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2026-02-04
category: Java Dates
tags:
- date-time
---
# 获取当前日期和时间
介绍在 Java 中获取当前 **日期 / 时间 / 日期时间** 的不同方式,分 Java 8 及更高版本和旧版本来讲解。
- 对于 JDK 8 或更高版本,推荐使用 [LocalDate](https://www.runoob.com/java/java-localdate-class.html) 和 [LocalTime](https://www.runoob.com/java/java-localtime-class.html) 类。
- 对于 JDK 7 或更早版本,我们只能使用 [Date](https://www.runoob.com/java/java-date-class.html) 和 [Calendar](https://www.runoob.com/java/java-calendar-class.html) 类。
## 1. Java 8 及以后(推荐方式)
### 1.1 核心 API(java.time 包)
- [java.time.LocalDate](https://howtodoinjava.com/java/date-time/java-time-localdate-class/) – **仅**表示 _yyyy-MM-dd_ 格式的日期信息。
- [java.time.LocalTime](https://howtodoinjava.com/java/date-time/java-localtime/) – 表示 _HH:mm:ss.SSSSSSSS_ 格式的时间信息 。
- [java.time.LocalDateTime](https://howtodoinjava.com/java/date-time/java-localdatetime-class/) – 表示**日期和时间信息,不包含任何时区信息** 。其模式是本地日期和时间信息的组合。
要获取**其他时区/语言环境下的当前日期和时间信息** ,我们可以使用以下类。
- [java.time.ZonedDateTime](https://howtodoinjava.com/java/date-time/zoneddatetime-class/) – 表示**给定时区的日期和时间信息** 。
### 1.2 示例代码
```java
LocalDate today = LocalDate.now(); //2026-02-04
LocalTime currentTime = LocalTime.now(); //13:05:55.540946
LocalDateTime now = LocalDateTime.now(); //2026-02-04T13:05:55.540982
```
若需要带时区:
```java
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("GMT")); //2026-02-04T05:06:28.188180Z[GMT]
```
默认的 `now()` 返回当前系统时区的日期/时间。
### 1.3 自定义格式化输出
如果希望控制显示格式(比如 `dd‑MM‑yyyy hh:mm`),可以用 **DateTimeFormatter**:
```java
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd-MM-yyyy hh:mm");
String formatted = fmt.format(LocalDateTime.now()); // 04-02-2026 01:06
```
这样可以输出自定义样式的字符串。
## 2. 旧版 Java(JDK 7 及更早)
在 Java 8 之前,没有 `java.time` 包,需要用旧类:
- **java.util.Date**
- **java.util.Calendar**
### 2.1 代码示例
```java
Date date = new Date(); //Wed Feb 04 13:07:38 CST 2026
Calendar cal = Calendar.getInstance(); //Wed Feb 04 13:08:13 CST 2026
```
### 2.2 自定义格式化输出
并通过 **SimpleDateFormat** 做格式化输出。
```java
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm");
System.out.println(sdf.format(date)); //04-02-2026 01:10
System.out.println(sdf.format(cal.getTime())); //04-02-2026 01:10
```
⚠️ 这种方式的类设计较旧且非线程安全,因此不推荐在新代码中使用。
================================================
FILE: src/md/java/datetime/locale.md
================================================
---
title: 获取用户的区域设置、国际化
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2026-02-04
category: Java Dates
tags:
- date-time
- 国际化
---
# 获取用户的区域设置、国际化
> 此文参考文献:
>
> * [【howtodoinjava】- 在 Java 中获取当前区域设置](https://howtodoinjava.com/java/date-time/how-to-get-current-user-locale-in-java/)
> * [【howtodoinjava】- Java 本地化:一份全面的指南](https://howtodoinjava.com/java/date-time/java-locale-api-examples/)
## 1. Locale 简介
`java.util.Locale` 是 Java 国际化 (i18n) 的核心类,用于标识特定的**语言**和**地区**。它是所有**区域设置敏感**类(如 `DateFormat`, `NumberFormat`, `MessageFormat`)的基础配置对象。
### 1.1 核心组成
`Locale` 对象在逻辑上由语言、国家、脚本、变体和扩展等字段组成(遵循 [IETF BCP 47](https://www.rfc-editor.org/info/bcp47) 标准)
| 组成部分 | 描述 | 示例 |
| :------------------ | :---------------------- | :------------------------------------------------ |
| **语言** (Language) | ISO 639-1 两字母代码 | `en` (英语), `zh` (中文) |
| **国家/地区** (Country) | ISO 3166-1 两字母代码 | `US` (美国), `CN` (中国) |
| 脚本(Script) | ISO 15924 四字母代码 | `"Latn"` (拉丁字母), `"Hans"` (简体中文), `"Hant"` (繁体中文) |
| 变体 (Variant) | 特定方言或版本 (可选) | `Traditional_WIN`, `POSIX` |
| 扩展(Extensions) | 额外信息,遵循 BCP 47 扩展语法(可选) | `u-ca-gregory`(使用公历), `x-lvariant-POSIX`(私有扩展) |
### 1.2 获取用户区域设置

**Web 应用**:通常根据 HTTP 请求头 `Accept-Language` 获取用户偏好:
```java
Locale locale = request.getLocale();
System.out.println(locale.getDisplayName()); // 例如: 中文 (中国)
```
**桌面/服务端应用**:默认使用 JVM 或操作系统的设置:
```java
// 获取默认 Locale
Locale defaultLocale = Locale.getDefault();
// 或者通过系统属性
String lang = System.getProperty("user.language");
String region = System.getProperty("user.country");
```
## 2. 创建 Locale 实例
### 2.1 推荐方式 (Java 19+)
从 Java 19 开始,推荐使用静态工厂方法 `Locale.of()`:
```java
Locale us = Locale.of("en", "US");
Locale zh = Locale.of("zh", "CN");
```
> **注意**:`new Locale("en", "US")` 构造函数在 Java 19 中已被弃用,建议改用 `Locale.of()`。
### 2.2 内置常量
对于主要国家和语言,直接使用内置常量:
```java
Locale us = Locale.US;
Locale china = Locale.CHINA;
Locale simplifiedChinese = Locale.SIMPLIFIED_CHINESE;
```
### 2.3 构建器与标签解析
针对复杂场景或标准标签:
```java
// 1. 使用 Builder (更灵活,自带校验)
Locale locale = new Locale.Builder()
.setLanguage("en")
.setRegion("US")
.build();
// 2. 解析 BCP 47 语言标签
Locale usLocale = Locale.forLanguageTag("en-US");
Locale fromTag = Locale.forLanguageTag("zh-cmn-Hans-CN");
```
## 3. 设置默认 Locale
虽然通常**不建议**修改全局默认值,但在某些特定场景下需要强制指定:
```java
// 全局设置
Locale.setDefault(Locale.US);
// 分类设置 (Java 7+):独立控制显示与格式化
Locale.setDefault(Locale.Category.DISPLAY, Locale.US); // 影响 UI 界面/日志语言
Locale.setDefault(Locale.Category.FORMAT, Locale.FRANCE); // 影响 日期/货币格式
```
## 4. 常见应用场景
### 4.1 格式化 (日期/数字/货币)
`Locale` 决定了数据的展示格式:
```java
Locale us = Locale.US;
double num = 123456.789;
// 1. 数字格式化
System.out.println(NumberFormat.getInstance(us).format(num));
// 输出: 123,456.789
// 2. 货币格式化
System.out.println(NumberFormat.getCurrencyInstance(us).format(num));
// 输出: $123,456.79
// 3. 日期格式化
System.out.println(DateFormat.getDateInstance(DateFormat.LONG, us).format(new Date()));
// 输出示例: February 5, 2026
```
### 4.2 国际化消息 (ResourceBundle)
根据 `Locale` 加载对应的资源文件(如 `msg_en.properties`, `msg_zh.properties`):
```java
Locale zhCN = Locale.SIMPLIFIED_CHINESE; //简化中文
Locale enUS = Locale.US; //美式英语
// 加载 resources/i18n 包下的
// messages_zh_CN.properties 和 messages_en_US.properties
ResourceBundle bundleZh = ResourceBundle.getBundle("i18n.messages", zhCN);
ResourceBundle bundleEn = ResourceBundle.getBundle("i18n.messages", enUS);
System.out.println("中文消息: " + bundleZh.getString("greeting"));
System.out.println("英文消息: " + bundleEn.getString("greeting"));
```
---
**参考资料:**
* [Java国际化实践实现多语言及日期货币本地化-开发者社区-阿里云](https://developer.aliyun.com/article/1556409)
* [Java学习路线-21:国际化Locale、ResourceBundle、MessageFormat-阿里云开发者社区](https://developer.aliyun.com/article/1008126)
**资源:**
* [ISO 国家代码](https://www.iso.org/obp/ui/#search)
* [ISO 语言代码](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
================================================
FILE: src/md/java/datetime/timestamp.md
================================================
---
title: 获取当前时间戳
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2026-02-04
category: Java Dates
tags:
- date-time
---
# 获取当前时间戳
> 在Java中,**时间戳**(Timestamp)用来表示一个特定的**时间点**(`Instant`),本质上是一个与时区无关的时间线坐标。
> 它通常表示自 **1970-01-01 00:00:00 UTC**(Unix 纪元) 起经过的时间长度。精度到**纳秒**。
## 1. 获取当前时间戳
在Java中,时间戳用以下类表示:
- [java.time.Instant](https://www.runoob.com/java/java-instant-class.html)
- `java.sql.Timestamp`(Java 7 及以前)
### 1.1 Instant
`Instant`表示从 **系统 UTC 时钟** 获取的 **当前时间点**。
```java
Instant instant = Instant.now(); //2026-02-04T14:19:17.793293Z
```
⚠️ 思考 [Java 17 中 Instant.now 的精度改变了吗?](https://www.reddit.com/r/java/comments/1ffwkc7/has_the_precision_of_instantnow_changed_in_java_17/?tl=zh-hans)
### 1.2 Timestamp
`Timestamp`是`java.util.Date`的子类,表示一个具体的时间点,精确到**毫秒**。
```java
// 基于系统毫秒时间戳
Timestamp timestamp1 = new Timestamp(System.currentTimeMillis()); //2026-02-04 22:47:47.582
// 通过 Date 转换
Date date = new Date();
Timestamp timestamp2 = new Timestamp(date.getTime()); //2026-02-04 22:47:47.586
```
如果你需要兼容旧 API(比如 JDBC),可以用 `java.sql.Timestamp`:
## 2. Instant vs ZonedDateTime
从表面上看, _Instant 类_ 和 [ZonedDateTime](https://howtodoinjava.com/java/date-time/zoneddatetime-class/) 类似乎很相似,但实际上并非如此。
- `Instant` 是 UTC时间的一个时间点。
- `ZonedDateTime` 是一个**特定时区**的实际时间点。

[【howtodoinjava】- 了解 java.time.ZonedDateTime](https://howtodoinjava.com/java/date-time/zoneddatetime-class/)
================================================
FILE: src/md/java/datetime/zoneddatetime-vs-offsetdatetime.md
================================================
---
title: ZonedDateTime 和 OffsetDateTime 的区别
shortTitle:
description: 详解 Java 8 日期时间 API 中 ZonedDateTime 和 OffsetDateTime 的核心区别、使用场景及代码示例。
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2026-02-07
category: Java Dates
tags:
- date-time
---
# ZonedDateTime 和 OffsetDateTime 的区别
> 此文参考文献:1
>
> * [【howtodoinjava】- ZonedDateTime 和 OffsetDateTime 的区别](https://howtodoinjava.com/java/date-time/zoneddatetime-vs-offsetdatetime/)
> * [【Baeldung】- ZonedDateTime 和 OffsetDateTime 的区别](https://www.baeldung.com/java-zoneddatetime-offsetdatetime)
先了解两个所依赖的两个核心概念:
- [ZoneOffset](https://docs.oracle.com/javase/8/docs/api/java/time/ZoneOffset.html):**UTC 偏移量**(如 `+08:00`)
- [ZoneId](https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html):**时区标识符**(如 `Asia/Shanghai`),包含该区域的所有时间规则(**夏令时**切换等)。
## 1. 核心定义
| 特性 | OffsetDateTime | ZonedDateTime |
|:--------------|:-------------------------------|:--------------------------------------------|
| **组成** | `LocalDateTime` + `ZoneOffset` | `LocalDateTime` + `ZoneId` (+ `ZoneOffset`) |
| **时区感知** | 仅知道偏移量(Offset),不知道地理时区 | 知道具体的地理时区(Zone ID) |
| **夏令时 (DST)** | **不处理**。偏移量是固定的。 | **自动处理**。根据规则调整偏移量。 |
| **使用场景** | 数据库存储、网络通信、日志记录 | 用户界面显示、复杂的日期计算(如日历应用) |
| **复杂度** | 较低 | 较高 |
### 1.1 OffsetDateTime
`OffsetDateTime` 表示一个**不可变的日期时间**,精确到纳秒,并携带相对于 UTC 的**固定偏移量**(ISO-8601)。
- 每个实例都对应**时间线上的唯一时刻**
- 非常适合**与时区无关的时间戳**场景(数据库存储,网络传输 / XML / API 时间戳)
```java
// 本质上:OffsetDateTime = LocalDateTime + ZoneOffset
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.of("UTC"));
```
### 1.2 ZonedDateTime
`ZonedDateTime` 也是带时区的日期时间表示,但它基于**完整的时区规则**。
- 使用 **ZoneId**
- **会自动处理夏令时(DST)**
- 同一地区在不同时间点,**偏移量可能不同**
```java
// 本质上:ZonedDateTime = LocalDateTime + ZoneId
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));
```
内置方法,用于将给定日期从一个时区转换为另一个时区:
```java
```java
ZonedDateTime destZonedDateTime = sourceZonedDateTime.withZoneSameInstant(destZoneId);
```
## 2. 代码示例
### 2.1 创建实例
```java
// 获取当前时间
OffsetDateTime odt = OffsetDateTime.now();
ZonedDateTime zdt = ZonedDateTime.now();
System.out.println("OffsetDateTime: "+odt);
// 输出示例: 2026-02-07T23:30:00.132+08:00
System.out.println("ZonedDateTime: "+zdt);
// 输出示例: 2026-02-07T23:32:53.132632+08:00[Asia/Shanghai]
```
⚠️注意 `ZonedDateTime` 的输出末尾包含 `[Asia/Shanghai]` 这样的时区 ID。
### 2.2 相互转换
可以轻松地在两者之间进行转换:
```java
// ZonedDateTime -> OffsetDateTime
OffsetDateTime odtFromZdt = zdt.toOffsetDateTime();
// OffsetDateTime -> ZonedDateTime (需要提供 ZoneId)
ZonedDateTime zdtFromOdt = odt.atZoneSameInstant(ZoneId.of("America/New_York"));
```
### 2.3 夏令时处理差异
假设我们要给当前时间加上 6 个月。如果跨越了夏令时切换点:
- `OffsetDateTime` 会简单地增加时间,**保持偏移量不变**。
- `ZonedDateTime` 会增加时间,并**检查新日期的时区规则**,如果该日期处于夏令时(或退出了夏令时),它会自动调整偏移量。
```java
// 使用纽约时区,2026 年美国夏令时切换是在 3月8日(第二个周日)
ZoneId zoneId = ZoneId.of("America/New_York");
// LocalDateTime(本地时间不包含时区信息)
LocalDateTime localDateTime = LocalDateTime.of(2026, 3, 7, 10, 0);
System.out.println("LocalDateTime (未关联时区): " + localDateTime);
// ZonedDateTime(会关联时区并自动考虑夏令时规则)
ZonedDateTime zdt = ZonedDateTime.of(localDateTime, zoneId);
System.out.println("ZonedDateTime (关联时区): " + zdt);
ZonedDateTime zdtNextDay = zdt.plusDays(1);
System.out.println("ZonedDateTime (DST感知 +1天): " + zdtNextDay);
// OffsetDateTime(固定偏移量,不受夏令时影响)
OffsetDateTime odt = OffsetDateTime.of(localDateTime, ZoneOffset.of("-05:00"));
System.out.println("OffsetDateTime (固定偏移): " + odt);
OffsetDateTime odtNextDay = odt.plusDays(1);
System.out.println("OffsetDateTime (固定偏移 +1天): " + odtNextDay);
```
================================================
FILE: src/md/java/features/Java10/jep286-local-variable-type-inference.md
================================================
---
title: Java 10 新特性:局部变量类型推断
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
date: 2023-12-23
sticky: false
star: false
category: Java Features
tag:
- java
order: 286
---
# Java 10 新特性:局部变量类型推断
Java 10 引入了一项新的语言特性,即**局部变量类型推断**(Local-Variable Type Inference),
它允许在局部变量声明时,根据变量的初始值,推断出变量的数据类型。
## 语法
局部变量类型推断的语法非常简单,只需要将 `var` 关键字作为局部变量的类型即可。
```java
var list = new ArrayList<String>(); // 自动推断 ArrayList<String>
var stream = list.stream(); // 自动推断 Stream<String>
```
## 示例
相比传统的方式和 Java 7 的钻石操作符(Diamond Operator),Java 10 的局部变量类型推断使得代码更加精炼:
```java
// 传统方式(等号两边都需要)
List<String> list = new ArrayList<String>();
// Java7的钻石操作符(Diamond Operator)(只需要在左边申明类型即可)
List<String> list = new ArrayList<>();
// Java10的局部变量类型推断(类型在等号右边决定)
var list = new ArrayList<String>();
```
在使用 var 进行局部变量类型推断时,需要注意以下几点:
1. 必须在声明的同时进行初始化
2. 仅限于局部变量,不能用于定义成员变量、方法参数和返回类型
3. 每次只能定义一个变量,不能复合声明多个变量
通过使用局部变量类型推断,我们能够在不失代码可读性的前提下,减少了冗余的类型声明,使得代码更加简洁清晰。
这一特性尤其在Lambda表达式、集合初始化等场景下表现突出,提高了代码的书写效率。
在实际项目中,合理运用局部变量类型推断,将有助于代码的维护和阅读。
================================================
FILE: src/md/java/features/Java11/jep320-remove-JavaEE-CORBA.md
================================================
---
title: Java 11 新特性 :移除JavaEE和CORBA模块以及JavaFX
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2023-12-24
category: Java Features
tag:
- java
order: 320
---
# Java 11 新特性 :移除JavaEE和CORBA模块以及JavaFX
Java 11 中移除了 `Java EE` 和 `CORBA` 模块,同时 `JavaFX` 也被剥离,但仍可作为独立模块使用。
## Java9 弃用过程
在 Java 9 中,`Java EE` 和 `CORBA` 模块被标记为 @Deprecated,为开发者提供了适应期。
## Java11 彻底删除
Java 11 完全删除了以下九个模块:
* java.xml.ws(包含 JAX-WS、SAAJ 和 Web 服务元数据)
* java.xml.bind(JAXB)
* java.activation(JAF)
* java.xml.ws.annotation(常用注解)
* java.corba(CORBA)
* java.transaction(JTA)
* java.se.ee (以上6个模块的聚合模块)
* jdk.xml.ws (JAX-WS 工具)
* jdk.xml.bind (JAXB 工具)
删除后的影响:
* 源代码从 OpenJDK 存储库中删除
* 在 JDK 运行时映像中将不包含这些类
* 相关工具将不再可用:
* wsgen and wsimport (来自 jdk.xml.ws)
* schemagen and xjc (来自 jdk.xml.bind)
* idlj, orbd, servertool, and tnamesrv (来自 java.corba)
* JNDI CosNaming 提供者 (来自 java.corba) 将不再可用
* 不再有命令行标志能够启用它们,就像 JDK 9 上的 --add-modules 一样
## JavaFX 移除
`JavaFX` 在 Java 11 中被移除,但仍可以作为独立模块使用。
开发者需要额外的配置和依赖,以在项目中继续使用 JavaFX 技术。
================================================
FILE: src/md/java/features/Java14/jep361-switch-expressions.md
================================================
---
title: Java 14 新特性:switch表达式增强
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2023-12-25
category: Java Features
tag:
- java
order: 361
---
# Java 14 新特性:switch表达式增强
Java 14(JEP 361)引入了 switch 表达式的新特性,其中包括了 "**箭头标签**(`case ... ->`)" 和 `yield` 语句的增强,
同时支持 `Lambda` 语法,使得代码更加灵活、简洁,并为未来的**模式匹配**(JEP 305)特性做好了准备。
## 传统的switch语句
首先,让我们回顾一下传统的switch语句,它们在处理多个条件时可能显得有些冗长:
```java
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
break;
case TUESDAY:
System.out.println(7);
break;
case THURSDAY:
case SATURDAY:
System.out.println(8);
break;
case WEDNESDAY:
System.out.println(9);
break;
}
```
传统的 switch 语句存在以下问题:
1. 设计受到C和C++等低级语言的影响,且默认支持fall through语义
2. 过多的`break`语句使得代码显得冗长
## switch表达式增强
### 箭头标签(case L ->)
1. 引入了一种新的开关标签"`case L ->`",用于表示只有一个分支的情况
2. 允许每种情况下有多个常量,用逗号分隔
3. 标签右侧的代码仅限于表达式、块或抛出异常throw语句
```java
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}
```
### 局部变量独立作用域
在 Java 14 中,允许在每个分支中声明局部变量,避免块中变量命名冲突和误用。
```java
switch (day) {
case MONDAY:
case TUESDAY:
int temp = ... // 'temp'的作用域延续到 }
break;
case WEDNESDAY:
case THURSDAY:
int temp2 = ... // 不能将此变量命名为'temp'
break;
default:
int temp3 = ... // 不能将此变量命名为'temp'
}
```
### switch表达式
Switch 表达式被引入,允许将 `switch` 语句用作表达式,通过 `Lambda` 语法,根据输入值返回不同的结果。
```java
// 根据输入值`k`的不同,返回不同的字符串,并通过`System.out.println`打印结果
static void howMany(int k) {
System.out.println(
switch (k) {
case 1 -> "one";
case 2 -> "two";
default -> "many";
}
);
}
```
Switch表达式的常见形式如下:
```java
T result = switch (arg) {
case L1 -> e1;
case L2 -> e2;
default -> e3;
};
```
> Switch表达式是多态表达式(poly expression)。
>
> 多态性是指在编译时不确定具体类型,而在运行时确定类型的特性。
### yield语句返回值
允许在switch表达式中使用`yield`语句,而不是使用`break`语句,用于返回一个值,结束switch表达式的执行。
```java
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> {
int temp = performComplexCalculation(); // 在这里进行一些复杂的计算
yield temp; // 使用yield返回计算结果
}
};
```
## 发展脉络
追溯JEP 361的发展历程:从JDK 12预览版(JEP 325)到JDK 13预览版(JEP 354),
虽然部分功能在早期版本中已经出现,但建议在 JDK 14 及以后的版本中使用,以获得更好的稳定性和支持。
================================================
FILE: src/md/java/features/Java15/jep371-hidden-classes.md
================================================
---
title: Java 15 新特性:隐藏类(Hidden Classes)
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2023-12-26
category: Java Features
tag:
- java
order: 371
---
# Java 15 新特性:隐藏类(Hidden Classes)
**隐藏类**(Hidden Classes) 提供了一种在运行时生成类的机制,在编译时未知,并且不能直接在源代码中引用,
需要通过反射间接使用它们,隐藏类是为框架设计的,具有以下特性:
* **动态生成内部类**:隐藏类天生为框架设计,在运行时生成内部类
* **反射访问限制**:隐藏类只能通过反射访问,不能直接被其他类的字节码访问
* **独立加载和卸载**:隐藏类可以独立于其他类加载和卸载
* **框架扩展性**:适用于需要在运行时生成类的框架,提高语言的灵活性和效率
## 原理
## 框架中应用
[https://bugs.openjdk.org/browse/JDK-8220607](https://bugs.openjdk.org/browse/JDK-8220607)
================================================
FILE: src/md/java/features/Java15/jep378-text-blocks.md
================================================
---
title: Java 15 新特性:文本块(Text Blocks)
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2023-12-27
category: Java Features
tag:
- java
order: 378
---
# Java 15 新特性:文本块(Text Blocks)
Java 15(JEP 378)引入了**文本块**(Text Blocks)这一新特性,旨在简化多行字符串的表示,提高代码可读性,并减少在字符串中使用转义符的需求。
文本块通过引入三个双引号的**胖分隔符**(`"""`)来实现,同时支持转义序列,为开发人员提供更直观、易读的字符串处理方式。
## 快速上手
**HTML示例**
```java
// 使用“一维”字符串文字
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
// 使用“二维”文本块
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
```
**SQL示例**
```sql
// 使用“一维”字符串文字
String query = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" +
"WHERE \"CITY\" = 'INDIANAPOLIS'\n" +
"ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";
// 使用“二维”文本块
String query = """
SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"
WHERE "CITY" = 'INDIANAPOLIS'
ORDER BY "EMP_ID", "LAST_NAME";
""";
```
**Polyglot语言示例**
```polyglot
// 使用“一维”字符串文字
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval("function hello() {\n" +
" print('\"Hello, world\"');\n" +
"}\n" +
"\n" +
"hello();\n");
// 使用“二维”文本块
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval("function hello() {\n" +
" print('\"Hello, world\"');\n" +
"}\n" +
"\n" +
"hello();\n");
```
## 编译时处理
文本块是String类型的常量表达式,类似于字符串字面量。然而,与字符串字面值不同,文本块的内容在编译时经历三个步骤的处理:==行终止符的规范化==、==附带白色空间的移除==和==解释转义序列==:
1. 转换内容的行终止符
* 行终止符从CR(\u000D)和CRLF(\u000D\u000A)规范化为`LF(\u000A)`
2. 删除内容周围附带的白色空间(用于匹配Java源代码的缩进)
3. 解释内容中的转义序列,执行解释作为最后一步开发人员可以编写转义序列,如\n,而不会被前面的步骤修改或删除
处理后的内容以`CONSTANT_String_info`形式记录在**类文件的常量池**中,运行时,文本块被计算为String的实例。
## 新增转义序列
为了更精细地控制==换行符==和==空格==的处理,引入了两个新的转义序列:\ <line-terminator\> 和 \s。
### 换行符 \ <line-terminator\>
```java
// 传统方式
String literal = "Lorem ipsum dolor sit amet, consectetur adipiscing " +
"elit, sed do eiusmod tempor incididunt ut labore " +
"et dolore magna aliqua.";
// 使用 \ <line-terminator\>
String text = """
Lorem ipsum dolor sit amet, consectetur adipiscing \
elit, sed do eiusmod tempor incididunt ut labore \
et dolore magna aliqua.\
""";
```
> Tips: 因为字符和传统字符串不允许嵌入换行符,所以\ <line-terminator\> 转义序列只适用于文本块
### 单个空格 \s
新的 \s 转义序列简单地转换为单个空格(\u0020)
```java
// 使用 \s 保持固定长度
String colors = """
red \s
green\s
blue \s
""";
```
转义序列直到去除无意义的空格后才被解释,\s 可以作为栅栏,防止尾随空格被去除。
在这个示例中,每行末尾使用 \s 可以确保每行长度恰好为六个字符。
## 文本块连接
文本块的连接是引入的一个方便的特性,使得字符串的拼接变得更加简洁。
在连接时,相邻的文本块将自动合并,无需显式使用加号连接操作符。
```java
// 字符串和文本块连接
String code = "public void print(Object o) {" +
"""
System.out.println(Objects.toString(o));
}
""";
// 相邻的文本块将自动合并,无需显式使用加号连接操作符
String code = """
public void print(Object o) {
"""
"""
System.out.println(Objects.toString(o));
}
""";
```
在上述示例中,两个相邻的文本块会自动连接,形成一个整体的字符串。
这种自动连接的特性让代码更加清晰,减少了冗余的拼接操作。
## 文本块新方法
文本块引入了一些新方法,以便更方便地处理多行字符串:
- `String::stripIndent()`:去除多行字符串的前导空格
- `String::translateEscapes()`:转义多行字符串中的转义字符
- `String::formatted()`:在文本块中使用占位符进行值替换
- `String::lines():`:将多行字符串拆分为行的流,方便逐行处理。
================================================
FILE: src/md/java/features/Java16/jep394-pattern-matching-for-instanceof.md
================================================
---
title: Java 16 新特性:instanceof 模式匹配
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2023-12-28
category: Java Features
tag:
- java
order: 394
---
# Java 16 新特性:instanceof 模式匹配
Java 16 引入了`instanceof`**模式匹配**的增强语法,用于更简便地判断对象是否是某个类的实例并进行相应的**局部类型转换**。
## instanceof 基础用法
```java
if (obj instanceof String) {
String someString = (String) obj; // 强制类型转换
// ...
}
```
这个**强制转换**通常是在 `instanceof` 检查之后 的第一件事,所以为什么不围绕它优化一下语法呢?
## instanceof 增强用法
```java
if (obj instanceof String someString) {
// ...
}
// 这里 someString 超出了作用域
```
1. 若 `instanceof` 检查成功,将自动将变量转换为指定类型
2. 定义的变量实质上是一个**局部变量**,只在if语句的范围内可见
## 常见用法建议
不仅如此!使用模式匹配,我们可以更灵活地应用条件测试。
* 利用已定义的 obj,在不需要额外嵌套的情况下判断字符串是否以“Awesome”开头
```java
// 以前
return (someObject instanceof String) && ((String) someObject).startsWith("Awesome");
// 现在
return someObject instanceof String someString && someString.startsWith("Awesome");
```
* 甚至在 equals 方法中,代码会更加简洁
```java
// 以前
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer) obj).intValue();
}
return false;
}
// 现在
public boolean equals(Object obj) {
return (obj instanceof Integer i) && value == i.intValue();
}
```
多么不同!现在代码简洁而直观。
## 发展脉络
该功能经历了2个预览版本(JDK 14中的JEP 305、JDK 15中的JEP 375),最终定稿于JDK 16中的JEP 394。
================================================
FILE: src/md/java/features/Java16/jep395-records.md
================================================
---
title: Java 16 新特性:record类
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2023-12-29
category: Java Features
tag:
- java
order: 395
---
# Java 16 新特性:record类
Java 16 引入的**记录类**(Records Classes)是一种用于简化不可变数据管理的特殊类。
它通过紧凑的语法提供了对不可变数据的支持,并自动生成常见的方法,
如`equals()`、`hashCode()`和`toString()`等,从而减少了开发者的样板代码。
## 传统Java Bean问题
在处理不可变数据时,传统的Java Bean存在“==繁琐==”和“==冗长==”的问题。
为了管理少量值的不可变数据,开发者需要编写大量低价值、重复且容易出错的代码,
包括`构造函数`、`访问器(getter/setter)`、`equals`、`hashCode`、`toString`等。
例如,用于携带x和y坐标的类通常会演变成以下繁琐形式:
```java
class Point {
private final int x;
private final int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
int x() { return x; }
int y() { return y; }
public boolean equals(Object o) {
if (!(o instanceof Point)) return false;
Point other = (Point) o;
return other.x == x && other.y == y;
}
public int hashCode() {
return Objects.hash(x, y);
}
public String toString() {
return String.format("Point[x=%d, y=%d]", x, y);
}
}
```
## 引入record类
**语法如下**:使用 `record`==关键字==,指定==类名称==为 Point,定义==参数列表== x 和 y 作为组件
```java
record Point(int x, int y) { }
```
record申明的类,具备这些特点:
1. 它是一个`final`类
2. 自动实现`equals`、`hashCode`、`toString`函数
3. 成员变量均为`public`属性
所以,对于之前写的Point类,它等价于一个这样的类:
```java
// Record类声明,使用record关键字,名称为Point,带有两个参数x和y
public final class Point {
// 1. 自动生成成员变量(fields)
final int x;
final int y;
// 2. 自动生成构造函数(constructor)
public Point( int x, int y){
this.x = x;
this.y = y;
}
// 3. 自动生成的访问方法
public int x () {
return x;
}
public int y () {
return y;
}
// 4. 自动生成equals和hashCode方法
@Override
public boolean equals (Object obj){
// 实现相等性比较的逻辑
}
@Override
public int hashCode () {
// 生成哈希码的逻辑
}
// 5. 自动生成toString方法
@Override
public String toString () {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
}
```
通过使用record类,你可以更专注于业务逻辑而不是样板代码,提高了代码的可读性和可维护性。
## 显示声明紧凑构造函数
未显式声明构造函数时,系统会自动生成包含所有成员变量的隐式构造函数。
当显式声明紧凑构造函数可以==省略形式参数列表==、编译后在构造函数的末尾==自动分配==给相应的形式参数(this.x = x;)。
* **验证参数**的紧凑构造函数
```java
record Book(String title, String author, int pageCount) {
Book {
if (pageCount <= 0) {
throw new IllegalArgumentException("页数必须大于零.");
}
}
}
```
* **规范**的紧凑构造函数
```java
// 记录类 Rational 表示有理数,包含分子(num)和分母(denom)两个成员变量
record Rational(int num, int denom) {
Rational {
int gcd = gcd(num, denom); // 计算最大公约数
num /= gcd; // 将分子除以最大公约数
denom /= gcd; // 将分母除以最大公约数
}
}
```
这个声明等同于传统的构造函数形式:
```java
record Rational(int num, int denom) {
Rational(int num, int demon) {
// 逻辑代码
int gcd = gcd(num, denom);
num /= gcd;
denom /= gcd;
// 赋值代码
this.num = num;
this.denom = denom;
}
}
```
* 记录类**语义一致性**
例如,考虑以下方式声明的记录类R:
```java
record R(T1 c1, ..., Tn cn){ }
```
如果通过以下方式复制R的实例r1:
```java
R r2 = new R(r1.c1(), r1.c2(), ..., r1.cn());
```
则假设 r1 不是空引用,表达式 r1.equals(r2) 总是为 true。
这是因为记录类的隐式声明的 equals 方法保证了相同字段值的两个记录实例相等。
> Tips: 程序员需要谨慎确保显式声明的方法维持语义一致性
* 避免不良风格的代码
```java
record SmallPoint(int x, int y) {
public int x() { return this.x < 100 ? this.x : 100; }
public int y() { return this.y < 100 ? this.y : 100; }
}
```
这是一个不良风格的代码,违反了语义一致性的原则,访问器`x()`,`y()`方法调整类实例的状态;
**改进建议**, 如果需要限制坐标值的范围,应该在构造函数或其他明确的位置处理。
```java
record SmallPoint(int x, int y) {
// 紧凑构造函数中限制坐标值的范围
public SmallPoint {
this.x = Math.min(x, 100);
this.y = Math.min(y, 100);
}
}
```
## 发展脉络
`record` 类最初在JDK 14预览版(JEP 359)提出,随后在JDK 15预览版(JEP 384)再次推出。
最终,它在JDK 16中(JEP 395)正式发布,成为Java语言的一项重要特性。
================================================
FILE: src/md/java/features/Java17/jep406-pattern-matching-for-switch-preview.md
================================================
---
title: Java 17 新特性:switch模式匹配(Preview)
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2023-12-30
category: Java Features
tag:
- java
order: 406
---
# Java 17 新特性:switch模式匹配(Preview)
当case标签可以有模式时,有如下四个主要的设计问题,我们一一来看:
1. 增强类型检查
2. switch表达式和语句的完整性
3. 模式变量声明的作用域
4. 处理null
## 模式匹配设计
### 增强类型检查
通过扩展`switch`模式匹配的`case`标签,现在支持除了**原始数据类型**(`char`、`byte`、`short` 或 `int`)之外,
相应的**包装类**(`Character`、`Byte`、`Short` 或 `Integer`)、`String` 以及`Enum`类型等**任何引用类型**。
```java
record Point(int i, int j) {}
enum Color { RED, GREEN, BLUE; }
static void typeTester(Object o) {
switch (o) {
case null -> System.out.println("null");
case String s -> System.out.println("String");
case Color c -> System.out.println("Enum,颜色具有 " + Color.values().length + " 个值");
case Point p -> System.out.println("Record Class: " + p.toString());
case int[] ia -> System.out.println("Array,长度为" + ia.length);
default -> System.out.println("其他情况");
}
}
```
> **注意⚠️:要避免模式标签支配**(编译异常)
>
> 如果一个模式标签在switch块中被先前的模式标签支配, 或者存在多个全匹配的标签(default 和 total类型模式), 则会产生编译时错误。
* 例1: 模式 `case CharSequence cs` 支配 `case String s` ,因为 String 是 CharSequence 的子类
* 例2: 总模式的情况,如 `case p` 支配 `case null` 模式,因为总模式匹配所有值,包括null
* 例3: 模式 `case p` 支配 `case p && e` ,因为满足第一个模式的值也满足第二个模式
* 例4: 模式 `case String s` 支配了带条件的模式 `case String s && s.length() > 0`
```java
switch(o) {
case CharSequence cs ->
System.out.println("一个长度为" + cs.length() + "的序列");
case String s -> // 编译错误 - 模式被前一个模式支配
System.out.println("一个字符串:" + s);
default -> {
break;
}
}
```
### switch表达式和语句的完整性
通常情况下,通过添加`default`标签,可以确保`switch`块的完整性。
```java
static void printType(Object o) {
switch (o) {
case String s -> System.out.println("String");
case Integer i -> System.out.println("Integer");
default -> System.out.println("Other");
}
}
```
如果switch表达式的类型是**密封类**([JEP 409](https://openjdk.org/jeps/409)),
则类型覆盖检查会考虑密封类的permits子句,以确保switch块的完整性。
以下是一个密封接口Animal的示例,包括Dog和Cat两个允许的子类:
```java
sealed interface Animal permits Dog, Cat {}
class Dog implements Animal {}
class Cat implements Animal {}
static String getSound(Animal animal) {
return switch (animal) {
case Dog d -> "Woof!";
case Cat c -> "Meow!";
// no default needed!
};
}
```
在这种情况下,由于编译器知道只有Dog和Cat是可能的类型,所以可以不需要`default`标签。
同样,对于枚举类,每个常量都有一个子句,也不需要default标签。
### 模式变量声明的作用域
`instanceof`([JEP 394](https://openjdk.org/jeps/394))进行**模式匹配**,
**模式变量**的作用域限定在`匹配的条件表达式`和相应的`then`块中。 如果匹配失败,模式变量在`else`块中不可见。
```java
static void test(Object o) {
if ((o instanceof String s) && s.length() > 3) {
System.out.println(s);
} else {
System.out.println("Not a string");
}
}
```
`switch`语句的`case`标签进行**模式匹配**,有以下两条规则:
1. `->`形式:作用域包括箭头右侧的表达式、块或 throw 语句
```java
static void test(Object o) {
switch (o) {
case Character c -> {
if (c.charValue() == 7) {
System.out.println("Ding!");
}
System.out.println("Character");
}
case Integer i ->
throw new IllegalStateException("Invalid Integer argument of value " + i.intValue());
default -> {
break;
}
}
}
```
2. `:`形式,则其作用域包括语句组的块语句,直到遇到下一个`switch`标签或其他控制流语句
```java
static void test(Object o) {
switch (o) {
case Character c:
if (c.charValue() == 7) {
System.out.print("Ding ");
}
if (c.charValue() == 9) {
System.out.print("Tab ");
}
System.out.println("character");
default:
System.out.println();
}
}
```
### 处理null
引入新的`null`标签,用于明确处理选择表达式为`null`的情况
```java
// test(null) 不再抛出NullPointerException,而是打印 "null!"
static void test(Object o) {
switch (o) {
case null -> System.out.println("null!");
case String s -> System.out.println("String");
default -> System.out.println("Something else");
}
}
```
由空标签产生的新标签形式, JDK 16中,`switch`块支持两种风格,
1. `:` 形式,允许`fallthrough`,多个标签通常写为`case l1: case l2:`
2. `->`形式,不允许`fallthrough`,多个标签写为`case l1, l2->`
```java
// 处理 null 和 String 标签,使用 : 形式
switch (o) {
case null: case String s:
System.out.println("String, including null");
break;
// 更多的 cases...
}
// 结合 null case 和 default 标签,使用 -> 形式
switch (o) {
// 更多的 cases...
case null, default ->
System.out.println("The rest (including null)");
}
```
## 保护模式和括号模式
为了增强代码的可读性并避免歧义,引入了两种新的模式匹配技术:
* 保护模式 (guarded patterns),允许在模式匹配成功后添加一个布尔表达式
* 括号模式 (parenthesized patterns),将模式放在括号中,避免歧义,控制顺序
在成功匹配模式后,我们经常会进一步测试匹配结果。这会导致代码变得繁琐,例如:
```java
static void test(Object o) {
switch (o) {
case String s:
if (s.length() == 1) { ... }
else { ... }
break;
...
}
}
```
使用**保护模式**,写成`p && e`改进上面的代码,使其更加简洁
```java
static void test(Object o) {
switch (o) {
case String s && s.length() == 1 -> ...
case String s -> ...
}
}
```
> JDK 17中还加入了**括号模式**,以避免解析歧义。支持括号内写入`(p)` 其中p是一个模式。在JDK 21中,括号模式被移除。
## 启用预览功能
Preview阶段的功能并不是默认开启的,需要在编译和运行时启用。
```shell
java --enable-preview --source 17 PatternMatching.java
```
================================================
FILE: src/md/java/features/Java17/jep409-sealed-classes.md
================================================
---
title: Java 17 新特性:sealed类
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2023-12-31
category: Java Features
tag:
- java
order: 409
---
# Java 17 新特性:sealed类
Java 17 中引入了**密封类**(Sealed Classes),它是一种限制的类和接口,
可以控制哪些类继承或实现它,保证在编译时就能够确定类的继承关系,提高代码的可读性和可维护性。
## 密封类语法
密封类的声明使用关键字 `sealed`,并通过 `permits` 关键字声明允许继承或实现的类。
```java
// 密封类
public abstract sealed class 类名 extends 父类名 permits 子类名1, 子类名2, ... {
// 类的成员
}
// 密封接口
public sealed interface 接口名 extends 父接口名 permits 子类名1, 子类名2, ... {
// 接口的成员
}
```
密封类对其允许的子类施加了三个约束:
1. 密封类及其允许的子类必须属于同一个模块或同一包(对于未命名模块)
2. 每个允许的子类必须直接扩展密封类
3. 每个允许的子类必须使用修饰符描述其继承关系:
* `final`:表示该类不能被继承(记录类隐式声明为 `final`)
* `sealed`:表示该类可以被继承,但只能被允许的子类继承
* `non-sealed`:表示该类可以被继承,且可以被任意类继承
## 历史限制继承手段
对于继承能力的限制,Java 语言已经提供了以下几种手段:
1. `final`修饰类,这样类就无法被继承了
2. 构造函数声明为`private`或`package-private`,则只能在同一类或同一包中创建该类的子类
## 发展脉络
该功能经历了2个预览版本(JDK 15中的JEP 360、JDK 16中的JEP 397),最终定稿于JDK 17中的JEP 409。
================================================
FILE: src/md/java/features/Java18/jep400-utf8-by-default.md
================================================
---
title: Java 18 新特性:指定UTF-8为默认字符集
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-01-01
category: Java Features
tag:
- java
order: 400
---
# Java 18 新特性:指定UTF-8为默认字符集
在Java 18中,将`UTF-8`指定为标准Java API 的默认字符集,
以提高Java程序在不同实现、操作系统、区域设置和配置下的一致性。
## 目标
* 使Java程序在依赖默认字符集的代码上更加可预测和**可移植**
* 明确标准Java API在何处使用默认字符集
* 在标准Java API中统一使用UTF-8,除了控制台I/O
尽管这项工作可能会发现新的便利方法可能会使现有的API更易于使用,但这一更改并不是要弃用或删除依赖默认字符集的标准Java API。
## 动机
默认情况下,Java API 会根据**运行时环境**(操作系统、用户的区域设置等)选择默认字符集。
为了提高 Java API 的一致性并降低潜在的兼容性问题,我们建议将所有 Java API 统一使用 `UTF-8` 作为默认字符集。
尽管这一变更可能对迁移到 JDK 18 的程序产生兼容性影响,但我们提供了一个 `COMPAT` 选项,允许恢复到之前的行为,即默认字符集取决于环境。
## 描述
### 兼容性危害示例
在MacOS上以`UTF-8`编码的日语文本文件在Windows上以美英或日语区域设置读取时被损坏
```java
java.io.FileReader(“hello.txt”) -> “こんにちは” (macOS)
java.io.FileReader(“hello.txt”) -> “ã?“ã‚“ã?«ã?¡ã? ” (Windows (en-US))
java.io.FileReader(“hello.txt”) -> “縺ォ縺。縺ッ” (Windows (ja-JP)
```
### 查询默认字符集
通过方法 `java.nio.charset.Charset.defaultCharset()` 可以获取默认字符集。
另外,使用以下命令可以快速查看当前 JDK 的默认字符集:
```java
java -XshowSettings:properties -version 2>&1 | grep file.encoding
```
如果想在所有 Java 版本上获取从环境中确定的字符集,可以使用以下代码:
```java
// 获取native.encoding系统属性(在Java 18及更高版本上赋值)
String encoding = System.getProperty("native.encoding");
// 使用三元运算符选择字符集,如果encoding不为null,则使用指定字符集,否则使用默认字符集
Charset cs = (encoding != null) ? Charset.forName(encoding) : Charset.defaultCharset();
// 使用指定字符集创建 FileReader 对象,打开名为 "file.txt" 的文件
var reader = new FileReader("file.txt", cs);
```
### 兼容使用默认字符集API(迁移)
多个标准 Java API 使用默认字符集,包括:
* 在 java.io 包中,InputStreamReader、FileReader、OutputStreamWriter、FileWriter 和 PrintStream
提供了构造函数,用于创建使用默认字符集进行编码或解码的读取器、写入器和打印流
* 在 java.util 包中,Formatter 和 Scanner 提供了构造函数,使用默认字符集进行操作
* 在 java.net 包中,URLEncoder 和 URLDecoder 提供了使用默认字符集的已弃用方法
我们将更新所有使用 Charset.defaultCharset() 进行交叉引用的标准 Java API 的规范。
这些 API 包括上述提到的 API,但不包括 System.out 和 System.err,它们的字符集将由 Console.charset() 指定。
### file.encoding 和 native.encoding 系统属性
`file.encoding` 是 Java 虚拟机的系统属性,用于指定默认的字符编码
```shell
java -Dfile.encoding=COMPAT # COMPAT 模式, 默认字符集取决于环境
java -Dfile.encoding=UTF-8 # UTF-8 模式, 默认字符集为UTF-8
```
`native.encoding` 在Java 17 中引入,该属性提供了底层主机环境的字符编码名称
Java内部使用了三个字符集相关的系统属性,它们目前未指定且不受支持。这里简要记录一下:
1. `sun.stdout.encoding`
2. `sun.stderr.encoding`
3. `sun.jnu.encoding`:
> Tips:对于JDK(8-17):强烈建议开发人员使用`java -Dfile.encoding=UTF-8`指定默认字符集为UTF-8启动程序
### 源文件编码
Java语言允许源代码使用`UTF-16`编码方式表达`Unicode`字符,并且这不受默认字符集UTF-8的影响。
但是,`javac`编译器会受到影响,因为它需要将源代码转换为平台默认的字符集,除非通过`-encoding`选项进行配置
如果源文件以非UTF-8编码保存并在较早的JDK上进行编译,然后在JDK 18或更高版本上重新编译,可能会导致问题。
例如,如果非UTF-8源文件中的字符串文字包含非ASCII字符,则在JDK 18或更高版本中,除非使用`-encoding`选项,否则这些文字可能会被`javac`错误解释。
在使用UTF-8作为默认字符集的JDK上编译之前,强烈建议开发人员通过在当前JDK(8-17)上使用javac -encoding UTF-8 ... 进行编译来检查字符集问题。
另外,喜欢以非UTF-8编码保存源文件的开发人员可以通过将JDK 17及更高版本上的`-encoding`选项设置为`native.encoding`系统属性的值,防止javac假定UTF-8。
### 旧版默认字符集(US-ASCII)
在JDK 17及更早版本中,名称`default`会被识别为`US-ASCII`字符集的别名。
在JDK 18中,默认字符集`UTF-8`,保留`default`作为`US-ASCII`的别名将会非常混乱,于是重新定义`default`不再是`US-ASCII`的别名。
Java程序使用枚举常量StandardCharsets.US_ASCII来明确其开发人员意图,而不是向Charset.forName(...)传递字符串。
因此,在JDK 18中,`Charset.forName("default")`将抛出 UnsupportedCharsetException。
这将为开发人员提供检测到这种惯用法并迁移到US-ASCII或Charset.defaultCharset()结果的机会。
================================================
FILE: src/md/java/features/Java18/jep408-simple-web-server.md
================================================
---
title: Java 18 新特性:简单Web服务器
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-01-02
category: Java Features
tag:
- java
order: 408
---
# Java 18 新特性:简单Web服务器
Java 18 引入了**简单Web服务**器(Simple Web Server),一个专为教育或非正式任务设计的最小HTTP服务器,为单个目录层次结构提供服务。
基于JDK中的`com.sun.net.httpserver`包实现,旨在简化服务器的创建和请求处理过程。
主要特点:
* 不能替代成熟的商业服务器,如`Jetty`、`Nginx` 和 `Apache Tomcat`等
* 不提供身份验证、访问控制或加密等安全功能
* 仅支持HTTP/1.1,不支持HTTPS
* 仅支持GET、HEAD请求,否则返回 501 Not Implemented 或 405 Not Allowed
## 命令行工具
为了开始使用简单Web服务器,您需要准备一个`index.html`文件,并执行以下步骤:
1. 打开终端。
2. 输入命令:`jwebserver`。
```shell
$ jwebserver
```
默认情况下,服务器将绑定到本地回环地址,并在端口8000上提供服务。看到类似以下的输出:
```shell
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /cwd and its subdirectories on 127.0.0.1 port 8000
URL: http://127.0.0.1:8000/
```
尝试访问一下 `http://127.0.0.1:8000/` ,就可以获得之前准备的HTML内容了。
### 支持的命令行选项
```shell
选项:
-h 或 -? 或 --help
打印帮助信息并退出.
-b addr 或 --bind-address addr
指定绑定的地址。默认:127.0.0.1或::1(回环地址)。要使用所有接口,请使用 -b 0.0.0.0 或 -b ::.
-d dir 或 --directory dir
指定要提供服务的目录。默认:当前目录.
-o level 或 --output level
指定输出格式。none | info | verbose。默认:info.
-p port 或 --port port
指定要监听的端口。默认:8000.
-version 或 --version
打印版本信息并退出。
要停止服务器,请按 Ctrl + C.
```
## API编程方式
尽管命令行工具提供了便利,但为了更灵活地定制处理程序的行为,与现有代码集成,提高代码的可读性和可维护性,我们引入了新的API。
> 新的API中引入了三个新的类是`SimpleFileServer`、`HttpHandlers`和`Request`,
> 每个类都构建在`com.sun.net.httpserver`包中的现有类和接口上:`HttpServer`、`HttpHandler`、`Filter`和`HttpExchange`。
### 简单文件服务器(SimpleFileServer)
`SimpleFileServer`支持创建文件服务器、文件服务器处理程序和输出过滤器。
```java
package com.sun.net.httpserver;
public final class SimpleFileServer {
// 创建文件服务器实例
public static 1 createFileServer(
InetSocketAddress addr, Path rootDirectory, OutputLevel outputLevel) {...}
// 创建文件服务器处理程序
public static HttpHandler createFileHandler(
Path rootDirectory) {...}
// 创建输出过滤器
public static Filter createOutputFilter(
OutputStream out, OutputLevel outputLevel) {...}
...
}
```
有了这个类,在`jshell`中只需几行代码,就可以启动一个最小但定制的**文件服务器**:
```java
jshell> var server = SimpleFileServer.createFileServer(new InetSocketAddress(8080),
...> Path.of("/some/path"), SimpleFileServer.OutputLevel.INFO);
jshell> server.start()
```
相当于命令行模式的:
```shell
jwebserver -p 8080 -d /some/path -o info
```
### 自定义处理程序和过滤器
将自定义的**文件服务器处理程序**添加到现有服务器:
```java
jshell> var handler = SimpleFileServer.createFileHandler(Path.of("/some/path"));
jshell> var server = HttpServer.create(new InetSocketAddress(8080),
...> 10, "/store/", new SomePutHandler());
jshell> server.createContext("/browse/", handler);
jshell> server.start();
```
将自定义的**输出过滤器**在创建过程中添加到服务器:
```java
jshell> var filter = SimpleFileServer.createOutputFilter(System.out,
...> OutputLevel.INFO);
jshell> var server = HttpServer.create(new InetSocketAddress(8080),
...> 10, "/store/", new SomePutHandler(), filter);
jshell> server.start();
```
两个例子是由`HttpServer`和`HttpsServer`类中的新重载`create`方法启用的:
```java
public static HttpServer create(InetSocketAddress addr,
int backlog,
String root,
HttpHandler handler,
Filter... filters) throws IOException {...}
```
### 增强的请求处理(HttpHandlers)
简单Web服务器的核心功能是**处理程序**。为了与现有代码兼容,我们引入了`HttpHandlers`类,
提供两个静态方法用于==创建==和==自定义处理程序==,还有`Filter`类中的新方法用于适配请求:
```java
package com.sun.net.httpserver;
public final class HttpHandlers {
// handleOrElse方法补充条件处理程序
public static HttpHandler handleOrElse(Predicate<Request> handlerTest,
HttpHandler handler,
HttpHandler fallbackHandler) {...}
// of方法创建具有预设响应状态的处理程序
public static HttpHandler of(int statusCode, Headers headers, String body) {...}
{...}
}
```
```java
public abstract class Filter {
// adaptRequest方法获取预处理过滤器,用于在处理请求之前检查和调整请求的某些属性
public static Filter adaptRequest(
String description, UnaryOperator<Request> requestOperator) {...}
{...}
}
```
这些方法的用例包括基于请求方法委托交换,创建总是返回特定响应的“canned response”处理程序,或向所有传入请求添加标头。
### 请求(Request)
现有API中,使用HttpExchange类来表达HTTP==请求-响应对==,描述了请求-响应交换的完整可变状态。
然而,并非所有这状态对于处理程序的定制和适配都是必要的。
因此,我们引入了更简单的Request接口,提供==请求==的不可变状态的有限视图。
```java
public interface Request {
URI getRequestURI(); // 获取请求的URI
String getRequestMethod(); // 获取请求的方法
Headers getRequestHeaders(); // 获取请求的标头
// 用于修改请求头部信息
default Request with(String headerName, List<String> headerValues)
{...}
}
```
这使得可以直接定制现有的处理程序,例如:
```java
// 创建一个处理程序,根据请求方法选择对应的处理器,如果请求方法为 PUT,则使用 SomePutHandler,否则使用 SomeHandler
var h = HttpHandlers.handleOrElse(r ->
r.getRequestMethod().equals("PUT"), new SomePutHandler(), new SomeHandler());
// 创建一个过滤器,用于修改请求头部信息,在请求中添加名为 "Foo" 的头部,值为 "Bar"
var f = Filter.adaptRequest("Add Foo header", r -> r.with("Foo", List.of("Bar")));
// 创建一个 HTTP 服务器,并指定端口为 8080,最大连接数为 10,根路径为 "/",处理程序为 h,过滤器为 f
var s = HttpServer.create(new InetSocketAddress(8080), 10, "/", h, f);
// 启动服务器
s.start();
```
## 替代品
**命令行工具**的替代方案:
* 最初,使用 `java -m jdk.httpserver` 命令运行 Simple Web Server,没有专门的命令行工具
* 为了提高便利性和可访问性,我们引入了一个专门的工具 `jwebserver`
* 实际上 `jwebserver` 在后台使用了 `java -m ...` 命令
**API编程方式**替代方案:
* 新的 `DelegatingHandler` 类:捆绑定制方法在一个单独的类中,但由于引入了新类型并未添加更多功能,我们放弃了这个选项。
* 将 `HttpHandler` 作为服务:将 `HttpHandler` 转换为服务,并提供内部文件服务器处理程序实现。然而,这种方法对于我们要提供的功能来说过于复杂。
* 使用**过滤器**而不是 `HttpHandler`:仅使用过滤器来处理请求,但这样做不符合直觉,并且过滤器的方法会更难找到。
================================================
FILE: src/md/java/features/Java18/jep413-code-snippets-in-api-documentation.md
================================================
---
title: Java 18 新特性:新增@snipppet标签
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-01-03
category: Java Features
tag:
- java
order: 413
---
# Java 18 新特性:新增@snipppet标签
Java 18 引入了`@snippet`标签,用于在API文档中嵌入代码片段,以便更好地展示API的使用方法。
主要特点:
* 有效性检查,代码包含语法错误时,会出现错误提示
* 启用现代样式,例如语法高亮显示,以及名称与声明的自动链接
* 为创建和编辑代码段提供更好的IDE支持
## 存在的@code标签
用于单独的小段代码, 当代码片段复杂时, 使用复合模式的文档注释,如下所示:
```java
* <pre>{@code
* 源代码行1
* ...
* 源代码行n
* }</pre>
```
## 引入@snippet标签
解决了`@code`标签的不足,允许在API文档中直接嵌入代码片段,以便更好地展示API的使用方法。
```java
/**
* 以下代码显示了如何使用 {@code Optional.isPresent}:
* {@snippet :
* if (v.isPresent()) {
* System.out.println("v: " + v.get());
* }
* }
*/
```
作为外部片段导入
```java
/**
* 以下代码显示了如何使用 {@code Optional.isPresent}:
* {@snippet file="ShowOptional.java" region="example"}
*/
```
其中`ShowOptional.java`是一个包含以下内容的文件:
```java
public class ShowOptional {
void show(Optional<String> v) {
// @start region="example"
if (v.isPresent()) {
System.out.println("v: " + v.get());
}
// @end
}
}
```
================================================
FILE: src/md/java/features/Java19/java19-new-features-summary.md
================================================
---
title: Java19 新特性总结
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-01-04
category: Java Features
tag:
- java
---
# Java 19 新特性总结
该版本推出的均为孵化与预览功能,所以这里不做单独的详细解读,大部分内容均放在Java 21中介绍。
* 422: Linux/RISC-V Port:RISC-V是一个基于精简指令集(RISC)原则的开源指令集架构(ISA),这个JEP的主旨则是移植JDK到RISC-V上。
以下预览特性在Java 21中正式定稿:
* [405: Record Patterns (Preview):终稿见 440: Record Patterns](/java-features/Java21/jep440-record-partterns)
* [425: Virtual Threads (Preview):终稿见 444: Virtual Threads](/java-features/Java21/jep444-virtual-threads)
* [427: Pattern Matching for switch (Third Preview):终稿见 441: Pattern Matching for switch](/java-features/Java21/jep441-pattern-matching-for-switch)
以下内容在Java 21中继续迭代:
* 424: Foreign Function & Memory API (Preview)
* 426: Vector API (Fourth Incubator)
* 428: Structured Concurrency (Incubator)
================================================
FILE: src/md/java/features/Java20/java20-new-features-summary.md
================================================
---
title: Java20 新特性总结
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-01-05
category: Java Features
tag:
- java
---
# Java 20 新特性总结
该版本推出的均为孵化与预览功能,所以这里不做单独的详细解读,大部分内容均放在Java 21中介绍。
以下内容在Java 21中正式定稿,可根据链接查看终稿内容:
* [432: Record Patterns (Second Preview):终稿见440: Record Patterns](/java-features/Java21/jep440-record-partterns)
* [433: Pattern Matching for switch (Fourth Preview):终稿见441: Pattern Matching for switch](/java-features/Java21/jep441-pattern-matching-for-switch)
* [436: Virtual Threads (Second Preview):终稿见444: Virtual Threads](/java-features/Java21/jep444-virtual-threads)
以下内容在Java 21中继续迭代:
* 429: Scoped Values (Incubator)
* 434: Foreign Function & Memory API (Second Preview)
* 437: Structured Concurrency (Second Incubator)
* 438: Vector API (Fifth Incubator)
================================================
FILE: src/md/java/features/Java21/jep430-string-templates.md
================================================
---
title: Java 21 新特性:字符串模版(Preview)
shortTitle:
description:
icon:
cover:
author: 流浪码客
isOriginal: true
sticky: false
star: false
date: 2024-01-06
category: Java Features
tag:
- java
order: 430
---
# Java 21 新特性:String Templates(字符串模版)
gitextract_4cg6voya/
├── .github/
│ └── workflows/
│ └── deploy-docs.yml
├── .gitignore
├── DirectoryV3.xml
├── README.md
├── package.json
└── src/
├── .vuepress/
│ ├── client.ts
│ ├── config/
│ │ └── docSearchLocales.ts
│ ├── config.ts
│ ├── path/
│ │ ├── navbar.ts
│ │ └── sidebar/
│ │ ├── index.ts
│ │ ├── installation-guide.ts
│ │ ├── java-datetime.ts
│ │ ├── java-features.ts
│ │ ├── java.ts
│ │ ├── jvm.ts
│ │ └── spring-framework.ts
│ ├── public/
│ │ ├── CNAME
│ │ └── special/
│ │ └── wedding-chenzhuo.html
│ ├── styles/
│ │ ├── config.scss
│ │ ├── index.scss
│ │ └── palette.scss
│ └── theme.ts
├── README.md
├── about-me.md
├── article.md
└── md/
├── blockchain/
│ └── README.md
├── database/
│ └── mysql/
│ ├── README.md
│ └── overview/
│ └── what-is-database.md
├── docker/
│ ├── install.md
│ ├── mirror-acceleration.md
│ ├── overview.md
│ └── top20-commands.md
├── flutter/
│ └── flutter-guide.md
├── idea-tips/
│ └── activation.md
├── installation-guide/
│ ├── README.md
│ ├── base-tools/
│ │ └── Homebrew.md
│ ├── dev-env/
│ │ ├── java/
│ │ │ └── SDKMAN.md
│ │ └── nodejs/
│ │ ├── Corepack.md
│ │ ├── nrm.md
│ │ └── nvm.md
│ └── os/
│ └── windows-office-activation.md
├── java/
│ ├── basic/
│ │ ├── java-basic-oop.md
│ │ ├── java-common-classes.md
│ │ └── java-from-scratch.md
│ ├── datetime/
│ │ ├── README.md
│ │ ├── api.md
│ │ ├── compare-dates.md
│ │ ├── convert-dates.md
│ │ ├── date-diff.md
│ │ ├── datetime.md
│ │ ├── locale.md
│ │ ├── timestamp.md
│ │ └── zoneddatetime-vs-offsetdatetime.md
│ ├── features/
│ │ ├── Java10/
│ │ │ └── jep286-local-variable-type-inference.md
│ │ ├── Java11/
│ │ │ └── jep320-remove-JavaEE-CORBA.md
│ │ ├── Java14/
│ │ │ └── jep361-switch-expressions.md
│ │ ├── Java15/
│ │ │ ├── jep371-hidden-classes.md
│ │ │ └── jep378-text-blocks.md
│ │ ├── Java16/
│ │ │ ├── jep394-pattern-matching-for-instanceof.md
│ │ │ └── jep395-records.md
│ │ ├── Java17/
│ │ │ ├── jep406-pattern-matching-for-switch-preview.md
│ │ │ └── jep409-sealed-classes.md
│ │ ├── Java18/
│ │ │ ├── jep400-utf8-by-default.md
│ │ │ ├── jep408-simple-web-server.md
│ │ │ └── jep413-code-snippets-in-api-documentation.md
│ │ ├── Java19/
│ │ │ └── java19-new-features-summary.md
│ │ ├── Java20/
│ │ │ └── java20-new-features-summary.md
│ │ ├── Java21/
│ │ │ ├── jep430-string-templates.md
│ │ │ ├── jep431-sequenced-collections.md
│ │ │ ├── jep439-generational-zgc.md
│ │ │ ├── jep440-record-partterns.md
│ │ │ ├── jep441-pattern-matching-for-switch.md
│ │ │ └── jep444-virtual-threads.md
│ │ ├── Java9/
│ │ │ ├── jep222-jshell.md
│ │ │ └── jep269-convenience-factory-methods-for-collections.md
│ │ └── README.md
│ ├── jvm/
│ │ ├── README.md
│ │ ├── part1/
│ │ │ ├── compile_jdk.md
│ │ │ └── overview.md
│ │ ├── part2/
│ │ │ ├── heap-object-flow.md
│ │ │ ├── runtime-data-areas.md
│ │ │ └── visual-tools/
│ │ │ └── visualvm.md
│ │ └── part3/
│ │ ├── bytecode-instructions-set.md
│ │ ├── class-file-structure.md
│ │ └── class-loading-mechanism.md
│ ├── kotlin/
│ │ └── kotlin-quick-for-java.md
│ └── thread/
│ └── thread-concurrency.md
├── spring-boot/
│ ├── README.md
│ └── quickstart.md
├── spring-data-jpa/
│ ├── README.md
│ └── jetbrains/
│ └── getting-started.md
├── spring-framework/
│ ├── core/
│ │ ├── README.md
│ │ ├── beans-definition.md
│ │ ├── beans-lifecycle.md
│ │ ├── beans-scope.md
│ │ ├── child-bean-definitions.md
│ │ ├── dependencies/
│ │ │ ├── README.md
│ │ │ ├── factory-autowire.md
│ │ │ ├── factory-collaborators.md
│ │ │ ├── factory-dependson.md
│ │ │ ├── factory-lazy-init.md
│ │ │ ├── factory-method-injection.md
│ │ │ └── factory-properties-detailed.md
│ │ └── ioc-container.md
│ └── overview/
│ ├── README.md
│ └── quickstart.md
└── template/
└── blog template.md
SYMBOL INDEX (2 symbols across 1 files)
FILE: src/.vuepress/client.ts
method enhance (line 20) | enhance({app, router, siteData}) {
method setup (line 33) | setup() {
Condensed preview — 107 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (627K chars).
[
{
"path": ".github/workflows/deploy-docs.yml",
"chars": 1391,
"preview": "# 全局配置参考:https://vuejs.press/zh/guide/deployment.html\nname: docs\n\non:\n # push 到 master 分支时自动部署\n push:\n branches: [m"
},
{
"path": ".gitignore",
"chars": 110,
"preview": "/.idea/\n/**/.obsidian/\nnode_modules/\nsrc/.vuepress/.cache/\nsrc/.vuepress/.temp/\nsrc/.vuepress/dist/\n.DS_Store\n"
},
{
"path": "DirectoryV3.xml",
"chars": 194,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n <trees>\n <tree path=\"/src/md/jvm/part2/basic-tools\" title=\"基础故障处理工具\"/>\n "
},
{
"path": "README.md",
"chars": 944,
"preview": "## 在线访问地址\n\nhttps://www.geekyspace.cn/\n\n## 博客效果图展示:\n\n<img width=\"1440\" alt=\"image\" src=\"https://github.com/joeljhou/geeky"
},
{
"path": "package.json",
"chars": 1064,
"preview": "{\n \"name\": \"vuepress-theme-hope-template\",\n \"version\": \"2.0.0\",\n \"description\": \"A project of vuepress-theme-hope\",\n "
},
{
"path": "src/.vuepress/client.ts",
"chars": 914,
"preview": "// client.ts ---> 客户端配置文件\n// @ts-ignore\nimport {defineGiscusConfig} from 'vuepress-plugin-comment2/client'\n// @ts-igno"
},
{
"path": "src/.vuepress/config/docSearchLocales.ts",
"chars": 1338,
"preview": "export const docSearchLocales = {\n placeholder: \"搜索geekyspace.cn的文档\",\n translations: {\n button: {\n "
},
{
"path": "src/.vuepress/config.ts",
"chars": 1929,
"preview": "// config.ts ---> 配置文件\nimport {defineUserConfig} from \"vuepress\";\nimport {redirectPlugin} from '@vuepress/plugin-redir"
},
{
"path": "src/.vuepress/path/navbar.ts",
"chars": 2238,
"preview": "import {navbar} from \"vuepress-theme-hope\";\n\nexport default navbar([\n {text: \"首页\", icon: \"home\", link: \"/\"},\n {tex"
},
{
"path": "src/.vuepress/path/sidebar/index.ts",
"chars": 1918,
"preview": "import {sidebar} from \"vuepress-theme-hope\";\n\nimport {java} from \"./java.js\";\nimport {springFramework} from \"./spring-fr"
},
{
"path": "src/.vuepress/path/sidebar/installation-guide.ts",
"chars": 1110,
"preview": "import {arraySidebar} from \"vuepress-theme-hope\";\n\nexport const installationGuide = arraySidebar([\n {text: \"开发者安装大全\","
},
{
"path": "src/.vuepress/path/sidebar/java-datetime.ts",
"chars": 1045,
"preview": "import {arraySidebar} from \"vuepress-theme-hope\";\n\nexport const javaDatetime = arraySidebar([\n {text: \"总目录\", pref"
},
{
"path": "src/.vuepress/path/sidebar/java-features.ts",
"chars": 3217,
"preview": "import {arraySidebar} from \"vuepress-theme-hope\";\n\nexport const javaFeatures = arraySidebar([\n {text: \"总目录\", pref"
},
{
"path": "src/.vuepress/path/sidebar/java.ts",
"chars": 976,
"preview": "import {arraySidebar} from \"vuepress-theme-hope\";\n\nexport const java = arraySidebar([\n {\n text: \"Java "
},
{
"path": "src/.vuepress/path/sidebar/jvm.ts",
"chars": 1748,
"preview": "import {arraySidebar} from \"vuepress-theme-hope\";\n\nexport const jvm = arraySidebar([\n {text: \"总目录\", prefix: \"/md/"
},
{
"path": "src/.vuepress/path/sidebar/spring-framework.ts",
"chars": 1355,
"preview": "import {arraySidebar} from \"vuepress-theme-hope\";\n\nexport const springFramework = arraySidebar([\n {\n t"
},
{
"path": "src/.vuepress/public/CNAME",
"chars": 18,
"preview": "www.geekyspace.cn\n"
},
{
"path": "src/.vuepress/public/special/wedding-chenzhuo.html",
"chars": 1464,
"preview": "<!DOCTYPE html>\n<html lang=\"zh\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width"
},
{
"path": "src/.vuepress/styles/config.scss",
"chars": 689,
"preview": "// 你可以在这里更改配置 https://theme-hope.vuejs.press/zh/config/style.html\n/* Content Class */\n$content-class: \".theme-hope-conte"
},
{
"path": "src/.vuepress/styles/index.scss",
"chars": 2430,
"preview": "// fix:解决新版Chrome字体加粗\nbody {\n font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantare"
},
{
"path": "src/.vuepress/styles/palette.scss",
"chars": 96,
"preview": "// 设置默认主题色\n$theme-color: #3eaf7c;\n\n// 主题色选择器\n$theme-colors: #2196f3, #a266f3, #e04c8a, #fb9b5f;\n"
},
{
"path": "src/.vuepress/theme.ts",
"chars": 24772,
"preview": "import {hopeTheme} from \"vuepress-theme-hope\";\n\nimport navbar from \"./path/navbar.js\";\nimport sidebar from \"./path/sideb"
},
{
"path": "src/README.md",
"chars": 1054,
"preview": "---\n# 博客主页配置:https://theme-hope.vuejs.press/zh/config/frontmatter/blog-home.html\nhome: true\nlayout: BlogHome\nhero: false"
},
{
"path": "src/about-me.md",
"chars": 958,
"preview": "---\n# 信息 Frontmatter 配置\ntitle: 个人简介\ndescription: 一个专注于技术分享的博客网站\nicon: circle-info\n# cover: /assets/images/cover3.jpg\naut"
},
{
"path": "src/article.md",
"chars": 1588,
"preview": "---\nhome: true\nicon: home\ntitle: 文库汇总\n\n# 指定首页背景头像\nheroImage: /images/personal/geekyspace.png\nheroImageDark: /images/pers"
},
{
"path": "src/md/blockchain/README.md",
"chars": 1276,
"preview": "---\ntitle: 区块链基础\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 202"
},
{
"path": "src/md/database/mysql/README.md",
"chars": 225,
"preview": "---\ntitle: MySQL 必知必会\nshortTitle:\ndescription:\nicon: mysql\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: fals"
},
{
"path": "src/md/database/mysql/overview/what-is-database.md",
"chars": 1018,
"preview": "---\ntitle: 什么是数据库?\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 2"
},
{
"path": "src/md/docker/install.md",
"chars": 805,
"preview": "---\ntitle: Docker安装\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: "
},
{
"path": "src/md/docker/mirror-acceleration.md",
"chars": 1561,
"preview": "---\ntitle: Docker镜像加速器\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndat"
},
{
"path": "src/md/docker/overview.md",
"chars": 2234,
"preview": "---\ntitle: Docker概述\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: "
},
{
"path": "src/md/docker/top20-commands.md",
"chars": 4322,
"preview": "---\ntitle: Top20常用命令\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate:"
},
{
"path": "src/md/flutter/flutter-guide.md",
"chars": 6220,
"preview": "---\ntitle: Flutter入门指南\nshortTitle:\ndescription: Flutter是一个跨端的平台开发框架\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: f"
},
{
"path": "src/md/idea-tips/activation.md",
"chars": 1431,
"preview": "---\ntitle: 2025最新IntelliJ IDEA专业版稳定正版激活码\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: fal"
},
{
"path": "src/md/installation-guide/README.md",
"chars": 219,
"preview": "---\ntitle: 开发者安装大全\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 2"
},
{
"path": "src/md/installation-guide/base-tools/Homebrew.md",
"chars": 3105,
"preview": "---\ntitle: macOS必备包管理工具—Homebrew\nshortTitle: \ndescription: \nicon: \ncover: \nauthor: 流浪码客\nisOriginal: true\nsticky: false\ns"
},
{
"path": "src/md/installation-guide/dev-env/java/SDKMAN.md",
"chars": 1446,
"preview": "---\ntitle: Java生态版本管理神器—SDKMAN\nshortTitle: \ndescription: \nicon: \ncover: \nauthor: 流浪码客\nisOriginal: true\nsticky: false\nsta"
},
{
"path": "src/md/installation-guide/dev-env/nodejs/Corepack.md",
"chars": 1718,
"preview": "---\ntitle: Corepack核心包管理工具\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false"
},
{
"path": "src/md/installation-guide/dev-env/nodejs/nrm.md",
"chars": 1954,
"preview": "---\ntitle: npm源切换加速利器—nrm\nshortTitle: \ndescription: \nicon: \ncover: \nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: fa"
},
{
"path": "src/md/installation-guide/dev-env/nodejs/nvm.md",
"chars": 1755,
"preview": "---\ntitle: Node.js版本管理神器—nvm\nshortTitle: \ndescription: \nicon: \ncover: \nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar:"
},
{
"path": "src/md/installation-guide/os/windows-office-activation.md",
"chars": 3724,
"preview": "---\ntitle: Windows、Office激活密钥,脚本,程序\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nst"
},
{
"path": "src/md/java/basic/java-basic-oop.md",
"chars": 2260,
"preview": "---\ntitle: Java核心思想 - 面向对象编程(OOP)\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar"
},
{
"path": "src/md/java/basic/java-common-classes.md",
"chars": 8979,
"preview": "---\ntitle: Java 常用类与工具\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndat"
},
{
"path": "src/md/java/basic/java-from-scratch.md",
"chars": 19988,
"preview": "---\ntitle: Java基础 - 从零开始学习Java\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: f"
},
{
"path": "src/md/java/datetime/README.md",
"chars": 4994,
"preview": "---\ntitle: Java 日期时间\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate:"
},
{
"path": "src/md/java/datetime/api.md",
"chars": 6521,
"preview": "---\ntitle: Java 日期时间 API\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\nd"
},
{
"path": "src/md/java/datetime/compare-dates.md",
"chars": 4097,
"preview": "---\ntitle: 比较两个日期\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 20"
},
{
"path": "src/md/java/datetime/convert-dates.md",
"chars": 6454,
"preview": "---\ntitle: 转换日期时间实例\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: "
},
{
"path": "src/md/java/datetime/date-diff.md",
"chars": 4081,
"preview": "---\ntitle: 获取两个日期之间的时间差\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\nda"
},
{
"path": "src/md/java/datetime/datetime.md",
"chars": 2470,
"preview": "---\ntitle: 获取当前日期和时间\nshortTitle:\ndescription: Java 提供了许多有用的方法来获取当前日期或当前时间,可以使用 `Date`、`Calendar` 以及 Java 8 Date/Time API"
},
{
"path": "src/md/java/datetime/locale.md",
"chars": 4233,
"preview": "---\ntitle: 获取用户的区域设置、国际化\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\nd"
},
{
"path": "src/md/java/datetime/timestamp.md",
"chars": 1541,
"preview": "---\ntitle: 获取当前时间戳\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 2"
},
{
"path": "src/md/java/datetime/zoneddatetime-vs-offsetdatetime.md",
"chars": 3819,
"preview": "---\ntitle: ZonedDateTime 和 OffsetDateTime 的区别\nshortTitle:\ndescription: 详解 Java 8 日期时间 API 中 ZonedDateTime 和 OffsetDateTi"
},
{
"path": "src/md/java/features/Java10/jep286-local-variable-type-inference.md",
"chars": 1048,
"preview": "---\ntitle: Java 10 新特性:局部变量类型推断\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\ndate: 2023-12-23\nsti"
},
{
"path": "src/md/java/features/Java11/jep320-remove-JavaEE-CORBA.md",
"chars": 1063,
"preview": "---\ntitle: Java 11 新特性 :移除JavaEE和CORBA模块以及JavaFX\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsti"
},
{
"path": "src/md/java/features/Java14/jep361-switch-expressions.md",
"chars": 2638,
"preview": "---\ntitle: Java 14 新特性:switch表达式增强\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nsta"
},
{
"path": "src/md/java/features/Java15/jep371-hidden-classes.md",
"chars": 595,
"preview": "---\ntitle: Java 15 新特性:隐藏类(Hidden Classes)\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: f"
},
{
"path": "src/md/java/features/Java15/jep378-text-blocks.md",
"chars": 3803,
"preview": "---\ntitle: Java 15 新特性:文本块(Text Blocks)\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: fals"
},
{
"path": "src/md/java/features/Java16/jep394-pattern-matching-for-instanceof.md",
"chars": 1397,
"preview": "---\ntitle: Java 16 新特性:instanceof 模式匹配\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false"
},
{
"path": "src/md/java/features/Java16/jep395-records.md",
"chars": 4124,
"preview": "---\ntitle: Java 16 新特性:record类\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: f"
},
{
"path": "src/md/java/features/Java17/jep406-pattern-matching-for-switch-preview.md",
"chars": 5397,
"preview": "---\ntitle: Java 17 新特性:switch模式匹配(Preview)\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: f"
},
{
"path": "src/md/java/features/Java17/jep409-sealed-classes.md",
"chars": 996,
"preview": "---\ntitle: Java 17 新特性:sealed类\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: f"
},
{
"path": "src/md/java/features/Java18/jep400-utf8-by-default.md",
"chars": 3247,
"preview": "---\ntitle: Java 18 新特性:指定UTF-8为默认字符集\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\ns"
},
{
"path": "src/md/java/features/Java18/jep408-simple-web-server.md",
"chars": 5702,
"preview": "---\ntitle: Java 18 新特性:简单Web服务器\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: "
},
{
"path": "src/md/java/features/Java18/jep413-code-snippets-in-api-documentation.md",
"chars": 1125,
"preview": "---\ntitle: Java 18 新特性:新增@snipppet标签\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\ns"
},
{
"path": "src/md/java/features/Java19/java19-new-features-summary.md",
"chars": 867,
"preview": "---\ntitle: Java19 新特性总结\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\nda"
},
{
"path": "src/md/java/features/Java20/java20-new-features-summary.md",
"chars": 845,
"preview": "---\ntitle: Java20 新特性总结\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\nda"
},
{
"path": "src/md/java/features/Java21/jep430-string-templates.md",
"chars": 6590,
"preview": "---\ntitle: Java 21 新特性:字符串模版(Preview)\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\n"
},
{
"path": "src/md/java/features/Java21/jep431-sequenced-collections.md",
"chars": 4256,
"preview": "---\ntitle: Java 21 新特性:有序集合\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: fals"
},
{
"path": "src/md/java/features/Java21/jep439-generational-zgc.md",
"chars": 3880,
"preview": "---\ntitle: Java 21 新特性:分代ZGC\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: fal"
},
{
"path": "src/md/java/features/Java21/jep440-record-partterns.md",
"chars": 2878,
"preview": "---\ntitle: Java 21 新特性:记录模式\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: fals"
},
{
"path": "src/md/java/features/Java21/jep441-pattern-matching-for-switch.md",
"chars": 1706,
"preview": "---\ntitle: Java 21 新特性:switch模式匹配\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar"
},
{
"path": "src/md/java/features/Java21/jep444-virtual-threads.md",
"chars": 3247,
"preview": "---\ntitle: Java 21 新特性:虚拟线程\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: fals"
},
{
"path": "src/md/java/features/Java9/jep222-jshell.md",
"chars": 5089,
"preview": "---\ntitle: Java 9 新特性:交互式编程环境JShell\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nst"
},
{
"path": "src/md/java/features/Java9/jep269-convenience-factory-methods-for-collections.md",
"chars": 2952,
"preview": "---\ntitle: Java 9 新特性:不可变集合的快捷创建方法\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nsta"
},
{
"path": "src/md/java/features/README.md",
"chars": 11737,
"preview": "---\ntitle: Java新版本特性(持续连载)\nshortTitle:\ndescription: Java 8-21:前沿特性解读系列(持续连载),截至2023年9月中旬,Java已达到第21版本。\n 尽管如此,众多开发者仍停滞在J"
},
{
"path": "src/md/java/jvm/README.md",
"chars": 4455,
"preview": "---\ntitle: 深入理解Java虚拟机\nshortTitle:\ndescription:\nicon: jvm-xx\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: true # 置顶特定文章"
},
{
"path": "src/md/java/jvm/part1/compile_jdk.md",
"chars": 660,
"preview": "---\ntitle: 实战编译JDK\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 2"
},
{
"path": "src/md/java/jvm/part1/overview.md",
"chars": 7215,
"preview": "---\ntitle: Java虚拟机概述\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate:"
},
{
"path": "src/md/java/jvm/part2/heap-object-flow.md",
"chars": 1171,
"preview": "---\ntitle: 堆中对象分配、布局和访问的全过程\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: fals"
},
{
"path": "src/md/java/jvm/part2/runtime-data-areas.md",
"chars": 3287,
"preview": "---\ntitle: 运行时数据区\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 20"
},
{
"path": "src/md/java/jvm/part2/visual-tools/visualvm.md",
"chars": 422,
"preview": "---\ntitle: VisualVM介绍\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate"
},
{
"path": "src/md/java/jvm/part3/bytecode-instructions-set.md",
"chars": 9540,
"preview": "---\ntitle: 字节码指令集\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 20"
},
{
"path": "src/md/java/jvm/part3/class-file-structure.md",
"chars": 25004,
"preview": "---\ntitle: 类文件结构\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 202"
},
{
"path": "src/md/java/jvm/part3/class-loading-mechanism.md",
"chars": 8337,
"preview": "---\ntitle: 类加载机制\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate: 202"
},
{
"path": "src/md/java/kotlin/kotlin-quick-for-java.md",
"chars": 20091,
"preview": "---\ntitle: Java 程序员快速掌握 Kotlin\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: f"
},
{
"path": "src/md/java/thread/thread-concurrency.md",
"chars": 10862,
"preview": "---\ntitle: Java多线程与并发编程\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\nda"
},
{
"path": "src/md/spring-boot/README.md",
"chars": 205,
"preview": "---\ntitle: Spring Boot 入门教程\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: fals"
},
{
"path": "src/md/spring-boot/quickstart.md",
"chars": 214,
"preview": "---\ntitle: SpringBoot 快速入门\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false"
},
{
"path": "src/md/spring-data-jpa/README.md",
"chars": 286,
"preview": "---\ntitle: Spring Data JPA\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false"
},
{
"path": "src/md/spring-data-jpa/jetbrains/getting-started.md",
"chars": 12549,
"preview": "---\ntitle: Spring Data JPA 快速入门\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: "
},
{
"path": "src/md/spring-framework/core/README.md",
"chars": 1646,
"preview": "---\ntitle: Spring 核心技术\nicon: spring\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-18\ncategory: Spring\ntag: Spring Framewor"
},
{
"path": "src/md/spring-framework/core/beans-definition.md",
"chars": 6228,
"preview": "---\ntitle: Bean 定义(Definition)\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-18\ncategory: Spring\ntag: Spring Framework\n---"
},
{
"path": "src/md/spring-framework/core/beans-lifecycle.md",
"chars": 15656,
"preview": "---\ntitle: Bean生命周期(Lifecycle)\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-04-08\ncategory: Spring\ntag: Spring Framework\n---"
},
{
"path": "src/md/spring-framework/core/beans-scope.md",
"chars": 14611,
"preview": "---\ntitle: Bean作用域(Scope)\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-04-03\ncategory: Spring\ntag: Spring Framework\n---\n\n# B"
},
{
"path": "src/md/spring-framework/core/child-bean-definitions.md",
"chars": 2276,
"preview": "---\ntitle: Bean定义继承\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-04-10\ncategory: Spring\ntag: Spring Framework\n---\n\n# Bean定义继"
},
{
"path": "src/md/spring-framework/core/dependencies/README.md",
"chars": 535,
"preview": "---\ntitle: 依赖(Dependencies)\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-26\ncategory: Spring\ntag: Spring Framework\n---\n\n#"
},
{
"path": "src/md/spring-framework/core/dependencies/factory-autowire.md",
"chars": 3705,
"preview": "---\ntitle: 自动装配协作者\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-26\ncategory: Spring\ntag: Spring Framework\n---\n\n# 自动装配协作者("
},
{
"path": "src/md/spring-framework/core/dependencies/factory-collaborators.md",
"chars": 9553,
"preview": "---\ntitle: 依赖注入\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-26\ncategory: Spring\ntag: Spring Framework\n---\n\n# 依赖注入\n\n## 依赖"
},
{
"path": "src/md/spring-framework/core/dependencies/factory-dependson.md",
"chars": 1153,
"preview": "---\ntitle: 使用depends-on\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-26\ncategory: Spring\ntag: Spring Framework\n---\n\n# 使用d"
},
{
"path": "src/md/spring-framework/core/dependencies/factory-lazy-init.md",
"chars": 976,
"preview": "---\ntitle: 懒加载(Lazy Initialization)Bean\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-26\ncategory: Spring\ntag: Spring Fram"
},
{
"path": "src/md/spring-framework/core/dependencies/factory-method-injection.md",
"chars": 1806,
"preview": "---\ntitle: 方法注入\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-26\ncategory: Spring\ntag: Spring Framework\n---\n\n# 方法注入\n\n大多数应用"
},
{
"path": "src/md/spring-framework/core/dependencies/factory-properties-detailed.md",
"chars": 13569,
"preview": "---\ntitle: 依赖和配置详解\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-26\ncategory: Spring\ntag: Spring Framework\n---\n\n# 依赖和配置详解\n"
},
{
"path": "src/md/spring-framework/core/ioc-container.md",
"chars": 6542,
"preview": "---\ntitle: IoC 容器(Container)\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-18\ncategory: Spring\ntag: Spring Framework\n---\n\n"
},
{
"path": "src/md/spring-framework/overview/README.md",
"chars": 1584,
"preview": "---\ntitle: Spring Framework 概述\nicon: spring\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-15\ncategory: Spring\ntag: Spring "
},
{
"path": "src/md/spring-framework/overview/quickstart.md",
"chars": 4235,
"preview": "---\ntitle: Spring Framework 快速开始\nicon: spring\nauthor: 流浪码客\nisOriginal: true\ndate: 2024-03-15\ncategory: Spring\ntag: Sprin"
},
{
"path": "src/md/template/blog template.md",
"chars": 202,
"preview": "---\ntitle: {{title}}\nshortTitle:\ndescription:\nicon:\ncover:\nauthor: 流浪码客\nisOriginal: true\nsticky: false\nstar: false\ndate:"
}
]
About this extraction
This page contains the full source code of the joeljhou/geekyspace GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 107 files (410.9 KB), approximately 168.4k tokens, and a symbol index with 2 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.