Skip to content

Commit c86fd35

Browse files
committed
Enhance Java docs with practical examples and feedback
Added detailed examples and explanations for Java反射, 多线程应用场景, 索引创建实践, 以及数据导出功能的设计模式实现。补充了真实用户反馈和成长故事,丰富了文档的实用性和激励性。
1 parent 8b60e45 commit c86fd35

File tree

4 files changed

+219
-5
lines changed

4 files changed

+219
-5
lines changed

docs/src/sidebar/sanfene/javase.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2738,7 +2738,7 @@ Person 类的信息在编译时就确定了,那假如在编译期无法确定
27382738

27392739
![三分恶面渣逆袭:Java反射相关类](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javase-36.png)
27402740

2741-
比如说我们可以装来动态加载类并创建对象
2741+
比如说我们可以动态加载类并创建对象
27422742

27432743
```java
27442744
String className = "java.util.Date";
@@ -2774,7 +2774,7 @@ Class<?> clazz = Class.forName("com.example.MyClass");
27742774
Object instance = clazz.newInstance();
27752775
```
27762776

2777-
②、Java 的动态代理(Dynamic Proxy)机制就使用了反射来创建代理类。代理类可以在运行时动态处理方法调用,这在实现 AOP 和拦截器时非常有用。
2777+
②、Java 的动态代理机制就使用了反射来创建代理类。代理类可以在运行时动态处理方法调用,这在实现 AOP 和拦截器时非常有用。
27782778

27792779
```java
27802780
InvocationHandler handler = new MyInvocationHandler();
@@ -2792,16 +2792,35 @@ Method testMethod = testClass.getMethod("testSomething");
27922792
testMethod.invoke(testInstance);
27932793
```
27942794

2795+
④、最常见的是写通用的工具类,比如对象拷贝工具。比如说 BeanUtils、MapStruct 等等,能够自动拷贝两个对象之间的同名属性,就是通过反射来实现的。
2796+
2797+
![技术派:mapstruct](https://cdn.tobebetterjavaer.com/stutymore/javase-20250927172849.png)
2798+
2799+
27952800
#### 反射的原理是什么?
27962801

2797-
Java 程序的执行分为编译和运行两步,编译之后会生成字节码(.class)文件,JVM 进行类加载的时候,会加载字节码文件,将类型相关的所有信息加载进方法区,反射就是去获取这些信息,然后进行各种操作。
2802+
每个类在加载到 JVM 后,都会在方法区生成一个对应的 Class 对象,这个对象包含了类的所有元信息,比如字段、方法、构造器、注解等。
2803+
2804+
通过这个 Class 对象,我们就能在运行时动态地创建对象、调用方法、访问字段。
2805+
2806+
### 反射的优缺点是什么?
2807+
2808+
反射的优点还是很明显的。首先是能够在运行时动态操作类和对象。其次是能够编写通用的代码,一套代码可以处理不同类型的对象。还有就是能够突破访问限制,访问 private 字段和方法,这在反编译场景下很有用。
2809+
2810+
但反射的缺点也不少。最明显的是性能问题,反射操作比直接调用要慢很多,因为需要在运行时解析类信息、进行类型检查、权限验证等。
2811+
2812+
其次是反射能够绕过访问控制,访问和修改 private 成员,这会破坏类的封装。
27982813

27992814
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 2 Java 后端技术一面面试原题:Java 反射用过吗?
28002815
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 18 成都到家面试原题:反射及其应用场景
28012816
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米面经同学 F 面试原题:反射的介绍与使用场景
28022817
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 3 Java 后端技术一面面试原题:java 的反射机制,反射的应用场景 AOP 的实现原理是什么,与动态代理和反射有什么区别
28032818
> 5. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的比亚迪面经同学 12 Java 技术面试原题:java的反射
28042819
2820+
memo:2025 年 9 月 27 日修改至此,今天[在帮球友修改简历](https://javabetter.cn/zhishixingqiu/)的时候,碰到这样一个反馈,很感动:两个月前在特别焦虑迷茫时找过一次二哥,你说了别担心先去做先去投之类的话那次沟通后让我清醒了很多,我开始停止设想坏的结果,照着简历学习八股,投简历,最后收到了面试通知,运气也很好背的八股也派上用场,虽然没有一下子变得特别厉害,但是实打实地感觉自己比以前成熟稳重点了。学习过程中发现自己蛮喜欢软开的,也能获得成就感,所以特别感谢二哥一直以来对大家的帮助。
2821+
2822+
![球友在星球里的成长](https://cdn.tobebetterjavaer.com/stutymore/javase-20250927172411.png)
2823+
28052824
## JDK1.8 新特性
28062825

28072826
JDK 已经出到 17 了,但是你迭代你的版本,我用我的 8。JDK1.8 的一些新特性,当然现在也不新了,其实在工作中已经很常用了。

docs/src/sidebar/sanfene/javathread.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,14 @@ Thread: Finalizer (ID=3)
292292
- `Thread: Signal Dispatcher (ID=4)` - 信号调度线程,处理来自操作系统的信号,将它们转发给 JVM 进行进一步处理,例如响应中断、停止等信号。
293293
- `Thread: Monitor Ctrl-Break (ID=5)` - 监视器线程,通常由一些特定的 IDE 创建,用于在开发过程中监控和管理程序执行或者处理中断。
294294

295+
#### 你平时有用过多线程吗?你在代码中是哪些场景用呢?
296+
297+
用得比较多,批量数据处理、异步任务处理、定时任务调度都需要用到多线程。
298+
299+
比如说在[技术派的首页内容加载](https://javabetter.cn/zhishixingqiu/paicoding.html)中,就用到了多线程来并行加载不同的模块,提高页面的响应速度。
300+
301+
![技术派:并行首页内容加载](https://cdn.tobebetterjavaer.com/stutymore/javathread-20250927175506.png)
302+
295303
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的字节跳动面经同学 1 Java 后端技术一面面试原题:有多少种实现线程的方法?
296304
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的农业银行同学 1 面试原题:实现线程的方式和区别
297305
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的农业银行面经同学 3 Java 后端面试原题:说说线程的创建方法
@@ -301,7 +309,9 @@ Thread: Finalizer (ID=3)
301309
> 7. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的百度面经同学 1 文心一言 25 实习 Java 后端面试原题:java 如何创建线程?每次都要创建新线程来实现异步操作,很繁琐,有了解线程池吗?
302310
> 8. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 4 一面面试原题:平时怎么使用多线程
303311
304-
memo:2025 年 1 月 24 日修改至此。
312+
memo:2025 年 9 月 26 日修改至此。今天[有球友在星球里](https://javabetter.cn/zhishixingqiu/)报喜说拿到了字节的意向,感谢二哥的面渣逆袭。
313+
314+
![拿到字节的意向了](https://cdn.tobebetterjavaer.com/stutymore/javathread-20250927175050.png)
305315

306316
### 4.🌟调用 start 方法时会执行 run 方法,那怎么不直接调用 run方法?
307317

@@ -4671,6 +4681,8 @@ memo:2025 年 2 月 24 日修改至此。今天是出考研成绩的一天,
46714681

46724682
> 2024 年 03 月 16 日增补,推荐阅读:[Java线程池实现原理及其在美团业务中的实践](https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html)
46734683
4684+
线程池的配置优化是针对多线程应用性能调优的关键环节。
4685+
46744686
![三分恶面渣逆袭:线程池调优](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javathread-82.png)
46754687

46764688
首先我会根据任务类型设置核心线程数参数,比如 IO 密集型任务会设置为 CPU 核心数\*2 的经验值。
@@ -4679,6 +4691,10 @@ memo:2025 年 2 月 24 日修改至此。今天是出考研成绩的一天,
46794691

46804692
最后,我会通过内置的监控指标建立容量预警机制。比如通过 JMX 监控线程池的运行状态,设置阈值,当线程池的任务队列长度超过阈值时,触发告警。
46814693

4694+
memo:2025 年 9 月 26 日优化至此,今天有球友在 VIP 群里讲,投了 1 天就接面了,[二哥改的简历还是太好用](https://javabetter.cn/zhishixingqiu/jianli.html)。很感谢他的认可。
4695+
4696+
![球友对简历修改的认可](https://cdn.tobebetterjavaer.com/stutymore/javathread-投了1天就接面了,二哥改的简历还是太好用.png)
4697+
46824698
### 68.线程池在使用的时候需要注意什么?(补充)
46834699

46844700
> 2024 年 03 月 16 日增补

docs/src/sidebar/sanfene/mysql.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2504,7 +2504,7 @@ memo:2025 年 3 月 29 日修改至此,今天[有球友说](https://javabett
25042504

25052505
除了查得快,索引还能加速排序、分组、连接等操作。
25062506

2507-
可以通过 `create index` 创建索引,比如:
2507+
项目中最常见的做法就是通过 `create index` 为经常用作查询条件的字段建索引,比如:
25082508

25092509
```sql
25102510
create index idx_name on students(name);

docs/src/sidebar/sanfene/shejimoshi.md

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,185 @@ memo:2025 年 8 月 12 日修改至此,今天有球友在VIP 群里讲,他
464464

465465
后面想添加新的 AI 服务,只需要增加一个新的策略类,不需要修改原有代码,这样就提高了代码的可扩展性。
466466

467+
### 你想做一个导出的数据导出的功能,然后他可能导出的格式有Excel、有JSON,可能有XML,然后如果你用面向对象这些方法去做,会怎么去设计这个实现?
468+
469+
我会使用策略模式+工厂模式来实现。
470+
471+
首先,我会定义一个导出接口 `DataExporter`,该接口包含一个导出方法 `export(data)`,用于导出数据。
472+
473+
```java
474+
public interface DataExporter {
475+
void export(List<Object> data, OutputStream outputStream) throws Exception;
476+
String getContentType();
477+
String getFileExtension();
478+
}
479+
```
480+
481+
然后,我会为每种导出格式(Excel、JSON、XML)创建具体的策略类,这些类实现了 `ExportStrategy` 接口,并提供各自的导出逻辑。
482+
483+
```java
484+
public class ExcelExporter implements DataExporter {
485+
@Override
486+
public void export(List<Object> data, OutputStream outputStream) throws Exception {
487+
Workbook workbook = new XSSFWorkbook();
488+
Sheet sheet = workbook.createSheet("Data");
489+
490+
// 写入表头
491+
if (!data.isEmpty()) {
492+
Object firstRow = data.get(0);
493+
Row headerRow = sheet.createRow(0);
494+
Field[] fields = firstRow.getClass().getDeclaredFields();
495+
for (int i = 0; i < fields.length; i++) {
496+
headerRow.createCell(i).setCellValue(fields[i].getName());
497+
}
498+
499+
// 写入数据
500+
for (int i = 0; i < data.size(); i++) {
501+
Row dataRow = sheet.createRow(i + 1);
502+
Object obj = data.get(i);
503+
for (int j = 0; j < fields.length; j++) {
504+
fields[j].setAccessible(true);
505+
Object value = fields[j].get(obj);
506+
dataRow.createCell(j).setCellValue(value != null ? value.toString() : "");
507+
}
508+
}
509+
}
510+
511+
workbook.write(outputStream);
512+
workbook.close();
513+
}
514+
515+
@Override
516+
public String getContentType() {
517+
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
518+
}
519+
520+
@Override
521+
public String getFileExtension() {
522+
return "xlsx";
523+
}
524+
}
525+
526+
public class JsonExporter implements DataExporter {
527+
private ObjectMapper objectMapper = new ObjectMapper();
528+
529+
@Override
530+
public void export(List<Object> data, OutputStream outputStream) throws Exception {
531+
objectMapper.writeValue(outputStream, data);
532+
}
533+
534+
@Override
535+
public String getContentType() {
536+
return "application/json";
537+
}
538+
539+
@Override
540+
public String getFileExtension() {
541+
return "json";
542+
}
543+
}
544+
545+
public class XmlExporter implements DataExporter {
546+
@Override
547+
public void export(List<Object> data, OutputStream outputStream) throws Exception {
548+
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
549+
DocumentBuilder builder = factory.newDocumentBuilder();
550+
Document document = builder.newDocument();
551+
552+
Element root = document.createElement("data");
553+
document.appendChild(root);
554+
555+
for (Object obj : data) {
556+
Element item = document.createElement("item");
557+
Field[] fields = obj.getClass().getDeclaredFields();
558+
for (Field field : fields) {
559+
field.setAccessible(true);
560+
Element element = document.createElement(field.getName());
561+
Object value = field.get(obj);
562+
element.setTextContent(value != null ? value.toString() : "");
563+
item.appendChild(element);
564+
}
565+
root.appendChild(item);
566+
}
567+
568+
TransformerFactory transformerFactory = TransformerFactory.newInstance();
569+
Transformer transformer = transformerFactory.newTransformer();
570+
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
571+
DOMSource source = new DOMSource(document);
572+
StreamResult result = new StreamResult(outputStream);
573+
transformer.transform(source, result);
574+
}
575+
576+
@Override
577+
public String getContentType() {
578+
return "application/xml";
579+
}
580+
581+
@Override
582+
public String getFileExtension() {
583+
return "xml";
584+
}
585+
}
586+
```
587+
588+
接下来,我会创建一个工厂类 `DataExporterFactory`,用于根据导出格式创建相应的导出策略实例。
589+
590+
```java
591+
public class DataExporterFactory {
592+
private static final Map<String, DataExporter> exporters = new HashMap<>();
593+
594+
static {
595+
exporters.put("excel", new ExcelExporter());
596+
exporters.put("json", new JsonExporter());
597+
exporters.put("xml", new XmlExporter());
598+
}
599+
600+
public static DataExporter getExporter(String format) {
601+
DataExporter exporter = exporters.get(format.toLowerCase());
602+
if (exporter == null) {
603+
throw new IllegalArgumentException("不支持的导出格式: " + format);
604+
}
605+
return exporter;
606+
}
607+
608+
public static Set<String> getSupportedFormats() {
609+
return exporters.keySet();
610+
}
611+
}
612+
```
613+
614+
最后,我会定义导出服务的上下文类,我根据请求参数选择合适的导出策略,并调用其导出方法。
615+
616+
```java
617+
@Service
618+
public class DataExportService {
619+
620+
public void exportData(List<Object> data, String format, OutputStream outputStream)
621+
throws Exception {
622+
DataExporter exporter = DataExporterFactory.getExporter(format);
623+
exporter.export(data, outputStream);
624+
}
625+
626+
public ResponseEntity<byte[]> exportDataAsResponse(List<Object> data, String format)
627+
throws Exception {
628+
DataExporter exporter = DataExporterFactory.getExporter(format);
629+
630+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
631+
exporter.export(data, baos);
632+
633+
HttpHeaders headers = new HttpHeaders();
634+
headers.setContentType(MediaType.parseMediaType(exporter.getContentType()));
635+
headers.setContentDispositionFormData("attachment",
636+
"export_" + System.currentTimeMillis() + "." + exporter.getFileExtension());
637+
638+
return ResponseEntity.ok()
639+
.headers(headers)
640+
.body(baos.toByteArray());
641+
}
642+
}
643+
```
644+
645+
467646
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的字节跳动面经同学 1 Java 后端技术一面面试原题:了解哪些设计模式?
468647
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的奇安信面经同学 1 Java 技术一面面试原题:你真正使用过哪些设计模式?
469648
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的农业银行面经同学 7 Java 后端面试原题:介绍你熟悉的设计模式

0 commit comments

Comments
 (0)