Skip to content

Commit 4801444

Browse files
committed
update os notes
1 parent 74796dc commit 4801444

17 files changed

+571
-616
lines changed

JavaKnowledge/Git简介.md

+197-265
Large diffs are not rendered by default.

JavaKnowledge/Vim使用教程.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ Vim使用教程
4242
- `#l` 移动光标到该行第#个字的位置,如`5l`
4343
- `ctrl+g` 列出当前光标所在行的行号等信息
4444
- `: #` 如输入: 15会跳到文章的第15行
45-
- `ctrl + d`向下翻页
46-
- `ctrl + u`向上翻页
45+
- `ctrl+b`:向上滚动一屏
46+
- `ctrl+f`:向下滚动一屏
47+
- `ctrl+u`:向上滚动半屏
48+
- `ctrl+d`:向下滚动半屏
4749

4850
删除文字
4951
---

JavaKnowledge/强引用、软引用、弱引用、虚引用.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,10 @@
2323

2424
- 软引用(SoftReference)
2525

26-
描述一些还有用,但并非必需的对象。如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存,但是system.gc对其无效,有点像老板(OOM)的亲戚,在公司表现不好有可能会被开除,即使你投诉他(调用GC)上班看片,但是只要不被老板看到(被JVM检测到)就不会被开除(被虚拟机回收)。
26+
描述一些还有用,但并非必需的对象。如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存,但是system.gc对其无效,有点像老板(OOM)的亲戚,在公司表现不好有可能会被开除,即使你投诉他(调用GC)上班看片,但是只要不被老板看到(被JVM检测到)就不会被开除(被虚拟机回收)。**软引用可用来实现内存敏感的高速缓存**。 软引用可以和一个引用队列`(ReferenceQueue)`联合使用,如果软引用所引用的对象被垃圾回收,`Java`虚拟机就会把这个软引用加入到与之关联的引用队列中。
27+
2728

2829

29-
**软引用可用来实现内存敏感的高速缓存**。 软引用可以和一个引用队列`(ReferenceQueue)`联合使用,
30-
如果软引用所引用的对象被垃圾回收,`Java`虚拟机就会把这个软引用加入到与之关联的引用队列中。
31-
3230
- 弱引用(WeakReference)
3331

3432
同软引用,也用来描述非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。所以弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的声明周期。在对象没有其他引用的情况下,调用system.gc对象可被虚拟机回收,就是一个普通的员工,平常如果表现不佳会被开除(对象没有其他引用的情况下),遇到别人投诉(调用GC)上班看片,那开除是肯定了(被虚拟机回收)。

KotlinCourse/1.Kotlin_简介&变量&类&接口.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ val bird1 = Bird(color = "black")
565565
val bird2 = Bird(weight = 1000.00, color = "black")
566566
```
567567

568-
上面在Bird类中使用了val或者var来声明构造方法的参数。这一方面代表了参数的引用可变性,另一方面也使得我们再构造类的语法上得到了简化。事实上,构造方法的参数名前当然可以没有val和var。然而带上它们之后就等价于在Bird类内部声明了一个同名的属性,我们可以用this来进行调用。比如,上面定义的Bird类就类似于一下实现:
568+
上面在Bird类中使用了val或者var来声明构造方法的参数。这一方面代表了参数的引用可变性,另一方面也使得我们在构造类的语法上得到了简化。事实上,构造方法的参数名前当然可以没有val和var。然而带上它们之后就等价于在Bird类内部声明了一个同名的属性,我们可以用this来进行调用。比如,上面定义的Bird类就类似于一下实现:
569569

570570
```kotlin
571571
// 构造方法参数名前没有val
@@ -583,7 +583,7 @@ class Bird (weight: Double = 0.00, age: Int = 0, color: String = "blue"){
583583

584584
#### init语句块
585585

586-
Kotlin引入了一种叫作init语句块的语法,它属于上述构造方法的一部分,两者在表现形式上确实分离的。Bird类的构造方法在类的外部,它只能对参数进行赋值。如果我们需要在初始化时进行其他的额外操作,那么我们就可以使用init语句块来执行。比如:
586+
Kotlin引入了一种叫作init语句块的语法,它属于上述构造方法的一部分,两者在表现形式上确是分离的。Bird类的构造方法在类的外部,它只能对参数进行赋值。如果我们需要在初始化时进行其他的额外操作,那么我们就可以使用init语句块来执行。比如:
587587

588588
```kotlin
589589
class Bird(weight: Double, aget: Int, color: String) {
@@ -1092,7 +1092,7 @@ fun main(args: Array<String>) {
10921092
如果你有一个现有的值数组,则可以通过在数组名前加上`*`来将这些值传递给该函数。星号`(*)`被称为扩展运算符,以下是它的一些使用示例:
10931093

10941094
```kotlin
1095-
vval myArray = arrayOf(1, 2, 3, 4, 5)
1095+
val myArray = arrayOf(1, 2, 3, 4, 5)
10961096
val mList = vars(*myArray)
10971097
val mList2 = vars(0, *myArray, 6, 7)
10981098
```

KotlinCourse/2.Kotlin_高阶函数&Lambda&内联函数.md

+157-17
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ Runnable runnable2=()->{
289289
- 函数体(如果存在的话)在`->`后面。
290290

291291
`Lambda`表达式是定义匿名函数的简单方法。由于`Lambda`表达式避免在抽象类或接口中编写明确的函数声明,进而也避免了类的实现部分,
292-
所以它是非常有用的。在`Kotlin`语言中,可以将一函数作为另一函数的参数
292+
所以它是非常有用的。在`Kotlin`语言中,可以将一函数作为另一个函数的参数
293293

294294
`Lambda`表达式由箭头左侧函数的参数(在圆括号里的内容)定义的,将值返回到箭头右侧。
295295
`view.setOnClickListener({ view -> toast("Click")})`
@@ -373,7 +373,7 @@ Lambda类型也被认为是函数类型。
373373

374374

375375

376-
## Lambda开销
376+
### Lambda开销
377377

378378
```kotlin
379379
fun foo(int: Int) = {
@@ -388,13 +388,7 @@ listOf(1, 2, 3).forEach { foo(it) } // 对一个整数列表的元素遍历调
388388
listOf(1, 2, 3).forEach { item -> foo(item) }
389389
```
390390

391-
默认情况下,我们可以直接用it来代表item,而不需要用item -> 进行声明。
392-
393-
你可以将单独的参数替换为it。
394-
395-
如果lambda具有一个单独的参数,而且编译器能够推断其类型,你可以省略该参数,并在lambda的主体中使用关键字it指代它。
396-
397-
要了解它是如何工作的,如前所述,假设使用以下代码将lambda赋值给变量:
391+
如果lambda具有一个单独的参数,而且编译器能够推断其类型,你可以省略该参数,并在lambda的主体中使用关键字it指代它。要了解它是如何工作的,如前所述,假设使用以下代码将lambda赋值给变量:
398392

399393
```kotlin
400394
val addFive: (Int) -> Int = { x -> x + 5 }
@@ -445,8 +439,9 @@ Kotlin在JVM层设计了Function类型(Function0、Function1 ... Function22、Fu
445439

446440
```kotlin
447441
package kotlin.jvm.functions
448-
interface Function1<in P1, out R> : kotlin.Function<R> {
449-
fun invoke(p1: P1) : R
442+
public interface Function1<in P1, out R> : Function<R> {
443+
/** Invokes the function with the specified argument. */
444+
public operator fun invoke(p1: P1): R
450445
}
451446
```
452447

@@ -469,13 +464,11 @@ listOf(1, 2, 3).forEach { foo(it).invoke() } // 增加了invoke调用
469464
listOf(1, 2, 3).forEach{ foo(it)() }
470465
```
471466

472-
#### 闭包
467+
## 闭包
473468

474-
在Kotlin中,你会发现匿名函数体、Lambda在语法上都存在“{}",由这对花括号包裹的代码如果访问了外部环境变量则被称为一个闭包。
469+
在Kotlin中,你会发现匿名函数体、Lambda在语法上都存在“{}",由这对花括号包裹的代码如果访问了外部环境变量则被称为一个闭包。一个闭包可以被当做参数传递或直接使用,它可以简单的看成”访问外部环境变量的函数“。Lambda是Kotlin中最常见的闭包形式。
475470

476-
一个闭包可以被当做参数传递或直接使用,它可以简单的看成”访问外部环境变量的函数“。Lambda是Kotlin中最常见的闭包形式。
477-
478-
与Java不一样的地方在于,Kotlin中的闭包不仅可以访问外部变量,还能够对其进行修改,如下:
471+
与Java不一样的地方在于,Kotlin中的闭包不仅可以访问外部变量,还能够对其进行修改(我有点疑惑,Java为啥不能修改?下面说),如下:
479472

480473
```kotlin
481474
var sum = 0
@@ -485,9 +478,156 @@ listOf(1, 2, 3).filter { it > 0 }.forEach {
485478
println(sum) // 6
486479
```
487480

481+
看到这里我是懵逼的? 到底什么是闭包? 闭包有什么作用?
482+
483+
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。--百度百科
484+
第一句总结的很简洁了:闭包就是能够读取其他函数内部变量的函数。
485+
486+
### Java实现闭包
487+
488+
在Java8之前,是不支持闭包的,但是可以通过“接口+匿名内部类”来实现一个伪闭包的功能,为什么说是伪闭包?
489+
490+
## Anonymous inner class is not closure
491+
492+
Anonymous classes in java are close to being called as a closure. They don’t 100% support the definition but come close to it and thats why we see lot of literature calling anonymous inner classes as closure. Why do I say its not 100%? An anonymous inner class can access “only” the [final](https://javapapers.com/core-java/explain-the-final-keyword-in-java/) local variable of the enclosing method. It is because of this restriction, anonymous inner class in java is not a closure.
493+
494+
If you remember the [memory management in java](https://javapapers.com/core-java/java-jvm-memory-types/), you can recall that the local variables are stored in a stack. These java stacks are created when the method starts and destroyed when it returns. Unlike local variables, final fields are stored in method area which lives longer even after the return of the method. If we want to make anonymous inner class as a closure, then we should allow it to access all the fields surrounding it. But, as per the current memory management, they will be destroyed and will not be accessible after the method has returned.
495+
496+
## Closure in Java
497+
498+
In that case will we get closure in java in future? We have a specification written by Peter Ahe, James Gosling, Neal Gafter and Gilad Bracha on [closures for java](http://www.javac.info/closures-v05.html). It gives detailed description of how a closure can be implemented in java and example code on how to use them. We have JSR 335 for closures in java named as Lambda Expressions for the Java Programming Language.
499+
500+
```java
501+
class ClosureTest {
502+
public interface MutableAdder {
503+
int add(int x, boolean change);
504+
}
505+
506+
public MutableAdder makeAdderB(int n) {
507+
// Variable 'intHolder' is accessed from within inner class, needs to be declared final
508+
final int[] intHolder = new int[]{n};
509+
return new MutableAdder() {
510+
public int add(int x, boolean change) {
511+
if (change) {
512+
intHolder[0] = x;
513+
return x;
514+
} else {
515+
return intHolder[0] + x;
516+
}
517+
}
518+
};
519+
}
520+
}
521+
```
522+
523+
OK,实现看完了,那这么做有什么用呢? 反正我平时没用到...
524+
525+
现在继续来说上面提到的与Java不一样的地方在于,Kotlin中的闭包不仅可以访问外部变量,还能够对其进行修改。
526+
527+
#### 为什么java中内部类访问外部局部变量需要用final修饰
528+
529+
我学java的时候我就记着这种情况一定要加final,但是我不知道为啥。 今天就仔细看看
530+
531+
Variable 'a' is accessed from within inner class, needs to be final or effectively final(java 8)。
532+
533+
Java doesn't support closures, i.e. local variable can’t be accessed outside the method, but fields of class can be accessed from outside the class.
534+
535+
536+
537+
What are local variables in java?
538+
539+
All variables of the method are called local variables in java.
540+
541+
542+
543+
Where do local variables live in java?
544+
545+
[Methods are pushed on **stack**](http://www.javamadesoeasy.com/2015/03/threads-implement-their-own-stack.html) so local variables live on the stack.
546+
547+
Local variables of the method are kept on the stack and are lost as soon as the method ends in java.
548+
549+
550+
551+
Where do object of local inner class live in java?
552+
553+
As object of local inner class live on the **heap**, objects may be alive even after method ends in which local inner class have been defined.
554+
555+
**As, local variables of the method are kept on the stack and are lost as soon as the method ends,** **but even after the method ends, the local inner class object may still be alive on the heap.**
556+
557+
558+
559+
What java docs says about “Local Inner class cannot access the non-final local variables but can access final local variables.”
560+
561+
**A local class can only access local variables that are declared final in java**. When a local class accesses a local variable or parameter of the enclosing block, it captures that variable or parameter in java.
562+
563+
564+
565+
JVM create create a synthetic field inside the inner class in java -
566+
567+
As final variable will not change after initialization, when a inner class access final local variables **compiler create a synthetic field inside the inner class and also copy that variable into the heap.** So, these synthetic fields can be accessed inside local inner class even when execution of method is over in java.
568+
569+
570+
571+
You must be wondering, **What are synthetic fields in java?**
572+
573+
Synthetic fields are created by compiler and they actually doesn’t exist in source code in java.
574+
575+
576+
577+
The reason is that after the enclosing method returns, the local variable no longer exists. Therefore a copy of the variable is created when the anonymous class is instanciated. If Java allowed the local variable to be changed afterwards, the anonymous class would only know the old value.
578+
579+
简单的说就是: JVM在内部类初始化的时候帮我们拷贝了一个局部变量的备份到内部类中,并且把它的值复制到了堆内存中(变量有两份,同样的名字,一个在局部变量中用,一个在内部类中)。所以要是不用final修饰,那你后面把外部类中的变量的值修改了,而内部类中拷贝的值还是原来的,那这样岂不是两边的值不一样了? 所以不能让你改,必须加final。The solution was to required that captured variables are final (before JDK 8) or effectively final (since JDK 8), which means they cannot be assigned to.
580+
581+
582+
583+
### Kotlin中的闭包
584+
585+
想要理解kotlin中闭包的实现,首先要懂kotlin中的一个概念:在Kotlin中,函数是“一等公民”。
586+
587+
对比一下java和kotlin更好理解:
588+
589+
java代码:
590+
591+
```java
592+
public class TestJava{
593+
private void test(){
594+
private void test(){//错误,因为Java中不支持函数包含函数
595+
596+
}
597+
}
598+
}
599+
```
600+
601+
在java中是不支持这种写法的,因为函数是“二等公民”。
602+
603+
下面再看下kotlin代码:
604+
605+
```kotlin
606+
fun test(): () -> Unit {
607+
var a = 0
608+
return fun() {
609+
a++
610+
println(a)
611+
}
612+
}
613+
614+
fun main() {
615+
val t = test()
616+
t()
617+
}
618+
```
619+
620+
是不是发现了新世界的大门,内部函数很轻松地调用了外部变量a。
621+
622+
这只是一个最简单的闭包实现。按照这种思想,其他的实现例如:函数、条件语句、Lambda表达式等等都可以理解为闭包,这里不再赘述。不过万变不离其宗,只要记得一句话:**闭包就是能够读取其他函数内部变量的函数**。就是一个函数A可以访问另一个函数B的局部变量,即便另一个函数B执行完成了也没关系。目前把满足这样条件的函数A叫做闭包。
623+
624+
625+
626+
627+
488628
## 内联函数
489629

490-
在我开始学的时候,一直没搞明白内联函数到底是干什么? 有什么作用?Kotlin中的内联函数其实显得有点尴尬,因为它之所以被设计出来,主要是为了优化Kotlin支持Lambda表达式之后所带来的开销。然而,在Java中我们似乎并不需要特别关注这个问题,因为在Java 7之后,JVM引入了一种叫做invokedynamic的技术,它会自动帮助我们做Lambda优化。但是为什么Kotlin要引入内联函数这种手动的语法呢? 这主要还是因为Kotlin要兼容Java 6。
630+
刚被闭包搞蒙,这里又没搞明白内联函数到底是干什么? 有什么作用?Kotlin中的内联函数其实显得有点尴尬,因为它之所以被设计出来,主要是为了优化Kotlin支持Lambda表达式之后所带来的开销。然而,在Java中我们似乎并不需要特别关注这个问题,因为在Java 7之后,JVM引入了一种叫做invokedynamic的技术,它会自动帮助我们做Lambda优化。但是为什么Kotlin要引入内联函数这种手动的语法呢? 这主要还是因为Kotlin要兼容Java 6。
491631

492632

493633

0 commit comments

Comments
 (0)