Skip to content

Commit 59eab6a

Browse files
committed
add JVM架构.md
1 parent 4801444 commit 59eab6a

9 files changed

+470
-79
lines changed

Diff for: JavaKnowledge/JVM架构.md

+221
Large diffs are not rendered by default.

Diff for: JavaKnowledge/Java内存模型.md

+191
Large diffs are not rendered by default.

Diff for: KotlinCourse/10.Kotlin_设计模式.md

+8-10
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
## 工厂模式
66

7-
简单工厂的模式,它的核心作用是通过一个工厂类隐藏对象实例的创建逻辑,而不需要暴露给客户端。典型的使用场景就是当拥有一个父类
8-
与多个子类的时候,我们可以通过这种模式来创建子类对象。
7+
简单工厂的模式,它的核心作用是通过一个工厂类隐藏对象实例的创建逻辑,而不需要对外暴露。典型的使用场景就是当拥有一个父类与多个子类的时候,我们可以通过这种模式来创建子类对象。
98

109
假设现在有一个电脑加工厂,同时生产个人电脑和服务器主机。我们用熟悉的工厂模式设计描述其业务逻辑:
1110

@@ -29,7 +28,7 @@ class ComputerFactory {
2928
}
3029
}
3130
fun main() {
32-
val pc = ComputerFactory().produce(ComputerType.PC)
31+
val pc = ComputerFactory().produce(ComputerType.PC)
3332
println(pc.cpu) // Core
3433
}
3534
```
@@ -53,7 +52,7 @@ object ComputerFactory {
5352
}
5453
fun main() {
5554
// 这样我们就不用再每次都创建对象了
56-
val pc = ComputerFactory.produce(ComputerType.PC)
55+
val pc = ComputerFactory.produce(ComputerType.PC)
5756
println(pc.cpu)
5857
}
5958
```
@@ -72,7 +71,7 @@ object ComputerFactory {
7271
}
7372
fun main() {
7473
// 这样就会非常简洁
75-
val pc = ComputerFactory(ComputerType.PC)
74+
val pc = ComputerFactory(ComputerType.PC)
7675
println(pc.cpu)
7776
}
7877
```
@@ -99,7 +98,7 @@ interface Computer {
9998
}
10099

101100
fun main() {
102-
val pc = Computer(ComputerType.PC)
101+
val pc = Computer(ComputerType.PC)
103102
println(pc.cpu)
104103
}
105104
```
@@ -121,7 +120,7 @@ interface Computer {
121120
}
122121

123122
fun main() {
124-
val pc = Computer.Factory(ComputerType.PC)
123+
val pc = Computer.Factory(ComputerType.PC)
125124
println(pc.cpu)
126125
}
127126
```
@@ -143,7 +142,7 @@ fun Computer.Factory.fromCPU(cpu: String) : ComputerType? = when(cpu) {
143142
else -> null
144143
}
145144
fun main() {
146-
val pc = Computer.Factory.fromCPU("Core")
145+
val pc = Computer.Factory.fromCPU("Core")
147146
println(pc)
148147
}
149148
```
@@ -153,8 +152,7 @@ fun main() {
153152
### 内联函数简化抽象工厂
154153

155154
Kotlin中的内联函数有一个很大的作用,就是可以具体化参数类型。利用这一特性,可以改进一种更复杂的工厂模式,称为抽象工厂。
156-
上面的例子中已经用工厂模式很好的处理了一个产品登记结构的问题。但是如果现在引入了品牌商的概念,我们有好几个不同的电脑品牌,
157-
比如Dell、Asus、Acer,那么就有必要再增加一个工厂类。然而,我们并不希望对每个模型都建立一个工厂,这会让代码变得难以维护,
155+
上面的例子中已经用工厂模式很好的处理了一个产品等级结构的问题。但是如果现在引入了品牌商的概念,我们有好几个不同的电脑品牌,比如Dell、Asus、Acer,那么就有必要再增加一个工厂类。然而,我们并不希望对每个模型都建立一个工厂,这会让代码变得难以维护,
158156
所以这时候我们就需要引入抽象工厂模式。
159157

160158

Diff for: KotlinCourse/3.Kotlin_数字&字符串&数组&集合.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ var value2 : String?
508508
value2 = null // 编译通过
509509
```
510510

511-
在对变量进行操作时,如果变量是可能为空的,那么将不能直接调用,因为编译器不知道你的变量是否为空,所以编译器就要求你一定要对变量进行判断
511+
在对变量进行操作时,如果变量是可能为空的,那么将不能直接调用,因为编译器不知道你的变量是否为空,所以编译器就要求你一定要对变量进行判断:
512512

513513
```kotlin
514514
var str : String? = null
@@ -612,18 +612,18 @@ class MyRomable {
612612

613613
fun myFunction() {
614614
if (r is Wolf) {
615-
r.eat() // 编译器无法智能的将Roamable的r属性转换成一个Wolf对象,这事因为编译器不能保证在判断r属性类型和使用它的器件,其它代码不会更新该属性,因此这段代码不能编译成功。
615+
r.eat() // 编译器无法智能的将Roamable的r属性转换成一个Wolf对象,这是因为编译器不能保证在判断r属性类型和使用它的器件,其它代码不会更新该属性,因此这段代码不能编译成功。
616616
}
617617
}
618618
}
619619
```
620620

621-
那么遇到这种情况我们应该如何处理呢?你无须记住所有不能使用智能转换的场景。如果你尝试使用智能转换的方式不合理,编译器会提醒你。编译器会提醒你。
621+
那么遇到这种情况我们应该如何处理呢?你无须记住所有不能使用智能转换的场景。如果你尝试使用智能转换的方式不合理,编译器会提醒你。
622622

623623
#### 安全的类型转换
624624

625625
如果对象不是目标类型,那么常规类型转换可能会导致`ClassCastException`
626-
另一个选择是使用安全的类型转换,如果尝试转换不成功则返回`null{: .keyword }`:
626+
另一个选择是使用安全的类型转换,如果尝试转换不成功则返回`null`:
627627

628628
```kotlin
629629
val aInt: Int? = a as? Int

Diff for: KotlinCourse/4.Kotlin_表达式&关键字.md

+12-14
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ val max = if (a > b) {
1818

1919
## `when`表达式
2020

21-
`when`表达式与`Java`中的`switch/case`类似,但是要强大得多。这个表达式会去试图匹配所有可能的分支直到找到满意的一项。
21+
`when`表达式与`Java`中的`switch/case`类似,但是要强大的多。这个表达式会去试图匹配所有可能的分支直到找到满意的一项。
2222
然后它会运行右边的表达式。
2323
`Java``switch/case`不同之处是参数可以是任何类型,并且分支也可以是一个条件。
2424

@@ -34,8 +34,7 @@ when (x){
3434
}
3535
```
3636

37-
因为它是一个表达式,它也可以返回一个值。我们需要考虑什么时候作为一个表达式使用,它必须要覆盖所有分支的可能性或者实现`else`分支。否则它不会被
38-
编译成功:
37+
因为它是一个表达式,它也可以返回一个值。我们需要考虑什么时候作为一个表达式使用,它必须要覆盖所有分支的可能性或者实现`else`分支。否则它不会被编译成功:
3938

4039
```kotlin
4140
val result = when (x) {
@@ -44,7 +43,7 @@ val result = when (x) {
4443
}
4544
```
4645

47-
如你所见,条件可以是一系列被逗号分割的值。但是它可以更多的匹配方式。比如,我们可以检测参数类型并进行判断:
46+
如你所见,条件可以是一系列被逗号分割的值。但是它可以有更多的匹配方式。比如,我们可以检测参数类型并进行判断:
4847

4948
```kotlin
5049
when(view) {
@@ -123,13 +122,13 @@ for (i in array.indices)
123122

124123
### Ranges
125124

126-
`Range`表达式使用一个`..`操作符。表示就是一个该范围内的数据的数组,包含头和尾
125+
`Range`表达式使用一个`..`操作符。表示就是一个该范围内的数据的数组,包含头和尾:
127126

128127
```kotlin
129128
var nums = 1..100
130129
for(num in nums) {
131-
println(num)
132-
// 打印出1 2 3 ....100
130+
println(num)
131+
// 打印出1 2 3 ....100
133132
}
134133
```
135134

@@ -168,7 +167,7 @@ for (i in 4 downTo 1 step 2) println(i)
168167

169168
### Until
170169

171-
上面的`Range`是包含了头和尾,那如果只想包含头不包含尾呢? 就要用`until`
170+
上面的`Range`是包含了头和尾,那如果只想包含头不包含尾呢? 就要用`until`:
172171

173172
```kotlin
174173
var nums = 1 until 100
@@ -205,18 +204,17 @@ for(num in nums) {
205204
- `public`所有调用的地方都可见
206205
- `internal`同一个模块中可见
207206
- `abstract`抽象类标示
208-
- `final`标示类不可继承,默认属性
209-
- `enum`标示类为枚举
207+
- `final`标识类不可继承,默认属性
208+
- `enum`标识类为枚举
210209
- `open`类可继承,类默认是`final`
211210
- `annotation`注解类
212211
- `init`主构造函数不能包含任何的代码。初始化的代码可以放到以`init`关键字作为前缀的初始化块(`initializer blocks`)中
213-
- `field`只能用在属性的访问器内。特别注意的是,`get set`方法中只能能使用`filed`。属性访问器就是`get set`方法。
212+
- `field`只能用在属性的访问器内。特别注意的是,`get set`方法中只能使用`filed`。属性访问器就是`get set`方法。
214213
- `:`用于类的继承,变量的定义
215-
- `..`围操作符(递增的) `1..5``2..6`千万不要`6..2`
214+
- `..`范围操作符(递增的) `1..5``2..6`千万不要`6..2`
216215
- `::`作用域限定符
217216
- `inner`类可以标记为`inner {: .keyword }`以便能够访问外部类的成员。内部类会带有一个对外部类的对象的引用
218-
- `object`对象声明并且它总是在`object{: .keyword }`关键字后跟一个名称。对象表达式:在要创建一个继承自某个(或某些)类型的匿名类的对象会
219-
用到
217+
- `object`对象声明并且它总是在`object{: .keyword }`关键字后跟一个名称。对象表达式:在要创建一个继承自某个(或某些)类型的匿名类的对象会用到
220218

221219

222220

Diff for: KotlinCourse/5.Kotlin_内部类&密封类&枚举&委托.md

+15-24
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ outter.Inner().execute()
108108
#### 匿名内部类
109109

110110
```kotlin
111-
// 通过对象表达式来 创建匿名内部类的对象,可以避免重写抽象类的子类和接口的实现类,这和Java中匿名内部类的是接口和抽象类的延伸一致。
111+
// 通过对象表达式来创建匿名内部类的对象,可以避免重写抽象类的子类和接口的实现类,这和Java中匿名内部类的是接口和抽象类的延伸一致。
112112
text.setOnClickListener(object : View.OnClickListener{
113113
override fun onClick(p0: View?) {
114114
Log.d("test", p0.string())
@@ -146,7 +146,7 @@ enum class Day {
146146

147147
```kotlin
148148
enum class DayOfWeek(val day: Int) {
149-
MON(1),
149+
MON(1),
150150
TUE(2),
151151
WEN(3),
152152
THU(4),
@@ -162,8 +162,8 @@ enum class DayOfWeek(val day: Int) {
162162
```
163163
枚举可以通过`String`匹配名字来获取,我们也可以获取包含所有枚举的`Array`,所以我们可以遍历它。
164164
```kotlin
165-
val search: Icon = Icon.valueOf("SEARCH")
166-
val iconList: Array<Icon> = Icon.values()
165+
val search: DayOfWeek = DayOfWeek.valueOf("MON")
166+
val iconList: Array<DayOfWeek> = DayOfWeek.values()
167167
```
168168
而且每一个枚举都有一些函数来获取它的名字、声明的位置:
169169
```kotlin
@@ -259,14 +259,9 @@ public abstract class Bird {
259259
```
260260

261261

262-
密封类用来表示受限的类继承结构:当一个值为有限集中的
263-
类型、而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合
264-
也是受限的,但每个枚举常量只存在一个实例,而密封类
265-
的一个子类可以有可包含状态的多个实例。
262+
密封类用来表示受限的类继承结构:当一个值为有限几种的类型、而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合也是受限的,但每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。
266263

267-
要声明一个密封类,需要在类名前面添加`sealed`修饰符。虽然密封类也可以
268-
有子类,但是所有子类都必须在与密封类自身相同的文件中声明。(在`Kotlin 1.1`之前,
269-
该规则更加严格:子类必须嵌套在密封类声明的内部)。
264+
虽然密封类也可以有子类,但是所有子类都必须在与密封类自身相同的文件中声明。(在`Kotlin 1.1`之前,该规则更加严格:子类必须嵌套在密封类声明的内部)。
270265

271266
```kotlin
272267
sealed class Expr
@@ -282,7 +277,7 @@ fun eval(expr: Expr): Double = when (expr) {
282277
```
283278

284279
使用密封类的关键好处在于使用`when`表达式 的时候,如果能够
285-
验证语句覆盖了所有情况,就不需要为该语句再添加一个`else`子句了
280+
验证语句覆盖了所有情况,就不需要为该语句再添加一个`else`语句了
286281

287282
```kotlin
288283
fun eval(expr: Expr): Double = when(expr) {
@@ -337,8 +332,7 @@ val s = try { x as String } catch(e: ClassCastException) { null }
337332
在Kotlin中,你将告别static这种语法,因为它引入了全新的关键字object,可以完美的代替使用static的所有场景。
338333
当然除了代替static的场景之外,它还能实现更多的功能,比如单例对象及简化匿名表达式等。
339334

340-
声明对象就如同声明一个类,你只需要用保留字`object`替代`class`,其他都相同。只需要考虑到对象不能有构造函数,因为我们不调用任何构造函数来访问
341-
它们。事实上,对象就是具有单一实现的数据类型。object声明的内容可以看成没有构造方法的类,它会在系统或者类加载时进行初始化。
335+
声明对象就如同声明一个类,你只需要用保留字`object`替代`class`,其他都相同。只需要考虑到对象不能有构造函数,因为我们不调用任何构造函数来访问它们。事实上,对象就是具有单一实现的数据类型。object声明的内容可以看成没有构造方法的类,它会在系统或者类加载时进行初始化。
342336

343337
```kotlin
344338
object Resource {
@@ -426,10 +420,9 @@ class Prize(val name: String, val count: Int, val type: Int) {
426420
}
427421
```
428422

429-
可以发现,该版本在语义上更清晰了。而且,companion object用花括号包裹了所有静态属性和方法,使得它可以与Prize类的普通
430-
方法和属性清晰的区分开来。最后,我们可以使用点号来对一个类的静态的成员进行调用。
423+
可以发现,该版本在语义上更清晰了。而且,companion object用花括号包裹了所有静态属性和方法,使得它可以与Prize类的普通方法和属性清晰的区分开来。最后,我们可以使用点号来对一个类的静态的成员进行调用。
431424

432-
伴生对象的另一个作用是可以实现工厂方法模式。前面也说过如何从构造方法实现工厂方法模式,然而这种方法存在以下缺点:
425+
伴生对象的另一个作用是可以实现工厂方法模式。当然也可以从构造方法实现工厂方法模式,然而这种方法存在以下缺点:
433426

434427
- 利用多个构造方法语义不够明确,只能靠参数区分
435428
- 每次获取对象时都需要重新创建对象
@@ -465,8 +458,8 @@ class Prize private constructor(val name: String, val count: Int, val type: Int)
465458
```java
466459
class App : Application() {
467460
companion object {
468-
lateinit var instance: App
469-
private set
461+
private lateinit var instance: App
462+
470463
}
471464

472465
override fun onCreate() {
@@ -476,9 +469,8 @@ class App : Application() {
476469
}
477470
```
478471

479-
在这例子中,创建一个由`Application`扩展的(派送)的类,并且在`companion object`中存储它的唯一实例。
480-
`lateinit`表示这个属性开始是没有值得,但是,在使用前将被赋值(否则,就会抛出异常)。
481-
`private set`用于说明外部类不能对其进行赋值。
472+
在这例子中,创建一个继承`Application`的类,并且在`companion object`中存储它的唯一实例。
473+
`lateinit`表示这个属性开始是没有值的,但是,在使用前将被赋值(否则,就会抛出异常)。
482474

483475
### 单例
484476

@@ -696,8 +688,7 @@ fun test(){
696688

697689
##### map映射
698690

699-
一个常见的用例是在一个映射`map`里存储属性的值。这经常出现在像解析`JSON`或者做其他“动态”事情的应用中。在这种情况下,你可以使用映射实例自身作
700-
为委托来实现委托属性。
691+
一个常见的用例是在一个映射`map`里存储属性的值。这经常出现在像解析`JSON`或者做其他“动态”事情的应用中。在这种情况下,你可以使用映射实例自身作为委托来实现委托属性。
701692

702693
```kotlin
703694
class User(val map: Map<String, Any?>) {

Diff for: KotlinCourse/6.Kotlin_多继承问题.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44

55

6-
继承和实现是面向对象程序设计中不变的主题。Java是不支持类的多继承的,Kotlin亦是如此。我们他们要这样设计呢? 现实中,其实多继承的需求经常会出现,然而类的多继承方式会导致进程关系上语义的混淆。
6+
继承和实现是面向对象程序设计中不变的主题。Java是不支持类的多继承的,Kotlin亦是如此。他们为什么要这样设计呢? 现实中,其实多继承的需求经常会出现,然而类的多继承方式会导致进程关系上语义的混淆。
77

88

99

@@ -177,10 +177,10 @@ fun main(args: Array<String>) {
177177
}
178178
```
179179

180-
有人可能会有疑问: 首先,委托方式怎么跟接口实现多继承如此相似,而且好像也并没有简单多少。其次,这种方式好像跟组合也很想,那么它到底有什么优势? 主要有以下两点:
180+
有人可能会有疑问: 首先,委托方式怎么跟接口实现多继承如此相似,而且好像也并没有简单多少。其次,这种方式好像跟组合也很像,那么它到底有什么优势? 主要有以下两点:
181181

182182
- 前面说到接口是无状态的,所以即使它提供了默认方法实现也是很简单的,不能实现复杂的逻辑,也不推荐在接口中实现复杂的方法逻辑。我们可以利用上面委托的这种方式,虽然它也是接口委托,但它是用一个具体的类去实现方法逻辑,可以拥有更强大的能力。
183-
- 假设我们需要继承的类是A,委托对象是BC我们再具体调用的时候并不是像组合一样A.B.method,而是可以直接调用A.method,这更能表达A拥有该method的能力,更加直观,虽然背后也是通过委托对象来执行具体的方法逻辑的。
183+
- 假设我们需要继承的类是A,委托对象是BC我们在具体调用的时候并不是像组合一样A.B.method,而是可以直接调用A.method,这更能表达A拥有该method的能力,更加直观,虽然背后也是通过委托对象来执行具体的方法逻辑的。
184184

185185

186186

0 commit comments

Comments
 (0)