Skip to content

Commit bd01e8b

Browse files
committed
Stage
1 parent 60ac77f commit bd01e8b

File tree

3 files changed

+182
-1
lines changed

3 files changed

+182
-1
lines changed

Gemfile.lock

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
GEM
2+
remote: https://rubygems.org/
3+
specs:
4+
addressable (2.8.7)
5+
public_suffix (>= 2.0.2, < 7.0)
6+
bigdecimal (3.1.9)
7+
colorator (1.1.0)
8+
concurrent-ruby (1.3.5)
9+
em-websocket (0.5.3)
10+
eventmachine (>= 0.12.9)
11+
http_parser.rb (~> 0)
12+
eventmachine (1.2.7)
13+
ffi (1.17.1-x64-mingw-ucrt)
14+
forwardable-extended (2.6.0)
15+
google-protobuf (4.30.2-x64-mingw-ucrt)
16+
bigdecimal
17+
rake (>= 13)
18+
http_parser.rb (0.8.0)
19+
i18n (1.14.7)
20+
concurrent-ruby (~> 1.0)
21+
jekyll (4.3.4)
22+
addressable (~> 2.4)
23+
colorator (~> 1.0)
24+
em-websocket (~> 0.5)
25+
i18n (~> 1.0)
26+
jekyll-sass-converter (>= 2.0, < 4.0)
27+
jekyll-watch (~> 2.0)
28+
kramdown (~> 2.3, >= 2.3.1)
29+
kramdown-parser-gfm (~> 1.0)
30+
liquid (~> 4.0)
31+
mercenary (>= 0.3.6, < 0.5)
32+
pathutil (~> 0.9)
33+
rouge (>= 3.0, < 5.0)
34+
safe_yaml (~> 1.0)
35+
terminal-table (>= 1.8, < 4.0)
36+
webrick (~> 1.7)
37+
jekyll-feed (0.17.0)
38+
jekyll (>= 3.7, < 5.0)
39+
jekyll-sass-converter (3.1.0)
40+
sass-embedded (~> 1.75)
41+
jekyll-seo-tag (2.8.0)
42+
jekyll (>= 3.8, < 5.0)
43+
jekyll-watch (2.2.1)
44+
listen (~> 3.0)
45+
kramdown (2.5.1)
46+
rexml (>= 3.3.9)
47+
kramdown-parser-gfm (1.1.0)
48+
kramdown (~> 2.0)
49+
liquid (4.0.4)
50+
listen (3.9.0)
51+
rb-fsevent (~> 0.10, >= 0.10.3)
52+
rb-inotify (~> 0.9, >= 0.9.10)
53+
mercenary (0.4.0)
54+
minima (2.5.2)
55+
jekyll (>= 3.5, < 5.0)
56+
jekyll-feed (~> 0.9)
57+
jekyll-seo-tag (~> 2.1)
58+
pathutil (0.16.2)
59+
forwardable-extended (~> 2.6)
60+
public_suffix (6.0.1)
61+
rake (13.2.1)
62+
rb-fsevent (0.11.2)
63+
rb-inotify (0.11.1)
64+
ffi (~> 1.0)
65+
rexml (3.4.1)
66+
rouge (4.5.1)
67+
safe_yaml (1.0.5)
68+
sass-embedded (1.86.1-x64-mingw-ucrt)
69+
google-protobuf (~> 4.30)
70+
terminal-table (3.0.2)
71+
unicode-display_width (>= 1.1.1, < 3)
72+
tzinfo (2.0.6)
73+
concurrent-ruby (~> 1.0)
74+
tzinfo-data (1.2025.2)
75+
tzinfo (>= 1.0.0)
76+
unicode-display_width (2.6.0)
77+
wdm (0.1.1)
78+
webrick (1.9.1)
79+
80+
PLATFORMS
81+
x64-mingw-ucrt
82+
83+
DEPENDENCIES
84+
http_parser.rb (~> 0.6.0)
85+
jekyll (~> 4.3.3)
86+
jekyll-feed (~> 0.12)
87+
minima (~> 2.5)
88+
tzinfo (>= 1, < 3)
89+
tzinfo-data
90+
wdm (~> 0.1.1)
91+
92+
BUNDLED WITH
93+
2.5.10

_posts/2024-10-04-csr.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
layout: post
33
title: "JDK 的 CSR"
44
categories: java
5-
tags: CSR
5+
tags: CSR zh
66
---
77

88
---

_posts/2025-04-02-reflection-zh.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
layout: post
3+
title: "Java 反射简介"
4+
categories: java
5+
tags: reflect zh
6+
---
7+
8+
Java 语言的标准库中包括了反射,名为 core reflection(核心反射),可以在运行时检索类的结构,包括在编译时不存在的类。同时也支持检索 Java 语言中的类型和注解。`java.lang.Class` 类上一些方法提供这些信息。这些模型类存在于 `java.lang.reflect` 包中。
9+
10+
## 类的结构
11+
12+
Java 语言中,类中的结构有字段(`Field`)、方法(`Method`)、构造器(`Constructor`)、参数(`Parameter`)、record component(`RecordComponent`)。
13+
14+
对字段、方法、构造器,`Class` 中有命名如 `get(Declared)Xxxs` 方法批量获得此类结构,例如 `getDeclaredFields`
15+
- 如果名称中包含 `Declared`,获得的结构不包含从上级类继承的,但是包括所有本类中定义的此类结构,包括非 `public` 结构。
16+
- 否则返回的结构包括上级继承的结构(最优先本类定义结构,然后字段继承先接口(只有静态字段)再上级类,方法继承优先上级类再接口(接口静态方法无继承)详见 JVMS 5.4,构造器无继承),只包括 `public` 结构。(不包含从上级类继承的 `protected` 结构)
17+
18+
同时还有 `get(Declared)Xxx` 接收参数,精准获得符合条件的结构。字段额外接收字段名称,方法接收方法名称和参数类型数组,构造器接收参数类型数组。能返回的结构必定存在于 `get(Declared)Xxxs` 返回中,如果无符合则报错。
19+
20+
`Parameter` 可以通过 `Executable::getParameters` (方法和构造器的公共上级类中)获得,`RecordComponent` 可以通过 `Class::getRecordComponents` 获得。
21+
22+
这些方法返回数组,所以标准库每次返回时会复制一份数组。字段、方法、构造器还是 `AccessibleObject` 子类,这个类有 `setAccessible`,是可变对象,所以这些结构在标准库返回时也会被复制一次。为了避免额外开销,使用这些方法时最好获取一次数组或者结构,然后缓存返回的数组或结构重复使用,避免获取和复制开销。
23+
24+
这些结构适合用来获得结构上的 Java 语言类型(例如泛型)和注解。字段、方法、构造器还提供方法获得及改变字段值和呼叫方法和构造器;这些用途方便一次性使用,但如果需要多次使用这些功能,使用 `MethodHandles.Lookup` 获得对应的 `MethodHandle` 或者 `VarHandle` 更合适,因为这些呼叫和改变方法每次使用时都会进行权限检查,影响性能。详见 `java.lang.invoke` 包相关介绍。
25+
26+
## Java 语言中的类型
27+
28+
Java 语言定义(Java Language Specification)第四章定义了 Java 语言中的类型,核心反射也有模型类,为了和已有的 `Class` 兼容,和语言中的类型有比较复杂的对应关系。
29+
30+
<!--
31+
<table class="striped">
32+
<thead>
33+
<tr><th colspan="3">类型或泛型参数
34+
<th>举例
35+
<th>模型类
36+
</th>
37+
<tbody>
38+
<tr><td colspan="3">基础类 (JLS 4.2)
39+
<td>int
40+
<td rowspan="3">Class
41+
<tr><td rowspan="7">引用类(JLS 4.3)
42+
<td rowspan="3">类与接口
43+
<td>非泛型类与接口 (JLS 8.1.3, 9.1.3)
44+
<td>String
45+
<tr><td>去参数类型 (JLS 4.8)
46+
<td>List
47+
<tr><td>带参数类型 (JLS 4.5)
48+
<td>List&lt;String&gt;
49+
<td>ParameterizedType
50+
<tr><td colspan="2">类型参数 (JLS 4.4)
51+
<td>T
52+
<td>TypeVariable
53+
<tr><td rowspan="3">数组 (JLS 10.1)
54+
<td>带参数成员类型
55+
<td>List&lt;String&gt;[]
56+
<td rowspan="2">GenericArrayType
57+
<tr><td>类型参数成员类型
58+
<td>T[]
59+
<tr><td>其他成员类型
60+
<td>int[]、String[]
61+
<td>Class
62+
<tr><td colspan="3">Wildcard Type Arguments (JLS 4.5.1)
63+
<td>? extends String
64+
<td>WildcardType</td>
65+
</tr>
66+
</tbody>
67+
</table>
68+
-->
69+
70+
各种结构中获得类型的接口 `getXxxType(s)` 返回 `Class` 类型,同时有 `getGenericXxxType(s)` 返回 `Type` 类型,可能是列表中的某一个模型类。
71+
72+
标准库返回的类型模型对象不可变,但是数组也是可变对象,有额外复制开销,所以如果返回的对象需要重复使用,推荐缓存数组或模型对象重复使用。
73+
74+
## 注解
75+
76+
注解可以携带自定义数据,可以存在于定义(结构)上(declaration annotation)或类型的用途中(type(-use) annotation)。携带类型的模型类都实现 `AnnotatedElement` 接口。以上提到的结构和类型都可以携带注解。核心反射能发现的注解都要有 `@Retention(RetentionPolicy.RUNTIME)` 元注解。
77+
78+
注解也有 `get(Declared)Annotation(s)` 的区分,类似结构;注解继承只存在于类与接口上,影响很小。Java 8 允许注解重复,有特殊的 `get(Declared)AnnotationsByType` 可以处理重复注解。
79+
80+
类型用途使用注解有一套模型类,和语言中的类型模型类相似但有些地方有细微差别,例如 `AnnotatedArrayType` 模型包含 `int[]`,但在语言类型模型中不由 `GenericArrayType`,而由 `Class` 模型此类型。
81+
82+
核心反射提供的注解皆通过代理(`Proxy`)实现,可序列化。所以性能会有些劣势。因为返回的数组可变,有复制开销,推荐有需要缓存注解及其数组重复使用。
83+
84+
## 代理
85+
86+
为了方便 reflect 提供了一个代理工具,允许提供一个类加载器和一个接口列表,返回一个实现全部接口,类由指定类加载器加载的代理实例。代理的工厂方法还接收一个处理器,所有代理对象的呼叫(包括所有继承的抽象与非抽象接口方法和`Object``equals``hashCode``toString`方法)都会转到处理器。
87+
88+
这个工具过去常用于实现 AOP,现在推荐能编译时预处理可以考虑编译时预处理。它所有方法都要转到处理器,对 JIT 编译采样及其不友好,所以性能不堪入目;现在有新的类文件接口,条件允许可以生成自己的高性能动态类替代。

0 commit comments

Comments
 (0)