From 2b3b1ce3eeaad3ba52e24da444fcc55bb14fdd70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Thu, 23 Jan 2020 10:34:25 +0800 Subject: [PATCH 01/98] Update ReadMe.md --- ReadMe.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index b9348a8..05909c0 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -9,14 +9,10 @@

- +

-

- 阅读 - 微信公众� -

推�使用 https://how2playlife.com/ 在线阅读,在线阅读内容本仓库�步一致。这�方�阅读的优势在于:左侧边�有目录,阅读体验更好。 From 76f85462e681cb91c187b3d8c234ed0a8f37797f Mon Sep 17 00:00:00 2001 From: Jack <30426054+dislazy@users.noreply.github.com> Date: Thu, 19 Mar 2020 15:27:09 +0800 Subject: [PATCH 02/98] =?UTF-8?q?=E9=94=99=E5=88=AB=E5=AD=97=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...34\254\346\225\260\346\215\256\347\261\273\345\236\213.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/docs/java/basic/2\343\200\201Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md" "b/docs/java/basic/2\343\200\201Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md" index d601d6e..655b4c2 100644 --- "a/docs/java/basic/2\343\200\201Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md" +++ "b/docs/java/basic/2\343\200\201Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md" @@ -468,9 +468,9 @@ public static void main(String[] args) { (2)Byte�用了全部256个对象[-128,127]; -(3)Short�用了[-128,127]这些对象; +(3)Short�用了[-128,127]这些对象; -(4)Long�用了[-128,127]; +(4)Long�用了[-128,127]; (5)Character�用了[0,127],Charater�能表示负数; From 2013dd94ec38f98fc13b05d05b86e9924261f18b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Sun, 22 Mar 2020 15:50:23 +0800 Subject: [PATCH 03/98] Update ReadMe.md --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 05909c0..4b9fe38 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -5,7 +5,7 @@ 为了更好地讲清楚�个知识模�,我们也�考了很多网上的优质�文,力求��掉�一个知识点,所有�考�文都将声明转载��,如有侵�,请�系我。 -点击关注[微信公众�](#微信公众�)�时获�笔主最新更新文章,并��费领�Java工程师必备学习资�,以�我原创的电�书《�鸟程�员�长之路:从技术�白到阿里巴巴Java工程师》 +点击关注[微信公众�](#微信公众�)�时获�笔主最新更新文章,并��费领�Java工程师必备学习资�

From 5ec9025967eb4e919d97c2acc0c321aebe7dcfcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Sun, 7 Jun 2020 13:26:31 +0800 Subject: [PATCH 04/98] Update ReadMe.md --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 4b9fe38..54edfa2 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -113,7 +113,7 @@ * [走进JavaWeb技术世界1:JavaWeb的由�和基础知识](docs/java-web/走进JavaWeb技术世界1:JavaWeb的由�和基础知识.md) * [走进JavaWeb技术世界2:JSP与Servlet的曾�与现在](docs/java-web/走进JavaWeb技术世界2:JSP与Servlet的曾�与现在.md) * [走进JavaWeb技术世界3:JDBC的进化与连接池技术](docs/java-web/走进JavaWeb技术世界3:JDBC的进化与连接池技术.md) -* [走进JavaWeb技术世界4:Servlet 工作原�详解](docs/java-web/走进JavaWeb技术世界4:Servlet%29工作原�详解.md) +* [走进JavaWeb技术世界4:Servlet 工作原�详解](docs/java-web/走进JavaWeb技术世界4:Servlet%20工作原�详解.md) * [走进JavaWeb技术世界5:�探Tomcat的HTTP请求过程](docs/java-web/走进JavaWeb技术世界5:�探Tomcat的HTTP请求过程.md) * [走进JavaWeb技术世界6:Tomcat5总体架构剖�](docs/java-web/走进JavaWeb技术世界6:Tomcat5总体架构剖�.md) * [走进JavaWeb技术世界7:Tomcat和其他WEB容器的区别](docs/java-web/走进JavaWeb技术世界7:Tomcat和其他WEB容器的区别.md) From e878afe820ef2cf19f4cf2b6166d7df145246608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=80=E9=9B=80=E4=B8=8A=E5=A4=B4=E7=B2=91=E9=A2=97?= =?UTF-8?q?=E9=A5=AD?= Date: Tue, 28 Jul 2020 15:03:00 +0800 Subject: [PATCH 05/98] =?UTF-8?q?Update=204=E3=80=81final=E5=85=B3?= =?UTF-8?q?=E9=94=AE=E5=AD=97=E7=89=B9=E6=80=A7.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正final域i�j部分地方写�了 --- ...\263\351\224\256\345\255\227\347\211\271\346\200\247.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/java/basic/4\343\200\201final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md" "b/docs/java/basic/4\343\200\201final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md" index f9c0f39..ff1118c 100644 --- "a/docs/java/basic/4\343\200\201final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md" +++ "b/docs/java/basic/4\343\200\201final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md" @@ -482,7 +482,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 在上图中,写普通域的�作被编译器�排�到了构造函数之外,读线程 B 错误的读�了普通�� i �始化之�的值。而写 final 域的�作,被写 final 域的�排�规则“�定�在了构造函数之内,读线程 B 正确的读�了 final ���始化之�的值。 -写 final 域的�排�规则�以确�:在对象引用为任�线程��之�,对象的 final 域已�被正确�始化过了,而普通域�具有这个�障。以上图为例,在读线程 B“看到�对象引用 obj 时,很�能 obj 对象还没有构造完�(对普通域 i 的写�作被�排�到构造函数外,此时�始值 2 还没有写入普通域 i)。 +写 final 域的�排�规则�以确�:在对象引用为任�线程��之�,对象的 final 域已�被正确�始化过了,而普通域�具有这个�障。以上图为例,在读线程 B“看到�对象引用 obj 时,很�能 obj 对象还没有构造完�(对普通域 i 的写�作被�排�到构造函数外,此时�始值 1 还没有写入普通域 i)。 ### 读 final 域的�排�规则 @@ -495,8 +495,8 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 reader() 方法包�三个�作: 1. �次读引用�� obj; -2. �次读引用�� obj 指�对象的普通域 j。 -3. �次读引用�� obj 指�对象的 final 域 i。 +2. �次读引用�� obj 指�对象的普通域 i。 +3. �次读引用�� obj 指�对象的 final 域 j。 现在我们�设写线程 A 没有�生任何�排�,�时程�在��守间接�赖的处�器上执行,下�是一��能的执行时�: From d0169757c46b00ff8425698481170ad8d7718190 Mon Sep 17 00:00:00 2001 From: Rorke76753 <36150718+Rorke76753@users.noreply.github.com> Date: Mon, 3 Aug 2020 17:47:14 +0800 Subject: [PATCH 06/98] =?UTF-8?q?Update=20Java=E5=B9=B6=E5=8F=91=E6=8C=87?= =?UTF-8?q?=E5=8D=9712=EF=BC=9A=E6=B7=B1=E5=BA=A6=E8=A7=A3=E8=AF=BB=20java?= =?UTF-8?q?=20=E7=BA=BF=E7=A8=8B=E6=B1=A0=E8=AE=BE=E8=AE=A1=E6=80=9D?= =?UTF-8?q?=E6=83=B3=E5=8F=8A=E6=BA=90=E7=A0=81=E5=AE=9E=E7=8E=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加worker的获�任务过程 --- ...20\347\240\201\345\256\236\347\216\260.md" | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" "b/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" index 76f6d4b..ef59855 100644 --- "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" +++ "b/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" @@ -8,6 +8,7 @@ * [AbstractExecutorService](#abstractexecutorservice) * [ThreadPoolExecutor](#threadpoolexecutor) * [Executors](#executors) + * [Worker获�任务](#getTask) * [总结](#总结) @@ -1275,6 +1276,51 @@ else if (!addWorker(command, false)) > SynchronousQueue 是一个比较特殊的 BlockingQueue,其本身�储存任何元素,它有一个虚拟队列(或虚拟栈),�管读�作还是写�作,如果当�队列中存储的是与当��作相�模�的线程,那么当��作也进入队列中等待;如果是相�模�,则�对�功,从当�队列中�队头节点。具体的信�,�以看我的�一篇关于 BlockingQueue 的文章。 +## getTask + �文已�分�了`runWorker`方法,我们�以看到该方法中有一行这样的代� + ```java + //... + while (task != null || (task = getTask()) != null) { + //... + ``` + 这一行代�如果`task!=null`,��一个�件为`true`时�味�传入的一个�`null`的`task`,�时代�会优化使得第二个�件�去执行;那么�一个�件为`false`时,就会�试调用`getTask`方法。在这一个方法中,`worker`会�试从工作队列中�出任务�进行执行。 + ```java + private Runnable getTask() { + boolean timedOut = false; + //�断�试获得任务 + for (;;) { + int c = ctl.get(); + int rs = runStateOf(c); + // �文已有相似的状�,这里��赘述 + if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { + decrementWorkerCount(); + return null; + } + int wc = workerCountOf(c); + //是�设置了�许核心线程超时(设置了之�核心线程在超时�会销�),或者当�worker数�比核心池大 + boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; + + if ((wc > maximumPoolSize || (timed && timedOut))&& (wc > 1 || workQueue.isEmpty())) { + if (compareAndDecrementWorkerCount(c)) + return null; + continue; + } + try { + //是�设置了�许核心线程超时(设置了之�核心线程在超时�会销�),或者当�worker数�比核心池大 + //如果是调用queue的poll(int,TimeUnit)方法,�则直接调用take方法 + Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); + //能获�到�空的任务就返回 + //对于�设置�许核心线程超时的情况,核心线程就一直在getTask的这个循环中 + //一直等待有新的任务�执行 + if (r != null) + return r; + timedOut = true; + } catch (InterruptedException retry) { + timedOut = false; + } + } + } + ``` ## 总结 我一��喜欢写总结,因为我把所有需�表达的都写在正文中了,写�篇幅的总结并�能真正将�说清楚,本文的总结部分为准备�试的读者而写,希望能帮到�试者或者没有足够的时间看完全文的读者。 From fadb4a9e986f3a2393382be1c224cafe7fe93eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=B2=E5=A8=87=E7=9A=84programer?= Date: Mon, 17 Aug 2020 20:37:52 +0800 Subject: [PATCH 07/98] =?UTF-8?q?Update=201=E3=80=81=E9=9D=A2=E5=90=91?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E5=9F=BA=E7=A1=80.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.修改文字�述错误 --- ...\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" "b/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" index 1ce17ab..3570358 100644 --- "a/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" +++ "b/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" @@ -74,7 +74,7 @@ Java 是��对象的编程语言,对象就是��对象程�设计的核   ��过程最大的问题在于��系统的膨胀,��过程将无法应付,最终导致系统的崩溃。为了解决这一�软件�机,我们�出��对象�想。 - ��过程的缺陷: -   是采用指定而下的设计模�,在设计阶段就需�考虑�一个模�应该分解�哪些�模�,�一个�模��细分为更�的�模�,如此类推,直到将模�细化为一个个函数。 +   是采用自顶而下的设计模�,在设计阶段就需�考虑�一个模�应该分解�哪些�模�,�一个�模��细分为更�的�模�,如此类推,直到将模�细化为一个个函数。 - 存在的问题 From fdb8b02c1bb3d3c72ffd465d6c89809ea6023bd4 Mon Sep 17 00:00:00 2001 From: cyd <690648264@qq.com> Date: Tue, 25 Aug 2020 14:01:42 +0800 Subject: [PATCH 08/98] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=9F=BA=E7=A1=80=E7=9F=A5=E8=AF=86=E4=B8=8B21?= =?UTF-8?q?=E3=80=8122=E3=80=8123=E6=8C=87=E5=AE=9A=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ReadMe.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 54edfa2..b382ce2 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -81,9 +81,8 @@ * [JavaIO�](docs/java/basic/16�JavaIO�.md) * [多线程](docs/java/basic/17�多线程.md) * [深入�解内部类](docs/java/basic/18�深入�解内部类.md) -* [javac和javap](docs/java/basic/19�Java集�框架梳�.md) -* [Java8新特性终�指�](docs/java/basic/20�javac和javap.md) -* [Java类和包](docs/java/basic/21�Java8新特性终�指�.md) +* [javac和javap](docs/java/basic/20�javac和javap.md) +* [Java8新特性终�指�](docs/java/basic/21�Java8新特性终�指�.md) * [�列化和��列化](docs/java/basic/22��列化和��列化.md) * [继承��装�多�的实现原�](docs/java/basic/23�继承��装�多�的实现原�.md) From 6d318f3aaf7ec53ab1d627f6b545a1246f3d3845 Mon Sep 17 00:00:00 2001 From: JustALee Date: Thu, 1 Oct 2020 17:49:25 +0800 Subject: [PATCH 09/98] Fix typo --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index b382ce2..83e1fb1 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -24,7 +24,7 @@ - [容器](#容器) - [设计模�](#设计模�) - [JavaWeb](#JavaWeb) - - [Srping](#Spring) + - [Spring](#Spring) - [SpringMVC](#SpringMVC) - [SpringBoot](#SpringBoot) - [Java进阶](#Java进阶) From d7eaa6d90b1bfab52fd2e8a9815b60b4096e51f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Fri, 14 May 2021 15:57:33 +0800 Subject: [PATCH 10/98] Update ReadMe.md --- ReadMe.md | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index b382ce2..f9a91fb 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -349,6 +349,12 @@ springboot和springcloud ## 微信公众� +### 黄�斜学Java + +微信公众��黄�斜学Java】 作者是蚂�金�Java工程师,专注分享Java领域干货,��于BAT�试,算法�计算机基础�数�库�分布��spring全家桶�微�务�高并��JVM�Docker容器,ELK�大数�等相关知识,希望我们�以一起进步。 + +**500页Java�试手册PDF:** 关注公众��回� **�PDF“** ��领�超级热门的Java�试�典pdf + ### Java技术江湖 如果大家想�实时关注我更新的文章以�分享的干货的�,�以关注我的公众��Java技术江湖】一�阿里 Java 工程师的技术�站,作者黄�斜,专注 Java 相关技术:SSM�SpringBoot�MySQL�分布��中间件�集群�Linux�网络�多线程,�尔讲点Docker�ELK,�时也分享技术干货和学习�验,致力于Java全栈开�� @@ -358,17 +364,3 @@ springboot和springcloud **Java进阶架构师资料:** 关注公众��回� **�架构师“** ��领� Java基础�进阶�项目和架构师等�费学习资料,更有数�库�分布��微�务等热门技术学习视频,内容丰富,兼顾原�和实践,�外也将赠�作者原创的Java学习指��Java程�员�试指�等干货资� ![我的公众�](https://img-blog.csdnimg.cn/20190805090108984.jpg) - -### 个人公众�:程�员黄�斜 -​ -黄�斜是 985 硕士,阿里巴巴Java工程师,在自学编程�技术求��Java学习等方�有丰富�验和独到�解,希望帮助到更多想�从事互�网行业的程�员们。 -​ -作者专注于 JAVA �端技术栈,热衷于分享程�员干货�学习�验�求�心得,以�自学编程和Java技术栈的相关干货。 -​ -黄�斜是一个斜��年,��学习和写作,相信终身学习的力�,希望和更多的程�员交朋�,一起进步和�长� - -**原创电�书:** 关注微信公众��程�员黄�斜】�回� **"原创电�书"** ��领�我原创的电�书《�鸟程�员修炼手册:从技术�白到阿里巴巴Java工程师》这份电�书总结了我2年的Java学习之路,包括学习方法�技术总结�求��验和�试技巧等内容,已�帮助很多的程�员拿到了心仪的offer� - -**程�员3T技术学习资�:** 一些程�员学习技术的资�大礼包,关注公众��程�员黄�斜】�,��回�关键字 **“资料�** ���费无套路获�,包括Java�python�C++�大数��机器学习��端�移动端等方�的技术资料。 - -![](https://img-blog.csdnimg.cn/20190829222750556.jpg) From 04e727568631b38bb83c73a93878a718d1f4987e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Thu, 9 Dec 2021 15:01:09 +0800 Subject: [PATCH 11/98] Update ReadMe.md --- ReadMe.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index f9a91fb..5c79614 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -349,9 +349,9 @@ springboot和springcloud ## 微信公众� -### 黄�斜学Java +### 程�员黄�斜 -微信公众��黄�斜学Java】 作者是蚂�金�Java工程师,专注分享Java领域干货,��于BAT�试,算法�计算机基础�数�库�分布��spring全家桶�微�务�高并��JVM�Docker容器,ELK�大数�等相关知识,希望我们�以一起进步。 +微信公众��程�员黄�斜】作者是�蚂�金�Java工程师,专注分享Java技术干货和求��长心得,��于BAT�试,算法�计算机基础�数�库�分布��spring全家桶�微�务�高并��JVM�Docker容器,ELK�大数�等 **500页Java�试手册PDF:** 关注公众��回� **�PDF“** ��领�超级热门的Java�试�典pdf From b23bd5cd9b2eda81800a9a2ffaea7f57d2dcede8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Thu, 9 Dec 2021 15:01:39 +0800 Subject: [PATCH 12/98] Create ReadMe.md From f95f5cf2edb343d583cbe41f1bb7b9f0a8350a76 Mon Sep 17 00:00:00 2001 From: h2pl <362294931@qq.com> Date: Sun, 26 Mar 2023 17:02:46 +0800 Subject: [PATCH 13/98] do nothing --- src/main/java/md/AtxMarkdownTocFileTest.java | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 src/main/java/md/AtxMarkdownTocFileTest.java diff --git a/src/main/java/md/AtxMarkdownTocFileTest.java b/src/main/java/md/AtxMarkdownTocFileTest.java deleted file mode 100644 index 531617d..0000000 --- a/src/main/java/md/AtxMarkdownTocFileTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package md; - -public class AtxMarkdownTocFileTest { -} From 8b486aeac24d32e8c1408e6d8146d9e0e4e00f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Sun, 26 Mar 2023 17:09:13 +0800 Subject: [PATCH 14/98] Update ReadMe.md --- ReadMe.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 5c79614..7df3d6d 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -349,15 +349,10 @@ springboot和springcloud ## 微信公众� -### 程�员黄�斜 - -微信公众��程�员黄�斜】作者是�蚂�金�Java工程师,专注分享Java技术干货和求��长心得,��于BAT�试,算法�计算机基础�数�库�分布��spring全家桶�微�务�高并��JVM�Docker容器,ELK�大数�等 - -**500页Java�试手册PDF:** 关注公众��回� **�PDF“** ��领�超级热门的Java�试�典pdf ### Java技术江湖 -如果大家想�实时关注我更新的文章以�分享的干货的�,�以关注我的公众��Java技术江湖】一�阿里 Java 工程师的技术�站,作者黄�斜,专注 Java 相关技术:SSM�SpringBoot�MySQL�分布��中间件�集群�Linux�网络�多线程,�尔讲点Docker�ELK,�时也分享技术干货和学习�验,致力于Java全栈开�� +如果大家想�实时关注我更新的文章以�分享的干货的�,�以关注我的公众��Java技术江湖】�阿里 Java 工程师的技术�站,作者黄�斜,专注 Java 相关技术:SSM�SpringBoot�MySQL�分布��中间件�集群�Linux�网络�多线程,�尔讲点Docker�ELK,�时也分享技术干货和学习�验,致力于Java全栈开�� **Java工程师技术学习资料:** 一些Java工程师常用学习资�,关注公众��,��回�关键字 **“Java�** ���费无套路获�。 From 6e86a2cdca52b19246e8eccbd312e49e9b7d2f4a Mon Sep 17 00:00:00 2001 From: h2pl <362294931@qq.com> Date: Fri, 31 Mar 2023 19:38:30 +0800 Subject: [PATCH 15/98] resolve distributed docs category problem --- ReadMe.md | 66 +++++++++---------- ...\200\247\343\200\2012PC\345\222\2143PC.md" | 0 ...5\237\272\347\241\2002 \357\274\232CAP.md" | 0 ...13\344\273\266\351\241\272\345\272\217.md" | 0 ...\237\272\347\241\2004\357\274\232Paxos.md" | 0 ...76\345\222\214\347\247\237\347\272\246.md" | 0 ...41\2006\357\274\232Raft\343\200\201Zab.md" | 0 ...17\350\260\203\346\234\215\345\212\241.md" | 0 ...15\345\222\214\344\274\230\345\214\226.md" | 0 ...06\344\270\216\345\256\236\350\267\265.md" | 0 ...44\270\200\350\207\264\346\200\247hash.md" | 0 ...37\346\210\220\346\226\271\346\241\210.md" | 0 ...04\351\202\243\344\272\233\344\272\213.md" | 0 ...6\210\220Redis\347\274\223\345\255\230.md" | 0 ...60\347\232\204\345\245\227\350\267\257.md" | 0 ...40\347\247\215\346\226\271\346\241\210.md" | 0 ...03\345\274\217\344\272\213\345\212\241.md" | 0 ...43\345\206\263\346\226\271\346\241\210.md" | 0 ...03\345\274\217\344\272\213\345\212\241.md" | 0 ...72\346\234\254\346\246\202\345\277\265.md" | 0 ...40\344\275\225\350\200\214\347\224\237.md" | 0 ...\201\257\346\212\200\346\234\257 Kafka.md" | 0 ...57\274\214Raft\347\256\227\346\263\225.md" | 0 ...0\203\346\234\215\345\212\241zookeeper.md" | 0 ...01\347\250\213\350\257\246\350\247\243.md" | 0 ...41\347\220\206\345\256\236\346\210\230.md" | 0 ...57\345\217\212\345\256\236\350\267\265.md" | 0 ...36\350\267\265\346\200\273\347\273\223.md" | 0 ...06\350\256\272\346\200\273\347\273\223.md" | 0 29 files changed, 33 insertions(+), 33 deletions(-) rename "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2001\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\2012PC\345\222\2143PC.md" => "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2001\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\2012PC\345\222\2143PC.md" (100%) rename "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2002 \357\274\232CAP.md" => "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2002 \357\274\232CAP.md" (100%) rename "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2003\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" => "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2003\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" (100%) rename "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2004\357\274\232Paxos.md" => "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2004\357\274\232Paxos.md" (100%) rename "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2005\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md" => "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2005\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md" (100%) rename "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2006\357\274\232Raft\343\200\201Zab.md" => "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2006\357\274\232Raft\343\200\201Zab.md" (100%) rename "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2008\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md" => "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2008\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md" (100%) rename "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\2667\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md" => "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\2667\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25710\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25710\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25711\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25711\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25712\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25712\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25713\357\274\232\347\274\223\345\255\230\347\232\204\351\202\243\344\272\233\344\272\213.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25713\357\274\232\347\274\223\345\255\230\347\232\204\351\202\243\344\272\233\344\272\213.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232Spring Boot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232Spring Boot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25715\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25715\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25716\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25716\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25717\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25717\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25718\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25718\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25719\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25719\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2571\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2571\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25720\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25720\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257 Kafka.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257 Kafka.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2572\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2572\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2573\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2573\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2574\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2574\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2575\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2575\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md" (100%) rename "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2576\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2576\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md" (100%) rename "docs/distrubuted/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md" => "docs/distributed/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md" (100%) rename "docs/distrubuted/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" => "docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" (100%) diff --git a/ReadMe.md b/ReadMe.md index 5c79614..0e7377f 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -292,40 +292,40 @@ todo ## 分布� ### �论 -* [分布�系统�论基础开篇:从放弃到入门](docs/distrubuted/�论/分布�系统�论基础开篇:从放弃到入门.md) -* [分布�系统�论基础1: 一致性�2PC和3PC ](docs/distrubuted/�论/分布�系统�论基础1:%20一致性�2PC和3PC.md) -* [分布�系统�论基础2:CAP ](docs/distrubuted/�论/分布�系统�论基础2%20:CAP.md) -* [分布�系统�论基础3: 时间�时钟和事件顺�](docs/distrubuted/�论/分布�系统�论基础3:%20时间�时钟和事件顺�.md) -* [分布�系统�论基础4:Paxos](docs/distrubuted/�论/分布�系统�论基础4:Paxos.md) -* [分布�系统�论基础5:选举�多数派和租约](docs/distrubuted/�论/分布�系统�论基础5:选举�多数派和租约.md) -* [分布�系统�论基础6:Raft�Zab ](docs/distrubuted/�论/分布�系统�论基础6:Raft�Zab.md) -* [分布�系统�论进阶7:Paxos��和优化 ](docs/distrubuted/�论/分布�系统�论进阶7:Paxos��和优化.md) -* [分布�系统�论基础8:zookeeper分布��调�务 ](docs/distrubuted/�论/分布�系统�论基础8:zookeeper分布��调�务.md) - +* [分布�系统�论基础1: 一致性�2PC和3PC ](docs/distributed/basic/分布�系统�论基础1:%20一致性�2PC和3PC.md) +* [分布�系统�论基础2:CAP ](docs/distributed/basic/分布�系统�论基础2%20:CAP.md) +* [分布�系统�论基础3: 时间�时钟和事件顺�](docs/distributed/basic/分布�系统�论基础3:%20时间�时钟和事件顺�.md) +* [分布�系统�论基础4:Paxos](docs/distributed/basic/分布�系统�论基础4:Paxos.md) +* [分布�系统�论基础5:选举�多数派和租约](docs/distributed/basic/分布�系统�论基础5:选举�多数派和租约.md) +* [分布�系统�论基础6:Raft�Zab ](docs/distributed/basic/分布�系统�论基础6:Raft�Zab.md) +* [分布�系统�论进阶7:Paxos��和优化 ](docs/distributed/basic/分布�系统�论进阶7:Paxos��和优化.md) +* [分布�系统�论基础8:zookeeper分布��调�务 ](docs/distributed/basic/分布�系统�论基础8:zookeeper分布��调�务.md) + +* [分布�技术实践总结](docs/distributed/分布��论总结.md) ### 技术 -* [�懂分布�技术1:分布�系统的一些基本概念 ](docs/distrubuted/实战/�懂分布�技术1:分布�系统的一些基本概念.md ) -* [�懂分布�技术2:分布�一致性�议与Paxos,Raft算法](docs/distrubuted/实战/�懂分布�技术2:分布�一致性�议与Paxos,Raft算法.md) -* [�懂分布�技术3:�探分布��调�务zookeeper ](docs/distrubuted/实战/�懂分布�技术3:�探分布��调�务zookeeper.md ) -* [�懂分布�技术4:ZAB�议概述与选主�程详解 ](docs/distrubuted/实战/�懂分布�技术4:ZAB�议概述与选主�程详解.md ) -* [�懂分布�技术5:Zookeeper的�置与集群管�实战](docs/distrubuted/实战/�懂分布�技术5:Zookeeper的�置与集群管�实战.md) -* [�懂分布�技术6:Zookeeper典型应用场景�实践 ](docs/distrubuted/实战/�懂分布�技术6:Zookeeper典型应用场景�实践.md ) -* [�懂分布�技术7:负载�衡概念与主�方案](docs/distrubuted/实战/�懂分布�技术7:负载�衡概念与主�方案.md) -* [�懂分布�技术8:负载�衡原�剖� ](docs/distrubuted/实战/�懂分布�技术8:负载�衡原�剖�.md ) -* [�懂分布�技术9:Nginx负载�衡原�与实践 ](docs/distrubuted/实战/�懂分布�技术9:Nginx负载�衡原�与实践.md) -* [�懂分布�技术10:LVS实现负载�衡的原�与实践 ](docs/distrubuted/实战/�懂分布�技术10:LVS实现负载�衡的原�与实践.md ) -* [�懂分布�技术11:分布�session解决方案与一致性hash](docs/distrubuted/实战/�懂分布�技术11:分布�session解决方案与一致性hash.md) -* [�懂分布�技术12:分布�ID生�方案 ](docs/distrubuted/实战/�懂分布�技术12:分布�ID生�方案.md ) -* [�懂分布�技术13:缓存的那些事](docs/distrubuted/实战/�懂分布�技术13:缓存的那些事.md) -* [�懂分布�技术14:Spring Boot使用注解集�Redis缓存](docs/distrubuted/实战/�懂分布�技术14:Spring%20Boot使用注解集�Redis缓存.md) -* [�懂分布�技术15:缓存更新的套路 ](docs/distrubuted/实战/�懂分布�技术15:缓存更新的套路.md ) -* [�懂分布�技术16:浅谈分布��的几�方案 ](docs/distrubuted/实战/�懂分布�技术16:浅谈分布��的几�方案.md ) -* [�懂分布�技术17:浅�分布�事务 ](docs/distrubuted/实战/�懂分布�技术17:浅�分布�事务.md ) -* [�懂分布�技术18:分布�事务常用解决方案 ](docs/distrubuted/实战/�懂分布�技术18:分布�事务常用解决方案.md ) -* [�懂分布�技术19:使用RocketMQ事务消�解决分布�事务 ](docs/distrubuted/实战/�懂分布�技术19:使用RocketMQ事务消�解决分布�事务.md ) -* [�懂分布�技术20:消�队列因何而生](docs/distrubuted/实战/�懂分布�技术20:消�队列因何而生.md) -* [�懂分布�技术21:浅谈分布�消�技术 Kafka ](docs/distrubuted/实战/�懂分布�技术21:浅谈分布�消�技术%20Kafka.md ) - - +* [�懂分布�技术1:分布�系统的一些基本概念 ](docs/distributed/practice/�懂分布�技术1:分布�系统的一些基本概念.md ) +* [�懂分布�技术2:分布�一致性�议与Paxos,Raft算法](docs/distributed/practice/�懂分布�技术2:分布�一致性�议与Paxos,Raft算法.md) +* [�懂分布�技术3:�探分布��调�务zookeeper ](docs/distributed/practice/�懂分布�技术3:�探分布��调�务zookeeper.md ) +* [�懂分布�技术4:ZAB�议概述与选主�程详解 ](docs/distributed/practice/�懂分布�技术4:ZAB�议概述与选主�程详解.md ) +* [�懂分布�技术5:Zookeeper的�置与集群管�实战](docs/distributed/practice/�懂分布�技术5:Zookeeper的�置与集群管�实战.md) +* [�懂分布�技术6:Zookeeper典型应用场景�实践 ](docs/distributed/practice/�懂分布�技术6:Zookeeper典型应用场景�实践.md ) +* [�懂分布�技术7:负载�衡概念与主�方案](docs/distributed/practice/�懂分布�技术7:负载�衡概念与主�方案.md) +* [�懂分布�技术8:负载�衡原�剖� ](docs/distributed/practice/�懂分布�技术8:负载�衡原�剖�.md ) +* [�懂分布�技术9:Nginx负载�衡原�与实践 ](docs/distributed/practice/�懂分布�技术9:Nginx负载�衡原�与实践.md) +* [�懂分布�技术10:LVS实现负载�衡的原�与实践 ](docs/distributed/practice/�懂分布�技术10:LVS实现负载�衡的原�与实践.md ) +* [�懂分布�技术11:分布�session解决方案与一致性hash](docs/distributed/practice/�懂分布�技术11:分布�session解决方案与一致性hash.md) +* [�懂分布�技术12:分布�ID生�方案 ](docs/distributed/practice/�懂分布�技术12:分布�ID生�方案.md ) +* [�懂分布�技术13:缓存的那些事](docs/distributed/practice/�懂分布�技术13:缓存的那些事.md) +* [�懂分布�技术14:Spring Boot使用注解集�Redis缓存](docs/distributed/practice/�懂分布�技术14:Spring%20Boot使用注解集�Redis缓存.md) +* [�懂分布�技术15:缓存更新的套路 ](docs/distributed/practice/�懂分布�技术15:缓存更新的套路.md ) +* [�懂分布�技术16:浅谈分布��的几�方案 ](docs/distributed/practice/�懂分布�技术16:浅谈分布��的几�方案.md ) +* [�懂分布�技术17:浅�分布�事务 ](docs/distributed/practice/�懂分布�技术17:浅�分布�事务.md ) +* [�懂分布�技术18:分布�事务常用解决方案 ](docs/distributed/practice/�懂分布�技术18:分布�事务常用解决方案.md ) +* [�懂分布�技术19:使用RocketMQ事务消�解决分布�事务 ](docs/distributed/practice/�懂分布�技术19:使用RocketMQ事务消�解决分布�事务.md ) +* [�懂分布�技术20:消�队列因何而生](docs/distributed/practice/�懂分布�技术20:消�队列因何而生.md) +* [�懂分布�技术21:浅谈分布�消�技术 Kafka ](docs/distributed/practice/�懂分布�技术21:浅谈分布�消�技术%20Kafka.md ) + +* [分布��论总结](docs/distributed/分布�技术实践总结.md) ## �试指� todo diff --git "a/docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2001\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\2012PC\345\222\2143PC.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2001\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\2012PC\345\222\2143PC.md" similarity index 100% rename from "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2001\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\2012PC\345\222\2143PC.md" rename to "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2001\357\274\232 \344\270\200\350\207\264\346\200\247\343\200\2012PC\345\222\2143PC.md" diff --git "a/docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2002 \357\274\232CAP.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2002 \357\274\232CAP.md" similarity index 100% rename from "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2002 \357\274\232CAP.md" rename to "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2002 \357\274\232CAP.md" diff --git "a/docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2003\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2003\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" similarity index 100% rename from "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2003\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" rename to "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2003\357\274\232 \346\227\266\351\227\264\343\200\201\346\227\266\351\222\237\345\222\214\344\272\213\344\273\266\351\241\272\345\272\217.md" diff --git "a/docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2004\357\274\232Paxos.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2004\357\274\232Paxos.md" similarity index 100% rename from "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2004\357\274\232Paxos.md" rename to "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2004\357\274\232Paxos.md" diff --git "a/docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2005\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2005\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md" similarity index 100% rename from "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2005\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md" rename to "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2005\357\274\232\351\200\211\344\270\276\343\200\201\345\244\232\346\225\260\346\264\276\345\222\214\347\247\237\347\272\246.md" diff --git "a/docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2006\357\274\232Raft\343\200\201Zab.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2006\357\274\232Raft\343\200\201Zab.md" similarity index 100% rename from "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2006\357\274\232Raft\343\200\201Zab.md" rename to "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2006\357\274\232Raft\343\200\201Zab.md" diff --git "a/docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2008\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2008\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md" similarity index 100% rename from "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2008\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md" rename to "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\345\237\272\347\241\2008\357\274\232zookeeper\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241.md" diff --git "a/docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\2667\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md" "b/docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\2667\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md" similarity index 100% rename from "docs/distrubuted/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\2667\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md" rename to "docs/distributed/basic/\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\220\206\350\256\272\350\277\233\351\230\2667\357\274\232Paxos\345\217\230\347\247\215\345\222\214\344\274\230\345\214\226.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25710\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25710\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25710\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25710\357\274\232LVS\345\256\236\347\216\260\350\264\237\350\275\275\345\235\207\350\241\241\347\232\204\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25711\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25711\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25711\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25711\357\274\232\345\210\206\345\270\203\345\274\217session\350\247\243\345\206\263\346\226\271\346\241\210\344\270\216\344\270\200\350\207\264\346\200\247hash.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25712\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25712\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25712\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25712\357\274\232\345\210\206\345\270\203\345\274\217ID\347\224\237\346\210\220\346\226\271\346\241\210.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25713\357\274\232\347\274\223\345\255\230\347\232\204\351\202\243\344\272\233\344\272\213.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25713\357\274\232\347\274\223\345\255\230\347\232\204\351\202\243\344\272\233\344\272\213.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25713\357\274\232\347\274\223\345\255\230\347\232\204\351\202\243\344\272\233\344\272\213.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25713\357\274\232\347\274\223\345\255\230\347\232\204\351\202\243\344\272\233\344\272\213.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232Spring Boot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232Spring Boot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232Spring Boot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232Spring Boot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25715\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25715\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25715\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25715\357\274\232\347\274\223\345\255\230\346\233\264\346\226\260\347\232\204\345\245\227\350\267\257.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25716\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25716\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25716\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25716\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\351\224\201\347\232\204\345\207\240\347\247\215\346\226\271\346\241\210.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25717\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25717\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25717\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25717\357\274\232\346\265\205\346\236\220\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25718\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25718\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25718\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25718\357\274\232\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241\345\270\270\347\224\250\350\247\243\345\206\263\346\226\271\346\241\210.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25719\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25719\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25719\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25719\357\274\232\344\275\277\347\224\250RocketMQ\344\272\213\345\212\241\346\266\210\346\201\257\350\247\243\345\206\263\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2571\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2571\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2571\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2571\357\274\232\345\210\206\345\270\203\345\274\217\347\263\273\347\273\237\347\232\204\344\270\200\344\272\233\345\237\272\346\234\254\346\246\202\345\277\265.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25720\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25720\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25720\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25720\357\274\232\346\266\210\346\201\257\351\230\237\345\210\227\345\233\240\344\275\225\350\200\214\347\224\237.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257 Kafka.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257 Kafka.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257 Kafka.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257 Kafka.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2572\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2572\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2572\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2572\357\274\232\345\210\206\345\270\203\345\274\217\344\270\200\350\207\264\346\200\247\345\215\217\350\256\256\344\270\216Paxos\357\274\214Raft\347\256\227\346\263\225.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2573\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2573\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2573\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2573\357\274\232\345\210\235\346\216\242\345\210\206\345\270\203\345\274\217\345\215\217\350\260\203\346\234\215\345\212\241zookeeper.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2574\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2574\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2574\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2574\357\274\232ZAB\345\215\217\350\256\256\346\246\202\350\277\260\344\270\216\351\200\211\344\270\273\346\265\201\347\250\213\350\257\246\350\247\243.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2575\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2575\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2575\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2575\357\274\232Zookeeper\347\232\204\351\205\215\347\275\256\344\270\216\351\233\206\347\276\244\347\256\241\347\220\206\345\256\236\346\210\230.md" diff --git "a/docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2576\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2576\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md" similarity index 100% rename from "docs/distrubuted/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2576\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\2576\357\274\232Zookeeper\345\205\270\345\236\213\345\272\224\347\224\250\345\234\272\346\231\257\345\217\212\345\256\236\350\267\265.md" diff --git "a/docs/distrubuted/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md" "b/docs/distributed/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md" similarity index 100% rename from "docs/distrubuted/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md" rename to "docs/distributed/\345\210\206\345\270\203\345\274\217\346\212\200\346\234\257\345\256\236\350\267\265\346\200\273\347\273\223.md" diff --git "a/docs/distrubuted/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" "b/docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" similarity index 100% rename from "docs/distrubuted/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" rename to "docs/distributed/\345\210\206\345\270\203\345\274\217\347\220\206\350\256\272\346\200\273\347\273\223.md" From 3bb0926b7a594dd566ae23f7bacead1566c8be38 Mon Sep 17 00:00:00 2001 From: h2pl <362294931@qq.com> Date: Fri, 31 Mar 2023 19:54:30 +0800 Subject: [PATCH 16/98] resolve pic problem in juc --- ...\227\357\274\214CAS\346\223\215\344\275\234.md" | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" "b/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" index 4220389..b778e5e 100644 --- "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" +++ "b/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" @@ -264,7 +264,7 @@ volatile写的内存语义如下: 以上�示例程�VolatileExample为例,�设线程A首先执行writer()方法,��线程B执行reader()方法,�始时两个线程的本地内存中的flag和a都是�始状�。下图是线程A执行volatile写�,共享��的状�示�图: -![](https://res.infoq.com/articles/java-memory-model-4/zh/resources/2.png) +![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9UTEgzQ2ljUFZpYnJlMXJ3emFJWjJkT3VVdDVjekVBdVQ3dmRtZ0NFNjBKeTlRODRsZ0VwdzNqaWFCREJmSjE2TkxZUEQ2a1dNeHBnOTNad0tUOVY2Ym1Ydy82NDA?x-oss-process=image/format,png) 如上图所示,线程A在写flag���,本地内存A中被线程A更新过的两个共享��的值被刷新到主内存中。此时,本地内存A和主内存中的共享��的值是一致的。 @@ -274,7 +274,7 @@ volatile读的内存语义如下: 下�是线程B读�一个volatile���,共享��的状�示�图: -![](https://res.infoq.com/articles/java-memory-model-4/zh/resources/3.png) +![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9UTEgzQ2ljUFZpYnJlMXJ3emFJWjJkT3VVdDVjekVBdVQ3WWcwMEt1bGVicDAza0MyU2ZHWmI3Tm5vaDcxaG5JS3dpYW5qcnJsUzBUN3dNZWljWUJySmY4YVEvNjQw?x-oss-process=image/format,png) 如上图所示,在读flag���,本地内存B已�被置为无效。此时,线程B必须从主内存中读�共享��。线程B的读��作将导致本地内存B与主内存中的共享��的值也��一致的了。 @@ -322,7 +322,7 @@ volatile读的内存语义如下: 下�是�守策略下,volatile写�入内存�障�生�的指令�列示�图: -![](https://res.infoq.com/articles/java-memory-model-4/zh/resources/4.png) +![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9UTEgzQ2ljUFZpYnJlMXJ3emFJWjJkT3VVdDVjekVBdVQ3U2dxcTJ0SnF1N1pwQllpYVZmZnpTd3F5NGhDY1dSWVhNVzlzM0VWSmljRFZzODY5cWc1M1A3eEEvNjQw?x-oss-process=image/format,png) 上图中的StoreStore�障�以��在volatile写之�,其��的所有普通写�作已�对任�处�器��了。这是因为StoreStore�障将�障上�所有的普通写在volatile写之�刷新到主内存。 @@ -330,7 +330,7 @@ volatile读的内存语义如下: 下�是在�守策略下,volatile读�入内存�障�生�的指令�列示�图: -![](https://res.infoq.com/articles/java-memory-model-4/zh/resources/5.png) +![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9UTEgzQ2ljUFZpYnJlMXJ3emFJWjJkT3VVdDVjekVBdVQ3U2dxcTJ0SnF1N1pwQllpYVZmZnpTd3F5NGhDY1dSWVhNVzlzM0VWSmljRFZzODY5cWc1M1A3eEEvNjQw?x-oss-process=image/format,png) 上图中的LoadLoad�障用��止处�器把上�的volatile读与下�的普通读�排�。LoadStore�障用��止处�器把上�的volatile读与下�的普通写�排�。 @@ -354,7 +354,7 @@ volatile读的内存语义如下: 针对readAndWrite()方法,编译器在生�字节�时�以�如下的优化: -![](https://res.infoq.com/articles/java-memory-model-4/zh/resources/6.png) +![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9UTEgzQ2ljUFZpYnJlMXJ3emFJWjJkT3VVdDVjekVBdVQ3RzlISFVoNTh0MHNCVUZwMEJyZVU4Njc0OGZHMFhKdmxRTXFpYXE3dUhRNklGd1Q5a1pZQktjZy82NDA?x-oss-process=image/format,png) 注�,最�的StoreLoad�障�能�略。因为第二个volatile写之�,方法立�return。此时编译器�能无法准确断定��是�会有volatile读或写,为了安全起�,编译器常常会在这里�入一个StoreLoad�障。 @@ -362,7 +362,7 @@ volatile读的内存语义如下: ���守策略下的volatile读和写,在 x86处�器平��以优化�: -![](https://res.infoq.com/articles/java-memory-model-4/zh/resources/7.png) +![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9UTEgzQ2ljUFZpYnJlMXJ3emFJWjJkT3VVdDVjekVBdVQ3aWNaU1h6dURzT2pnZ0hBTmljYnljbTNPYjkwbkVVOURCTm1JaHE1Y2NVdTZMUnZxS3V1cmlhQ29nLzY0MA?x-oss-process=image/format,png) �文�到过,x86处�器仅会对写-读�作��排�。X86�会对读-读,读-写和写-写�作��排�,因此在x86处�器中会�略掉这三��作类型对应的内存�障。在x86中,JMM仅需在volatile写���入一个StoreLoad�障��正确实现volatile写-读的内存语义。这�味�在x86处�器中,volatile写的开销比volatile读的开销会大很多(因为执行StoreLoad�障开销会比较大)。 @@ -370,7 +370,7 @@ volatile读的内存语义如下: 在JSR-133之�的旧Java内存模型中,虽然��许volatile��之间�排�,但旧的Java内存模型�许volatile��与普通��之间�排�。在旧的内存模型中,VolatileExample示例程��能被�排��下列时��执行: -![](https://res.infoq.com/articles/java-memory-model-4/zh/resources/8.png) +![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9UTEgzQ2ljUFZpYnJlMXJ3emFJWjJkT3VVdDVjekVBdVQ3TG9aamN2em13WUk3aGVJcksyemp2YWs5RGI5cHZKaFJ3NVR0cHFGMzNWUjFHb0tzd1lwNUdnLzY0MA?x-oss-process=image/format,png) 在旧的内存模型中,当1和2之间没有数��赖关系时,1和2之间就�能被�排�(3和4类似)。其结果就是:读线程B执行4时,�一定能看到写线程A在执行1时对共享��的修改。 From f6f1362df0adf58fde9f89cdef7680bf334887ab Mon Sep 17 00:00:00 2001 From: h2pl <362294931@qq.com> Date: Fri, 31 Mar 2023 20:13:19 +0800 Subject: [PATCH 17/98] =?UTF-8?q?resolve=20pic=20problem=20in=20=E5=A4=9A?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\271\350\261\241\345\237\272\347\241\200.md" | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git "a/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" "b/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" index 3570358..20a3a96 100644 --- "a/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" +++ "b/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" @@ -452,9 +452,10 @@ java里的多�主�表现在两个方�:   这两��是什么��呢,让我们用代��体验一下,首先我们创建一个父类Animal和一个�类Dog,在主函数里如下所示: -![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701155536086-1897896282.png) +![img](https://cdn.mianshigee.com/upload/note/thumbnails/202202211611552259.png) -  注�:我们�能使用一个�类的引用�指�父类的对象,如:![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701155839586-923083573.png)。 +  注�:我们�能使用一个�类的引用�指�父类的对象,如: +![img](https://cdn.mianshigee.com/upload/note/thumbnails/202202211611556958.png)。   这里我们必须深刻�解引用多�的�义,�能更好记忆这�多�的特性。为什么�类的引用�能用�指�父类的对象呢?我在这里通俗给大家讲解一下:就以上�的例��说,我们能说“狗是一�动物�,但是�能说“动物是一�狗�,狗和动物是父类和�类的继承关系,它们的从属是�能颠倒的。当父类的引用指��类的对象时,该对象将�是看�一�特殊的父类(里�有�写的方法和属性),�之,一个�类的引用�指�父类的对象是��行的�� @@ -482,23 +483,23 @@ java里的多�主�表现在两个方�:   就以上述的父类Animal和一个�类Dog�说明,当父类的引用�以指��类的对象时,就是**�上类型转�**。如: -![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701162630508-961507659.png) +![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2MjYzMDUwOC05NjE1MDc2NTkucG5n?x-oss-process=image/format,png)   **2. �下类型转�(强制类型转�),是大类型转�到�类型(有风险,�能出现数�溢出)。**   将上述代��加上一行,我们�次将父类转�为�类引用,那么会出现错误,编译器��许我们直接这么�**,**虽然我们知�这个父类引用指�的就是�类对象,但是编译器认为这�转�是存在风险的**。**如: -![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701162926477-3857975.png) +![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2MjkyNjQ3Ny0zODU3OTc1LnBuZw?x-oss-process=image/format,png) -  那么我们该怎么解决这个问题呢,我们�以在animal�加上(Dog)�强制类型转�。如:![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701163408383-2003626729.png) +  那么我们该怎么解决这个问题呢,我们�以在animal�加上(Dog)�强制类型转�。如:![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2NDIyOTg5OS0xMDU1MTkwNzc0LnBuZw?x-oss-process=image/format,png) -  但是如果父类引用没有指�**该�类的对象**,则�能�下类型转�,虽然编译器�会报错,但是�行的时候程�会出错,如:![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701164229899-1055190774.png) +  但是如果父类引用没有指�**该�类的对象**,则�能�下类型转�,虽然编译器�会报错,但是�行的时候程�会出错,如:![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2NTEzMzI4OS03MTc0MzkzNjAucG5n?x-oss-process=image/format,png)   其实这就是上�所说的�类的引用指�父类的对象,而强制转�类型也�能转���   还有一�情况是父类的引用指�**其他�类的对象**,则�能通过强制转为**该�类的对象**。如: -    ![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701165133289-717439360.png) +    ![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2NTEzMzI4OS03MTc0MzkzNjAucG5n?x-oss-process=image/format,png)   这是因为我们在编译的时候进行了强制类型转�,编译时的类型是我们强制转�的类型,所以编译器�会报错,而当我们�行的时候,程�给animal开辟的是Dog类型的内存空间,这与Cat类型内存空间�匹�,所以无法正常转�。这两�情况出错的本质是一样的,所以我们在使用强制类型转�的时候�特别注�这两�错误��下�有个更安全的方��实现�下类型转�。。。。 @@ -508,7 +509,7 @@ java里的多�主�表现在两个方�:   我们�使用instanceof�算符�规�上�的错误,代�修改如下: -  ![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701165626571-501228254.png) +  ![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2NTYyNjU3MS01MDEyMjgyNTQucG5n?x-oss-process=image/format,png)   利用if语�和instanceof�算符�判断两个对象的类型是�一致。 From 760cc8971613257429e4bd2332151e26e9242e48 Mon Sep 17 00:00:00 2001 From: h2pl <362294931@qq.com> Date: Fri, 31 Mar 2023 20:28:04 +0800 Subject: [PATCH 18/98] resolve pic problem in network programing --- ReadMe.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 23bde83..f8b8ed6 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -196,17 +196,17 @@ todo ### Java网络编程 -* [Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制](docs/java/jvm/Java网络编程和NIO详解1:JAVA%20中原生的%20socket%20通信机制.md) -* [Java网络编程与NIO详解2:JAVA NIO 一步步构建IO多路�用的请求模型](docs/java/jvm/Java网络编程与NIO详解2:JAVA%20NIO%20一步步构建IO多路�用的请求模型.md) -* [Java网络编程和NIO详解3:IO模型与Java网络编程模型](docs/java/jvm/Java网络编程和NIO详解3:IO模型与Java网络编程模型.md) -* [Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel 和 Selector](https://github.com/h2pl/Java-Tutorial/blob/master/docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E4%B8%8ENIO%E8%AF%A6%E8%A7%A34%EF%BC%9A%E6%B5%85%E6%9E%90NIO%E5%8C%85%E4%B8%AD%E7%9A%84Buffer%E3%80%81Channel%20%E5%92%8C%20Selector.md) -* [Java网络编程和NIO详解5:Java �阻塞 IO 和异步 IO](https://github.com/h2pl/Java-Tutorial/blob/master/docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E5%92%8CNIO%E8%AF%A6%E8%A7%A35%EF%BC%9AJava%20%E9%9D%9E%E9%98%BB%E5%A1%9E%20IO%20%E5%92%8C%E5%BC%82%E6%AD%A5%20IO.md) -* [Java网络编程和NIO详解6:Linux epoll实现原�详解](docs/java/jvm/Java网络编程和NIO详解6:Linux%20epoll实现原�详解.md) -* [Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原�](Java网络编程和NIO详解7:浅谈%20Linux%20中NIO%20Selector%20的实现原�.md) -* [Java网络编程与NIO详解8:浅�mmap和Direct Buffer](https://github.com/h2pl/Java-Tutorial/blob/master/docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E4%B8%8ENIO%E8%AF%A6%E8%A7%A38%EF%BC%9A%E6%B5%85%E6%9E%90mmap%E5%92%8CDirect%20Buffer.md) -* [Java网络编程和NIO详解9:基于NIO的网络编程框架Netty](docs/java/jvm/Java网络编程和NIO详解9:基于NIO的网络编程框架Netty.md) -* [Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型](https://github.com/h2pl/Java-Tutorial/blob/master/docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E4%B8%8ENIO%E8%AF%A6%E8%A7%A310%EF%BC%9A%E6%B7%B1%E5%BA%A6%E8%A7%A3%E8%AF%BBTomcat%E4%B8%AD%E7%9A%84NIO%E6%A8%A1%E5%9E%8B.md) -* [Java网络编程与NIO详解11:Tomcat中的Connector��分�(NIO)](docs/java/jvm/Java网络编程与NIO详解11:Tomcat中的Connector��分�(NIO).md) +* [Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制](docs/java/network-programming/Java网络编程和NIO详解1:JAVA%20中原生的%20socket%20通信机制.md) +* [Java网络编程与NIO详解2:JAVA NIO 一步步构建IO多路�用的请求模型](docs/java/network-programming/Java网络编程与NIO详解2:JAVA%20NIO%20一步步构建IO多路�用的请求模型.md) +* [Java网络编程和NIO详解3:IO模型与Java网络编程模型](docs/java/network-programming/Java网络编程和NIO详解3:IO模型与Java网络编程模型.md) +* [Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel 和 Selector](docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E4%B8%8ENIO%E8%AF%A6%E8%A7%A34%EF%BC%9A%E6%B5%85%E6%9E%90NIO%E5%8C%85%E4%B8%AD%E7%9A%84Buffer%E3%80%81Channel%20%E5%92%8C%20Selector.md) +* [Java网络编程和NIO详解5:Java �阻塞 IO 和异步 IO](docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E5%92%8CNIO%E8%AF%A6%E8%A7%A35%EF%BC%9AJava%20%E9%9D%9E%E9%98%BB%E5%A1%9E%20IO%20%E5%92%8C%E5%BC%82%E6%AD%A5%20IO.md) +* [Java网络编程和NIO详解6:Linux epoll实现原�详解](docs/java/network-programming/Java网络编程和NIO详解6:Linux%20epoll实现原�详解.md) +* [Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原�](docs/java/network-programming/Java网络编程和NIO详解7:浅谈%20Linux%20中NIO%20Selector%20的实现原�.md) +* [Java网络编程与NIO详解8:浅�mmap和Direct Buffer](docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E4%B8%8ENIO%E8%AF%A6%E8%A7%A38%EF%BC%9A%E6%B5%85%E6%9E%90mmap%E5%92%8CDirect%20Buffer.md) +* [Java网络编程和NIO详解9:基于NIO的网络编程框架Netty](docs/java/network-programming/Java网络编程和NIO详解9:基于NIO的网络编程框架Netty.md) +* [Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型](docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E4%B8%8ENIO%E8%AF%A6%E8%A7%A310%EF%BC%9A%E6%B7%B1%E5%BA%A6%E8%A7%A3%E8%AF%BBTomcat%E4%B8%AD%E7%9A%84NIO%E6%A8%A1%E5%9E%8B.md) +* [Java网络编程与NIO详解11:Tomcat中的Connector��分�(NIO)](docs/java/network-programming/Java网络编程与NIO详解11:Tomcat中的Connector��分�(NIO).md) ## 计算机基础 From bfb15b068176e70055ed8fd51bb76c6ccf7f217e Mon Sep 17 00:00:00 2001 From: h2pl <362294931@qq.com> Date: Fri, 31 Mar 2023 20:38:19 +0800 Subject: [PATCH 19/98] resolve docs in juc --- ...\233\206\345\220\210\347\261\273\346\200\273\347\273\223.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\347\261\273\346\200\273\347\273\223.md" "b/docs/java/collection/Java\351\233\206\345\220\210\347\261\273\346\200\273\347\273\223.md" index 2c05f7b..36d9432 100644 --- "a/docs/java/collection/Java\351\233\206\345\220\210\347\261\273\346\200\273\347\273\223.md" +++ "b/docs/java/collection/Java\351\233\206\345\220\210\347\261\273\346\200\273\347\273\223.md" @@ -91,7 +91,7 @@ hashmap的增删改查方�比较简�,都是�历,替�。有一点� ## CHM -concurrenthashmap也�微�一下把,chm1.7使用分段��控制并�,�个segment对应一个segmentmask,通过key的hash值相与这个segmentmask得到segment�置,然�在找到具体的entry数组下标。所以chm需�维护多个segment,�个segment对应一个数组。分段�使用的是reetreetlock��入�实现。查询时�加�。 +concurrenthashmap也�微�一下把,chm1.7使用分段��控制并�,�个segment对应一个segmentmask,通过key的hash值相与这个segmentmask得到segment�置,然�在找到具体的entry数组下标。所以chm需�维护多个segment,�个segment对应一个数组。分段�使用的是ReentrantLock��入�实现。查询时�加�。 1.8则放弃使用分段�,改用cas+synchronized方�实现并�控制,查询时�加�,�入时如果没有冲�直接cas到�功为止,有冲�则使用synchronized�入。 From 1d8d97d20f2cfcdf43fc1ebaf913b5eae589fa57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Mon, 3 Apr 2023 11:57:22 +0800 Subject: [PATCH 20/98] modify catalog --- ReadMe.md | 119 +++++++++--------- .../\345\211\221\346\214\207offer.md" | 0 ...46\344\271\240\346\200\273\347\273\223.md" | 0 ...46\344\271\240\346\200\273\347\273\223.md" | 0 ...46\344\271\240\346\200\273\347\273\223.md" | 0 ...4\232SpringMVC\346\246\202\350\277\260.md" | 0 ...5\277\265\344\270\216DispatcherServlet.md" | 0 ...67\346\261\202\350\275\254\345\217\221.md" | 0 ...\243\347\241\256\347\232\204Controller.md" | 0 ...43\346\236\220\345\216\237\347\220\206.md" | 0 ...6@ResponseBody\346\263\250\350\247\243.md" | 0 ...72\346\234\254\345\216\237\347\220\206.md" | 0 ...20\347\240\201\345\210\206\346\236\220.md" | 0 ...\351\230\237\345\210\227 BlockingQueue.md" | 0 ...20\347\240\201\345\256\236\347\216\260.md" | 0 ...p \345\205\250\350\247\243\346\236\220.md" | 0 ...7\232\204Unsafe\345\222\214Locksupport.md" | 0 ...27\346\263\225\345\211\226\346\236\220.md" | 0 ...va\345\244\232\347\272\277\347\250\213.md" | 0 ...345\255\230\346\250\241\345\236\213JMM.md" | 0 ...357\274\214CAS\346\223\215\344\275\234.md" | 0 ...1\224\201 Lock\345\222\214synchronized.md" | 0 ...56\345\255\227\350\247\243\346\236\220.md" | 0 ...345\236\213JMM\346\200\273\347\273\223.md" | 0 ...347\261\273AQS\350\257\246\350\247\243.md" | 0 ...71\263\351\224\201\357\274\214Condtion.md" | 0 ...73\347\232\204\345\256\236\347\216\260.md" | 0 ...46\344\271\240\346\200\273\347\273\223.md" | 0 ...00\347\273\210\346\225\210\346\236\234.md" | 2 +- 29 files changed, 62 insertions(+), 59 deletions(-) rename "docs/algorithms/\345\211\221\346\214\207offer.md" => "docs/cs/algorithms/\345\211\221\346\214\207offer.md" (100%) rename "docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md" => "docs/cs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md" (100%) rename "docs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" => "docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" (100%) rename "docs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md" => "docs/cs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md" (100%) rename "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2201\357\274\232SpringMVC\346\246\202\350\277\260.md" => "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2201\357\274\232SpringMVC\346\246\202\350\277\260.md" (100%) rename "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2202\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" => "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2202\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" (100%) rename "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2203\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" => "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2203\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" (100%) rename "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2204\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" => "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2204\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" (100%) rename "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2206\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" => "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2206\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" (100%) rename "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\211\226\346\236\2205\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" => "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\211\226\346\236\2205\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" (100%) rename "docs/java-web/\346\267\261\345\205\245JavaWeb\346\212\200\346\234\257\344\270\226\347\225\21415\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md" => "docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\21415\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java \350\257\273\345\206\231\351\224\201 ReentrantReadWriteLock \346\272\220\347\240\201\345\210\206\346\236\220.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java \350\257\273\345\206\231\351\224\201 ReentrantReadWriteLock \346\272\220\347\240\201\345\210\206\346\236\220.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273 Java \351\230\273\345\241\236\351\230\237\345\210\227 BlockingQueue.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273 Java \351\230\273\345\241\236\351\230\237\345\210\227 BlockingQueue.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java \344\270\255\347\232\204 HashMap \345\222\214 ConcurrentHashMap \345\205\250\350\247\243\346\236\220.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java \344\270\255\347\232\204 HashMap \345\222\214 ConcurrentHashMap \345\205\250\350\247\243\346\236\220.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22714\357\274\232JUC\344\270\255\345\270\270\347\224\250\347\232\204Unsafe\345\222\214Locksupport.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22714\357\274\232JUC\344\270\255\345\270\270\347\224\250\347\232\204Unsafe\345\222\214Locksupport.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\347\274\226\347\250\213\346\214\207\345\215\22715\357\274\232Fork join\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22715\357\274\232Fork join\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2271\357\274\232\345\271\266\345\217\221\345\237\272\347\241\200\344\270\216Java\345\244\232\347\272\277\347\250\213.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2271\357\274\232\345\271\266\345\217\221\345\237\272\347\241\200\344\270\216Java\345\244\232\347\272\277\347\250\213.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2272\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2272\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201 Lock\345\222\214synchronized.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201 Lock\345\222\214synchronized.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2275\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2275\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2276\357\274\232Java\345\206\205\345\255\230\346\250\241\345\236\213JMM\346\200\273\347\273\223.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2276\357\274\232Java\345\206\205\345\255\230\346\250\241\345\236\213JMM\346\200\273\347\273\223.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2277\357\274\232JUC\347\232\204\346\240\270\345\277\203\347\261\273AQS\350\257\246\350\247\243.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2277\357\274\232JUC\347\232\204\346\240\270\345\277\203\347\261\273AQS\350\257\246\350\247\243.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2278\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2278\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2279\357\274\232AQS\345\205\261\344\272\253\346\250\241\345\274\217\344\270\216\345\271\266\345\217\221\345\267\245\345\205\267\347\261\273\347\232\204\345\256\236\347\216\260.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2279\357\274\232AQS\345\205\261\344\272\253\346\250\241\345\274\217\344\270\216\345\271\266\345\217\221\345\267\245\345\205\267\347\261\273\347\232\204\345\256\236\347\216\260.md" (100%) rename "docs/java/currency/Java\345\271\266\345\217\221\346\200\273\347\273\223.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\255\246\344\271\240\346\200\273\347\273\223.md" (100%) diff --git a/ReadMe.md b/ReadMe.md index f8b8ed6..f63c941 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -63,28 +63,28 @@ ### 基础知识 -* [��对象基础](docs/java/basic/1���对象基础.md) -* [Java基本数�类型](docs/java/basic/2�Java基本数�类型.md) -* [string和包装类](docs/java/basic/3�string和包装类.md) -* [final关键字特性](docs/java/basic/4�final关键字特性.md) -* [Java类和包](docs/java/basic/5�Java类和包.md) -* [抽象类和接�](docs/java/basic/6�抽象类和接�.md) -* [代��和代�执行顺�](docs/java/basic/7�代��和代�执行顺�.md) -* [Java自动拆箱装箱里��的秘密](docs/java/basic/8�Java自动拆箱装箱里��的秘密.md) -* [Java中的Class类和Object类](docs/java/basic/9�Java中的Class类和Object类.md) -* [Java异常](docs/java/basic/10�Java异常.md) -* [解读Java中的回调](docs/java/basic/11�解读Java中的回调.md) -* [�射](docs/java/basic/12��射.md) -* [泛型](docs/java/basic/13�泛型.md) -* [枚举类](docs/java/basic/14�枚举类.md) -* [Java注解和最佳实践](docs/java/basic/15�Java注解和最佳实践.md) -* [JavaIO�](docs/java/basic/16�JavaIO�.md) -* [多线程](docs/java/basic/17�多线程.md) -* [深入�解内部类](docs/java/basic/18�深入�解内部类.md) -* [javac和javap](docs/java/basic/20�javac和javap.md) -* [Java8新特性终�指�](docs/java/basic/21�Java8新特性终�指�.md) -* [�列化和��列化](docs/java/basic/22��列化和��列化.md) -* [继承��装�多�的实现原�](docs/java/basic/23�继承��装�多�的实现原�.md) +* [1���对象基础](docs/java/basic/1���对象基础.md) +* [2�Java基本数�类型](docs/java/basic/2�Java基本数�类型.md) +* [3�string和包装类](docs/java/basic/3�string和包装类.md) +* [4�final关键字特性](docs/java/basic/4�final关键字特性.md) +* [5�Java类和包](docs/java/basic/5�Java类和包.md) +* [6�抽象类和接�](docs/java/basic/6�抽象类和接�.md) +* [7�代��和代�执行顺�](docs/java/basic/7�代��和代�执行顺�.md) +* [8�Java自动拆箱装箱里��的秘密](docs/java/basic/8�Java自动拆箱装箱里��的秘密.md) +* [9�Java中的Class类和Object类](docs/java/basic/9�Java中的Class类和Object类.md) +* [10�Java异常](docs/java/basic/10�Java异常.md) +* [11�解读Java中的回调](docs/java/basic/11�解读Java中的回调.md) +* [12��射](docs/java/basic/12��射.md) +* [13�泛型](docs/java/basic/13�泛型.md) +* [14�枚举类](docs/java/basic/14�枚举类.md) +* [15�Java注解和最佳实践](docs/java/basic/15�Java注解和最佳实践.md) +* [16�JavaIO�](docs/java/basic/16�JavaIO�.md) +* [17�多线程](docs/java/basic/17�多线程.md) +* [18�深入�解内部类](docs/java/basic/18�深入�解内部类.md) +* [20�javac和javap](docs/java/basic/20�javac和javap.md) +* [21�Java8新特性终�指�](docs/java/basic/21�Java8新特性终�指�.md) +* [22��列化和��列化](docs/java/basic/22��列化和��列化.md) +* [23�继承��装�多�的实现原�](docs/java/basic/23�继承��装�多�的实现原�.md) ### 容器 @@ -123,7 +123,7 @@ * [走进JavaWeb技术世界12:从手动编译打包到项目构建工具Maven](docs/java-web/走进JavaWeb技术世界12:从手动编译打包到项目构建工具Maven.md) * [走进JavaWeb技术世界13:Hibernate入门�典与注解�开�](docs/java-web/走进JavaWeb技术世界13:Hibernate入门�典与注解�开�.md) * [走进JavaWeb技术世界14:Mybatis入门](docs/java-web/走进JavaWeb技术世界14:Mybatis入门.md) -* [深入JavaWeb技术世界15:深入浅出Mybatis基本原�](docs/java-web/深入JavaWeb技术世界15:深入浅出Mybatis基本原�.md) +* [走进JavaWeb技术世界15:深入浅出Mybatis基本原�](docs/java-web/走进JavaWeb技术世界15:深入浅出Mybatis基本原�.md) * [走进JavaWeb技术世界16:�简�置的SpringBoot](docs/java-web/走进JavaWeb技术世界16:�简�置的SpringBoot.md) ### Spring @@ -140,12 +140,12 @@ ### SpringMVC -* [SpringMVC��分�1:SpringMVC概述](docs/java-web/Spring/SSM/SpringMVC��分�1:SpringMVC概述.md) -* [SpringMVC��分�2:SpringMVC设计�念与DispatcherServlet](docs/java-web/Spring/SSM/SpringMVC��分�2:SpringMVC设计�念与DispatcherServlet.md) -* [SpringMVC��分�3:DispatcherServlet的�始化与请求转� ](docs/java-web/Spring/SSM/SpringMVC��分�3:DispatcherServlet的�始化与请求转�.md) -* [SpringMVC��分�4:DispatcherServlet如何找到正确的Controller ](docs/java-web/Spring/SSM/SpringMVC��分�4:DispatcherServlet如何找到正确的Controller.md) -* [SpringMVC��剖�5:消�转�器HttpMessageConverter与@ResponseBody注解](docs/java-web/Spring/SSM/SpringMVC��剖�5:消�转�器HttpMessageConverter与@ResponseBody注解.md) -* [SpringMVC��分�6:SpringMVC的视图解�原� ](docs/java-web/Spring/SSM/SpringMVC��分�6:SpringMVC的视图解�原�.md) +* [SpringMVC��分�1:SpringMVC概述](docs/java-web/SpringMVC/SpringMVC��分�1:SpringMVC概述.md) +* [SpringMVC��分�2:SpringMVC设计�念与DispatcherServlet](docs/java-web/SpringMVC/SpringMVC��分�2:SpringMVC设计�念与DispatcherServlet.md) +* [SpringMVC��分�3:DispatcherServlet的�始化与请求转� ](docs/java-web/SpringMVC/SpringMVC��分�3:DispatcherServlet的�始化与请求转�.md) +* [SpringMVC��分�4:DispatcherServlet如何找到正确的Controller ](docs/java-web/SpringMVC/SpringMVC��分�4:DispatcherServlet如何找到正确的Controller.md) +* [SpringMVC��剖�5:消�转�器HttpMessageConverter与@ResponseBody注解](docs/java-web/SpringMVC/SpringMVC��剖�5:消�转�器HttpMessageConverter与@ResponseBody注解.md) +* [SpringMVC��分�6:SpringMVC的视图解�原� ](docs/java-web/SpringMVC/SpringMVC��分�6:SpringMVC的视图解�原�.md) ### SpringBoot @@ -159,22 +159,22 @@ todo ### 并� -* [Java并�指�1:并�基础与Java多线程](docs/java/currency/Java并�指�1:并�基础与Java多线程.md) -* [Java并�指�2:深入�解Java内存模型JMM](docs/java/currency/Java并�指�2:深入�解Java内存模型JMM.md) -* [Java并�指�3:并�三大问题与volatile关键字,CAS�作](docs/java/currency/Java并�指�3:并�三大问题与volatile关键字,CAS�作.md) -* [Java并�指�4:Java中的� Lock和synchronized](docs/java/currency/Java并�指�4:Java中的�%20Lock和synchronized.md) -* [Java并�指�5:JMM中的final关键字解�](docs/java/currency/Java并�指�5:JMM中的final关键字解�.md) -* [Java并�指�6:Java内存模型JMM总结](docs/java/currency/Java并�指�6:Java内存模型JMM总结.md) -* [Java并�指�7:JUC的核心类AQS详解](docs/java/currency/Java并�指�7:JUC的核心类AQS详解.md) -* [Java并�指�8:AQS中的公平�与�公平�,Condtion](docs/java/currency/Java并�指�8:AQS中的公平�与�公平�,Condtion.md) -* [Java并�指�9:AQS共享模�与并�工具类的实现](docs/java/currency/Java并�指�9:AQS共享模�与并�工具类的实现.md) -* [Java并�指�10:Java 读写� ReentrantReadWriteLock ��分�](docs/java/currency/Java并�指�10:Java%20读写�%20ReentrantReadWriteLock%20��分�.md) -* [Java并�指�11:解读 Java 阻塞队列 BlockingQueue](docs/java/currency/Java并�指�11:解读%20Java%20阻塞队列%20BlockingQueue.md) -* [Java并�指�12:深度解读 java 线程池设计�想���实现](docs/java/currency/Java并�指�12:深度解读%20java%20线程池设计�想���实现.md) -* [Java并�指�13:Java 中的 HashMap 和 ConcurrentHashMap 全解�](https://github.com/h2pl/Java-Tutorial/blob/master/docs/java/currency/Java%E5%B9%B6%E5%8F%91%E6%8C%87%E5%8D%9713%EF%BC%9AJava%20%E4%B8%AD%E7%9A%84%20HashMap%20%E5%92%8C%20ConcurrentHashMap%20%E5%85%A8%E8%A7%A3%E6%9E%90.md) -* [Java并�指�14:JUC中常用的Unsafe和Locksupport](docs/java/currency/Java并�指�14:JUC中常用的Unsafe和Locksupport.md) -* [Java并�指�15:Fork join并�框架与工作窃�算法剖�](docs/java/currency/Java并�编程指�15:Fork%20join并�框架与工作窃�算法剖�.md) -* [Java并�编程学习总结](https://github.com/h2pl/Java-Tutorial/blob/master/docs/java/currency/Java%E5%B9%B6%E5%8F%91%E6%80%BB%E7%BB%93.md) +* [Java并�指�1:并�基础与Java多线程](docs/java/concurrency/Java并�指�1:并�基础与Java多线程.md) +* [Java并�指�2:深入�解Java内存模型JMM](docs/java/concurrency/Java并�指�2:深入�解Java内存模型JMM.md) +* [Java并�指�3:并�三大问题与volatile关键字,CAS�作](docs/java/concurrency/Java并�指�3:并�三大问题与volatile关键字,CAS�作.md) +* [Java并�指�4:Java中的� Lock和synchronized](docs/java/concurrency/Java并�指�4:Java中的�%20Lock和synchronized.md) +* [Java并�指�5:JMM中的final关键字解�](docs/java/concurrency/Java并�指�5:JMM中的final关键字解�.md) +* [Java并�指�6:Java内存模型JMM总结](docs/java/concurrency/Java并�指�6:Java内存模型JMM总结.md) +* [Java并�指�7:JUC的核心类AQS详解](docs/java/concurrency/Java并�指�7:JUC的核心类AQS详解.md) +* [Java并�指�8:AQS中的公平�与�公平�,Condtion](docs/java/concurrency/Java并�指�8:AQS中的公平�与�公平�,Condtion.md) +* [Java并�指�9:AQS共享模�与并�工具类的实现](docs/java/concurrency/Java并�指�9:AQS共享模�与并�工具类的实现.md) +* [Java并�指�10:Java 读写� ReentrantReadWriteLock ��分�](docs/java/concurrency/Java并�指�10:Java 读写� ReentrantReadWriteLock ��分�.md) +* [Java并�指�11:解读 Java 阻塞队列 BlockingQueue](docs/java/concurrency/Java并�指�11:解读 Java 阻塞队列 BlockingQueue.md) +* [Java并�指�12:深度解读 java 线程池设计�想���实现](docs/java/concurrency/Java并�指�12:深度解读 java 线程池设计�想���实现.md) +* [Java并�指�13:Java 中的 HashMap 和 ConcurrentHashMap 全解�](docs/java/concurrency/Java并�指�13:Java 中的 HashMap 和 ConcurrentHashMap 全解�.md) +* [Java并�指�14:JUC中常用的Unsafe和Locksupport](docs/java/concurrency/Java并�指�14:JUC中常用的Unsafe和Locksupport.md) +* [Java并�指�15:Fork join并�框架与工作窃�算法剖�](docs/java/concurrency/Java并�指�15:Fork join并�框架与工作窃�算法剖�.md) +* [Java并�编程学习总结](docs/java/concurrency/Java并�编程学习总结.md) ### JVM @@ -196,16 +196,16 @@ todo ### Java网络编程 -* [Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制](docs/java/network-programming/Java网络编程和NIO详解1:JAVA%20中原生的%20socket%20通信机制.md) -* [Java网络编程与NIO详解2:JAVA NIO 一步步构建IO多路�用的请求模型](docs/java/network-programming/Java网络编程与NIO详解2:JAVA%20NIO%20一步步构建IO多路�用的请求模型.md) +* [Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制](docs/java/network-programming/Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制.md) +* [Java网络编程与NIO详解2:JAVA NIO 一步步构建IO多路�用的请求模型](docs/java/network-programming/Java网络编程与NIO详解2:JAVA NIO 一步步构建IO多路�用的请求模型.md) * [Java网络编程和NIO详解3:IO模型与Java网络编程模型](docs/java/network-programming/Java网络编程和NIO详解3:IO模型与Java网络编程模型.md) -* [Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel 和 Selector](docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E4%B8%8ENIO%E8%AF%A6%E8%A7%A34%EF%BC%9A%E6%B5%85%E6%9E%90NIO%E5%8C%85%E4%B8%AD%E7%9A%84Buffer%E3%80%81Channel%20%E5%92%8C%20Selector.md) -* [Java网络编程和NIO详解5:Java �阻塞 IO 和异步 IO](docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E5%92%8CNIO%E8%AF%A6%E8%A7%A35%EF%BC%9AJava%20%E9%9D%9E%E9%98%BB%E5%A1%9E%20IO%20%E5%92%8C%E5%BC%82%E6%AD%A5%20IO.md) +* [Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel 和 Selector](docs/java/network-programming/Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel 和 Selector.md) +* [Java网络编程和NIO详解5:Java �阻塞 IO 和异步 IO](docs/java/network-programming/Java网络编程和NIO详解5:Java �阻塞 IO 和异步 IO.md) * [Java网络编程和NIO详解6:Linux epoll实现原�详解](docs/java/network-programming/Java网络编程和NIO详解6:Linux%20epoll实现原�详解.md) -* [Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原�](docs/java/network-programming/Java网络编程和NIO详解7:浅谈%20Linux%20中NIO%20Selector%20的实现原�.md) -* [Java网络编程与NIO详解8:浅�mmap和Direct Buffer](docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E4%B8%8ENIO%E8%AF%A6%E8%A7%A38%EF%BC%9A%E6%B5%85%E6%9E%90mmap%E5%92%8CDirect%20Buffer.md) +* [Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原�](docs/java/network-programming/Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原�.md) +* [Java网络编程与NIO详解8:浅�mmap和Direct Buffer](docs/java/network-programming/Java网络编程与NIO详解8:浅�mmap和Direct Buffer.md) * [Java网络编程和NIO详解9:基于NIO的网络编程框架Netty](docs/java/network-programming/Java网络编程和NIO详解9:基于NIO的网络编程框架Netty.md) -* [Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型](docs/java/network-programming/Java%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E4%B8%8ENIO%E8%AF%A6%E8%A7%A310%EF%BC%9A%E6%B7%B1%E5%BA%A6%E8%A7%A3%E8%AF%BBTomcat%E4%B8%AD%E7%9A%84NIO%E6%A8%A1%E5%9E%8B.md) +* [Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型](docs/java/network-programming/Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型.md) * [Java网络编程与NIO详解11:Tomcat中的Connector��分�(NIO)](docs/java/network-programming/Java网络编程与NIO详解11:Tomcat中的Connector��分�(NIO).md) ## 计算机基础 @@ -236,7 +236,7 @@ todo ### MySQL * [Mysql原�与实践总结](docs/database/Mysql原�与实践总结.md) * [�新学习Mysql数�库1:无废�MySQL入门](docs/database/�新学习Mysql数�库1:无废�MySQL入门.md) -* [�新学习Mysql数�库2:『浅入浅出�MySQL 和 InnoDB](docs/database/�新学习Mysql数�库2:%20『浅入浅出�MySQL%20和%20InnoDB.md) +* [�新学习Mysql数�库2:『浅入浅出�MySQL 和 InnoDB](docs/database/�新学习Mysql数�库2:『浅入浅出�MySQL 和 InnoDB.md) * [�新学习Mysql数�库3:Mysql存储引擎与数�存储原�](docs/database/�新学习Mysql数�库3:Mysql存储引擎与数�存储原�.md) * [�新学习Mysql数�库4:Mysql索引实现原�和相关数�结构算法](docs/database/�新学习Mysql数�库4:Mysql索引实现原�和相关数�结构算法.md) * [�新学习Mysql数�库5:根�MySQL索引原�进行分�与优化](docs/database/�新学习Mysql数�库5:根�MySQL索引原�进行分�与优化.md) @@ -309,21 +309,24 @@ todo * [�懂分布�技术4:ZAB�议概述与选主�程详解 ](docs/distributed/practice/�懂分布�技术4:ZAB�议概述与选主�程详解.md ) * [�懂分布�技术5:Zookeeper的�置与集群管�实战](docs/distributed/practice/�懂分布�技术5:Zookeeper的�置与集群管�实战.md) * [�懂分布�技术6:Zookeeper典型应用场景�实践 ](docs/distributed/practice/�懂分布�技术6:Zookeeper典型应用场景�实践.md ) -* [�懂分布�技术7:负载�衡概念与主�方案](docs/distributed/practice/�懂分布�技术7:负载�衡概念与主�方案.md) -* [�懂分布�技术8:负载�衡原�剖� ](docs/distributed/practice/�懂分布�技术8:负载�衡原�剖�.md ) -* [�懂分布�技术9:Nginx负载�衡原�与实践 ](docs/distributed/practice/�懂分布�技术9:Nginx负载�衡原�与实践.md) + +[//]: # (* [�懂分布�技术7:负载�衡概念与主�方案](docs/distributed/practice/�懂分布�技术7:负载�衡概念与主�方案.md)) + +[//]: # (* [�懂分布�技术8:负载�衡原�剖� ](docs/distributed/practice/�懂分布�技术8:负载�衡原�剖�.md )) + +[//]: # (* [�懂分布�技术9:Nginx负载�衡原�与实践 ](docs/distributed/practice/�懂分布�技术9:Nginx负载�衡原�与实践.md)) * [�懂分布�技术10:LVS实现负载�衡的原�与实践 ](docs/distributed/practice/�懂分布�技术10:LVS实现负载�衡的原�与实践.md ) * [�懂分布�技术11:分布�session解决方案与一致性hash](docs/distributed/practice/�懂分布�技术11:分布�session解决方案与一致性hash.md) * [�懂分布�技术12:分布�ID生�方案 ](docs/distributed/practice/�懂分布�技术12:分布�ID生�方案.md ) * [�懂分布�技术13:缓存的那些事](docs/distributed/practice/�懂分布�技术13:缓存的那些事.md) -* [�懂分布�技术14:Spring Boot使用注解集�Redis缓存](docs/distributed/practice/�懂分布�技术14:Spring%20Boot使用注解集�Redis缓存.md) +* [�懂分布�技术14:Spring Boot使用注解集�Redis缓存](docs/distributed/practice/�懂分布�技术14:Spring Boot使用注解集�Redis缓存.md) * [�懂分布�技术15:缓存更新的套路 ](docs/distributed/practice/�懂分布�技术15:缓存更新的套路.md ) * [�懂分布�技术16:浅谈分布��的几�方案 ](docs/distributed/practice/�懂分布�技术16:浅谈分布��的几�方案.md ) * [�懂分布�技术17:浅�分布�事务 ](docs/distributed/practice/�懂分布�技术17:浅�分布�事务.md ) * [�懂分布�技术18:分布�事务常用解决方案 ](docs/distributed/practice/�懂分布�技术18:分布�事务常用解决方案.md ) * [�懂分布�技术19:使用RocketMQ事务消�解决分布�事务 ](docs/distributed/practice/�懂分布�技术19:使用RocketMQ事务消�解决分布�事务.md ) * [�懂分布�技术20:消�队列因何而生](docs/distributed/practice/�懂分布�技术20:消�队列因何而生.md) -* [�懂分布�技术21:浅谈分布�消�技术 Kafka ](docs/distributed/practice/�懂分布�技术21:浅谈分布�消�技术%20Kafka.md ) +* [�懂分布�技术21:浅谈分布�消�技术 Kafka ](docs/distributed/practice/�懂分布�技术21:浅谈分布�消�技术 Kafka.md ) * [分布��论总结](docs/distributed/分布�技术实践总结.md) ## �试指� diff --git "a/docs/algorithms/\345\211\221\346\214\207offer.md" "b/docs/cs/algorithms/\345\211\221\346\214\207offer.md" similarity index 100% rename from "docs/algorithms/\345\211\221\346\214\207offer.md" rename to "docs/cs/algorithms/\345\211\221\346\214\207offer.md" diff --git "a/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/cs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md" similarity index 100% rename from "docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md" rename to "docs/cs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\255\246\344\271\240\346\200\273\347\273\223.md" diff --git "a/docs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" similarity index 100% rename from "docs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" rename to "docs/cs/operating-system/Linux\345\206\205\346\240\270\344\270\216\345\237\272\347\241\200\345\221\275\344\273\244\345\255\246\344\271\240\346\200\273\347\273\223.md" diff --git "a/docs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/cs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md" similarity index 100% rename from "docs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md" rename to "docs/cs/operating-system/\346\223\215\344\275\234\347\263\273\347\273\237\345\255\246\344\271\240\346\200\273\347\273\223.md" diff --git "a/docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2201\357\274\232SpringMVC\346\246\202\350\277\260.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2201\357\274\232SpringMVC\346\246\202\350\277\260.md" similarity index 100% rename from "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2201\357\274\232SpringMVC\346\246\202\350\277\260.md" rename to "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2201\357\274\232SpringMVC\346\246\202\350\277\260.md" diff --git "a/docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2202\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2202\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" similarity index 100% rename from "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2202\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" rename to "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2202\357\274\232SpringMVC\350\256\276\350\256\241\347\220\206\345\277\265\344\270\216DispatcherServlet.md" diff --git "a/docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2203\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2203\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" similarity index 100% rename from "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2203\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" rename to "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2203\357\274\232DispatcherServlet\347\232\204\345\210\235\345\247\213\345\214\226\344\270\216\350\257\267\346\261\202\350\275\254\345\217\221.md" diff --git "a/docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2204\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2204\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" similarity index 100% rename from "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2204\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" rename to "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2204\357\274\232DispatcherServlet\345\246\202\344\275\225\346\211\276\345\210\260\346\255\243\347\241\256\347\232\204Controller.md" diff --git "a/docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2206\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2206\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" similarity index 100% rename from "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2206\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" rename to "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\210\206\346\236\2206\357\274\232SpringMVC\347\232\204\350\247\206\345\233\276\350\247\243\346\236\220\345\216\237\347\220\206.md" diff --git "a/docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\211\226\346\236\2205\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" "b/docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\211\226\346\236\2205\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" similarity index 100% rename from "docs/java-web/SSM/SpringMVC\346\272\220\347\240\201\345\211\226\346\236\2205\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" rename to "docs/java-web/springMVC/SpringMVC\346\272\220\347\240\201\345\211\226\346\236\2205\357\274\232\346\266\210\346\201\257\350\275\254\346\215\242\345\231\250HttpMessageConverter\344\270\216@ResponseBody\346\263\250\350\247\243.md" diff --git "a/docs/java-web/\346\267\261\345\205\245JavaWeb\346\212\200\346\234\257\344\270\226\347\225\21415\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\21415\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md" similarity index 100% rename from "docs/java-web/\346\267\261\345\205\245JavaWeb\346\212\200\346\234\257\344\270\226\347\225\21415\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md" rename to "docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\21415\357\274\232\346\267\261\345\205\245\346\265\205\345\207\272Mybatis\345\237\272\346\234\254\345\216\237\347\220\206.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java \350\257\273\345\206\231\351\224\201 ReentrantReadWriteLock \346\272\220\347\240\201\345\210\206\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java \350\257\273\345\206\231\351\224\201 ReentrantReadWriteLock \346\272\220\347\240\201\345\210\206\346\236\220.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java \350\257\273\345\206\231\351\224\201 ReentrantReadWriteLock \346\272\220\347\240\201\345\210\206\346\236\220.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java \350\257\273\345\206\231\351\224\201 ReentrantReadWriteLock \346\272\220\347\240\201\345\210\206\346\236\220.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273 Java \351\230\273\345\241\236\351\230\237\345\210\227 BlockingQueue.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273 Java \351\230\273\345\241\236\351\230\237\345\210\227 BlockingQueue.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273 Java \351\230\273\345\241\236\351\230\237\345\210\227 BlockingQueue.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273 Java \351\230\273\345\241\236\351\230\237\345\210\227 BlockingQueue.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java \344\270\255\347\232\204 HashMap \345\222\214 ConcurrentHashMap \345\205\250\350\247\243\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java \344\270\255\347\232\204 HashMap \345\222\214 ConcurrentHashMap \345\205\250\350\247\243\346\236\220.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java \344\270\255\347\232\204 HashMap \345\222\214 ConcurrentHashMap \345\205\250\350\247\243\346\236\220.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java \344\270\255\347\232\204 HashMap \345\222\214 ConcurrentHashMap \345\205\250\350\247\243\346\236\220.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22714\357\274\232JUC\344\270\255\345\270\270\347\224\250\347\232\204Unsafe\345\222\214Locksupport.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22714\357\274\232JUC\344\270\255\345\270\270\347\224\250\347\232\204Unsafe\345\222\214Locksupport.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\22714\357\274\232JUC\344\270\255\345\270\270\347\224\250\347\232\204Unsafe\345\222\214Locksupport.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22714\357\274\232JUC\344\270\255\345\270\270\347\224\250\347\232\204Unsafe\345\222\214Locksupport.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\347\274\226\347\250\213\346\214\207\345\215\22715\357\274\232Fork join\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22715\357\274\232Fork join\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\347\274\226\347\250\213\346\214\207\345\215\22715\357\274\232Fork join\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22715\357\274\232Fork join\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2271\357\274\232\345\271\266\345\217\221\345\237\272\347\241\200\344\270\216Java\345\244\232\347\272\277\347\250\213.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2271\357\274\232\345\271\266\345\217\221\345\237\272\347\241\200\344\270\216Java\345\244\232\347\272\277\347\250\213.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2271\357\274\232\345\271\266\345\217\221\345\237\272\347\241\200\344\270\216Java\345\244\232\347\272\277\347\250\213.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2271\357\274\232\345\271\266\345\217\221\345\237\272\347\241\200\344\270\216Java\345\244\232\347\272\277\347\250\213.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2272\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2272\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2272\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2272\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243Java\345\206\205\345\255\230\346\250\241\345\236\213JMM.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2273\357\274\232\345\271\266\345\217\221\344\270\211\345\244\247\351\227\256\351\242\230\344\270\216volatile\345\205\263\351\224\256\345\255\227\357\274\214CAS\346\223\215\344\275\234.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201 Lock\345\222\214synchronized.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201 Lock\345\222\214synchronized.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201 Lock\345\222\214synchronized.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201 Lock\345\222\214synchronized.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2275\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2275\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2275\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2275\357\274\232JMM\344\270\255\347\232\204final\345\205\263\351\224\256\345\255\227\350\247\243\346\236\220.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2276\357\274\232Java\345\206\205\345\255\230\346\250\241\345\236\213JMM\346\200\273\347\273\223.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2276\357\274\232Java\345\206\205\345\255\230\346\250\241\345\236\213JMM\346\200\273\347\273\223.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2276\357\274\232Java\345\206\205\345\255\230\346\250\241\345\236\213JMM\346\200\273\347\273\223.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2276\357\274\232Java\345\206\205\345\255\230\346\250\241\345\236\213JMM\346\200\273\347\273\223.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2277\357\274\232JUC\347\232\204\346\240\270\345\277\203\347\261\273AQS\350\257\246\350\247\243.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2277\357\274\232JUC\347\232\204\346\240\270\345\277\203\347\261\273AQS\350\257\246\350\247\243.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2277\357\274\232JUC\347\232\204\346\240\270\345\277\203\347\261\273AQS\350\257\246\350\247\243.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2277\357\274\232JUC\347\232\204\346\240\270\345\277\203\347\261\273AQS\350\257\246\350\247\243.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2278\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2278\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2278\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2278\357\274\232AQS\344\270\255\347\232\204\345\205\254\345\271\263\351\224\201\344\270\216\351\235\236\345\205\254\345\271\263\351\224\201\357\274\214Condtion.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2279\357\274\232AQS\345\205\261\344\272\253\346\250\241\345\274\217\344\270\216\345\271\266\345\217\221\345\267\245\345\205\267\347\261\273\347\232\204\345\256\236\347\216\260.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2279\357\274\232AQS\345\205\261\344\272\253\346\250\241\345\274\217\344\270\216\345\271\266\345\217\221\345\267\245\345\205\267\347\261\273\347\232\204\345\256\236\347\216\260.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\214\207\345\215\2279\357\274\232AQS\345\205\261\344\272\253\346\250\241\345\274\217\344\270\216\345\271\266\345\217\221\345\267\245\345\205\267\347\261\273\347\232\204\345\256\236\347\216\260.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2279\357\274\232AQS\345\205\261\344\272\253\346\250\241\345\274\217\344\270\216\345\271\266\345\217\221\345\267\245\345\205\267\347\261\273\347\232\204\345\256\236\347\216\260.md" diff --git "a/docs/java/currency/Java\345\271\266\345\217\221\346\200\273\347\273\223.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\255\246\344\271\240\346\200\273\347\273\223.md" similarity index 100% rename from "docs/java/currency/Java\345\271\266\345\217\221\346\200\273\347\273\223.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\255\246\344\271\240\346\200\273\347\273\223.md" diff --git "a/\346\234\200\347\273\210\346\225\210\346\236\234.md" "b/\346\234\200\347\273\210\346\225\210\346\236\234.md" index dc34623..0cf3d7d 100644 --- "a/\346\234\200\347\273\210\346\225\210\346\236\234.md" +++ "b/\346\234\200\347\273\210\346\225\210\346\236\234.md" @@ -52,7 +52,7 @@ ### 并� -* [1 ��对象基础](docs/java/currency/Java并�总结.md) +* [1 ��对象基础](docs/java/concurrency/Java并�编程学习总结.md) ### JVM From 2831f9c502018b322da022c42558248468326e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Mon, 3 Apr 2023 12:24:40 +0800 Subject: [PATCH 21/98] modify catalog --- ReadMe.md | 38 +++++++++---------- ...272\343\200\217MySQL\345\222\214InnoDB.md" | 0 ...6\210\220Redis\347\274\223\345\255\230.md" | 0 ...6\201\257\346\212\200\346\234\257Kafka.md" | 0 ...20\347\240\201\345\210\206\346\236\220.md" | 0 ...6\351\230\237\345\210\227BlockingQueue.md" | 0 ...20\347\240\201\345\256\236\347\216\260.md" | 0 ...ap\345\205\250\350\247\243\346\236\220.md" | 0 ...27\346\263\225\345\211\226\346\236\220.md" | 0 ...51\224\201Lock\345\222\214synchronized.md" | 0 ...32\344\277\241\346\234\272\345\210\266.md" | 0 ...67\346\261\202\346\250\241\345\236\213.md" | 0 ...26\347\250\213\346\250\241\345\236\213.md" | 0 ...343\200\201Channel\345\222\214Selector.md" | 0 ...\345\222\214\345\274\202\346\255\245IO.md" | 0 ...37\347\220\206\350\257\246\350\247\243.md" | 0 ...36\347\216\260\345\216\237\347\220\206.md" | 0 ...46\236\220mmap\345\222\214DirectBuffer.md" | 0 ...7\250\213\346\241\206\346\236\266Netty.md" | 0 19 files changed, 19 insertions(+), 19 deletions(-) rename "docs/database/\351\207\215\346\226\260\345\255\246\344\271\240Mysql\346\225\260\346\215\256\345\272\2232\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL \345\222\214 InnoDB.md" => "docs/database/\351\207\215\346\226\260\345\255\246\344\271\240Mysql\346\225\260\346\215\256\345\272\2232\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL\345\222\214InnoDB.md" (100%) rename "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232Spring Boot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232SpringBoot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" (100%) rename "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257 Kafka.md" => "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md" (100%) rename "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java \350\257\273\345\206\231\351\224\201 ReentrantReadWriteLock \346\272\220\347\240\201\345\210\206\346\236\220.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java\350\257\273\345\206\231\351\224\201ReentrantReadWriteLock\346\272\220\347\240\201\345\210\206\346\236\220.md" (100%) rename "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273 Java \351\230\273\345\241\236\351\230\237\345\210\227 BlockingQueue.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273Java\351\230\273\345\241\236\351\230\237\345\210\227BlockingQueue.md" (100%) rename "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Java\347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" (100%) rename "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java \344\270\255\347\232\204 HashMap \345\222\214 ConcurrentHashMap \345\205\250\350\247\243\346\236\220.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java\344\270\255\347\232\204HashMap\345\222\214ConcurrentHashMap\345\205\250\350\247\243\346\236\220.md" (100%) rename "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22715\357\274\232Fork join\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22715\357\274\232ForkJoin\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" (100%) rename "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201 Lock\345\222\214synchronized.md" => "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201Lock\345\222\214synchronized.md" (100%) rename "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2431\357\274\232JAVA \344\270\255\345\216\237\347\224\237\347\232\204 socket \351\200\232\344\277\241\346\234\272\345\210\266.md" => "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2431\357\274\232JAVA\344\270\255\345\216\237\347\224\237\347\232\204socket\351\200\232\344\277\241\346\234\272\345\210\266.md" (100%) rename "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2432\357\274\232JAVA NIO \344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md" => "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2432\357\274\232JavaNIO\344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md" (100%) rename "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2433\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md" => "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2433\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md" (100%) rename "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2434\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel \345\222\214 Selector.md" => "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2434\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel\345\222\214Selector.md" (100%) rename "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2435\357\274\232Java \351\235\236\351\230\273\345\241\236 IO \345\222\214\345\274\202\346\255\245 IO.md" => "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2435\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md" (100%) rename "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2436\357\274\232Linux epoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" => "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2436\357\274\232LinuxEpoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" (100%) rename "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2437\357\274\232\346\265\205\350\260\210 Linux \344\270\255NIO Selector \347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md" => "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2437\357\274\232\346\265\205\350\260\210Linux\344\270\255Selector\347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md" (100%) rename "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2438\357\274\232\346\265\205\346\236\220mmap\345\222\214Direct Buffer.md" => "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2438\357\274\232\346\265\205\346\236\220mmap\345\222\214DirectBuffer.md" (100%) rename "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2439\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md" => "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2439\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md" (100%) diff --git a/ReadMe.md b/ReadMe.md index f63c941..54c9ba8 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -162,18 +162,18 @@ todo * [Java并�指�1:并�基础与Java多线程](docs/java/concurrency/Java并�指�1:并�基础与Java多线程.md) * [Java并�指�2:深入�解Java内存模型JMM](docs/java/concurrency/Java并�指�2:深入�解Java内存模型JMM.md) * [Java并�指�3:并�三大问题与volatile关键字,CAS�作](docs/java/concurrency/Java并�指�3:并�三大问题与volatile关键字,CAS�作.md) -* [Java并�指�4:Java中的� Lock和synchronized](docs/java/concurrency/Java并�指�4:Java中的�%20Lock和synchronized.md) +* [Java并�指�4:Java中的�Lock和synchronized](docs/java/concurrency/Java并�指�4:Java中的�Lock和synchronized.md) * [Java并�指�5:JMM中的final关键字解�](docs/java/concurrency/Java并�指�5:JMM中的final关键字解�.md) * [Java并�指�6:Java内存模型JMM总结](docs/java/concurrency/Java并�指�6:Java内存模型JMM总结.md) * [Java并�指�7:JUC的核心类AQS详解](docs/java/concurrency/Java并�指�7:JUC的核心类AQS详解.md) * [Java并�指�8:AQS中的公平�与�公平�,Condtion](docs/java/concurrency/Java并�指�8:AQS中的公平�与�公平�,Condtion.md) * [Java并�指�9:AQS共享模�与并�工具类的实现](docs/java/concurrency/Java并�指�9:AQS共享模�与并�工具类的实现.md) -* [Java并�指�10:Java 读写� ReentrantReadWriteLock ��分�](docs/java/concurrency/Java并�指�10:Java 读写� ReentrantReadWriteLock ��分�.md) -* [Java并�指�11:解读 Java 阻塞队列 BlockingQueue](docs/java/concurrency/Java并�指�11:解读 Java 阻塞队列 BlockingQueue.md) -* [Java并�指�12:深度解读 java 线程池设计�想���实现](docs/java/concurrency/Java并�指�12:深度解读 java 线程池设计�想���实现.md) -* [Java并�指�13:Java 中的 HashMap 和 ConcurrentHashMap 全解�](docs/java/concurrency/Java并�指�13:Java 中的 HashMap 和 ConcurrentHashMap 全解�.md) +* [Java并�指�10:Java读写�ReentrantReadWriteLock��分�](docs/java/concurrency/Java并�指�10:Java读写�ReentrantReadWriteLock��分�.md) +* [Java并�指�11:解读Java阻塞队列BlockingQueue](docs/java/concurrency/Java并�指�11:解读Java阻塞队列BlockingQueue.md) +* [Java并�指�12:深度解读java线程池设计�想���实现](docs/java/concurrency/Java并�指�12:深度解读Java线程池设计�想���实现.md) +* [Java并�指�13:Java中的HashMap和ConcurrentHashMap全解�](docs/java/concurrency/Java并�指�13:Java中的HashMap和ConcurrentHashMap全解�.md) * [Java并�指�14:JUC中常用的Unsafe和Locksupport](docs/java/concurrency/Java并�指�14:JUC中常用的Unsafe和Locksupport.md) -* [Java并�指�15:Fork join并�框架与工作窃�算法剖�](docs/java/concurrency/Java并�指�15:Fork join并�框架与工作窃�算法剖�.md) +* [Java并�指�15:ForkJoin并�框架与工作窃�算法剖�](docs/java/concurrency/Java并�指�15:ForkJoin并�框架与工作窃�算法剖�.md) * [Java并�编程学习总结](docs/java/concurrency/Java并�编程学习总结.md) ### JVM @@ -196,16 +196,16 @@ todo ### Java网络编程 -* [Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制](docs/java/network-programming/Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制.md) -* [Java网络编程与NIO详解2:JAVA NIO 一步步构建IO多路�用的请求模型](docs/java/network-programming/Java网络编程与NIO详解2:JAVA NIO 一步步构建IO多路�用的请求模型.md) -* [Java网络编程和NIO详解3:IO模型与Java网络编程模型](docs/java/network-programming/Java网络编程和NIO详解3:IO模型与Java网络编程模型.md) -* [Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel 和 Selector](docs/java/network-programming/Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel 和 Selector.md) -* [Java网络编程和NIO详解5:Java �阻塞 IO 和异步 IO](docs/java/network-programming/Java网络编程和NIO详解5:Java �阻塞 IO 和异步 IO.md) -* [Java网络编程和NIO详解6:Linux epoll实现原�详解](docs/java/network-programming/Java网络编程和NIO详解6:Linux%20epoll实现原�详解.md) -* [Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原�](docs/java/network-programming/Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原�.md) -* [Java网络编程与NIO详解8:浅�mmap和Direct Buffer](docs/java/network-programming/Java网络编程与NIO详解8:浅�mmap和Direct Buffer.md) -* [Java网络编程和NIO详解9:基于NIO的网络编程框架Netty](docs/java/network-programming/Java网络编程和NIO详解9:基于NIO的网络编程框架Netty.md) -* [Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型](docs/java/network-programming/Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型.md) +* [Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制](docs/java/network-programming/Java网络编程与NIO详解1:JAVA中原生的socket通信机制.md) +* [Java网络编程与NIO详解2:JAVA NIO 一步步构建IO多路�用的请求模型](docs/java/network-programming/Java网络编程与NIO详解2:JavaNIO一步步构建IO多路�用的请求模型.md) +* [Java网络编程和NIO详解3:IO模型与Java网络编程模型](docs/java/network-programming/Java网络编程与NIO详解3:IO模型与Java网络编程模型.md) +* [Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel 和 Selector](docs/java/network-programming/Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel和Selector.md) +* [Java网络编程和NIO详解5:Java �阻塞 IO 和异步 IO](docs/java/network-programming/Java网络编程与NIO详解5:Java�阻塞IO和异步IO.md) +* [Java网络编程与NIO详解6:LinuxEpoll实现原�详解](docs/java/network-programming/Java网络编程与NIO详解6:LinuxEpoll实现原�详解.md.md) +* [Java网络编程与NIO详解7:浅谈Linux中Selector的实现原�](docs/java/network-programming/Java网络编程与NIO详解7:浅谈Linux中Selector的实现原�.md) +* [Java网络编程与NIO详解8:浅�mmap和DirectBuffer](docs/java/network-programming/Java网络编程与NIO详解8:浅�mmap和DirectBuffer.md) +* [Java网络编程与NIO详解9:基于NIO的网络编程框架Netty](docs/java/network-programming/Java网络编程与NIO详解9:基于NIO的网络编程框架Netty.md) +* [Java网络编程与NIO详解10:Java网络编程与NIO详解10](docs/java/network-programming/Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型.md) * [Java网络编程与NIO详解11:Tomcat中的Connector��分�(NIO)](docs/java/network-programming/Java网络编程与NIO详解11:Tomcat中的Connector��分�(NIO).md) ## 计算机基础 @@ -236,7 +236,7 @@ todo ### MySQL * [Mysql原�与实践总结](docs/database/Mysql原�与实践总结.md) * [�新学习Mysql数�库1:无废�MySQL入门](docs/database/�新学习Mysql数�库1:无废�MySQL入门.md) -* [�新学习Mysql数�库2:『浅入浅出�MySQL 和 InnoDB](docs/database/�新学习Mysql数�库2:『浅入浅出�MySQL 和 InnoDB.md) +* [�新学习Mysql数�库2:『浅入浅出�MySQL和InnoDB](docs/database/�新学习Mysql数�库2:『浅入浅出�MySQL和InnoDB.md) * [�新学习Mysql数�库3:Mysql存储引擎与数�存储原�](docs/database/�新学习Mysql数�库3:Mysql存储引擎与数�存储原�.md) * [�新学习Mysql数�库4:Mysql索引实现原�和相关数�结构算法](docs/database/�新学习Mysql数�库4:Mysql索引实现原�和相关数�结构算法.md) * [�新学习Mysql数�库5:根�MySQL索引原�进行分�与优化](docs/database/�新学习Mysql数�库5:根�MySQL索引原�进行分�与优化.md) @@ -319,14 +319,14 @@ todo * [�懂分布�技术11:分布�session解决方案与一致性hash](docs/distributed/practice/�懂分布�技术11:分布�session解决方案与一致性hash.md) * [�懂分布�技术12:分布�ID生�方案 ](docs/distributed/practice/�懂分布�技术12:分布�ID生�方案.md ) * [�懂分布�技术13:缓存的那些事](docs/distributed/practice/�懂分布�技术13:缓存的那些事.md) -* [�懂分布�技术14:Spring Boot使用注解集�Redis缓存](docs/distributed/practice/�懂分布�技术14:Spring Boot使用注解集�Redis缓存.md) +* [�懂分布�技术14:SpringBoot使用注解集�Redis缓存](docs/distributed/practice/�懂分布�技术14:SpringBoot使用注解集�Redis缓存.md) * [�懂分布�技术15:缓存更新的套路 ](docs/distributed/practice/�懂分布�技术15:缓存更新的套路.md ) * [�懂分布�技术16:浅谈分布��的几�方案 ](docs/distributed/practice/�懂分布�技术16:浅谈分布��的几�方案.md ) * [�懂分布�技术17:浅�分布�事务 ](docs/distributed/practice/�懂分布�技术17:浅�分布�事务.md ) * [�懂分布�技术18:分布�事务常用解决方案 ](docs/distributed/practice/�懂分布�技术18:分布�事务常用解决方案.md ) * [�懂分布�技术19:使用RocketMQ事务消�解决分布�事务 ](docs/distributed/practice/�懂分布�技术19:使用RocketMQ事务消�解决分布�事务.md ) * [�懂分布�技术20:消�队列因何而生](docs/distributed/practice/�懂分布�技术20:消�队列因何而生.md) -* [�懂分布�技术21:浅谈分布�消�技术 Kafka ](docs/distributed/practice/�懂分布�技术21:浅谈分布�消�技术 Kafka.md ) +* [�懂分布�技术21:浅谈分布�消�技术Kafka](docs/distributed/practice/�懂分布�技术21:浅谈分布�消�技术Kafka.md ) * [分布��论总结](docs/distributed/分布�技术实践总结.md) ## �试指� diff --git "a/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240Mysql\346\225\260\346\215\256\345\272\2232\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL \345\222\214 InnoDB.md" "b/docs/database/\351\207\215\346\226\260\345\255\246\344\271\240Mysql\346\225\260\346\215\256\345\272\2232\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL\345\222\214InnoDB.md" similarity index 100% rename from "docs/database/\351\207\215\346\226\260\345\255\246\344\271\240Mysql\346\225\260\346\215\256\345\272\2232\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL \345\222\214 InnoDB.md" rename to "docs/database/\351\207\215\346\226\260\345\255\246\344\271\240Mysql\346\225\260\346\215\256\345\272\2232\357\274\232\343\200\216\346\265\205\345\205\245\346\265\205\345\207\272\343\200\217MySQL\345\222\214InnoDB.md" diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232Spring Boot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232SpringBoot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" similarity index 100% rename from "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232Spring Boot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25714\357\274\232SpringBoot\344\275\277\347\224\250\346\263\250\350\247\243\351\233\206\346\210\220Redis\347\274\223\345\255\230.md" diff --git "a/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257 Kafka.md" "b/docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md" similarity index 100% rename from "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257 Kafka.md" rename to "docs/distributed/practice/\346\220\236\346\207\202\345\210\206\345\270\203\345\274\217\346\212\200\346\234\25721\357\274\232\346\265\205\350\260\210\345\210\206\345\270\203\345\274\217\346\266\210\346\201\257\346\212\200\346\234\257Kafka.md" diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java \350\257\273\345\206\231\351\224\201 ReentrantReadWriteLock \346\272\220\347\240\201\345\210\206\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java\350\257\273\345\206\231\351\224\201ReentrantReadWriteLock\346\272\220\347\240\201\345\210\206\346\236\220.md" similarity index 100% rename from "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java \350\257\273\345\206\231\351\224\201 ReentrantReadWriteLock \346\272\220\347\240\201\345\210\206\346\236\220.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22710\357\274\232Java\350\257\273\345\206\231\351\224\201ReentrantReadWriteLock\346\272\220\347\240\201\345\210\206\346\236\220.md" diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273 Java \351\230\273\345\241\236\351\230\237\345\210\227 BlockingQueue.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273Java\351\230\273\345\241\236\351\230\237\345\210\227BlockingQueue.md" similarity index 100% rename from "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273 Java \351\230\273\345\241\236\351\230\237\345\210\227 BlockingQueue.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22711\357\274\232\350\247\243\350\257\273Java\351\230\273\345\241\236\351\230\237\345\210\227BlockingQueue.md" diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Java\347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" similarity index 100% rename from "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273 java \347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22712\357\274\232\346\267\261\345\272\246\350\247\243\350\257\273Java\347\272\277\347\250\213\346\261\240\350\256\276\350\256\241\346\200\235\346\203\263\345\217\212\346\272\220\347\240\201\345\256\236\347\216\260.md" diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java \344\270\255\347\232\204 HashMap \345\222\214 ConcurrentHashMap \345\205\250\350\247\243\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java\344\270\255\347\232\204HashMap\345\222\214ConcurrentHashMap\345\205\250\350\247\243\346\236\220.md" similarity index 100% rename from "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java \344\270\255\347\232\204 HashMap \345\222\214 ConcurrentHashMap \345\205\250\350\247\243\346\236\220.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22713\357\274\232Java\344\270\255\347\232\204HashMap\345\222\214ConcurrentHashMap\345\205\250\350\247\243\346\236\220.md" diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22715\357\274\232Fork join\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22715\357\274\232ForkJoin\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" similarity index 100% rename from "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22715\357\274\232Fork join\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\22715\357\274\232ForkJoin\345\271\266\345\217\221\346\241\206\346\236\266\344\270\216\345\267\245\344\275\234\347\252\203\345\217\226\347\256\227\346\263\225\345\211\226\346\236\220.md" diff --git "a/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201 Lock\345\222\214synchronized.md" "b/docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201Lock\345\222\214synchronized.md" similarity index 100% rename from "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201 Lock\345\222\214synchronized.md" rename to "docs/java/concurrency/Java\345\271\266\345\217\221\346\214\207\345\215\2274\357\274\232Java\344\270\255\347\232\204\351\224\201Lock\345\222\214synchronized.md" diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2431\357\274\232JAVA \344\270\255\345\216\237\347\224\237\347\232\204 socket \351\200\232\344\277\241\346\234\272\345\210\266.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2431\357\274\232JAVA\344\270\255\345\216\237\347\224\237\347\232\204socket\351\200\232\344\277\241\346\234\272\345\210\266.md" similarity index 100% rename from "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2431\357\274\232JAVA \344\270\255\345\216\237\347\224\237\347\232\204 socket \351\200\232\344\277\241\346\234\272\345\210\266.md" rename to "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2431\357\274\232JAVA\344\270\255\345\216\237\347\224\237\347\232\204socket\351\200\232\344\277\241\346\234\272\345\210\266.md" diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2432\357\274\232JAVA NIO \344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2432\357\274\232JavaNIO\344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md" similarity index 100% rename from "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2432\357\274\232JAVA NIO \344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md" rename to "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2432\357\274\232JavaNIO\344\270\200\346\255\245\346\255\245\346\236\204\345\273\272IO\345\244\232\350\267\257\345\244\215\347\224\250\347\232\204\350\257\267\346\261\202\346\250\241\345\236\213.md" diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2433\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2433\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md" similarity index 100% rename from "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2433\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md" rename to "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2433\357\274\232IO\346\250\241\345\236\213\344\270\216Java\347\275\221\347\273\234\347\274\226\347\250\213\346\250\241\345\236\213.md" diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2434\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel \345\222\214 Selector.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2434\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel\345\222\214Selector.md" similarity index 100% rename from "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2434\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel \345\222\214 Selector.md" rename to "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2434\357\274\232\346\265\205\346\236\220NIO\345\214\205\344\270\255\347\232\204Buffer\343\200\201Channel\345\222\214Selector.md" diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2435\357\274\232Java \351\235\236\351\230\273\345\241\236 IO \345\222\214\345\274\202\346\255\245 IO.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2435\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md" similarity index 100% rename from "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2435\357\274\232Java \351\235\236\351\230\273\345\241\236 IO \345\222\214\345\274\202\346\255\245 IO.md" rename to "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2435\357\274\232Java\351\235\236\351\230\273\345\241\236IO\345\222\214\345\274\202\346\255\245IO.md" diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2436\357\274\232Linux epoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2436\357\274\232LinuxEpoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" similarity index 100% rename from "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2436\357\274\232Linux epoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" rename to "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2436\357\274\232LinuxEpoll\345\256\236\347\216\260\345\216\237\347\220\206\350\257\246\350\247\243.md" diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2437\357\274\232\346\265\205\350\260\210 Linux \344\270\255NIO Selector \347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2437\357\274\232\346\265\205\350\260\210Linux\344\270\255Selector\347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md" similarity index 100% rename from "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2437\357\274\232\346\265\205\350\260\210 Linux \344\270\255NIO Selector \347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md" rename to "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2437\357\274\232\346\265\205\350\260\210Linux\344\270\255Selector\347\232\204\345\256\236\347\216\260\345\216\237\347\220\206.md" diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2438\357\274\232\346\265\205\346\236\220mmap\345\222\214Direct Buffer.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2438\357\274\232\346\265\205\346\236\220mmap\345\222\214DirectBuffer.md" similarity index 100% rename from "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2438\357\274\232\346\265\205\346\236\220mmap\345\222\214Direct Buffer.md" rename to "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2438\357\274\232\346\265\205\346\236\220mmap\345\222\214DirectBuffer.md" diff --git "a/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2439\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md" "b/docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2439\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md" similarity index 100% rename from "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\345\222\214NIO\350\257\246\350\247\2439\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md" rename to "docs/java/network-programming/Java\347\275\221\347\273\234\347\274\226\347\250\213\344\270\216NIO\350\257\246\350\247\2439\357\274\232\345\237\272\344\272\216NIO\347\232\204\347\275\221\347\273\234\347\274\226\347\250\213\346\241\206\346\236\266Netty.md" From cfcc5bd7e56daccf03c1929491bf2735e907baac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Mon, 3 Apr 2023 20:28:04 +0800 Subject: [PATCH 22/98] use oss picgo --- ReadMe.md | 30 +- ...70\345\277\203\346\265\201\347\250\213.md" | 0 ...40\350\275\275\350\277\207\347\250\213.md" | 0 ...4\232SpringAOP\346\246\202\350\277\260.md" | 0 ...45\350\257\206\346\270\205\345\215\225.md" | 0 ...37\347\220\206\350\257\246\350\247\243.md" | 0 ...71\350\261\241\345\237\272\347\241\200.md" | 124 +-- ...60\346\215\256\347\261\273\345\236\213.md" | 169 ++-- ...14\345\214\205\350\243\205\347\261\273.md" | 923 +++++++++--------- ...56\345\255\227\347\211\271\346\200\247.md" | 54 +- ...va\347\261\273\345\222\214\345\214\205.md" | 263 +++-- ...17\347\232\204\347\247\230\345\257\206.md" | 422 ++++---- ...43\346\236\220\345\256\236\350\267\265.md" | 0 ...14\346\234\237\344\274\230\345\214\226.md" | 0 14 files changed, 918 insertions(+), 1067 deletions(-) rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2202\357\274\232\345\210\235\346\216\242Spring IOC\346\240\270\345\277\203\346\265\201\347\250\213.md" => "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2202\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md" (100%) rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2203\357\274\232Spring IOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" => "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2203\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" (100%) rename "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2206\357\274\232Spring AOP\346\246\202\350\277\260.md" => "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2206\357\274\232SpringAOP\346\246\202\350\277\260.md" (100%) rename "docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275Spring Boot\347\237\245\350\257\206\346\270\205\345\215\225.md" => "docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" (100%) rename "docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\2144\357\274\232Servlet \345\267\245\344\275\234\345\216\237\347\220\206\350\257\246\350\247\243.md" => "docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\2144\357\274\232Servlet\345\267\245\344\275\234\345\216\237\347\220\206\350\257\246\350\247\243.md" (100%) rename "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2724\357\274\232Java class\344\273\213\347\273\215\344\270\216\350\247\243\346\236\220\345\256\236\350\267\265.md" => "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2724\357\274\232Java\345\255\227\350\212\202\347\240\201\344\273\213\347\273\215\344\270\216\350\247\243\346\236\220\345\256\236\350\267\265.md" (100%) rename "docs/java/jvm/\346\267\261\345\205\245\344\272\206\350\247\243JVM\350\231\232\346\213\237\346\234\2728\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md" => "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2728\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md" (100%) diff --git a/ReadMe.md b/ReadMe.md index 54c9ba8..9e8a447 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -67,6 +67,7 @@ * [2�Java基本数�类型](docs/java/basic/2�Java基本数�类型.md) * [3�string和包装类](docs/java/basic/3�string和包装类.md) * [4�final关键字特性](docs/java/basic/4�final关键字特性.md) + * [5�Java类和包](docs/java/basic/5�Java类和包.md) * [6�抽象类和接�](docs/java/basic/6�抽象类和接�.md) * [7�代��和代�执行顺�](docs/java/basic/7�代��和代�执行顺�.md) @@ -112,7 +113,7 @@ * [走进JavaWeb技术世界1:JavaWeb的由�和基础知识](docs/java-web/走进JavaWeb技术世界1:JavaWeb的由�和基础知识.md) * [走进JavaWeb技术世界2:JSP与Servlet的曾�与现在](docs/java-web/走进JavaWeb技术世界2:JSP与Servlet的曾�与现在.md) * [走进JavaWeb技术世界3:JDBC的进化与连接池技术](docs/java-web/走进JavaWeb技术世界3:JDBC的进化与连接池技术.md) -* [走进JavaWeb技术世界4:Servlet 工作原�详解](docs/java-web/走进JavaWeb技术世界4:Servlet%20工作原�详解.md) +* [走进JavaWeb技术世界4:Servlet工作原�详解](docs/java-web/走进JavaWeb技术世界4:Servlet工作原�详解.md) * [走进JavaWeb技术世界5:�探Tomcat的HTTP请求过程](docs/java-web/走进JavaWeb技术世界5:�探Tomcat的HTTP请求过程.md) * [走进JavaWeb技术世界6:Tomcat5总体架构剖�](docs/java-web/走进JavaWeb技术世界6:Tomcat5总体架构剖�.md) * [走进JavaWeb技术世界7:Tomcat和其他WEB容器的区别](docs/java-web/走进JavaWeb技术世界7:Tomcat和其他WEB容器的区别.md) @@ -182,11 +183,11 @@ todo * [深入�解JVM虚拟机1:JVM内存的结构与消失的永久代](docs/java/jvm/深入�解JVM虚拟机1:JVM内存的结构与消失的永久代.md) * [深入�解JVM虚拟机2:JVM垃圾回收基本原�和算法](docs/java/jvm/深入�解JVM虚拟机2:JVM垃圾回收基本原�和算法.md) * [深入�解JVM虚拟机3:垃圾回收器详解](docs/java/jvm/深入�解JVM虚拟机3:垃圾回收器详解.md) -* [深入�解JVM虚拟机4:Javaclass介�与解�实践](docs/java/jvm/深入�解JVM虚拟机4:Javaclass介�与解�实践.md) +* [深入�解JVM虚拟机4:Javaclass介�与解�实践](docs/java/jvm/深入�解JVM虚拟机4:Java字节�介�与解�实践.md) * [深入�解JVM虚拟机5:虚拟机字节�执行引擎](docs/java/jvm/深入�解JVM虚拟机5:虚拟机字节�执行引擎.md) * [深入�解JVM虚拟机6:深入�解JVM类加载机制](docs/java/jvm/深入�解JVM虚拟机6:深入�解JVM类加载机制.md) * [深入�解JVM虚拟机7:JNDI,OSGI,Tomcat类加载器实现](docs/java/jvm/深入�解JVM虚拟机7:JNDI,OSGI,Tomcat类加载器实现.md) -* [深入了解JVM虚拟机8:Java的编译期优化与�行期优化](docs/java/jvm/深入了解JVM虚拟机8:Java的编译期优化与�行期优化.md) +* [深入了解JVM虚拟机8:Java的编译期优化与�行期优化](docs/java/jvm/深入�解JVM虚拟机8:Java的编译期优化与�行期优化.md) * [深入�解JVM虚拟机9:JVM监控工具与诊断实践](docs/java/jvm/深入�解JVM虚拟机9:JVM监控工具与诊断实践.md) * [深入�解JVM虚拟机10:JVM常用�数以�调优实践](docs/java/jvm/深入�解JVM虚拟机10:JVM常用�数以�调优实践.md) * [深入�解JVM虚拟机11:Java内存异常原�与实践](docs/java/jvm/深入�解JVM虚拟机11:Java内存异常原�与实践.md) @@ -199,8 +200,8 @@ todo * [Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制](docs/java/network-programming/Java网络编程与NIO详解1:JAVA中原生的socket通信机制.md) * [Java网络编程与NIO详解2:JAVA NIO 一步步构建IO多路�用的请求模型](docs/java/network-programming/Java网络编程与NIO详解2:JavaNIO一步步构建IO多路�用的请求模型.md) * [Java网络编程和NIO详解3:IO模型与Java网络编程模型](docs/java/network-programming/Java网络编程与NIO详解3:IO模型与Java网络编程模型.md) -* [Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel 和 Selector](docs/java/network-programming/Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel和Selector.md) -* [Java网络编程和NIO详解5:Java �阻塞 IO 和异步 IO](docs/java/network-programming/Java网络编程与NIO详解5:Java�阻塞IO和异步IO.md) +* [Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel和Selector](docs/java/network-programming/Java网络编程与NIO详解4:浅�NIO包中的Buffer�Channel和Selector.md) +* [Java网络编程和NIO详解5:Java�阻塞IO和异步IO](docs/java/network-programming/Java网络编程与NIO详解5:Java�阻塞IO和异步IO.md) * [Java网络编程与NIO详解6:LinuxEpoll实现原�详解](docs/java/network-programming/Java网络编程与NIO详解6:LinuxEpoll实现原�详解.md.md) * [Java网络编程与NIO详解7:浅谈Linux中Selector的实现原�](docs/java/network-programming/Java网络编程与NIO详解7:浅谈Linux中Selector的实现原�.md) * [Java网络编程与NIO详解8:浅�mmap和DirectBuffer](docs/java/network-programming/Java网络编程与NIO详解8:浅�mmap和DirectBuffer.md) @@ -255,7 +256,7 @@ todo ### Redis * [Redis原�与实践总结](docs/cache/Redis原�与实践总结.md) * [探索Redis设计与实现开篇:什么是Redis](docs/cache/探索Redis设计与实现开篇:什么是Redis.md) -* [探索Redis设计与实现1:Redis 的基础数�结构概览](docs/cache/探索Redis设计与实现1:Redis%20的基础数�结构概览.md) +* [探索Redis设计与实现1:Redis的基础数�结构概览](docs/cache/探索Redis设计与实现1:Redis的基础数�结构概览.md) * [探索Redis设计与实现2:Redis内部数�结构详解——dict](docs/cache/探索Redis设计与实现2:Redis内部数�结构详解——dict.md) * [探索Redis设计与实现3:Redis内部数�结构详解——sds](docs/cache/探索Redis设计与实现3:Redis内部数�结构详解——sds.md) * [探索Redis设计与实现4:Redis内部数�结构详解——ziplist](docs/cache/探索Redis设计与实现4:Redis内部数�结构详解——ziplist.md) @@ -292,9 +293,9 @@ todo ## 分布� ### �论 -* [分布�系统�论基础1: 一致性�2PC和3PC ](docs/distributed/basic/分布�系统�论基础1:%20一致性�2PC和3PC.md) -* [分布�系统�论基础2:CAP ](docs/distributed/basic/分布�系统�论基础2%20:CAP.md) -* [分布�系统�论基础3: 时间�时钟和事件顺�](docs/distributed/basic/分布�系统�论基础3:%20时间�时钟和事件顺�.md) +* [分布�系统�论基础1:一致性�2PC和3PC ](docs/distributed/basic/分布�系统�论基础1:一致性�2PC和3PC.md) +* [分布�系统�论基础2:CAP ](docs/distributed/basic/分布�系统�论基础2:CAP.md) +* [分布�系统�论基础3:时间�时钟和事件顺�](docs/distributed/basic/分布�系统�论基础3:时间�时钟和事件顺�.md) * [分布�系统�论基础4:Paxos](docs/distributed/basic/分布�系统�论基础4:Paxos.md) * [分布�系统�论基础5:选举�多数派和租约](docs/distributed/basic/分布�系统�论基础5:选举�多数派和租约.md) * [分布�系统�论基础6:Raft�Zab ](docs/distributed/basic/分布�系统�论基础6:Raft�Zab.md) @@ -302,13 +303,14 @@ todo * [分布�系统�论基础8:zookeeper分布��调�务 ](docs/distributed/basic/分布�系统�论基础8:zookeeper分布��调�务.md) * [分布�技术实践总结](docs/distributed/分布��论总结.md) + ### 技术 -* [�懂分布�技术1:分布�系统的一些基本概念 ](docs/distributed/practice/�懂分布�技术1:分布�系统的一些基本概念.md ) +* [�懂分布�技术1:分布�系统的一些基本概念](docs/distributed/practice/�懂分布�技术1:分布�系统的一些基本概念.md ) * [�懂分布�技术2:分布�一致性�议与Paxos,Raft算法](docs/distributed/practice/�懂分布�技术2:分布�一致性�议与Paxos,Raft算法.md) -* [�懂分布�技术3:�探分布��调�务zookeeper ](docs/distributed/practice/�懂分布�技术3:�探分布��调�务zookeeper.md ) -* [�懂分布�技术4:ZAB�议概述与选主�程详解 ](docs/distributed/practice/�懂分布�技术4:ZAB�议概述与选主�程详解.md ) +* [�懂分布�技术3:�探分布��调�务zookeeper](docs/distributed/practice/�懂分布�技术3:�探分布��调�务zookeeper.md ) +* [�懂分布�技术4:ZAB�议概述与选主�程详解](docs/distributed/practice/�懂分布�技术4:ZAB�议概述与选主�程详解.md ) * [�懂分布�技术5:Zookeeper的�置与集群管�实战](docs/distributed/practice/�懂分布�技术5:Zookeeper的�置与集群管�实战.md) -* [�懂分布�技术6:Zookeeper典型应用场景�实践 ](docs/distributed/practice/�懂分布�技术6:Zookeeper典型应用场景�实践.md ) +* [�懂分布�技术6:Zookeeper典型应用场景�实践](docs/distributed/practice/�懂分布�技术6:Zookeeper典型应用场景�实践.md ) [//]: # (* [�懂分布�技术7:负载�衡概念与主�方案](docs/distributed/practice/�懂分布�技术7:负载�衡概念与主�方案.md)) @@ -322,7 +324,7 @@ todo * [�懂分布�技术14:SpringBoot使用注解集�Redis缓存](docs/distributed/practice/�懂分布�技术14:SpringBoot使用注解集�Redis缓存.md) * [�懂分布�技术15:缓存更新的套路 ](docs/distributed/practice/�懂分布�技术15:缓存更新的套路.md ) * [�懂分布�技术16:浅谈分布��的几�方案 ](docs/distributed/practice/�懂分布�技术16:浅谈分布��的几�方案.md ) -* [�懂分布�技术17:浅�分布�事务 ](docs/distributed/practice/�懂分布�技术17:浅�分布�事务.md ) +* [�懂分布�技术17:浅�分布�事务](docs/distributed/practice/�懂分布�技术17:浅�分布�事务.md ) * [�懂分布�技术18:分布�事务常用解决方案 ](docs/distributed/practice/�懂分布�技术18:分布�事务常用解决方案.md ) * [�懂分布�技术19:使用RocketMQ事务消�解决分布�事务 ](docs/distributed/practice/�懂分布�技术19:使用RocketMQ事务消�解决分布�事务.md ) * [�懂分布�技术20:消�队列因何而生](docs/distributed/practice/�懂分布�技术20:消�队列因何而生.md) diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2202\357\274\232\345\210\235\346\216\242Spring IOC\346\240\270\345\277\203\346\265\201\347\250\213.md" "b/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2202\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md" similarity index 100% rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2202\357\274\232\345\210\235\346\216\242Spring IOC\346\240\270\345\277\203\346\265\201\347\250\213.md" rename to "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2202\357\274\232\345\210\235\346\216\242SpringIOC\346\240\270\345\277\203\346\265\201\347\250\213.md" diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2203\357\274\232Spring IOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" "b/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2203\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" similarity index 100% rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2203\357\274\232Spring IOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" rename to "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2203\357\274\232SpringIOC\345\256\271\345\231\250\347\232\204\345\212\240\350\275\275\350\277\207\347\250\213.md" diff --git "a/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2206\357\274\232Spring AOP\346\246\202\350\277\260.md" "b/docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2206\357\274\232SpringAOP\346\246\202\350\277\260.md" similarity index 100% rename from "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2206\357\274\232Spring AOP\346\246\202\350\277\260.md" rename to "docs/java-web/Spring/Spring\346\272\220\347\240\201\345\211\226\346\236\2206\357\274\232SpringAOP\346\246\202\350\277\260.md" diff --git "a/docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275Spring Boot\347\237\245\350\257\206\346\270\205\345\215\225.md" "b/docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" similarity index 100% rename from "docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275Spring Boot\347\237\245\350\257\206\346\270\205\345\215\225.md" rename to "docs/java-web/Spring/\347\273\231\344\275\240\344\270\200\344\273\275SpringBoot\347\237\245\350\257\206\346\270\205\345\215\225.md" diff --git "a/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\2144\357\274\232Servlet \345\267\245\344\275\234\345\216\237\347\220\206\350\257\246\350\247\243.md" "b/docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\2144\357\274\232Servlet\345\267\245\344\275\234\345\216\237\347\220\206\350\257\246\350\247\243.md" similarity index 100% rename from "docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\2144\357\274\232Servlet \345\267\245\344\275\234\345\216\237\347\220\206\350\257\246\350\247\243.md" rename to "docs/java-web/\350\265\260\350\277\233JavaWeb\346\212\200\346\234\257\344\270\226\347\225\2144\357\274\232Servlet\345\267\245\344\275\234\345\216\237\347\220\206\350\257\246\350\247\243.md" diff --git "a/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" "b/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" index 20a3a96..0037f49 100644 --- "a/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" +++ "b/docs/java/basic/1\343\200\201\351\235\242\345\220\221\345\257\271\350\261\241\345\237\272\347\241\200.md" @@ -16,10 +16,6 @@ * [二��装](#二��装) * [1��装的概念](#1��装的概念) * [2��装的优点](#2��装的优点) - * [3��装的实现步骤](#3��装的实现步骤) - * [A�访问修饰符](#a�访问修饰符) - * [B�this关键字](#b�this关键字) - * [C�Java 中的内部类](#c�java-中的内部类) * [三�多�](#三�多�) * [1�多�的概念](#1�多�的概念) * [2�多�的好处](#2�多�的好处) @@ -67,27 +63,23 @@ Java 是��对象的编程语言,对象就是��对象程�设计的核 ## ��对象和��过程的区别 - ��过程: -   一�较早的编程�想,顾��义就是该�想是站�过程的角度�考问题,强调的就是功能行为,功能的执行过程,�先�顺�,而�一个功能我们都使用函数(类似于方法)把这些步骤一步一步实现。使用的时候�次调用函数就�以了。 +一�较早的编程�想,顾��义就是该�想是站�过程的角度�考问题,强调的就是功能行为,功能的执行过程,�先�顺�,而�一个功能我们都使用函数(类似于方法)把这些步骤一步一步实现。使用的时候�次调用函数就�以了。 - ��过程的设计: -   最�的程��元是函数,�个函数负责完��一个功能,用于接�输入数�,函数对输入数�进行处�,然�输出结果数�,整个软件系统由一个个的函数组�,其中作为程�入�的函数称之为主函数,主函数�次调用其他函数,普通函数之间�以相互调用,从而实现整个系统功能。 -   ��过程最大的问题在于��系统的膨胀,��过程将无法应付,最终导致系统的崩溃。为了解决这一�软件�机,我们�出��对象�想。 + 最�的程��元是函数,�个函数负责完��一个功能,用于接�输入数�,函数对输入数�进行处�,然�输出结果数�,整个软件系统由一个个的函数组�,其中作为程�入�的函数称之为主函数,主函数�次调用其他函数,普通函数之间�以相互调用,从而实现整个系统功能。 + ��过程最大的问题在于��系统的膨胀,��过程将无法应付,最终导致系统的崩溃。为了解决这一�软件�机,我们�出��对象�想。 - ��过程的缺陷: -   是采用自顶而下的设计模�,在设计阶段就需�考虑�一个模�应该分解�哪些�模�,�一个�模��细分为更�的�模�,如此类推,直到将模�细化为一个个函数。 + 是采用自顶而下的设计模�,在设计阶段就需�考虑�一个模�应该分解�哪些�模�,�一个�模��细分为更�的�模�,如此类推,直到将模�细化为一个个函数。 -- 存在的问题 - - ​ 设计�够直观,与人类的�维习惯�一致 +- 存在的问题 + 设计�够直观,与人类的�维习惯�一致 系统软件适应新差,�拓展性差,维护性低 -- ��对象: - - ​ 一�基于��过程的新编程�想,顾��义就是该�想是站在对象的角度�考问题,我们把多个功能��放到��对象里,强调的是具备�些功能的对象。 - -   具备��功能的实体,称为对象。��对象最�的程��元是:类。��对象更加符�常规的�维方�,稳定性好,��用性强,易于开�大型软件产�,有良好的�维护性。 - -  在软件工程上,��对象�以使工程更加模�化,实现更低的耦�和更高的内�。 +- ��对象: + 一�基于��过程的新编程�想,顾��义就是该�想是站在对象的角度�考问题,我们把多个功能��放到��对象里,强调的是具备�些功能的对象。 + 具备��功能的实体,称为对象。��对象最�的程��元是:类。��对象更加符�常规的�维方�,稳定性好,��用性强,易于开�大型软件产�,有良好的�维护性。 + 在软件工程上,��对象�以使工程更加模�化,实现更低的耦�和更高的内�。 ## ��对象的三大核心特性简介 @@ -179,10 +171,7 @@ Java 是��对象的编程语言,对象就是��对象程�设计的核 使用这�层次形的分类方�,是为了将多个类的通用属性和方法��出�,放在它们的父类中,然��需�在�类中�自定义自己独有的属性和方法,并以继承的形�在父类中获�它们的通用属性和方法��。 - 继承是类与类的一�关系,是一�“is a�的关系。比如“狗�继承“动物�,这里动物类是狗类的父类或者基类,狗类是动物类的�类或者派生类。如下图所示: - -![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701123011243-2128400556.png) - + 继承是类与类的一�关系,是一�“is a�的关系。比如“狗�继承“动物�,这里动物类是狗类的父类或者基类,狗类是动物类的�类或者派生类。 注:java中的继承是**�继承**,�**一个类�有一个父类。** **补充:Java中的继承�能�继承,但是�以通过内部类继承其他类�实现多继承。** @@ -218,47 +207,37 @@ System.out.println("mom cook");  �类拥有父类的所有属性和方法(除了private修饰的属性�能拥有)从而实现了实现代�的�用;  -#### 3�语法规则 - -![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701123421961-647167245.png) - ------- - ##### A�方法的�写 - �类如果对继承的父类的方法�满�(�适�),�以自己编写继承的方法,这�方�就称为**方法的�写。当调用方法时会优先调用�类的方法。** +�类如果对继承的父类的方法�满�(�适�),�以自己编写继承的方法,这�方�就称为**方法的�写。当调用方法时会优先调用�类的方法。** - **�写�注�:** +**�写�注�:** -  a�返回值类型 +a�返回值类型 -  b�方法� +b�方法� -  c��数类型�个数 +c��数类型�个数 - 都�与父类继承的方法相�,��方法的�写。 +都�与父类继承的方法相�,��方法的�写。 - **�载和�写的区别:** +**�载和�写的区别:** -  方法�载:在�一个类中处���数�的多个相�方法�的多�手段。 +方法�载:在�一个类中处���数�的多个相�方法�的多�手段。 -  方法�写:相对继承而言,�类中对父类已�存在的方法进行区别化的修改。 +方法�写:相对继承而言,�类中对父类已�存在的方法进行区别化的修改。 ------ ##### B�继承的�始化顺� -  1��始化父类��始化�类 - -  2�先执行�始化对象中属性,�执行构造方法中的�始化。 +1��始化父类��始化�类 - 基于上�两点,我们就知�实例化一个�类,java程�的执行顺�是: +2�先执行�始化对象中属性,�执行构造方法中的�始化。 - **父类对象属性�始化---->父类对象构造方法---->�类对象属性�始化--->�类对象构造方法**    +基于上�两点,我们就知�实例化一个�类,java程�的执行顺�是: - 下�有个形象的图: - -![img](https://images2015.cnblogs.com/blog/1189312/201707/1189312-20170701144019071-1063399032.png) +**父类对象属性�始化---->父类对象构造方法---->�类对象属性�始化--->�类对象构造方法**    ------ @@ -345,55 +324,22 @@ Java �装,说白了就是将一大�公共通用的实现逻辑玩�,装 4. 一对一,一个功能就�为这个功能�务;��头�绳�一�用,导致最�一团糟 -#### 3��装的实现步骤 - -![img](https://images2015.cnblogs.com/blog/1189312/201706/1189312-20170630170717493-357592353.png) - -    需�注�:对�装的属性�一定�通过get/set方法,其他方法也�以对�装的属性进行�作。当然最好使用get/set方法,比较标准。 - ------- - - - -##### A�访问修饰符 - -![img](https://images2015.cnblogs.com/blog/1189312/201706/1189312-20170630174919274-1857293801.png) - -    从表格�以看出**从上到下�装性越�越差**。 - - - -##### B�this关键字 - - 1.this关键字**代表当�对象** - -  this.属性 �作当�对象的属性 - -  this.方法 调用当�对象的方法。 - - 2.�装对象的属性的时候,�常会使用this关键字。 - - 3.当getter和setter函数�数�和�员函数���的时候,**�以使用this****区别。如:** - -![img](https://images2015.cnblogs.com/blog/1189312/201706/1189312-20170630180217524-833886832.png) - - ##### C�Java 中的内部类 - 内部类( Inner Class )就是定义在�外一个类**里�**的类。与之对应,包�内部类的类被称为外部类。 +内部类( Inner Class )就是定义在�外一个类**里�**的类。与之对应,包�内部类的类被称为外部类。 - 那么问题�了:那为什么�将一个类定义在�一个类里�呢?清清爽爽的独立的一个类多好啊�� +那么问题�了:那为什么�将一个类定义在�一个类里�呢?清清爽爽的独立的一个类多好啊�� - 答:内部类的主�作用如下: +答:内部类的主�作用如下: -  1. 内部类�供了**更好的�装**,�以把内部类**��**在外部类之内,**��许**�一个包中的其他类访问该类。 +1. 内部类�供了**更好的�装**,�以把内部类**��**在外部类之内,**��许**�一个包中的其他类访问该类。 -  2. 内部类的方法�以**直接访问外部类的所有数�**,包括**�有的数�**。 +2. 内部类的方法�以**直接访问外部类的所有数�**,包括**�有的数�**。 -  3. 内部类所实现的功能使用外部类�样�以实现,�是有时使用内部类更方便。 +3. 内部类所实现的功能使用外部类�样�以实现,�是有时使用内部类更方便。 -  内部类�分为以下几�: +内部类�分为以下几�: - �员内部类 @@ -401,8 +347,6 @@ Java �装,说白了就是将一大�公共通用的实现逻辑玩�,装 - 方法内部类 - 匿�内部类   - - ### 三�多� #### 1�多�的概念 @@ -483,13 +427,13 @@ java里的多�主�表现在两个方�:   就以上述的父类Animal和一个�类Dog�说明,当父类的引用�以指��类的对象时,就是**�上类型转�**。如: -![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2MjYzMDUwOC05NjE1MDc2NTkucG5n?x-oss-process=image/format,png) + ![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2MjYzMDUwOC05NjE1MDc2NTkucG5n?x-oss-process=image/format,png)   **2. �下类型转�(强制类型转�),是大类型转�到�类型(有风险,�能出现数�溢出)。**   将上述代��加上一行,我们�次将父类转�为�类引用,那么会出现错误,编译器��许我们直接这么�**,**虽然我们知�这个父类引用指�的就是�类对象,但是编译器认为这�转�是存在风险的**。**如: -![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2MjkyNjQ3Ny0zODU3OTc1LnBuZw?x-oss-process=image/format,png) + ![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2MjkyNjQ3Ny0zODU3OTc1LnBuZw?x-oss-process=image/format,png)   那么我们该怎么解决这个问题呢,我们�以在animal�加上(Dog)�强制类型转�。如:![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2NDIyOTg5OS0xMDU1MTkwNzc0LnBuZw?x-oss-process=image/format,png) @@ -499,7 +443,7 @@ java里的多�主�表现在两个方�:   还有一�情况是父类的引用指�**其他�类的对象**,则�能通过强制转为**该�类的对象**。如: -    ![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2NTEzMzI4OS03MTc0MzkzNjAucG5n?x-oss-process=image/format,png) +  ![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMTE4OTMxMi8yMDE3MDcvMTE4OTMxMi0yMDE3MDcwMTE2NTEzMzI4OS03MTc0MzkzNjAucG5n?x-oss-process=image/format,png)   这是因为我们在编译的时候进行了强制类型转�,编译时的类型是我们强制转�的类型,所以编译器�会报错,而当我们�行的时候,程�给animal开辟的是Dog类型的内存空间,这与Cat类型内存空间�匹�,所以无法正常转�。这两�情况出错的本质是一样的,所以我们在使用强制类型转�的时候�特别注�这两�错误��下�有个更安全的方��实现�下类型转�。。。。 diff --git "a/docs/java/basic/2\343\200\201Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md" "b/docs/java/basic/2\343\200\201Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md" index 655b4c2..c6349c6 100644 --- "a/docs/java/basic/2\343\200\201Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md" +++ "b/docs/java/basic/2\343\200\201Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md" @@ -34,9 +34,6 @@ 如果对本系列文章有什么建议,或者是有什么疑问的�,也�以关注公众��Java技术江湖】�系作者,欢迎你�与本系列�文的创作和修订。 - - - # Java 基本数�类型 @@ -53,7 +50,6 @@ - 内置数�类型 - 引用数�类型 -- - * ### 内置数�类型 @@ -128,50 +124,6 @@ Java语言�供了八�基本类型。六�数字类型(四个整数型, - char 数�类型�以储存任何字符; - 例�:char letter = 'A';。 -``` -//8� -byte bx = Byte.MAX_VALUE; -byte bn = Byte.MIN_VALUE; -//16� -short sx = Short.MAX_VALUE; -short sn = Short.MIN_VALUE; -//32� -int ix = Integer.MAX_VALUE; -int in = Integer.MIN_VALUE; -//64� -long lx = Long.MAX_VALUE; -long ln = Long.MIN_VALUE; -//32� -float fx = Float.MAX_VALUE; -float fn = Float.MIN_VALUE; -//64� -double dx = Double.MAX_VALUE; -double dn = Double.MIN_VALUE; -//16� -char cx = Character.MAX_VALUE; -char cn = Character.MIN_VALUE; -//1� -boolean bt = Boolean.TRUE; -boolean bf = Boolean.FALSE; -``` - - `127` - `-128` - `32767` - `-32768` - `2147483647` - `-2147483648` - `9223372036854775807` - `-9223372036854775808` - `3.4028235E38` - `1.4E-45` - `1.7976931348623157E308` - `4.9E-324` - `￿` - - `true` - `false` - ### 引用类型 - 在Java中,引用类型的���常类似于C/C++的指针。引用类型指�一个对象,指�对象的��是引用��。这些��在声明时被指定为一个特定的类型,比如 Employee�Puppy 等。��一旦声明�,类型就�能被改�了。 @@ -202,22 +154,24 @@ char a = 'A' ## 自动拆箱和装箱(详解) Java 5增加了自动装箱与自动拆箱机制,方便基本类型与包装类型的相互转��作。在Java 5之�,如果�将一个int型的值转��对应的包装器类型Integer,必须显�的使用new创建一个新的Integer对象,或者调用��方法Integer.valueOf()。 - - //在Java 5之�,�能这样� - Integer value = new Integer(10); - //或者这样� - Integer value = Integer.valueOf(10); - //直接赋值是错误的 - //Integer value = 10;` - +```` +//在Java 5之�,�能这样� +Integer value = new Integer(10); +//或者这样� +Integer value = Integer.valueOf(10); +//直接赋值是错误的 +//Integer value = 10; +```` 在Java 5中,�以直接将整型赋给Integer对象,由编译器�完�从int型到Integer类型的转�,这就�自动装箱。 - `//在Java 5中,直接赋值是�法的,由编译器�完�转�` - `Integer value = 10;` - `与此对应的,自动拆箱就是�以将包装类型转�为基本类型,具体的转�工作由编译器�完�。` - `//在Java 5 中�以直接这么�` - `Integer value = new Integer(10);` - `int i = value;` +```` +//在Java 5中,直接赋值是�法的,由编译器�完�转� +Integer value = 10; +与此对应的,自动拆箱就是�以将包装类型转�为基本类型,具体的转�工作由编译器�完�。 +//在Java 5 中�以直接这么� +Integer value = new Integer(10); +int i = value; +```` 自动装箱与自动拆箱为程�员�供了很大的方便,而在实际的应用中,自动装箱与拆箱也是使用最广泛的特性之一。自动装箱和自动拆箱其实是Java编译器�供的一颗语法糖(语法糖是指在计算机语言中添加的��语法,这�语法对语言的功能并没有影�,但是更方便程�员使用。通过��高开�效率,增加代��读性,增加代�的安全性)。 @@ -229,43 +183,41 @@ Java 5增加了自动装箱与自动拆箱机制,方便基本类型与包装 实例方法xxxValue():将具体的包装类型对象转��基本类型; 下�我们以int和Integer为例,说明Java中自动装箱与自动拆箱的实现机制。看如下代�: - - class Auto //code1 - { - public static void main(String[] args) - { - //自动装箱 - Integer inte = 10; - //自动拆箱 - int i = inte; - - //�double和Double�验�一下 - Double doub = 12.40; - double d = doub; - - } - - } +```` + class Auto //code1 + { + public static void main(String[] args) + { + //自动装箱 + Integer inte = 10; + //自动拆箱 + int i = inte; + + //�double和Double�验�一下 + Double doub = 12.40; + double d = doub; + + } + + } +```` 上�的代�先将int型转为Integer对象,�讲Integer对象转�为int型,毫无疑问,这是�以正确�行的。�是,这�转�是怎么进行的呢?使用�编译工具,将生�的Class文件在�编译为Java文件,让我们看看�生了什么: +```` class Auto//code2 { public static void main(String[] paramArrayOfString) { Integer localInteger = Integer.valueOf(10); - - -​ -​ int i = localInteger.intValue(); - - -​ -​ -​ Double localDouble = Double.valueOf(12.4D); -​ double d = localDouble.doubleValue(); -​ -​ } -​ } + + int i = localInteger.intValue(); + + Double localDouble = Double.valueOf(12.4D); + double d = localDouble.doubleValue(); + + } + } +```` 我们�以看到�过javac编译之�,code1的代�被转��了code2,实际�行时,虚拟机�行的就是code2的代�。也就是说,虚拟机根本�知�有自动拆箱和自动装箱这回事;在将Java�文件编译为class文件的过程中,javac编译器在自动装箱的时候,调用了Integer.valueOf()方法,在自动拆箱时,�调用了intValue()方法。我们�以看到,double和Double也是如此。 实现总结:其实自动装箱和自动�箱是编译器为我们�供的一颗语法糖。在自动装箱时,编译器调用包装类型的valueOf()方法;在自动拆箱时,编译器调用了相应的xxxValue()方法。 @@ -276,7 +228,7 @@ Java 5增加了自动装箱与自动拆箱机制,方便基本类型与包装 Integer�� -``` +```` public final class Integer extends Number implements Comparable { private final int value; @@ -343,7 +295,7 @@ public final class Integer extends Number implements Comparable { private IntegerCache() {} } -``` +```` 以上是Oracle(Sun)公�JDK 1.7中Integer��的一部分,通过分�上�的代�,得到: @@ -363,21 +315,22 @@ public final class Integer extends Number implements Comparable { 5)调用intValue(),直接返回value的值。 通过3)和4)�以�现,默认情况下,在使用自动装箱时,VM会�用[-128,127]之间的Integer对象。 - - Integer a1 = 1; - Integer a2 = 1; - Integer a3 = new Integer(1); - //会打�true,因为a1和a2是�一个对象,都是Integer.cache[129] - System.out.println(a1 == a2); - //false,a3构造了一个新的对象,��于a1,a2 - System.out.println(a1 == a3); - +```` +Integer a1 = 1; +Integer a2 = 1; +Integer a3 = new Integer(1); +//会打�true,因为a1和a2是�一个对象,都是Integer.cache[129] +System.out.println(a1 == a2); +//false,a3构造了一个新的对象,��于a1,a2 +System.out.println(a1 == a3); +```` ### 了解基本类型缓存(常�池)的最佳实践 ``` //基本数�类型的常�池是-128到127之间。 // 在这个范围中的基本数�类的包装类�以自动拆箱,比较时直接比较数值大�。 public static void main(String[] args) { + //int的自动拆箱和装箱�在-128到127范围中进行,超过该范围的两个integer的 == 判断是会返回false的。 Integer a1 = 128; Integer a2 = -128; @@ -394,7 +347,6 @@ public static void main(String[] args) { System.out.println(b1 == b2); System.out.println(b3 == b4); - // Long c1 = 128L; Long c2 = 128L; Long c3 = -128L; @@ -411,7 +363,6 @@ public static void main(String[] args) { System.out.println(d1 == d2); System.out.println(d3 == d4); - `结果` `false` @@ -423,8 +374,6 @@ public static void main(String[] args) { `false` `true` - - Integer i = 10; Byte b = 10; //比较Byte和Integer.两个对象无法直接比较,报错 @@ -460,8 +409,6 @@ public static void main(String[] args) { 需�注�的是:“==�在没�到算术�算时,�会自动拆箱;基本类型�会自动装箱为对应的包装类型,代�中最�一�说明的内容。 - - 在JDK 1.5中�供了自动装箱与自动拆箱,这其实是Java 编译器的语法糖,编译器通过调用包装类型的valueOf()方法实现自动装箱,调用xxxValue()方法自动拆箱。自动装箱和拆箱会有一些陷阱,那就是包装类型�用了�些对象。 (1)Integer默认�用了[-128,127]这些对象,其中高�置�以修改; @@ -574,10 +521,6 @@ System.out.println(s3 == s4); JDK1.6以�以下:false false JDK1.7以�以上:false true ``` - -![image](https://img-blog.csdn.net/20180422231916788?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E3MjQ4ODg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) - -![image](https://img-blog.csdn.net/20180422231929413?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E3MjQ4ODg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) JDK1.6查找到常�池存在相�值的对象时会直接返回该对象的地�。 JDK 1.7�,intern方法还是会先去查询常�池中是�有已�存在,如果存在,则返回常�池中的引用,这一点与之�没有区别,区别在于,如果在常�池找�到对应的字符串,则�会�将字符串拷�到常�池,而�是在常�池中生�一个对原字符串的引用。 diff --git "a/docs/java/basic/3\343\200\201string\345\222\214\345\214\205\350\243\205\347\261\273.md" "b/docs/java/basic/3\343\200\201string\345\222\214\345\214\205\350\243\205\347\261\273.md" index 13dfe0a..064cb24 100644 --- "a/docs/java/basic/3\343\200\201string\345\222\214\345\214\205\350\243\205\347\261\273.md" +++ "b/docs/java/basic/3\343\200\201string\345\222\214\345\214\205\350\243\205\347\261\273.md" @@ -46,11 +46,8 @@ 如果对本系列文章有什么建议,或者是有什么疑问的�,也�以关注公众��Java技术江湖】�系作者,欢迎你�与本系列�文的创作和修订。 - - - ## string基础 ### Java String 类 @@ -70,9 +67,14 @@ String greeting = "�鸟教程"; String 类有 11 �构造方法,这些方法�供��的�数��始化字符串,比如�供一个字符数组�数: ### StringDemo.java 文件代�: - - public class StringDemo{ public static void main(String args[]){ char[] helloArray = { 'r', 'u', 'n', 'o', 'o', 'b'}; String helloString = new String(helloArray); System.out.println( helloString ); } } - +```` +public class StringDemo{ +public static void main(String args[]){ +char[] helloArray = { 'r', 'u', 'n', 'o', 'o', 'b'}; +String helloString = new String(helloArray); +System.out.println( helloString ); +} } +```` 以上实例编译�行结果如下: ``` @@ -87,35 +89,37 @@ runoob ### 创建String对象的常用方法 -(1) String s1 = "mpptest" +(1) String s1 = "mpptest" - (2) String s2 = new String(); +(2) String s2 = new String(); - (3) String s3 = new String("mpptest") +(3) String s3 = new String("mpptest") ### String中常用的方法,用法如图所示,具体问度娘 ![](https://img2018.cnblogs.com/blog/710412/201902/710412-20190213220237169-1966705420.png) ### 三个方法的使用: lenth() substring() charAt() - - - -

package com.mpp.string; public class StringDemo1 { public static void main(String[] args) { //定义一个字符串"晚�天欲雪 能饮一�无"
+````
+package com.mpp.string; 
+public class StringDemo1 {
+    public static void main(String[] args) { //定义一个字符串"晚�天欲雪 能饮一�无"
         String str = "晚�天欲雪 能饮一�无";
         System.out.println("字符串的长度是:"+str.length()); //字符串的雪字打�输出  charAt(int index)
         System.out.println(str.charAt(4)); //�出�串  天欲
         System.out.println(str.substring(2));   //�出从index2开始直到最�的�串,包�2
         System.out.println(str.substring(2,4));  //�出index从2到4的�串,包�2�包�4  顾头�顾尾
- }
-}
- - + } +} +```` - 两个方法的使用,求字符或�串第一次/最�一次在字符串中出现的�置: indexOf() lastIndexOf() +两个方法的使用,求字符或�串第一次/最�一次在字符串中出现的�置: +indexOf() lastIndexOf() -
package com.mpp.string; public class StringDemo2 { public static void main(String[] args) {
+````
+package com.mpp.string; public class StringDemo2 { 
+    public static void main(String[] args) {
         String str = new String("赵客缦胡缨 �钩胡缨霜雪明"); //查找胡在字符串中第一次出现的�置
         System.out.println("\"胡\"在字符串中第一次出现的�置:"+str.indexOf("胡")); //查找�串"胡缨"在字符串中第一次出现的�置
         System.out.println("\"胡缨\"在字符串中第一次出现的�置"+str.indexOf("胡缨")); //查找胡在字符串中最�一次次出现的�置
@@ -123,35 +127,40 @@ runoob
         System.out.println(str.lastIndexOf("胡缨")); //从indexof为5的�置,找第一次出现的"�"
         System.out.println(str.indexOf("�",5));
     }
-}
- +} +```` ### 字符串与byte数组间的相互转� - -
package com.mpp.string; import java.io.UnsupportedEncodingException; public class StringDemo3 { public static void main(String[] args) throws UnsupportedEncodingException { //字符串和byte数组之间的相互转�
- String str = new String("hhhabc银�照白马 飒沓如�星"); //将字符串转�为byte数组,并打�输出
-        byte[] arrs = str.getBytes("GBK"); for(int i=0;i){
+````
+package com.mpp.string; import java.io.UnsupportedEncodingException; 
+public class StringDemo3 { 
+    public static void main(String[] args) throws UnsupportedEncodingException { 
+        
+        //字符串和byte数组之间的相互转�
+        String str = new String("hhhabc银�照白马 飒沓如�星"); //将字符串转�为byte数组,并打�输出
+        byte[] arrs = str.getBytes("GBK"); 
+        for(int i=0;i){
             System.out.print(arrs[i]);
-        } //将byte数组转��字符串
- System.out.println();
+        } 
+        
+        //将byte数组转��字符串
+        System.out.println();
         String str1 = new String(arrs,"GBK");  //��字符集的一致,�则会出现乱�
- System.out.println(str1);
+        System.out.println(str1);
     }
-}
- +} +```` ### ==�算符和equals之间的区别: -
引用指�的内容和引用指�的地�
+引用指�的内容和引用指�的地� -![](https://img2018.cnblogs.com/blog/710412/201902/710412-20190214223341972-1204335921.png) - - - -
package com.mpp.string; public class StringDemo5 { public static void main(String[] args) {
+````
+package com.mpp.string; public class StringDemo5 { 
+    public static void main(String[] args) {
         String str1 = "mpp";
         String str2 = "mpp";
         String str3 = new String("mpp");
@@ -160,9 +169,9 @@ runoob
         System.out.println(str1.equals(str3));   //true  内容相�
         System.out.println(str1==str2);   //true   地�相�
         System.out.println(str1==str3);   //false  地���
- }
-}
- + } +} +```` ### 字符串的���性 @@ -170,7 +179,7 @@ String的对象一旦被创建,则�能修改,是���的 所谓的修改其实是创建了新的对象,所指�的内存空间�� -![](https://img2018.cnblogs.com/blog/710412/201902/710412-20190214224055939-746946317.png) +![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/blog/Java%E6%8A%80%E6%9C%AF%E6%B1%9F%E6%B9%96/%E4%BA%8C%E7%BB%B4%E7%A0%81/710412-20190214224055939-746946317.png) 上图中,s1��指�imooc所在的内存空间,而是指�了hello,imooc ### String的连接 @@ -218,85 +227,86 @@ String str = "aa"+"bb"+"cc"; ## String类的��分� ### String类型的intern - - public void intern () { - //2:string的intern使用 - //s1是基本类型,比较值。s2是string实例,比较实例地� - //字符串类型用equals方法比较时�会比较值 - String s1 = "a"; - String s2 = new String("a"); - //调用intern时,如果s2中的字符�在常�池,则加入常�池并返回常�的引用 - String s3 = s2.intern(); - System.out.println(s1 == s2); - System.out.println(s1 == s3); - } - +```` +public void intern () { + //2:string的intern使用 + //s1是基本类型,比较值。s2是string实例,比较实例地� + //字符串类型用equals方法比较时�会比较值 + String s1 = "a"; + String s2 = new String("a"); + //调用intern时,如果s2中的字符�在常�池,则加入常�池并返回常�的引用 + String s3 = s2.intern(); + System.out.println(s1 == s2); + System.out.println(s1 == s3); +} +```` ### String类型的equals - - //字符串的equals方法 - // public boolean equals(Object anObject) { - // if (this == anObject) { - // return true; - // } - // if (anObject instanceof String) { - // String anotherString = (String)anObject; - // int n = value.length; - // if (n == anotherString.value.length) { - // char v1[] = value; - // char v2[] = anotherString.value; - // int i = 0; - // while (n-- != 0) { - // if (v1[i] != v2[i]) - // return false; - // i++; - // } - // return true; - // } - // } - // return false; - // } - +```` +//字符串的equals方法 +// public boolean equals(Object anObject) { +// if (this == anObject) { +// return true; +// } +// if (anObject instanceof String) { +// String anotherString = (String)anObject; +// int n = value.length; +// if (n == anotherString.value.length) { +// char v1[] = value; +// char v2[] = anotherString.value; +// int i = 0; +// while (n-- != 0) { +// if (v1[i] != v2[i]) +// return false; +// i++; +// } +// return true; +// } +// } +// return false; +// } +```` ### StringBuffer和Stringbuilder 底层是继承父类的��字符数组value +```` +/** + +- The value is used for character storage. + */ + char[] value; + �始化容�为16 + +/** + +- Constructs a string builder with no characters in it and an +- initial capacity of 16 characters. + */ + public StringBuilder() { + super(16); + } + 这两个类的append方法都是�自父类AbstractStringBuilder的方法 + +public AbstractStringBuilder append(String str) { + if (str == null) + return appendNull(); + int len = str.length(); + ensureCapacityInternal(count + len); + str.getChars(0, len, value, count); + count += len; + return this; +} +@Override +public StringBuilder append(String str) { + super.append(str); + return this; +} - /** - - - The value is used for character storage. - */ - char[] value; - �始化容�为16 - - /** - - - Constructs a string builder with no characters in it and an - - initial capacity of 16 characters. - */ - public StringBuilder() { - super(16); - } - 这两个类的append方法都是�自父类AbstractStringBuilder的方法 - - public AbstractStringBuilder append(String str) { - if (str == null) - return appendNull(); - int len = str.length(); - ensureCapacityInternal(count + len); - str.getChars(0, len, value, count); - count += len; - return this; - } - @Override - public StringBuilder append(String str) { - super.append(str); - return this; - } - - @Override - public synchronized StringBuffer append(String str) { - toStringCache = null; - super.append(str); - return this; - } +@Override +public synchronized StringBuffer append(String str) { + toStringCache = null; + super.append(str); + return this; +} +```` ### append方法 Stringbuffer在大部分涉�字符串修改的�作上加了synchronized关键字���线程安全,效率较低。 @@ -312,19 +322,19 @@ a = a + a;时,实际上先把a�装�stringbuilder,调用append方法� ensureCapacityInternal(count + len); 该方法是计算append之�的空间是�足够,�足的�需�进行扩容 - - public void ensureCapacity(int minimumCapacity) { - if (minimumCapacity > 0) - ensureCapacityInternal(minimumCapacity); - } - private void ensureCapacityInternal(int minimumCapacity) { - // overflow-conscious code - if (minimumCapacity - value.length > 0) { - value = Arrays.copyOf(value, - newCapacity(minimumCapacity)); - } +```` +public void ensureCapacity(int minimumCapacity) { + if (minimumCapacity > 0) + ensureCapacityInternal(minimumCapacity); +} +private void ensureCapacityInternal(int minimumCapacity) { + // overflow-conscious code + if (minimumCapacity - value.length > 0) { + value = Arrays.copyOf(value, + newCapacity(minimumCapacity)); } - +} +```` 如果新字符串长度大于value数组长度则进行扩容 扩容�的长度一般为原�的两� + 2; @@ -334,42 +344,39 @@ ensureCapacityInternal(count + len); 考虑两�情况 如果新的字符串长度超过int最大值,则抛出异常,�则直接使用数组最大长度作为新数组的长度。 - - private int hugeCapacity(int minCapacity) { - if (Integer.MAX_VALUE - minCapacity < 0) { // overflow - throw new OutOfMemoryError(); - } - return (minCapacity > MAX_ARRAY_SIZE) - ? minCapacity : MAX_ARRAY_SIZE; +```` +private int hugeCapacity(int minCapacity) { + if (Integer.MAX_VALUE - minCapacity < 0) { // overflow + throw new OutOfMemoryError(); } - + return (minCapacity > MAX_ARRAY_SIZE) + ? minCapacity : MAX_ARRAY_SIZE; +} +```` ### 删除 这两个类型的删除�作: 都是调用父类的delete方法进行删除 - - public AbstractStringBuilder delete(int start, int end) { - if (start < 0) - throw new StringIndexOutOfBoundsException(start); - if (end > count) - end = count; - if (start > end) - throw new StringIndexOutOfBoundsException(); - int len = end - start; - if (len > 0) { - System.arraycopy(value, start+len, value, start, count-end); - count -= len; - } - return this; - } - +```` +public AbstractStringBuilder delete(int start, int end) { + if (start < 0) + throw new StringIndexOutOfBoundsException(start); + if (end > count) + end = count; + if (start > end) + throw new StringIndexOutOfBoundsException(); + int len = end - start; + if (len > 0) { + System.arraycopy(value, start+len, value, start, count-end); + count -= len; + } + return this; +} +```` 事实上是将剩余的字符�新拷�到字符数组value。 这里用到了system.arraycopy�拷�数组,速度是比较快的 - - - ### system.arraycopy方法 转自知乎: @@ -386,37 +393,26 @@ ensureCapacityInternal(count + len); ## String和JVM的关系 - - - 下�我们了解下Java栈�Java堆�方法区和常�池: - - Java栈(线程�有数�区): ``` �个Java虚拟机线程都有自己的Java虚拟机栈,Java虚拟机栈用�存放栈帧,�个方法被执行的时候都会�时创建一个栈帧(Stack Frame)用于存储局部��表��作栈�动�链接�方法出�等信�。�一个方法被调用直至执行完�的过程,就对应�一个栈帧在虚拟机栈中从入栈到出栈的过程。 ``` - - Java堆(线程共享数�区): ``` 在虚拟机�动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分�。 ``` - - 方法区(线程共享数�区): ``` 方法区在虚拟机�动的时候被创建,它存储了�一个类的结构信�,例如�行时常�池�字段和方法数��构造函数和普通方法的字节�内容�还包括在类�实例�接��始化时用到的特殊方法。在JDK8之�永久代是方法区的一�实现,而JDK8元空间替代了永久代,永久代被移除,也�以�解为元空间是方法区的一�实现。 ``` - - 常�池(线程共享数�区): ``` @@ -437,23 +433,18 @@ Java堆(线程共享数�区): 使用字符串常�池,�当我们使用字��(String s=�1�;)创建字符串常�时,JVM会首先检查字符串常�池,如果该字符串已�存在常�池中,那么就将此字符串对象的地�赋值给引用s(引用s在Java栈中)。如果字符串�存在常�池中,就会实例化该字符串并且将其放到常�池中,并将此字符串对象的地�赋值给引用s(引用s在Java栈中)。 ``` - - ``` 使用字符串常�池,�当我们使用关键字new(String s=new String(�1�);)创建字符串常�时,JVM会首先检查字符串常�池,如果该字符串已�存在常�池中,那么��在字符串常�池创建该字符串对象,而直接堆中�制该对象的副本,然�将堆中对象的地�赋值给引用s,如果字符串�存在常�池中,就会实例化该字符串并且将其放到常�池中,然�在堆中�制该对象的副本,然�将堆中对象的地�赋值给引用s。 ``` - - - ## String为什么���? 翻开JDK��,java.lang.String类起手�三行,是这样写的: - - public final class String implements java.io.Serializable, Comparable, CharSequence { - /** String本质是个char数组. 而且用final关键字修饰.*/ - private final char value[]; ... ... - } - +```` +public final class String implements java.io.Serializable, Comparable, CharSequence { + /** String本质是个char数组. 而且用final关键字修饰.*/ +private final char value[]; ... ... + } +```` 首先String类是用final关键字修饰,这说明String��继承。�看下�,String类的主力�员字段value是个char[]数组,而且是用final修饰的。 final修饰的字段创建以�就��改�。 有的人以为故事就这样完了,其实没有。因为虽然value是���,也�是value这个引用地����。挡��Array数组是��的事实。 @@ -463,16 +454,16 @@ Array的数�结构看下图。 也就是说Array���是stack上的一个引用,数组的本体结构在heap堆。 String类里的value用final修饰,�是说stack里的这个�value的引用地����。没有说堆里array本身数����。看下�这个例�, - - final int[] value={1,2,3} ; - int[] another={4,5,6}; - value=another; //编译器报错,final��� value用final修饰,编译器��许我把value指�堆区�一个地�。 - 但如果我直接对数组元素动手,分分钟�定。 - - final int[] value={1,2,3}; - value[2]=100; //这时候数组里已�是{1,2,100} 所以String是���,关键是因为SUN公�的工程师。 - 在��所有String的方法里很�心的没有去动Array里的元素,没有暴露内部�员字段。private final char value[]这一�里,private的�有访问��的作用都比final大。而且设计师还很�心地把整个String设�final�止继承,��被其他人继承�破�。所以String是���的关键都在底层的实现,而�是一个final。考验的是工程师构造数�类型,�装数�的功力。 - +```` +final int[] value={1,2,3} ; +int[] another={4,5,6}; + value=another; //编译器报错,final��� value用final修饰,编译器��许我把value指�堆区�一个地�。 +但如果我直接对数组元素动手,分分钟�定。 + + final int[] value={1,2,3}; + value[2]=100; //这时候数组里已�是{1,2,100} 所以String是���,关键是因为SUN公�的工程师。 + 在��所有String的方法里很�心的没有去动Array里的元素,没有暴露内部�员字段。private final char value[]这一�里,private的�有访问��的作用都比final大。而且设计师还很�心地把整个String设�final�止继承,��被其他人继承�破�。所以String是���的关键都在底层的实现,而�是一个final。考验的是工程师构造数�类型,�装数�的功力。 +```` ### ���有什么好处? 这个最简�地原因,就是为了安全。看下�这个场景(有评论�应例��够清楚,现在完整地写出�),一个函数appendStr( )在���的String�数��加上一段“bbb��返回。appendSb( )负责在��的StringBuilder��加“bbb�。 @@ -485,28 +476,28 @@ String类里的value用final修饰,�是说stack里的这个�value的引用 > 3 final修饰的char数组��了char数组的引用���。但是�以通过char[0] = 'a’�修改值。�过String内部并��供方法�完�这一�作,所以String的���也是基于代��装和访问控制的。 举个例� +```` +final class Fi { + int a; + final int b = 0; + Integer s; - final class Fi { - int a; - final int b = 0; - Integer s; - - } - final char[]a = {'a'}; - final int[]b = {1}; - @Test - public void final修饰类() { - //引用没有被final修饰,所以是��的。 - //final�修饰了Fi类型,�Fi实例化的对象在堆中内存地�是���的。 - //虽然内存地����,但是�以对内部的数��改�。 - Fi f = new Fi(); - f.a = 1; - System.out.println(f); - f.a = 2; - System.out.println(f); - //改�实例中的值并�改�内存地�。 - -``` +} +final char[]a = {'a'}; +final int[]b = {1}; +@Test +public void final修饰类() { + //引用没有被final修饰,所以是��的。 + //final�修饰了Fi类型,�Fi实例化的对象在堆中内存地�是���的。 + //虽然内存地����,但是�以对内部的数��改�。 + Fi f = new Fi(); + f.a = 1; + System.out.println(f); + f.a = 2; + System.out.println(f); + //改�实例中的值并�改�内存地�。 +```` +```` Fi ff = f; //让引用指�新的Fi对象,原�的f对象由新的引用ff�有。 //引用的指�改�也�会改�原�对象的地� @@ -515,7 +506,7 @@ System.out.println(f); System.out.println(ff); } -``` +```` 这里的对f.a的修改�以�解为char[0] = 'a'这样的�作。�改�数�值,�改�内存值。 @@ -523,279 +514,283 @@ System.out.println(ff); 问题�述 很多时候我们需�对字符串进行很多固定的�作,而这些�作在JDK/JRE中�没有预置,于是我们想到了apache-commons组件,但是它也�能完全覆盖我们的业务需求,所以很多时候还是�自己写点代�的,下�就是基于apache-commons组件写的部分常用方法: - MAVEN�赖 + +```` org.apache.commons commons-lang3 ${commons-lang3.version} +```` 代��果 - public class StringUtils extends org.apache.commons.lang3.StringUtils { - - /** 值为"NULL"的字符串 */ - private static final String NULL_STRING = "NULL"; - - private static final char SEPARATOR = '_'; - - - /** - * 满足一下情况返回true
- * ①.入�为空 - * ②.入�为空字符串 - * ③.入�为"null"字符串 - * - * @param string 需�判断的字符型 - * @return boolean - */ - public static boolean isNullOrEmptyOrNULLString(String string) { - return isBlank(string) || NULL_STRING.equalsIgnoreCase(string); - } - - /** - * 把字符串转为二进制�
- * 本方法�会返回null - * - * @param str 需�转�的字符串 - * @return 二进制字节�数组 - */ - public static byte[] toBytes(String str) { - return isBlank(str) ? new byte[]{} : str.getBytes(); - } - - /** - * 把字符串转为二进制�
- * 本方法�会返回null - * - * @param str 需�转�的字符串 - * @param charset 编�类型 - * @return 二进制字节�数组 - * @throws UnsupportedEncodingException 字符串转�的时候编��支�时出现 - */ - public static byte[] toBytes(String str, Charset charset) throws UnsupportedEncodingException { - return isBlank(str) ? new byte[]{} : str.getBytes(charset.displayName()); - } - - /** - * 把字符串转为二进制�
- * 本方法�会返回null - * - * @param str 需�转�的字符串 - * @param charset 编�类型 - * @param locale 编�类型对应的地区 - * @return 二进制字节�数组 - * @throws UnsupportedEncodingException 字符串转�的时候编��支�时出现 - */ - public static byte[] toBytes(String str, Charset charset, Locale locale) throws UnsupportedEncodingException { - return isBlank(str) ? new byte[]{} : str.getBytes(charset.displayName(locale)); - } - - /** - * 二进制�转字符串
- * 本方法�会返回null - * - * @param bytes 二进制� - * @return 字符串 - */ - public static String bytesToString(byte[] bytes) { - return bytes == null || bytes.length == 0 ? EMPTY : new String(bytes); - } - - /** - * 二进制�转字符串
- * 本方法�会返回null - * - * @param bytes 二进制� - * @param charset 编�集 - * @return 字符串 - * @throws UnsupportedEncodingException 当�二进制��能�支�传入的编� - */ - public static String byteToString(byte[] bytes, Charset charset) throws UnsupportedEncodingException { - return bytes == null || bytes.length == 0 ? EMPTY : new String(bytes, charset.displayName()); - } - - /** - * 二进制�转字符串
- * 本方法�会返回null - * - * @param bytes 二进制� - * @param charset 编�集 - * @param locale 本地化 - * @return 字符串 - * @throws UnsupportedEncodingException 当�二进制��能�支�传入的编� - */ - public static String byteToString(byte[] bytes, Charset charset, Locale locale) throws UnsupportedEncodingException { - return bytes == null || bytes.length == 0 ? EMPTY : new String(bytes, charset.displayName(locale)); - } - - /** - * 把对象转为字符串 - * - * @param object 需�转化的字符串 - * @return 字符串, �能为空 - */ - public static String parseString(Object object) { - if (object == null) { - return null; - } - if (object instanceof byte[]) { - return bytesToString((byte[]) object); - } - return object.toString(); - } - - /** - * 把字符串转为int类型 - * - * @param str 需�转化的字符串 - * @return int - * @throws NumberFormatException 字符串格��正确时抛出 - */ - public static int parseInt(String str) throws NumberFormatException { - return isBlank(str) ? 0 : Integer.parseInt(str); - } - - /** - * 把字符串转为double类型 - * - * @param str 需�转化的字符串 - * @return double - * @throws NumberFormatException 字符串格��正确时抛出 - */ - public static double parseDouble(String str) throws NumberFormatException { - return isBlank(str) ? 0D : Double.parseDouble(str); - } - - /** - * 把字符串转为long类型 - * - * @param str 需�转化的字符串 - * @return long - * @throws NumberFormatException 字符串格��正确时抛出 - */ - public static long parseLong(String str) throws NumberFormatException { - return isBlank(str) ? 0L : Long.parseLong(str); +```` +public class StringUtils extends org.apache.commons.lang3.StringUtils { + +/** 值为"NULL"的字符串 */ +private static final String NULL_STRING = "NULL"; + +private static final char SEPARATOR = '_'; + + +/** + * 满足一下情况返回true
+ * ①.入�为空 + * ②.入�为空字符串 + * ③.入�为"null"字符串 + * + * @param string 需�判断的字符型 + * @return boolean + */ +public static boolean isNullOrEmptyOrNULLString(String string) { + return isBlank(string) || NULL_STRING.equalsIgnoreCase(string); +} + +/** + * 把字符串转为二进制�
+ * 本方法�会返回null + * + * @param str 需�转�的字符串 + * @return 二进制字节�数组 + */ +public static byte[] toBytes(String str) { + return isBlank(str) ? new byte[]{} : str.getBytes(); +} + +/** + * 把字符串转为二进制�
+ * 本方法�会返回null + * + * @param str 需�转�的字符串 + * @param charset 编�类型 + * @return 二进制字节�数组 + * @throws UnsupportedEncodingException 字符串转�的时候编��支�时出现 + */ +public static byte[] toBytes(String str, Charset charset) throws UnsupportedEncodingException { + return isBlank(str) ? new byte[]{} : str.getBytes(charset.displayName()); +} + +/** + * 把字符串转为二进制�
+ * 本方法�会返回null + * + * @param str 需�转�的字符串 + * @param charset 编�类型 + * @param locale 编�类型对应的地区 + * @return 二进制字节�数组 + * @throws UnsupportedEncodingException 字符串转�的时候编��支�时出现 + */ +public static byte[] toBytes(String str, Charset charset, Locale locale) throws UnsupportedEncodingException { + return isBlank(str) ? new byte[]{} : str.getBytes(charset.displayName(locale)); +} + +/** + * 二进制�转字符串
+ * 本方法�会返回null + * + * @param bytes 二进制� + * @return 字符串 + */ +public static String bytesToString(byte[] bytes) { + return bytes == null || bytes.length == 0 ? EMPTY : new String(bytes); +} + +/** + * 二进制�转字符串
+ * 本方法�会返回null + * + * @param bytes 二进制� + * @param charset 编�集 + * @return 字符串 + * @throws UnsupportedEncodingException 当�二进制��能�支�传入的编� + */ +public static String byteToString(byte[] bytes, Charset charset) throws UnsupportedEncodingException { + return bytes == null || bytes.length == 0 ? EMPTY : new String(bytes, charset.displayName()); +} + +/** + * 二进制�转字符串
+ * 本方法�会返回null + * + * @param bytes 二进制� + * @param charset 编�集 + * @param locale 本地化 + * @return 字符串 + * @throws UnsupportedEncodingException 当�二进制��能�支�传入的编� + */ +public static String byteToString(byte[] bytes, Charset charset, Locale locale) throws UnsupportedEncodingException { + return bytes == null || bytes.length == 0 ? EMPTY : new String(bytes, charset.displayName(locale)); +} + +/** + * 把对象转为字符串 + * + * @param object 需�转化的字符串 + * @return 字符串, �能为空 + */ +public static String parseString(Object object) { + if (object == null) { + return null; } - - /** - * 把字符串转为float类型 - * - * @param str 需�转化的字符串 - * @return float - * @throws NumberFormatException 字符串格��正确时抛出 - */ - public static float parseFloat(String str) throws NumberFormatException { - return isBlank(str) ? 0L : Float.parseFloat(str); + if (object instanceof byte[]) { + return bytesToString((byte[]) object); } - - /** - * 获�i18n字符串 - * - * @param code - * @param args - * @return - */ - public static String getI18NMessage(String code, Object[] args) { - //LocaleResolver localLocaleResolver = (LocaleResolver) SpringContextHolder.getBean(LocaleResolver.class); - //HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); - //Locale locale = localLocaleResolver.resolveLocale(request); - //return SpringContextHolder.getApplicationContext().getMessage(code, args, locale); + return object.toString(); +} + +/** + * 把字符串转为int类型 + * + * @param str 需�转化的字符串 + * @return int + * @throws NumberFormatException 字符串格��正确时抛出 + */ +public static int parseInt(String str) throws NumberFormatException { + return isBlank(str) ? 0 : Integer.parseInt(str); +} + +/** + * 把字符串转为double类型 + * + * @param str 需�转化的字符串 + * @return double + * @throws NumberFormatException 字符串格��正确时抛出 + */ +public static double parseDouble(String str) throws NumberFormatException { + return isBlank(str) ? 0D : Double.parseDouble(str); +} + +/** + * 把字符串转为long类型 + * + * @param str 需�转化的字符串 + * @return long + * @throws NumberFormatException 字符串格��正确时抛出 + */ +public static long parseLong(String str) throws NumberFormatException { + return isBlank(str) ? 0L : Long.parseLong(str); +} + +/** + * 把字符串转为float类型 + * + * @param str 需�转化的字符串 + * @return float + * @throws NumberFormatException 字符串格��正确时抛出 + */ +public static float parseFloat(String str) throws NumberFormatException { + return isBlank(str) ? 0L : Float.parseFloat(str); +} + +/** + * 获�i18n字符串 + * + * @param code + * @param args + * @return + */ +public static String getI18NMessage(String code, Object[] args) { + //LocaleResolver localLocaleResolver = (LocaleResolver) SpringContextHolder.getBean(LocaleResolver.class); + //HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); + //Locale locale = localLocaleResolver.resolveLocale(request); + //return SpringContextHolder.getApplicationContext().getMessage(code, args, locale); + return ""; +} + +/** + * 获得用户远程地� + * + * @param request 请求头 + * @return 用户ip + */ +public static String getRemoteAddr(HttpServletRequest request) { + String remoteAddr = request.getHeader("X-Real-IP"); + if (isNotBlank(remoteAddr)) { + remoteAddr = request.getHeader("X-Forwarded-For"); + } else if (isNotBlank(remoteAddr)) { + remoteAddr = request.getHeader("Proxy-Client-IP"); + } else if (isNotBlank(remoteAddr)) { + remoteAddr = request.getHeader("WL-Proxy-Client-IP"); + } + return remoteAddr != null ? remoteAddr : request.getRemoteAddr(); +} + +/** + * 驼峰命�法工具 + * + * @return toCamelCase(" hello_world ") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ +public static String toCamelCase(String s, Locale locale, char split) { + if (isBlank(s)) { return ""; } - - /** - * 获得用户远程地� - * - * @param request 请求头 - * @return 用户ip - */ - public static String getRemoteAddr(HttpServletRequest request) { - String remoteAddr = request.getHeader("X-Real-IP"); - if (isNotBlank(remoteAddr)) { - remoteAddr = request.getHeader("X-Forwarded-For"); - } else if (isNotBlank(remoteAddr)) { - remoteAddr = request.getHeader("Proxy-Client-IP"); - } else if (isNotBlank(remoteAddr)) { - remoteAddr = request.getHeader("WL-Proxy-Client-IP"); - } - return remoteAddr != null ? remoteAddr : request.getRemoteAddr(); - } - - /** - * 驼峰命�法工具 - * - * @return toCamelCase(" hello_world ") == "helloWorld" - * toCapitalizeCamelCase("hello_world") == "HelloWorld" - * toUnderScoreCase("helloWorld") = "hello_world" - */ - public static String toCamelCase(String s, Locale locale, char split) { - if (isBlank(s)) { - return ""; - } - - s = s.toLowerCase(locale); - - StringBuilder sb = new StringBuilder(); - for (char c : s.toCharArray()) { - sb.append(c == split ? Character.toUpperCase(c) : c); - } - - return sb.toString(); - } - - public static String toCamelCase(String s) { - return toCamelCase(s, Locale.getDefault(), SEPARATOR); - } - - public static String toCamelCase(String s, Locale locale) { - return toCamelCase(s, locale, SEPARATOR); - } - - public static String toCamelCase(String s, char split) { - return toCamelCase(s, Locale.getDefault(), split); - } - - public static String toUnderScoreCase(String s, char split) { - if (isBlank(s)) { - return ""; - } - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - boolean nextUpperCase = (i < (s.length() - 1)) && Character.isUpperCase(s.charAt(i + 1)); - boolean upperCase = (i > 0) && Character.isUpperCase(c); - sb.append((!upperCase || !nextUpperCase) ? split : "").append(Character.toLowerCase(c)); - } - - return sb.toString(); + + s = s.toLowerCase(locale); + + StringBuilder sb = new StringBuilder(); + for (char c : s.toCharArray()) { + sb.append(c == split ? Character.toUpperCase(c) : c); } - - public static String toUnderScoreCase(String s) { - return toUnderScoreCase(s, SEPARATOR); + + return sb.toString(); +} + +public static String toCamelCase(String s) { + return toCamelCase(s, Locale.getDefault(), SEPARATOR); +} + +public static String toCamelCase(String s, Locale locale) { + return toCamelCase(s, locale, SEPARATOR); +} + +public static String toCamelCase(String s, char split) { + return toCamelCase(s, Locale.getDefault(), split); +} + +public static String toUnderScoreCase(String s, char split) { + if (isBlank(s)) { + return ""; } - - /** - * 把字符串转�为JS获�对象值的三目�算表达� - * - * @param objectString 对象串 - * 例如:入�:row.user.id/返回:!row?'':!row.user?'':!row.user.id?'':row.user.id - */ - public static String toJsGetValueExpression(String objectString) { - StringBuilder result = new StringBuilder(); - StringBuilder val = new StringBuilder(); - String[] fileds = split(objectString, "."); - for (int i = 0; i < fileds.length; i++) { - val.append("." + fileds[i]); - result.append("!" + (val.substring(1)) + "?'':"); - } - result.append(val.substring(1)); - return result.toString(); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + boolean nextUpperCase = (i < (s.length() - 1)) && Character.isUpperCase(s.charAt(i + 1)); + boolean upperCase = (i > 0) && Character.isUpperCase(c); + sb.append((!upperCase || !nextUpperCase) ? split : "").append(Character.toLowerCase(c)); } + return sb.toString(); +} - } +public static String toUnderScoreCase(String s) { + return toUnderScoreCase(s, SEPARATOR); +} + +/** + * 把字符串转�为JS获�对象值的三目�算表达� + * + * @param objectString 对象串 + * 例如:入�:row.user.id/返回:!row?'':!row.user?'':!row.user.id?'':row.user.id + */ +public static String toJsGetValueExpression(String objectString) { + StringBuilder result = new StringBuilder(); + StringBuilder val = new StringBuilder(); + String[] fileds = split(objectString, "."); + for (int i = 0; i < fileds.length; i++) { + val.append("." + fileds[i]); + result.append("!" + (val.substring(1)) + "?'':"); + } + result.append(val.substring(1)); + return result.toString(); +} + + +} +```` ## �考文章 https://blog.csdn.net/qq_34490018/article/details/82110578 diff --git "a/docs/java/basic/4\343\200\201final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md" "b/docs/java/basic/4\343\200\201final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md" index ff1118c..5609da9 100644 --- "a/docs/java/basic/4\343\200\201final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md" +++ "b/docs/java/basic/4\343\200\201final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md" @@ -184,7 +184,7 @@ final方法的好处: 2. final��在多线程中并�安全,无需�外的�步开销 3. final方法是��编译的,�高了调用速度 4. **final类创建的对象是��读的,在多线程�以安全共享** -5. + ## final关键字的最佳实践 ### final的用法 @@ -198,7 +198,7 @@ final修饰的��有三�:�����实例��和局部��,分  �外,final��定义的时候,�以先声明,而�给�值,这中��也称为final空白,无论什么情况,编译器都确�空白final在使用之�必须被�始化。   但是,final空白在final关键字final的使用上�供了更大的�活性,为此,一个类中的final数��员就�以实现�对象而有所��,�有��其�定��的特�。 - +```` public class FinalTest { final int p; final int q=3; @@ -210,19 +210,20 @@ final修饰的��有三�:�����实例��和局部��,分 q=i;//�能为一个final��赋值 } } - +```` ### final内存分� 刚�到了内嵌机制,现在详细展开。 �知�调用一个函数除了函数本身的执行时间之外,还需��外的时间去寻找这个函数(类内部有一个函数签�和函数地�的映射表)。所以�少函数调用次数就等于�低了性能消耗。 final修饰的函数会被编译器优化,优化的结果是�少了函数调用的次数。如何实现的,举个例�给你看: - +```` public class Test{ final void func(){System.out.println("g");}; public void main(String[] args){ for(int j=0;j<1000;j++) func(); }} + �过编译器优化之�,这个类��了相当于这样写: public class Test{ final void func(){System.out.println("g");}; @@ -230,7 +231,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 for(int j=0;j<1000;j++) {System.out.println("g");} }} - +```` 看出�区别了�?编译器直接将func的函数体内嵌到了调用函数的地方,这样的结果是节�了1000次函数调用,当然编译器处��字节�,�是我们�以想象�这样,看个明白。 �过,当函数体太长的�,用final�能适得其�,因为�过编译器内嵌之�代�长度大大增加,于是就增加了jvm解释字节�的时间。 @@ -243,7 +244,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 �下�的测试代�,我会执行五次: - +```` public class Test { public static void getJava() @@ -283,6 +284,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 } } +```` 结果为: 第一次: @@ -308,13 +310,13 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 由以上�行结果�难看出,执行最快的是“正常的执行��代�直接编写,而使用final修饰的方法,��有些书上或者文章上所说的那样,速度与效率与“正常的执行�无异,而是�于第二�,最差的是调用�加final修饰的方法。 -观点:加了比�加好一点。 + 观点:加了比�加好一点。 ### 使用final修饰��会让��的值�能被改��; �代�: - +```` public class Final { public static void main(String[] args) @@ -335,18 +337,18 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 red blue yellow white 看�,黑色��了白色。 - -​ -​ 在使用findbugs�件时,就会�示public static String[] color = { "red", "blue", "yellow", "black" };这行代��安全,但加上final修饰,这行代��然是�安全的,因为final没有�到����的值�会被修改� -​ -​ 原因是:final关键字�能����本身�能被赋与新值,而�能����的内部结构�被修改。例如在main方法有如下代�Color.color = new String[]{""};就会报错了。 +```` + + 在使用findbugs�件时,就会�示public static String[] color = { "red", "blue", "yellow", "black" };这行代��安全,但加上final修饰,这行代��然是�安全的,因为final没有�到����的值�会被修改� + + 原因是:final关键字�能����本身�能被赋与新值,而�能����的内部结构�被修改。例如在main方法有如下代�Color.color = new String[]{""};就会报错了。 ### 如何��数组内部�被修改 那�能有的�学就会问了,加上final关键字�能��数组�会被外部修改,那有什么方法能够��呢?答案就是�低访问级别,把数组设为private。这样的�,就解决了数组在外部被修改的�安全性,但也产生了�一个问题,那就是这个数组�被外部使用的。 解决这个问题�代�: - +```` import java.util.AbstractList; import java.util.List; @@ -384,7 +386,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 } - +```` 这样就OK了,既��了代�安全,�能让数组中的元素被访问了。 @@ -397,7 +399,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 规则3:父类中private final方法,�类�以�新定义,这�情况�是�写。 代�示例 - +```` 规则1代� public class FinalMethodTest @@ -429,7 +431,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 // 下�方法定义将�会出现问题 public void test(){} } - +```` ## final 和 jvm的关系 @@ -439,8 +441,8 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 2. �次读一个包� final 域的对象的引用,与���次读这个 final 域,这两个�作之间�能�排�。 下�,我们通过一些示例性的代��分别说明这两个规则: - -
public class FinalExample {
+````
+public class FinalExample {
     int i;                            // 普通�� 
     final int j;                      //final �� 
     static FinalExample obj;
@@ -460,7 +462,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
         int b = object.j;                // 读 final 域 
     }
 }
-
+```` 这里�设一个线程 A 执行 writer () 方法,���一个线程 B 执行 reader () 方法。下�我们通过这两个线程的交互�说明这两个规则。 @@ -478,7 +480,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调 �设线程 B 读对象引用与读对象的�员域之间没有�排�(马上会说明为什么需�这个�设),下图是一��能的执行时�: -![](https://static001.infoq.cn/resource/image/66/3a/6628576a54f0ba625c8c3af4586cef3a.jpg) +![img](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/6628576a54f0ba625c8c3af4586cef3a.jpg) 在上图中,写普通域的�作被编译器�排�到了构造函数之外,读线程 B 错误的读�了普通�� i �始化之�的值。而写 final 域的�作,被写 final 域的�排�规则“�定�在了构造函数之内,读线程 B 正确的读�了 final ���始化之�的值。 @@ -511,8 +513,8 @@ reader() 方法包�三个�作: 上�我们看到的 final 域是基础数�类型,下�让我们看看如果 final 域是引用类型,将会有什么效果? 请看下列示例代�: - -
public class FinalReferenceExample {
+````
+public class FinalReferenceExample {
 final int[] intArray;                     //final 是引用类型 
 static FinalReferenceExample obj;
 
@@ -535,7 +537,7 @@ public static void reader () {              // 读线程 C 执行
     }
 }
 }
-
+```` 这里 final 域为一个引用类型,它引用一个 int 型的数组对象。对于引用类型,写 final 域的�排�规则对编译器和处�器增加了如下约�: @@ -543,14 +545,14 @@ public static void reader () { // 读线程 C 执行 对上�的示例程�,我们�设首先线程 A 执行 writerOne() 方法,执行完�线程 B 执行 writerTwo() 方法,执行完�线程 C 执行 reader () 方法。下�是一��能的线程执行时�: -![](https://static001.infoq.cn/resource/image/29/db/29b097c36fd531028991826bb7c835db.png) - +![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/29b097c36fd531028991826bb7c835db.png) 在上图中,1 是对 final 域的写入,2 是对这个 final 域引用的对象的�员域的写入,3 是把被构造的对象的引用赋值给�个引用��。这里除了���到的 1 �能和 3 �排�外,2 和 3 也�能�排�。 JMM �以确�读线程 C 至少能看到写线程 A 在构造函数中对 final 引用对象的�员域的写入。� C 至少能看到数组下标 0 的值为 1。而写线程 B 对数组元素的写入,读线程 C �能看的到,也�能看�到。JMM ���线程 B 的写入对读线程 C ��,因为写线程 B 和读线程 C 之间存在数�竞争,此时的执行结果��预知。 如果想�确�读线程 C 看到写线程 B 对数组元素的写入,写线程 B 和读线程 C 之间需�使用�步原语(lock 或 volatile)�确�内存��性。 + ## �考文章 https://www.infoq.cn/article/java-memory-model-6 diff --git "a/docs/java/basic/5\343\200\201Java\347\261\273\345\222\214\345\214\205.md" "b/docs/java/basic/5\343\200\201Java\347\261\273\345\222\214\345\214\205.md" index 4084792..89dda2c 100644 --- "a/docs/java/basic/5\343\200\201Java\347\261\273\345\222\214\345\214\205.md" +++ "b/docs/java/basic/5\343\200\201Java\347\261\273\345\222\214\345\214\205.md" @@ -1,28 +1,24 @@ # 目录 - * [Java中的包概念](#java中的包概念) +* [Java中的包概念](#java中的包概念) * [包的作用](#包的作用) * [package 的目录结构](#package-的目录结构) * [设置 CLASSPATH 系统��](#设置-classpath-系统��) - * [常用jar包](#常用jar包) +* [常用jar包](#常用jar包) * [java软件包的类型](#java软件包的类型) * [dt.jar](#dtjar) * [rt.jar](#rtjar) - * [*.java文件的奥秘](#java文件的奥秘) +* [*.java文件的奥秘](#java文件的奥秘) * [*.Java文件简介](#java文件简介) * [为什么一个java�文件中�能有一个public类?](#为什么一个java�文件中�能有一个public类?) * [Main方法](#main方法) * [外部类的访问��](#外部类的访问��) * [Java包的命�规则](#java包的命�规则) - * [�考文章](#�考文章) - * [微信公众�](#微信公众�) +* [�考文章](#�考文章) +* [微信公众�](#微信公众�) * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) ---- - - Java类 ---- - 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -74,11 +70,7 @@ Java 使用包(package)这�机制是为了防止命�冲�,访问控 package net.java.util; public class Something{ ... } - - - - -那么它的路径应该是 **net/java/util/Something.java** 这样�存的。 package(包) 的作用是把��的 java 程�分类�存,更方便的被其他 java 程�调用。 +那么它的路径应该是**net/java/util/Something.java**这样�存的。 package(包) 的作用是把��的 java 程�分类�存,更方便的被其他 java 程�调用。 一个包(package)�以定义为一组相互�系的类型(类�接��枚举和注释),为这些类型�供访问�护和命�空间管�的功能。 @@ -91,8 +83,6 @@ Java 使用包(package)这�机制是为了防止命�冲�,访问控 由于包创建了新的命�空间(namespace),所以�会跟其他包中的任何�字产生命�冲�。使用包这�机制,更容易实现访问控制,并且让定�相关类更加简�。 - - ### package 的目录结构 类放在包中会有两�主�的结果: @@ -104,28 +94,18 @@ Java 使用包(package)这�机制是为了防止命�冲�,访问控 将类�接�等类型的��放在一个文本中,这个文件的�字就是这个类型的�字,并以.java作为扩展�。例如: - - - - -// 文件� : Car.java package vehicle; public class Car { // 类实现 } - - - - +```` +// 文件� : Car.java +package vehicle; +public class Car { +// 类实现 +} +```` 接下�,把�文件放在一个目录中,这个目录�对应类所在包的�字。 - - - - ....\vehicle\Car.java - - - - 现在,正确的类�和路径将会是如下样�: * 类� -> vehicle.Car @@ -134,51 +114,49 @@ Java 使用包(package)这�机制是为了防止命�冲�,访问控 通常,一个公�使用它互�网域�的颠倒形��作为它的包�.例如:互�网域�是 runoob.com,所有的包�都以 com.runoob 开头。包�中的�一个部分对应一个�目录。 -例如:有一个 **com.runoob.test** 的包,这个包包�一个�� Runoob.java 的�文件,那么相应的,应该有如下�的一连串�目录: - - - - +例如:有一个**com.runoob.test**的包,这个包包�一个�� Runoob.java 的�文件,那么相应的,应该有如下�的一连串�目录: ....\com\runoob\test\Runoob.java - - - - 编译的时候,编译器为包中定义的�个类�接�等类型�创建一个��的输出文件,输出文件的�字就是这个类型的�字,并加上 .class 作为扩展�缀。 例如: - - - - - -// 文件�: Runoob.java package com.runoob.test; public class Runoob { } class Google { } - - - +```` +// 文件�: Runoob.java +package com.runoob.test; +public class Runoob { } +class Google { } +```` 现在,我们用-d选项�编译这个文件,如下: - -
$javac -d .  Runoob.java
- +```` + $javac -d . Runoob.java +```` 这样会�下�这样放置编译了的文件: -
.\com\runoob\test\Runoob.class  .\com\runoob\test\Google.class
- -你�以�下�这样�导入所有** \com\runoob\test\ **中定义的类�接�等: +```` + .\com\runoob\test\Runoob.class + .\com\runoob\test\Google.class +```` -
import com.runoob.test.*;
+你�以�下�这样�导入所有**\com\runoob\test\**中定义的类�接�等: +```` + import com.runoob.test.*; +```` 编译之�的 .class 文件应该和 .java �文件一样,它们放置的目录应该跟包的�字对应起�。但是,并��求 .class 文件的路径跟相应的 .java 的路径一样。你�以分开�安排��和类的目录。 -
\sources\com\runoob\test\Runoob.java \classes\com\runoob\test\Google.class
+```` + \sources\com\runoob\test\Runoob.java + \classes\com\runoob\test\Google.class +```` 这样,你�以将你的类目录分享给其他的编程人员,而�用�露自己的��。用这�方法管���和类文件�以让编译器和java 虚拟机(JVM)�以找到你程�中使用的所有类型。 -类目录的�对路径�� **class path**。设置在系统�� **CLASSPATH** 中。编译器和 java 虚拟机通过将 package �字加到 class path ��构造 .class 文件的路径。 +类目录的�对路径��**class path**。设置在系统��**CLASSPATH**中。编译器和 java 虚拟机通过将 package �字加到 class path ��构造 .class 文件的路径。 -\classes 是 class path,package �字是 com.runoob.test,而编译器和 JVM 会在 \classes\com\runoob\test 中找 .class 文件。 +```` + \classes 是 class path,package �字是 com.runoob.test,而编译器和 JVM 会在 \classes\com\runoob\test 中找 .class 文件。 +```` 一个 class path �能会包�好几个路径,多路径应该用分隔符分开。默认情况下,编译器和 JVM 查找当�目录。JAR 文件按包� Java 平�相关的类,所以他们的目录默认放在了 class path 中。 @@ -222,55 +200,54 @@ java包的作用是为了区别类�的命�空间   在 animals 包中加入一个接�(interface): - package animals; - - interface Animal { - public void eat(); - public void travel(); - } -  接下�,在�一个包中加入该接�的实现: - - package animals; - - /* 文件� : MammalInt.java */ - public class MammalInt implements Animal{ - - public void eat(){ - System.out.println("Mammal eats"); - } - - public void travel(){ - System.out.println("Mammal travels"); - } - - public int noOfLegs(){ - return 0; - } - - public static void main(String args[]){ - MammalInt m = new MammalInt(); - m.eat(); - m.travel(); - } - } - +```` +package animals; +interface Animal { + public void eat(); + public void travel(); +} +```` + +接下�,在�一个包中加入该接�的实现: + +```` +package animals; +/* 文件� : MammalInt.java */ +public class MammalInt implements Animal{ + public void eat(){ + System.out.println("Mammal eats"); + } + public void travel(){ + System.out.println("Mammal travels"); + } + public int noOfLegs(){ + return 0; + } + public static void main(String args[]){ + MammalInt m = new MammalInt(); + m.eat(); + m.travel(); + } +} +```` import 关键字 为了能够使用�一个包的�员,我们需�在 Java 程�中明确导入该包。使用 "import" 语��完�此功能。 在 java �文件中 import 语�应�于 package 语�之�,所有类的定义之�,�以没有,也�以有多�,其语法格�为: -1 -import package1[.package2…].(classname|*); -  如果在一个包中,一个类想�使用本包中的�一个类,那么该包��以�略。 +```` + import package1[.package2…].(classname|*); +```` + +如果在一个包中,一个类想�使用本包中的�一个类,那么该包��以�略。 通常,一个公�使用它互�网域�的颠倒形��作为它的包�.例如:互�网域�是 runoob.com,所有的包�都以 com.runoob 开头。包�中的�一个部分对应一个�目录。 例如:有一个 com.runoob.test 的包,这个包包�一个�� Runoob.java 的�文件,那么相应的,应该有如下�的一连串�目录: - -1 -....\com\runoob\test\Runoob.java - +``` + ....\com\runoob\test\Runoob.java +``` ## 常用jar包 ### java软件包的类型 @@ -291,36 +268,30 @@ import package1[.package2…].(classname|*); 6) java.net:包�支�网络�作的类。 ### dt.jar -> SUN对于dt.jar的定义:Also includes dt.jar, the DesignTime archive of BeanInfo files that tell interactive development environments (IDE's) how to display the Java components and how to let the developer customize them for the application。 -中文翻译过�就是:dt.jar是BeanInfo文件的DesignTime归档,BeanInfo文件用�告诉集�开�环境(IDE)如何显示Java组件还有如何让开�人员根�应用程�自定义它们。这段文字中�到了几个关键字:DesignTime,BeanInfo,IDE,Java components。其实dt.jar就是DesignTime Archive的缩写。那么何为DesignTime。 - -    何为DesignTime?翻译过�就是设计时。其实了解JavaBean的人都知�design time和runtime(�行时)这两个术语的�义。设计时(DesignTIme)是指在开�环境中通过添加控件,设置控件或窗体属性等方法,建立应用程�的时间。 -    -    与此相对应的�行时(RunTIme)是指�以象用户那样与应用程�交互作用的时间。那么现在��解一下上�的翻译,其实dt.jar包�了swing控件中的BeanInfo,而IDE的GUI Designer需�这些信�。那让我们看一下dt.jar中到底有什么?下�是一张dt.jar下�的内容截图: +> SUN对于dt.jar的定义:Also includesdt.jar, the DesignTime archive of BeanInfo files that tell interactive development environments (IDE's) how to display the Java components and how to let the developer customize them for the application。 -![image](http://www.blogjava.net/images/blogjava_net/landon/dt-jar.jpg) +中文翻译过�就是:dt.jar是BeanInfo文件的DesignTime归档,BeanInfo文件用�告诉集�开�环境(IDE)如何显示Java组件还有如何让开�人员根�应用程�自定义它们。这段文字中�到了几个关键字:DesignTime,BeanInfo,IDE,Java components。其实dt.jar就是DesignTime Archive的缩写。那么何为DesignTime。 -    从上�的截图�以看出,dt.jar中全部是Swing组件的BeanInfo。那么到底什么是BeanInfo呢? +何为DesignTime?翻译过�就是设计时。其实了解JavaBean的人都知�design time和runtime(�行时)这两个术语的�义。设计时(DesignTIme)是指在开�环境中通过添加控件,设置控件或窗体属性等方法,建立应用程�的时间。 -    何为BeanInfo?JavaBean和BeanInfo有很大的关系。Sun所制定的JavaBean规范,很大程度上是为IDE准备的——它让IDE能够以�视化的方�设置JavaBean的属性。如果在IDE中开�一个�视化应用程�,我们需�通过属性设置的方�对组�应用的��组件进行定制,IDE通过属性编辑器让开�人员使用�视化的方�设置组件的属性。 +与此相对应的�行时(RunTIme)是指�以象用户那样与应用程�交互作用的时间。那么现在��解一下上�的翻译,其实dt.jar包�了swing控件中的BeanInfo,而IDE的GUI Designer需�这些信�。那让我们看一下dt.jar中到底有什么? -    一般的IDE都支�JavaBean规范所定义的属性编辑器,当组件开�商�布一个组件时,它往往将组件对应的属性编辑器�绑�行,这样开�者就�以在IDE环境下方便地利用属性编辑器对组件进行定制工作。JavaBean规范通过java.beans.PropertyEditor定义了设置JavaBean属性的方法,通过BeanInfo�述了JavaBean哪些属性是�定制的,此外还�述了�定制属性与PropertyEditor的对应关系。 +dt.jar中全部是Swing组件的BeanInfo。那么到底什么是BeanInfo呢? -    BeanInfo与JavaBean之间的对应关系,通过两者之间规范的命�确立:对应JavaBean的BeanInfo采用如下的命�规范:BeanInfo。当JavaBean连�其属性编辑器相�的组件注册到IDE中�,当在开�界�中对JavaBean进行定制时,IDE就会根�JavaBean规范找到对应的BeanInfo,�根�BeanInfo中的�述信�找到JavaBean属性�述(是�开放�使用哪个属性编辑器),进而为JavaBean生�特定开�编辑界�。 +何为BeanInfo?JavaBean和BeanInfo有很大的关系。Sun所制定的JavaBean规范,很大程度上是为IDE准备的——它让IDE能够以�视化的方�设置JavaBean的属性。如果在IDE中开�一个�视化应用程�,我们需�通过属性设置的方�对组�应用的��组件进行定制,IDE通过属性编辑器让开�人员使用�视化的方�设置组件的属性。 -    dt.jar里�主�是swing组件的BeanInfo。IDE根�这些BeanInfo显示这些组件以�开�人员如何定制他们。 +dt.jar里�主�是swing组件的BeanInfo。IDE根�这些BeanInfo显示这些组件以�开�人员如何定制他们。 ### rt.jar rt.jar是runtime的归档。Java基础类库,也就是Java doc里�看到的所有的类的class文件。 -![image](https://img-blog.csdnimg.cn/20181115130130739.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Z1aGFuZ2hhbmc=,size_16,color_FFFFFF,t_70) +![image](https://www.pianshen.com/images/75/856cbbdf52da90fa4f9bbb7b0597ce63.png) - rt.jar 默认就在Root Classloader的加载路径里�的,而在Claspath�置该��是�需�的;�时jre/lib目录下的其他jar:jce.jar�jsse.jar�charsets.jar�resources.jar都在Root Classloader中。 +rt.jar 默认就在Root Classloader的加载路径里�的,而在Claspath�置该��是�需�的;�时jre/lib目录下的其他jar:jce.jar�jsse.jar�charsets.jar�resources.jar都在Root Classloader中。 -## *.java文件的奥秘 - -### *.Java文件简介 +## java文件的奥秘 +### Java文件简介 .java文件你�以认为�是一个文本文件, 这个文件�是用java语言写�的程�,或者说任务的代��。 @@ -335,43 +306,41 @@ rt.jar是runtime的归档。Java基础类库,也就是Java doc里�看到的 这里的.class文件在计算的体系结构中本质上对应的是一�机器语言(而这里的机器�作JVM),所以JVM本身是�以直接�行这里的.class文件。所以 你�以进一步地认为,.java与.class与其它的编程语法一样,它们都是程�员用��述自己的任务的一�语言,�是它们��的对象�一样,而计算机本身�能识别它自已定义的那些指令什么的(�次强调,这里的计算机本身没有那么严格的定义) > In short: -> +> > .java是Java的�文件�缀,里�存放程�员编写的功能代�。 -> +> > .class文件是字节�文件,由.java�文件通过javac命令编译�生�的文件。是�以�行在任何支�Java虚拟机的硬件平�和�作系统上的二进制文件。 -> +> > .class文件并�本地的�执行程�。Java虚拟机就是去�行.class文件从而实现程�的�行。 - - ### 为什么一个java�文件中�能有一个public类? -  在java编程�想(第四版)一书中有这样3段�(6.4 类的访问��): +在java编程�想(第四版)一书中有这样3段�(6.4 类的访问��): >   1.�个编译�元(文件)都�能有一个public类,这表示,�个编译�元都有�一的公共接�,用public类�表现。该接��以按�求包�众多的支�包访问��的类。如果在�个编译�元内有一个以上的public类,编译器就会给出错误信�。 -> +> >   2.public类的�称必须完全与�有该编译�元的文件�相�,包�大�写。如果�匹�,�样将得到编译错误。 -> +> >   3.虽然�是很常用,但编译�元内完全�带public类也是�能的。在这�情况下,�以��对文件命�。 总结相关的几个问题: 1�一个�.java��文件中是��以包括多个类(�是内部类)?有什么�制? ->   答:�以有多个类,但�能有一个public的类,并且public的类�必须与文件�相一致。 +> 答:�以有多个类,但�能有一个public的类,并且public的类�必须与文件�相一致。 2�为什么一个文件中�能有一个public的类 ->   答:编译器在编译时,针对一个java�代�文件(也称为“编译�元�)�会接�一个public类。�则报错。 +> 答:编译器在编译时,针对一个java�代�文件(也称为“编译�元�)�会接�一个public类。�则报错。 3�在java文件中是��以没有public类 ->   答:public类�是必须的,java文件中�以没有public类。 +> 答:public类�是必须的,java文件中�以没有public类。 4�为什么这个public的类的类�必须和文件�相� ->   答: 是为了方便虚拟机在相应的路径中找到相应的类所对应的字节�文件。 +> 答: 是为了方便虚拟机在相应的路径中找到相应的类所对应的字节�文件。 ### Main方法 @@ -400,27 +369,25 @@ rt.jar是runtime的归档。Java基础类库,也就是Java doc里�看到的 为什么�对外部类或类�修饰呢? -> 1.存在包概念:public 和 default 能区分这个外部类能对��包作一个划分 (default修饰的类,其他包中引入�了这个类,public修饰的类�能被import) -> +> 1.存在包概念:public 和 default 能区分这个外部类能对��包作一个划分 (default修饰的类,其他包中引入�了这个类,public修饰的类�能被import) +> > 2.protected是包内��并且�类��,但是当一个外部类想�继承一个protected修饰的��包类时,压根找�到这个类,更别�几层了 -> +> > 3.private修饰的外部类,其他任何外部类都无法导入它。 - - //Java中的文件��和public修饰的类�相�,�则会报错 - //如果没有public修饰的类,则文件�以��命� - public class Java中的类文件 { - - } - - //�公共开类的访问��默认是包访问��,�能用private和protected - //一个外部类的访问���有两�,一�是包内��,一�是包外��。 - //如果用private修饰,其他类根本无法看到这个类,也就没有�义了。 - //如果用protected,虽然也是包内��,但是如果有�类想�继承该类但是��包时, - //压根找�到这个类,也��能继承它了,所以干脆用default代替。 - class A{ - - } +```` +//Java中的文件��和public修饰的类�相�,�则会报错 +//如果没有public修饰的类,则文件�以��命� +public class Java中的类文件 { +} +//�公共开类的访问��默认是包访问��,�能用private和protected +//一个外部类的访问���有两�,一�是包内��,一�是包外��。 +//如果用private修饰,其他类根本无法看到这个类,也就没有�义了。 +//如果用protected,虽然也是包内��,但是如果有�类想�继承该类但是��包时, +//压根找�到这个类,也��能继承它了,所以干脆用default代替。 +class A{ +} +```` ### Java包的命�规则 @@ -458,6 +425,6 @@ https://blog.csdn.net/qq_36626914/article/details/80627454 作者是 985 硕士,蚂�金� JAVA 工程师,专注于 JAVA �端技术栈:SpringBoot�MySQL�分布��中间件�微�务,�时也懂点投资�财,�尔讲点算法和计算机�论基础,��学习和写作,相信终身学习的力�� -**程�员3T技术学习资�:** 一些程�员学习技术的资�大礼包,关注公众��,��回�关键字 **“资料�** ���费无套路获�。 +**程�员3T技术学习资�:** 一些程�员学习技术的资�大礼包,关注公众��,��回�关键字 **“资料�** ���费无套路获�。 ![](https://img-blog.csdnimg.cn/20190829222750556.jpg) diff --git "a/docs/java/basic/8\343\200\201Java\350\207\252\345\212\250\346\213\206\347\256\261\350\243\205\347\256\261\351\207\214\351\232\220\350\227\217\347\232\204\347\247\230\345\257\206.md" "b/docs/java/basic/8\343\200\201Java\350\207\252\345\212\250\346\213\206\347\256\261\350\243\205\347\256\261\351\207\214\351\232\220\350\227\217\347\232\204\347\247\230\345\257\206.md" index c6ed3af..0408300 100644 --- "a/docs/java/basic/8\343\200\201Java\350\207\252\345\212\250\346\213\206\347\256\261\350\243\205\347\256\261\351\207\214\351\232\220\350\227\217\347\232\204\347\247\230\345\257\206.md" +++ "b/docs/java/basic/8\343\200\201Java\350\207\252\345\212\250\346\213\206\347\256\261\350\243\205\347\256\261\351\207\214\351\232\220\350\227\217\347\232\204\347\247\230\345\257\206.md" @@ -18,10 +18,6 @@ * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) - - - Java基本数�类型 ---- - 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -148,14 +144,14 @@ float fn = Float.MIN_VALUE; //64� double dx = Double.MAX_VALUE; double dn = Double.MIN_VALUE; -//16� -char cx = Character.MAX_VALUE; -char cn = Character.MIN_VALUE; //1� boolean bt = Boolean.TRUE; boolean bf = Boolean.FALSE; ``` +``` +打�它们的结果�以得到 + `127` `-128` `32767` @@ -168,10 +164,9 @@ boolean bf = Boolean.FALSE; `1.4E-45` `1.7976931348623157E308` `4.9E-324` -`￿` - `true` `false` +``` ### 引用类型 @@ -203,23 +198,23 @@ char a = 'A' ## 自动拆箱和装箱(详解) Java 5增加了自动装箱与自动拆箱机制,方便基本类型与包装类型的相互转��作。在Java 5之�,如果�将一个int型的值转��对应的包装器类型Integer,必须显�的使用new创建一个新的Integer对象,或者调用��方法Integer.valueOf()。 - +```` //在Java 5之�,�能这样� Integer value = new Integer(10); //或者这样� Integer value = Integer.valueOf(10); //直接赋值是错误的 //Integer value = 10;` - +```` 在Java 5中,�以直接将整型赋给Integer对象,由编译器�完�从int型到Integer类型的转�,这就�自动装箱。 - -`//在Java 5中,直接赋值是�法的,由编译器�完�转�` -`Integer value = 10;` -`与此对应的,自动拆箱就是�以将包装类型转�为基本类型,具体的转�工作由编译器�完�。` -`//在Java 5 中�以直接这么�` -`Integer value = new Integer(10);` -`int i = value;` - +```` +//在Java 5中,直接赋值是�法的,由编译器�完�转� +Integer value = 10; +与此对应的,自动拆箱就是�以将包装类型转�为基本类型,具体的转�工作由编译器�完�。 +//在Java 5 中�以直接这么� +Integer value = new Integer(10); +int i = value; +```` 自动装箱与自动拆箱为程�员�供了很大的方便,而在实际的应用中,自动装箱与拆箱也是使用最广泛的特性之一。自动装箱和自动拆箱其实是Java编译器�供的一颗语法糖(语法糖是指在计算机语言中添加的��语法,这�语法对语言的功能并没有影�,但是更方便程�员使用。通过��高开�效率,增加代��读性,增加代�的安全性)。 ### 简易实现 @@ -231,6 +226,7 @@ Integer value = Integer.valueOf(10); 实例方法xxxValue():将具体的包装类型对象转��基本类型; 下�我们以int和Integer为例,说明Java中自动装箱与自动拆箱的实现机制。看如下代�: +```` class Auto //code1 { public static void main(String[] args) @@ -246,7 +242,10 @@ class Auto //code1 } } +```` + 上�的代�先将int型转为Integer对象,�讲Integer对象转�为int型,毫无疑问,这是�以正确�行的。�是,这�转�是怎么进行的呢?使用�编译工具,将生�的Class文件在�编译为Java文件,让我们看看�生了什么: +```` class Auto//code2 { public static void main(String[] paramArrayOfString) @@ -254,17 +253,11 @@ class Auto//code2 Integer localInteger = Integer.valueOf(10); int i = localInteger.intValue(); - - - - - - - Double localDouble = Double.valueOf(12.4D); double d = localDouble.doubleValue(); } } +```` 我们�以看到�过javac编译之�,code1的代�被转��了code2,实际�行时,虚拟机�行的就是code2的代�。也就是说,虚拟机根本�知�有自动拆箱和自动装箱这回事;在将Java�文件编译为class文件的过程中,javac编译器在自动装箱的时候,调用了Integer.valueOf()方法,在自动拆箱时,�调用了intValue()方法。我们�以看到,double和Double也是如此。 实现总结:其实自动装箱和自动�箱是编译器为我们�供的一颗语法糖。在自动装箱时,编译器调用包装类型的valueOf()方法;在自动拆箱时,编译器调用了相应的xxxValue()方法。 @@ -274,128 +267,132 @@ class Auto//code2 Integer�� +```` public final class Integer extends Number implements Comparable { - private final int value; - - /*Integer的构造方法,接�一个整型�数,Integer对象表示的int值,�存在value中*/ - public Integer(int value) { - this.value = value; - } - - /*equals()方法判断的是:所代表的int型的值是�相等*/ - public boolean equals(Object obj) { - if (obj instanceof Integer) { - return value == ((Integer)obj).intValue(); - } - return false; - } - - /*返回这个Integer对象代表的int值,也就是�存在value中的值*/ - public int intValue() { - return value; - } - - /** - * 首先会判断i是�在[IntegerCache.low,Integer.high]之间 - * 如果是,直接返回Integer.cache中相应的元素 - * �则,调用构造方法,创建一个新的Integer对象 - */ - public static Integer valueOf(int i) { - assert IntegerCache.high >= 127; - if (i >= IntegerCache.low && i <= IntegerCache.high) - return IntegerCache.cache[i + (-IntegerCache.low)]; - return new Integer(i); - } - - /** - * ��内部类,缓存了从[low,high]对应的Integer对象 - * low -128这个值�会被改� - * high 默认是127,�以改�,最大�超过:Integer.MAX_VALUE - (-low) -1 - * cache �存从[low,high]对象的Integer对象 - */ - private static class IntegerCache { - static final int low = -128; - static final int high; - static final Integer cache[]; - - static { - // high value may be configured by property - int h = 127; - String integerCacheHighPropValue = - sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); - if (integerCacheHighPropValue != null) { - int i = parseInt(integerCacheHighPropValue); - i = Math.max(i, 127); - // Maximum array size is Integer.MAX_VALUE - h = Math.min(i, Integer.MAX_VALUE - (-low) -1); - } - high = h; - - cache = new Integer[(high - low) + 1]; - int j = low; - for(int k = 0; k < cache.length; k++) - cache[k] = new Integer(j++); - } - - private IntegerCache() {} - } + private final int value; + + /*Integer的构造方法,接�一个整型�数,Integer对象表示的int值,�存在value中*/ + public Integer(int value) { + this.value = value; + } + + /*equals()方法判断的是:所代表的int型的值是�相等*/ + public boolean equals(Object obj) { + if (obj instanceof Integer) { + return value == ((Integer)obj).intValue(); + } + return false; + } + + /*返回这个Integer对象代表的int值,也就是�存在value中的值*/ + public int intValue() { + return value; + } + + /** + * 首先会判断i是�在[IntegerCache.low,Integer.high]之间 + * 如果是,直接返回Integer.cache中相应的元素 + * �则,调用构造方法,创建一个新的Integer对象 + */ + public static Integer valueOf(int i) { + assert IntegerCache.high >= 127; + if (i >= IntegerCache.low && i <= IntegerCache.high) + return IntegerCache.cache[i + (-IntegerCache.low)]; + return new Integer(i); + } + + /** + * ��内部类,缓存了从[low,high]对应的Integer对象 + * low -128这个值�会被改� + * high 默认是127,�以改�,最大�超过:Integer.MAX_VALUE - (-low) -1 + * cache �存从[low,high]对象的Integer对象 + */ + private static class IntegerCache { + static final int low = -128; + static final int high; + static final Integer cache[]; + + static { + // high value may be configured by property + int h = 127; + String integerCacheHighPropValue = + sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); + if (integerCacheHighPropValue != null) { + int i = parseInt(integerCacheHighPropValue); + i = Math.max(i, 127); + // Maximum array size is Integer.MAX_VALUE + h = Math.min(i, Integer.MAX_VALUE - (-low) -1); + } + high = h; + + cache = new Integer[(high - low) + 1]; + int j = low; + for(int k = 0; k < cache.length; k++) + cache[k] = new Integer(j++); + } + + private IntegerCache() {} + } } -以上是Oracle(Sun)公�JDK 1.7中Integer��的一部分,通过分�上�的代�,得到: -1)Integer有一个实例域value,它�存了这个Integer所代表的int型的值,且它是final的,也就是说这个Integer对象一�构造完�,它所代表的值就�能�被改�。 -2)Integer�写了equals()方法,它通过比较两个Integer对象的value,�判断是�相等。 -3)�点是��内部类IntegerCache,通过类�就�以�现:它是用�缓存数�的。它有一个数组,里��存的是连续的Integer对象。 - (a) low:代表缓存数�中最�的值,固定是-128。 - (b) high:代表缓存数�中最大的值,它�以被该改�,默认是127。high最�是127,最大是Integer.MAX_VALUE-(-low)-1,如果high超过了这个值,那么cache[ ]的长度就超过Integer.MAX_VALUE了,也就溢出了。 - (c) cache[]:里��存�从[low,high]所对应的Integer对象,长度是high-low+1(因为有元素0,所以�加1)。 -4)调用valueOf(int i)方法时,首先判断i是�在[low,high]之间,如果是,则�用Integer.cache[i-low]。比如,如果Integer.valueOf(3),直接返回Integer.cache[131];如果i�在这个范围,则调用构造方法,构造出一个新的Integer对象。 -5)调用intValue(),直接返回value的值。 -通过3)和4)�以�现,默认情况下,在使用自动装箱时,VM会�用[-128,127]之间的Integer对象。 - -Integer a1 = 1; -Integer a2 = 1; -Integer a3 = new Integer(1); -//会打�true,因为a1和a2是�一个对象,都是Integer.cache[129] -System.out.println(a1 == a2); -//false,a3构造了一个新的对象,��于a1,a2 -System.out.println(a1 == a3); +```` + + 以上是Oracle(Sun)公�JDK 1.7中Integer��的一部分,通过分�上�的代�,得到: + 1)Integer有一个实例域value,它�存了这个Integer所代表的int型的值,且它是final的,也就是说这个Integer对象一�构造完�,它所代表的值就�能�被改�。 + 2)Integer�写了equals()方法,它通过比较两个Integer对象的value,�判断是�相等。 + 3)�点是��内部类IntegerCache,通过类�就�以�现:它是用�缓存数�的。它有一个数组,里��存的是连续的Integer对象。 + (a) low:代表缓存数�中最�的值,固定是-128。 + (b) high:代表缓存数�中最大的值,它�以被该改�,默认是127。high最�是127,最大是Integer.MAX_VALUE-(-low)-1,如果high超过了这个值,那么cache[ ]的长度就超过Integer.MAX_VALUE了,也就溢出了。 + (c) cache[]:里��存�从[low,high]所对应的Integer对象,长度是high-low+1(因为有元素0,所以�加1)。 + 4)调用valueOf(int i)方法时,首先判断i是�在[low,high]之间,如果是,则�用Integer.cache[i-low]。比如,如果Integer.valueOf(3),直接返回Integer.cache[131];如果i�在这个范围,则调用构造方法,构造出一个新的Integer对象。 + 5)调用intValue(),直接返回value的值。 + 通过3)和4)�以�现,默认情况下,在使用自动装箱时,VM会�用[-128,127]之间的Integer对象。 + + Integer a1 = 1; + Integer a2 = 1; + Integer a3 = new Integer(1); + //会打�true,因为a1和a2是�一个对象,都是Integer.cache[129] + System.out.println(a1 == a2); + //false,a3构造了一个新的对象,��于a1,a2 + System.out.println(a1 == a3); ### 了解基本类型缓存(常�池)的最佳实践 - //基本数�类型的常�池是-128到127之间。 - // 在这个范围中的基本数�类的包装类�以自动拆箱,比较时直接比较数值大�。 - public static void main(String[] args) { - //int的自动拆箱和装箱�在-128到127范围中进行,超过该范围的两个integer的 == 判断是会返回false的。 - Integer a1 = 128; - Integer a2 = -128; - Integer a3 = -128; - Integer a4 = 128; - System.out.println(a1 == a4); - System.out.println(a2 == a3); - - Byte b1 = 127; - Byte b2 = 127; - Byte b3 = -128; - Byte b4 = -128; - //byte都是相等的,因为范围就在-128到127之间 - System.out.println(b1 == b2); - System.out.println(b3 == b4); - - // - Long c1 = 128L; - Long c2 = 128L; - Long c3 = -128L; - Long c4 = -128L; - System.out.println(c1 == c2); - System.out.println(c3 == c4); - - //char没有负值 - //�现char也是在0到127之间自动拆箱 - Character d1 = 128; - Character d2 = 128; - Character d3 = 127; - Character d4 = 127; - System.out.println(d1 == d2); - System.out.println(d3 == d4); +```` +//基本数�类型的常�池是-128到127之间。 +// 在这个范围中的基本数�类的包装类�以自动拆箱,比较时直接比较数值大�。 +public static void main(String[] args) { + +//int的自动拆箱和装箱�在-128到127范围中进行,超过该范围的两个integer的 == 判断是会返回false的。 +Integer a1 = 128; +Integer a2 = -128; +Integer a3 = -128; +Integer a4 = 128; +System.out.println(a1 == a4); +System.out.println(a2 == a3); + +Byte b1 = 127; +Byte b2 = 127; +Byte b3 = -128; +Byte b4 = -128; +//byte都是相等的,因为范围就在-128到127之间 +System.out.println(b1 == b2); +System.out.println(b3 == b4); + +Long c1 = 128L; +Long c2 = 128L; +Long c3 = -128L; +Long c4 = -128L; +System.out.println(c1 == c2); +System.out.println(c3 == c4); + +//char没有负值 +//�现char也是在0到127之间自动拆箱 +Character d1 = 128; +Character d2 = 128; +Character d3 = 127; +Character d4 = 127; +System.out.println(d1 == d2); +System.out.println(d3 == d4); `结果` @@ -409,27 +406,29 @@ System.out.println(a1 == a3); `true` - Integer i = 10; - Byte b = 10; - //比较Byte和Integer.两个对象无法直接比较,报错 - //System.out.println(i == b); - System.out.println("i == b " + i.equals(b)); - //答案是false,因为包装类的比较时先比较是�是�一个类,�是的�直接返回false. - int ii = 128; - short ss = 128; - long ll = 128; - char cc = 128; - System.out.println("ii == bb " + (ii == ss)); - System.out.println("ii == ll " + (ii == ll)); - System.out.println("ii == cc " + (ii == cc)); - - 结果 - i == b false - ii == bb true - ii == ll true - ii == cc true - - //这时候都是true,因为基本数�类型直接比较值,值一样就�以。 +Integer i = 10; +Byte b = 10; +//比较Byte和Integer.两个对象无法直接比较,报错 +//System.out.println(i == b); +System.out.println("i == b " + i.equals(b)); +//答案是false,因为包装类的比较时先比较是�是�一个类,�是的�直接返回false. + +int ii = 128; +short ss = 128; +long ll = 128; +char cc = 128; +System.out.println("ii == bb " + (ii == ss)); +System.out.println("ii == ll " + (ii == ll)); +System.out.println("ii == cc " + (ii == cc)); + +结果 +i == b false +ii == bb true +ii == ll true +ii == cc true + +//这时候都是true,因为基本数�类型直接比较值,值一样就�以。 +```` ### 总结: @@ -439,12 +438,10 @@ System.out.println(a1 == a3); (2)当需�一个基本类型时会自动拆箱,比如int a = new Integer(10);算术�算是在基本类型间进行的,所以当�到算术�算时会自动拆箱,比如代�中的 c == (a + b); -(3) 包装类型 == 基本类型时,包装类型自动拆箱; +(3)包装类型 == 基本类型时,包装类型自动拆箱; 需�注�的是:“==�在没�到算术�算时,�会自动拆箱;基本类型�会自动装箱为对应的包装类型,代�中最�一�说明的内容。 - - 在JDK 1.5中�供了自动装箱与自动拆箱,这其实是Java 编译器的语法糖,编译器通过调用包装类型的valueOf()方法实现自动装箱,调用xxxValue()方法自动拆箱。自动装箱和拆箱会有一些陷阱,那就是包装类型�用了�些对象。 (1)Integer默认�用了[-128,127]这些对象,其中高�置�以修改; @@ -468,11 +465,13 @@ Boolean没有自动装箱与拆箱,它也�用了Boolean.TRUE和Boolean.FALSE 上�自动拆箱和装箱的原�其实与常�池有关。 ### 存在栈中: -public void(int a) -{ -int i = 1; -int j = 1; -} + + public void(int a) + { + int i = 1; + int j = 1; + } + 方法中的i 存在虚拟机栈的局部��表里,i是一个引用,j也是一个引用,它们都指�局部��表里的整型值 1. int a是传值引用,所以a也会存在局部��表。 @@ -485,50 +484,53 @@ i是类的�员��。类实例化的对象存在堆中,所以�员�� 3 包装类对象怎么存 其实我们说的常�池也�以�对象池。 + 比如String a= new String("a").intern()时会先在常�池找是�有“a"对象如果有的�直接返回“a"对象在常�池的地�,�让引用a指�常��a"对象的内存地�。 -public native String intern(); Integer也是��。 下图是Integer类型在常�池中查找�值对象的方法。 - public static Integer valueOf(int i) { - if (i >= IntegerCache.low && i <= IntegerCache.high) - return IntegerCache.cache[i + (-IntegerCache.low)]; - return new Integer(i); - } - private static class IntegerCache { - static final int low = -128; - static final int high; - static final Integer cache[]; - - static { - // high value may be configured by property - int h = 127; - String integerCacheHighPropValue = - sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); - if (integerCacheHighPropValue != null) { - try { - int i = parseInt(integerCacheHighPropValue); - i = Math.max(i, 127); - // Maximum array size is Integer.MAX_VALUE - h = Math.min(i, Integer.MAX_VALUE - (-low) -1); - } catch( NumberFormatException nfe) { - // If the property cannot be parsed into an int, ignore it. - } +```` +public static Integer valueOf(int i) { + if (i >= IntegerCache.low && i <= IntegerCache.high) + return IntegerCache.cache[i + (-IntegerCache.low)]; + return new Integer(i); +} +private static class IntegerCache { + static final int low = -128; + static final int high; + static final Integer cache[]; + + static { + // high value may be configured by property + int h = 127; + String integerCacheHighPropValue = + sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); + if (integerCacheHighPropValue != null) { + try { + int i = parseInt(integerCacheHighPropValue); + i = Math.max(i, 127); + // Maximum array size is Integer.MAX_VALUE + h = Math.min(i, Integer.MAX_VALUE - (-low) -1); + } catch( NumberFormatException nfe) { + // If the property cannot be parsed into an int, ignore it. } - high = h; - - cache = new Integer[(high - low) + 1]; - int j = low; - for(int k = 0; k < cache.length; k++) - cache[k] = new Integer(j++); - - // range [-128, 127] must be interned (JLS7 5.1.7) - assert IntegerCache.high >= 127; } - - private IntegerCache() {} + high = h; + + cache = new Integer[(high - low) + 1]; + int j = low; + for(int k = 0; k < cache.length; k++) + cache[k] = new Integer(j++); + + // range [-128, 127] must be interned (JLS7 5.1.7) + assert IntegerCache.high >= 127; } + + private IntegerCache() {} +} +```` + 所以基本数�类型的包装类型�以在常�池查找对应值的对象,找�到就会自动在常�池创建该值的对象。 而String类型�以通过intern�完�这个�作。 @@ -537,7 +539,6 @@ JDK1.7�,常�池被放入到堆空间中,这导致intern()函数的功能 ``` -[java] view plain copy String s = new String("1"); s.intern(); String s2 = "1"; @@ -554,9 +555,6 @@ JDK1.6以�以下:false false JDK1.7以�以上:false true ``` -![image](https://img-blog.csdn.net/20180422231916788?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E3MjQ4ODg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) - -![image](https://img-blog.csdn.net/20180422231929413?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E3MjQ4ODg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) JDK1.6查找到常�池存在相�值的对象时会直接返回该对象的地�。 JDK 1.7�,intern方法还是会先去查询常�池中是�有已�存在,如果存在,则返回常�池中的引用,这一点与之�没有区别,区别在于,如果在常�池找�到对应的字符串,则�会�将字符串拷�到常�池,而�是在常�池中生�一个对原字符串的引用。 diff --git "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2724\357\274\232Java class\344\273\213\347\273\215\344\270\216\350\247\243\346\236\220\345\256\236\350\267\265.md" "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2724\357\274\232Java\345\255\227\350\212\202\347\240\201\344\273\213\347\273\215\344\270\216\350\247\243\346\236\220\345\256\236\350\267\265.md" similarity index 100% rename from "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2724\357\274\232Java class\344\273\213\347\273\215\344\270\216\350\247\243\346\236\220\345\256\236\350\267\265.md" rename to "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2724\357\274\232Java\345\255\227\350\212\202\347\240\201\344\273\213\347\273\215\344\270\216\350\247\243\346\236\220\345\256\236\350\267\265.md" diff --git "a/docs/java/jvm/\346\267\261\345\205\245\344\272\206\350\247\243JVM\350\231\232\346\213\237\346\234\2728\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md" "b/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2728\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md" similarity index 100% rename from "docs/java/jvm/\346\267\261\345\205\245\344\272\206\350\247\243JVM\350\231\232\346\213\237\346\234\2728\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md" rename to "docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2728\357\274\232Java\347\232\204\347\274\226\350\257\221\346\234\237\344\274\230\345\214\226\344\270\216\350\277\220\350\241\214\346\234\237\344\274\230\345\214\226.md" From ed040831f5e5b92008008b284f03f51218f33a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=B0=8F=E6=96=9C?= <362294931@qq.com> Date: Mon, 3 Apr 2023 22:15:41 +0800 Subject: [PATCH 23/98] modify basic mds --- ...43\200\201Java\345\274\202\345\270\270.md" | 659 ++++++++--------- ...55\347\232\204\345\233\236\350\260\203.md" | 352 +++++---- ...12\343\200\201\345\217\215\345\260\204.md" | 561 +++++++-------- ...13\343\200\201\346\263\233\345\236\213.md" | 666 +++++++++-------- ...01\346\236\232\344\270\276\347\261\273.md" | 329 ++++----- ...00\344\275\263\345\256\236\350\267\265.md" | 123 ++-- .../16\343\200\201JavaIO\346\265\201.md" | 127 ++-- ...01\345\244\232\347\272\277\347\250\213.md" | 9 - ...43\345\206\205\351\203\250\347\261\273.md" | 568 +++++++-------- ...06\346\236\266\346\242\263\347\220\206.md" | 680 +++++++++--------- .../20\343\200\201javac\345\222\214javap.md" | 439 ++++++----- ...10\346\236\201\346\214\207\345\215\227.md" | 468 ++++++------ ...15\345\272\217\345\210\227\345\214\226.md" | 610 ++++++++-------- ...36\347\216\260\345\216\237\347\220\206.md" | 531 +++++--------- ...73\345\222\214\346\216\245\345\217\243.md" | 149 ++-- ...47\350\241\214\351\241\272\345\272\217.md" | 85 ++- ...\261\273\345\222\214Object\347\261\273.md" | 166 ++--- 17 files changed, 3118 insertions(+), 3404 deletions(-) diff --git "a/docs/java/basic/10\343\200\201Java\345\274\202\345\270\270.md" "b/docs/java/basic/10\343\200\201Java\345\274\202\345\270\270.md" index c937417..7e76b60 100644 --- "a/docs/java/basic/10\343\200\201Java\345\274\202\345\270\270.md" +++ "b/docs/java/basic/10\343\200\201Java\345\274\202\345\270\270.md" @@ -19,11 +19,6 @@ * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) ---- - - - Java异常 ---- - 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -51,7 +46,7 @@ > 3� 由调用函数�分�异常,这�求程�员对库函数有很深的了解。 > - 在OO中�供的异常处�机制是�供代��壮的强有力的方�。使用异常机制它能够�低错误处�代�的��度,如果�使用异常,那么就必须检查特定的错误,并在程�中的许多地方去处�它。 +在OO中�供的异常处�机制是�供代��壮的强有力的方�。使用异常机制它能够�低错误处�代�的��度,如果�使用异常,那么就必须检查特定的错误,并在程�中的许多地方去处�它。 而如果使用异常,那就�必在方法调用处进行检查,因为异常机制将��能够�获这个错误,并且,�需在一个地方处�错误,�所谓的异常处�程�中。 @@ -61,21 +56,20 @@ ## 异常基本定义 -> 在《Think in java》中是这样定义异常的:异常情形是指阻止当�方法或者作用域继续执行的问题。在这里一定�明确一点:异常代���程度的错误,尽管Java有异常处�机制,但是我们�能以“正常�的眼光�看待异常,异常处�机制的原因就是告诉你:这里�能会或者已�产生了错误,您的程�出现了�正常的情况,�能会导致程�失败� +> 在《Think in java》中是这样定义异常的:异常情形是指阻止当�方法或者作用域继续执行的问题。在这里一定�明确一点:异常代���程度的错误,尽管Java有异常处�机制,但是我们�能以“正常�的眼光�看待异常,异常处�机制的原因就是告诉你:这里�能会或者已�产生了错误,您的程�出现了�正常的情况,�能会导致程�失败� -> 那么什么时候�会出现异常呢?�有在你当�的环境下程�无法正常�行下去,也就是说程�已�无法�正确解决问题了,这时它所就会从当�环境中跳出,并抛出异常。抛出异常�,它首先会�几件事。 +> 那么什么时候�会出现异常呢?�有在你当�的环境下程�无法正常�行下去,也就是说程�已�无法�正确解决问题了,这时它所就会从当�环境中跳出,并抛出异常。抛出异常�,它首先会�几件事。 > 首先,它会使用new创建一个异常对象,然�在产生异常的�置终止程�,并且从当�环境中弹出对异常对象的引用,这时。异常处�机制就会接管程�,并开始寻找一个�当的地方�继续执行程�,这个�当的地方就是异常处�程�。 -> 总的�说异常处�机制就是当程��生异常时,它强制终止程��行,记录异常信�并将这些信��馈给我们,由我们�确定是�处�异常。 +> 总的�说异常处�机制就是当程��生异常时,它强制终止程��行,记录异常信�并将这些信��馈给我们,由我们�确定是�处�异常。 ## 异常体系 -[外链图片转存失败(img-KNxcBTK0-1569073569353)(https://images0.cnblogs.com/blog/381060/201311/22185952-834d92bc2bfe498f9a33414cc7a2c8a4.png)] +![img](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/22185952-834d92bc2bfe498f9a33414cc7a2c8a4.png) 从上�这幅图�以看出,Throwable是java语言中所有错误和异常的超类(万物��抛)。它有两个�类:Error�Exception。 - Java标准库内建了一些通用的异常,这些类以Throwable为顶层父类。 Throwable�派生出Error类和Exception类。 @@ -103,7 +97,7 @@ Throwable�派生出Error类和Exception类。 异常是在执行�个函数时引�的,而函数�是层级调用,形�调用栈的,因为,��一个函数�生了异常,那么他的所有的caller都会被异常影�。当这些被影�的函数以异常信�输出时,就形�的了异常追踪栈。 异常最先�生的地方,��异常抛出点。 - +```` public class 异常 { public static void main (String [] args ) { @@ -130,9 +124,7 @@ Throwable�派生出Error类和Exception类。 // at com.javase.异常.异常.devide(异常.java:24) // at com.javase.异常.异常.CMDCalculate(异常.java:19) // at com.javase.异常.异常.main(异常.java:12) - - -​ + // ----欢迎使用命令行除法计算器---- // r // Exception in thread "main" java.util.InputMismatchException @@ -143,8 +135,7 @@ Throwable�派生出Error类和Exception类。 // at com.javase.异常.异常.CMDCalculate(异常.java:17) // at com.javase.异常.异常.main(异常.java:12) - -[外链图片转存失败(img-9rqUQJQj-1569073569354)(http://incdn1.b0.upaiyun.com/2017/09/0b3e4ca2f4cf8d7116c7ad354940601f.png)] +```` 从上�的例��以看出,当devide函数�生除0异常时,devide函数将抛出ArithmeticException异常,因此调用他的CMDCalculate函数也无法正常完�,因此也��异常,而CMDCalculate的caller——main 因为CMDCalculate抛出异常,也�生了异常,这样一直�调用栈的栈底回溯。 @@ -157,7 +148,7 @@ Throwable�派生出Error类和Exception类。 ## 异常和错误 下�看一个例� - +```` //错误�error一般指jvm无法处�的错误 //异常是Java定义的用于简化错误处��程和定�错误的一�工具。 public class 错误和错误 { @@ -198,7 +189,7 @@ Throwable�派生出Error类和Exception类。 // at com.javase.异常.错误.main(错误.java:11) } - +```` ## 异常的处�方� 在编写代�处�异常时,对于检查异常,有2���的处�方�: @@ -213,7 +204,7 @@ Throwable�派生出Error类和Exception类。 上�的例�是�行时异常,�需�显示�获。 下�这个例�是�检查异常需,�显示�获或者抛出。 - +```` @Test public void testException() throws IOException { @@ -309,6 +300,7 @@ Throwable�派生出Error类和Exception类。 // at com.javase.异常.异常处�方�.test(异常处�方�.java:62) throw new StringIndexOutOfBoundsException(); } +```` 其实有的语言在�到异常��然�以继续�行 @@ -321,11 +313,12 @@ Throwable�派生出Error类和Exception类。 throws是�一�处�异常的方�,它��于try…catch…finally,throws仅仅是将函数中�能出现的异常�调用者声明,而自己则�具体处�。 采�这�异常处�的原因�能是:方法本身�知�如何处�这样的异常,或者说让调用者处�更好,调用者需�为�能�生的异常负责。 - - public void foo() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN - { - //foo内部�以抛出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 类的异常,或者他们的�类的异常对象。 - } +```` +public void foo() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN +{ + //foo内部�以抛出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 类的异常,或者他们的�类的异常对象。 +} +```` ## 纠结的finally @@ -341,6 +334,7 @@ finally��管异常是��生,��对应的try执行了,则它一定 3�在�一try…catch…finally�中 ,try�生异常,且匹�的catch�中处�异常时也抛出异常,那么��的finally也会执行:首先执行finally�,然�去外围调用者中寻找�适的catch�。 +```` public class finally使用 { public static void main(String[] args) { try { @@ -357,6 +351,7 @@ finally��管异常是��生,��对应的try执行了,则它一定 } } } +```` ## throw : JRE也使用的关键字 @@ -365,15 +360,14 @@ throw exceptionObject 程�员也�以通过throw语�手动显�的抛出一个异常。throw语�的��必须是一个异常对象。 throw 语�必须写在函数中,执行throw 语�的地方就是一个异常抛出点,==它和由JRE自动形�的异常抛出点没有任何差别。== - - public void save(User user) - { - if(user == null) - throw new IllegalArgumentException("User对象为空"); - //...... - - } - +```` +public void save(User user) +{ + if(user == null) + throw new IllegalArgumentException("User对象为空"); + //...... +} +```` ��开始的大部分内容都摘自http://www.cnblogs.com/lulipro/p/7504267.html 该文章写的�分细致到�,令人钦佩,是我目�为之看到关于异常最详尽的文章,�以说是站在巨人的肩膀上了。 @@ -389,88 +383,86 @@ throw 语�必须写在函数中,执行throw 语�的地方就是一个异 > 异常链化:以一个异常对象为�数构造新的异常对象。新的异对象将包�先�异常的信�。这项技术主�是异常类的一个带Throwable�数的函数�实现的。这个当��数的异常,我们�他根�异常(cause)。 查看Throwable类��,�以�现里�有一个Throwable字段cause,就是它�存了构造时传递的根�异常�数。这�设计和链表的结点类设计如出一辙,因此形�链也是自然的了。 - - public class Throwable implements Serializable { - private Throwable cause = this; - - public Throwable(String message, Throwable cause) { - fillInStackTrace(); - detailMessage = message; - this.cause = cause; - } - public Throwable(Throwable cause) { - fillInStackTrace(); - detailMessage = (cause==null ? null : cause.toString()); - this.cause = cause; - } - - //........ +```` +public class Throwable implements Serializable { + private Throwable cause = this; + public Throwable(String message, Throwable cause) { + fillInStackTrace(); + detailMessage = message; + this.cause = cause; } - + public Throwable(Throwable cause) { + fillInStackTrace(); + detailMessage = (cause==null ? null : cause.toString()); + this.cause = cause; + } + //........ +} +```` 下�看一个比较实在的异常链例�哈 - - public class 异常链 { - @Test - public void test() { - C(); - } - public void A () throws Exception { - try { - int i = 1; - i = i / 0; - //当我注释掉这行代�并使用B方法抛出一个error时,�行结果如下 - // 四月 27, 2018 10:12:30 下� org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines - // 信�: Discovered TestEngines with IDs: [junit-jupiter] - // java.lang.Error: B也犯了个错误 - // at com.javase.异常.异常链.B(异常链.java:33) - // at com.javase.异常.异常链.C(异常链.java:38) - // at com.javase.异常.异常链.test(异常链.java:13) - // at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - // Caused by: java.lang.Error - // at com.javase.异常.异常链.B(异常链.java:29) - - }catch (ArithmeticException e) { - //这里通过throwable类的构造方法将最底层的异常�新包装并抛出,此时注入了A方法的信�。最�打�栈信�时�以看到caused by - A方法的异常。 - //如果直接抛出,栈信�打�结果�能看到上层方法的错误信�,�能看到其实是A�生了错误。 - //所以需�包装并抛出 - throw new Exception("A方法计算错误", e); - } - +```` +public class 异常链 { + @Test + public void test() { + C(); + } + public void A () throws Exception { + try { + int i = 1; + i = i / 0; + //当我注释掉这行代�并使用B方法抛出一个error时,�行结果如下 +// 四月 27, 2018 10:12:30 下� org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines +// 信�: Discovered TestEngines with IDs: [junit-jupiter] +// java.lang.Error: B也犯了个错误 +// at com.javase.异常.异常链.B(异常链.java:33) +// at com.javase.异常.异常链.C(异常链.java:38) +// at com.javase.异常.异常链.test(异常链.java:13) +// at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) +// Caused by: java.lang.Error +// at com.javase.异常.异常链.B(异常链.java:29) + + }catch (ArithmeticException e) { + //这里通过throwable类的构造方法将最底层的异常�新包装并抛出,此时注入了A方法的信�。最�打�栈信�时�以看到caused by + A方法的异常。 + //如果直接抛出,栈信�打�结果�能看到上层方法的错误信�,�能看到其实是A�生了错误。 + //所以需�包装并抛出 + throw new Exception("A方法计算错误", e); } - public void B () throws Exception,Error { - try { - //接收到A的异常, - A(); - throw new Error(); - }catch (Exception e) { - throw e; - }catch (Error error) { - throw new Error("B也犯了个错误", error); - } + + } + public void B () throws Exception,Error { + try { + //接收到A的异常, + A(); + throw new Error(); + }catch (Exception e) { + throw e; + }catch (Error error) { + throw new Error("B也犯了个错误", error); } - public void C () { - try { - B(); - }catch (Exception | Error e) { - e.printStackTrace(); - } - + } + public void C () { + try { + B(); + }catch (Exception | Error e) { + e.printStackTrace(); } - - //最�结果 - // java.lang.Exception: A方法计算错误 - // at com.javase.异常.异常链.A(异常链.java:18) - // at com.javase.异常.异常链.B(异常链.java:24) - // at com.javase.异常.异常链.C(异常链.java:31) - // at com.javase.异常.异常链.test(异常链.java:11) - // �略 - // Caused by: java.lang.ArithmeticException: / by zero - // at com.javase.异常.异常链.A(异常链.java:16) - // ... 31 more + } + //最�结果 +// java.lang.Exception: A方法计算错误 +// at com.javase.异常.异常链.A(异常链.java:18) +// at com.javase.异常.异常链.B(异常链.java:24) +// at com.javase.异常.异常链.C(异常链.java:31) +// at com.javase.异常.异常链.test(异常链.java:11) +// �略 +// Caused by: java.lang.ArithmeticException: / by zero +// at com.javase.异常.异常链.A(异常链.java:16) +// ... 31 more +} +```` ## 自定义异常 如果�自定义异常类,则扩展Exception类��,因此这样的自定义异常都属于检查异常(checked exception)。如果�自定义�检查异常,则扩展自RuntimeException。 @@ -482,7 +474,7 @@ throw 语�必须写在函数中,执行throw 语�的地方就是一个异 一个带有String�数和Throwable�数,并都传递给父类构造函数 一个带有Throwable �数的构造函数,并传递给父类的构造函数。 下�是IOException类的完整�代�,�以借鉴。 - +```` public class IOException extends Exception { static final long serialVersionUID = 7818375828146090155L; @@ -507,7 +499,7 @@ throw 语�必须写在函数中,执行throw 语�的地方就是一个异 super(cause); } } - +```` ## 异常的注�事项 异常的注�事项 @@ -517,47 +509,47 @@ throw 语�必须写在函数中,执行throw 语�的地方就是一个异 > 例如,父类方法throws 的是2个异常,�类就�能throws 3个�以上的异常。父类throws IOException,�类就必须throws IOException或者IOException的�类。 至于为什么?我想,也许下�的例��以说明。 - - class Father +```` +class Father +{ + public void start() throws IOException { - public void start() throws IOException - { - throw new IOException(); - } + throw new IOException(); } - - class Son extends Father +} + +class Son extends Father +{ + public void start() throws Exception { - public void start() throws Exception - { - throw new SQLException(); - } + throw new SQLException(); } +} /**********************�设上�的代�是�许的(实质是错误的)***********************/ - class Test +class Test +{ + public static void main(String[] args) { - public static void main(String[] args) + Father[] objs = new Father[2]; + objs[0] = new Father(); + objs[1] = new Son(); + + for(Father obj:objs) { - Father[] objs = new Father[2]; - objs[0] = new Father(); - objs[1] = new Son(); - - for(Father obj:objs) + //因为Son类抛出的实质是SQLException,而IOException无法处�它。 + //那么这里的try。。catch就�能处�Son中的异常。 + //多�就�能实现了。 + try { + obj.start(); + }catch(IOException) { - //因为Son类抛出的实质是SQLException,而IOException无法处�它。 - //那么这里的try。。catch就�能处�Son中的异常。 - //多�就�能实现了。 - try { - obj.start(); - }catch(IOException) - { - //处�IOException - } - } - } - } - + //处�IOException + } + } + } +} +```` ==Java的异常执行�程是线程独立的,线程之间没有影�== > Java程��以是多线程的。�一个线程都是一个独立的执行�,独立的函数调用栈。如果程��有一个线程,那么没有被任何代�处�的异常 会导致程�终止。如果是多线程的,那么没有被任何代�处�的异常仅仅会导致异常所在的线程结�。 @@ -565,44 +557,44 @@ throw 语�必须写在函数中,执行throw 语�的地方就是一个异 > 也就是说,Java中的异常是线程独立的,线程的问题应该由线程自己�解决,而��委托到外部,也�会直接影�到其它线程的执行。 下�看一个例� - - public class 多线程的异常 { - @Test - public void test() { - go(); - } - public void go () { - ExecutorService executorService = Executors.newFixedThreadPool(3); - for (int i = 0;i <= 2;i ++) { - int finalI = i; - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - executorService.execute(new Runnable() { - @Override - //�个线程抛出异常时并�会影�其他线程的继续执行 - public void run() { - try { - System.out.println("start thread" + finalI); - throw new Exception(); - }catch (Exception e) { - System.out.println("thread" + finalI + " go wrong"); - } - } - }); +```` +public class 多线程的异常 { + @Test + public void test() { + go(); + } + public void go () { + ExecutorService executorService = Executors.newFixedThreadPool(3); + for (int i = 0;i <= 2;i ++) { + int finalI = i; + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); } - // 结果: - // start thread0 - // thread0 go wrong - // start thread1 - // thread1 go wrong - // start thread2 - // thread2 go wrong - } + executorService.execute(new Runnable() { + @Override + //�个线程抛出异常时并�会影�其他线程的继续执行 + public void run() { + try { + System.out.println("start thread" + finalI); + throw new Exception(); + }catch (Exception e) { + System.out.println("thread" + finalI + " go wrong"); + } + } + }); + } +// 结果: +// start thread0 +// thread0 go wrong +// start thread1 +// thread1 go wrong +// start thread2 +// thread2 go wrong } - +} +```` ## 当finally�上return @@ -610,163 +602,160 @@ throw 语�必须写在函数中,执行throw 语�的地方就是一个异 首先一个�容易�解的事实: 在 try�中�便有return,break,continue等改�执行�的语�,finally也会执行。 +```` +public static void main(String[] args) +{ + int re = bar(); + System.out.println(re); +} +private static int bar() +{ + try{ + return 5; + } finally{ + System.out.println("finally"); + } +} +/*输出: +finally +*/ +```` - public static void main(String[] args) +也就是说:try…catch…finally中的return ��能执行,就都执行了,他们共���一个内存地�(�设地�是0×80)写入返回值,�执行的将覆盖先执行的数�,而真正被调用者�的返回值就是最�一次写入的。那么,按照这个�想,下�的这个例�也就�难�解了。 + +finally中的return 会覆盖 try 或者catch中的返回值。 +```` +public static void main(String[] args) { - int re = bar(); - System.out.println(re); + int result; + + result = foo(); + System.out.println(result); /////////2 + + result = bar(); + System.out.println(result); /////////2 } - private static int bar() + + @SuppressWarnings("finally") + public static int foo() { - try{ - return 5; + trz{ + int a = 5 / 0; + } catch (Exception e){ + return 1; } finally{ - System.out.println("finally"); + return 2; } + } - /*输出: - finally - */ -很多人�对这个问题时,总是在归纳执行的顺�和规律,�过我觉得还是很难�解。我自己总结了一个方法。用如下GIF图说明。 - - -[外链图片转存失败(img-SceF4t85-1569073569354)(http://incdn1.b0.upaiyun.com/2017/09/0471c2805ebd5a463211ced478eaf7f8.gif)] - -也就是说:try…catch…finally中的return ��能执行,就都执行了,他们共���一个内存地�(�设地�是0×80)写入返回值,�执行的将覆盖先执行的数�,而真正被调用者�的返回值就是最�一次写入的。那么,按照这个�想,下�的这个例�也就�难�解了。 - - -finally中的return 会覆盖 try 或者catch中的返回值。 - - public static void main(String[] args) - { - int result; - - result = foo(); - System.out.println(result); /////////2 - - result = bar(); - System.out.println(result); /////////2 - } - - @SuppressWarnings("finally") - public static int foo() - { - trz{ - int a = 5 / 0; - } catch (Exception e){ - return 1; - } finally{ - return 2; - } - - } - - @SuppressWarnings("finally") - public static int bar() - { - try { - return 1; - }finally { - return 2; - } + + @SuppressWarnings("finally") + public static int bar() + { + try { + return 1; + }finally { + return 2; } - + } +```` finally中的return会抑制(消�)��try或者catch�中的异常 - - class TestException +```` +class TestException +{ + public static void main(String[] args) { - public static void main(String[] args) - { - int result; - try{ - result = foo(); - System.out.println(result); //输出100 - } catch (Exception e){ - System.out.println(e.getMessage()); //没有�获到异常 - } - - try{ - result = bar(); - System.out.println(result); //输出100 - } catch (Exception e){ - System.out.println(e.getMessage()); //没有�获到异常 - } + int result; + try{ + result = foo(); + System.out.println(result); //输出100 + } catch (Exception e){ + System.out.println(e.getMessage()); //没有�获到异常 } - - //catch中的异常被抑制 - @SuppressWarnings("finally") - public static int foo() throws Exception - { - try { - int a = 5/0; - return 1; - }catch(ArithmeticException amExp) { - throw new Exception("我将被忽略,因为下�的finally中使用了return"); - }finally { - return 100; - } + + try{ + result = bar(); + System.out.println(result); //输出100 + } catch (Exception e){ + System.out.println(e.getMessage()); //没有�获到异常 } - - //try中的异常被抑制 - @SuppressWarnings("finally") - public static int bar() throws Exception - { - try { - int a = 5/0; - return 1; - }finally { - return 100; - } + } + + //catch中的异常被抑制 + @SuppressWarnings("finally") + public static int foo() throws Exception + { + try { + int a = 5/0; + return 1; + }catch(ArithmeticException amExp) { + throw new Exception("我将被忽略,因为下�的finally中使用了return"); + }finally { + return 100; } } + + //try中的异常被抑制 + @SuppressWarnings("finally") + public static int bar() throws Exception + { + try { + int a = 5/0; + return 1; + }finally { + return 100; + } + } +} +```` finally中的异常会覆盖(消�)��try或者catch中的异常 - - class TestException +```` +class TestException +{ + public static void main(String[] args) { - public static void main(String[] args) - { - int result; - try{ - result = foo(); - } catch (Exception e){ - System.out.println(e.getMessage()); //输出:我是finaly中的Exception - } - - try{ - result = bar(); - } catch (Exception e){ - System.out.println(e.getMessage()); //输出:我是finaly中的Exception - } + int result; + try{ + result = foo(); + } catch (Exception e){ + System.out.println(e.getMessage()); //输出:我是finaly中的Exception } - - //catch中的异常被抑制 - @SuppressWarnings("finally") - public static int foo() throws Exception - { - try { - int a = 5/0; - return 1; - }catch(ArithmeticException amExp) { - throw new Exception("我将被忽略,因为下�的finally中抛出了新的异常"); - }finally { - throw new Exception("我是finaly中的Exception"); - } + + try{ + result = bar(); + } catch (Exception e){ + System.out.println(e.getMessage()); //输出:我是finaly中的Exception } - - //try中的异常被抑制 - @SuppressWarnings("finally") - public static int bar() throws Exception - { - try { - int a = 5/0; - return 1; - }finally { - throw new Exception("我是finaly中的Exception"); - } - + } + + //catch中的异常被抑制 + @SuppressWarnings("finally") + public static int foo() throws Exception + { + try { + int a = 5/0; + return 1; + }catch(ArithmeticException amExp) { + throw new Exception("我将被忽略,因为下�的finally中抛出了新的异常"); + }finally { + throw new Exception("我是finaly中的Exception"); } } - + + //try中的异常被抑制 + @SuppressWarnings("finally") + public static int bar() throws Exception + { + try { + int a = 5/0; + return 1; + }finally { + throw new Exception("我是finaly中的Exception"); + } + + } +} +```` 上�的3个例�都异于常人的编��维,因此我建议: > ��在fianlly中使用return。 @@ -782,22 +771,24 @@ finally中的异常会覆盖(消�)��try或者catch中的异常   下�是我个人总结的在Java和J2EE开�者在�试中�常被问到的有关Exception和Error的知识。在分享我的回答的时候,我也给这些问题作了快速修订,并且�供��以便深入�解。我总结了��难度的问题,适�新手�农和高级Java�农。如果你�到了我列表中没有的问题,并且这个问题�常好,请在下�评论中分享出�。你也�以在评论中分享你�试时答错的情况。 **1) Java中什么是Exception?** -  这个问题�常在第一次问有关异常的时候或者是�试�鸟的时候问。我从�没�过�高级或者资深工程师的时候有人问这玩�,但是对于�鸟,是很愿�问这个的。简��说,异常是Java传达给你的系统和程�错误的方�。在java中,异常功能是通过实现比如Throwable,Exception,RuntimeException之类的类,然�还有一些处�异常时候的关键字,比如throw,throws,try,catch,finally之类的。 所有的异常都是通过Throwable�生出�的。Throwable把错误进一步划分为 java.lang.Exception -和 java.lang.Error.  java.lang.Error 用�处�系统错误,例如java.lang.StackOverFlowError 之类的。然� Exception用�处�程�错误,请求的资���用等等。 +这个问题�常在第一次问有关异常的时候或者是�试�鸟的时候问。我从�没�过�高级或者资深工程师的时候有人问这玩�,但是对于�鸟,是很愿�问这个的。简��说,异常是Java传达给你的系统和程�错误的方�。在java中,异常功能是通过实现比如Throwable,Exception,RuntimeException之类的类,然�还有一些处�异常时候的关键字,比如throw,throws,try,catch,finally之类的。所有的异常都是通过Throwable�生出�的。Throwable把错误进一步划分为java.lang.Exception +和 java.lang.Error. + +java.lang.Error 用�处�系统错误,例如java.lang.StackOverFlowError 之类的。然�Exception用�处�程�错误,请求的资���用等等。 **2) Java中的检查型异常和�检查型异常有什么区别?** -  这�是一个�常�行的Java异常�试题,会出现在��层次的Java�试中。检查型异常和�检查型异常的主�区别在于其处�方�。检查型异常需�使用try, catch和finally关键字在编译期进行处�,�则会出现编译器会报错。对于�检查型异常则�需�这样�。Java中所有继承自java.lang.Exception类的异常都是检查型异常,所有继承自RuntimeException的异常都被称为�检查型异常。 +这�是一个�常�行的Java异常�试题,会出现在��层次的Java�试中。检查型异常和�检查型异常的主�区别在于其处�方�。检查型异常需�使用try, catch和finally关键字在编译期进行处�,�则会出现编译器会报错。对于�检查型异常则�需�这样�。Java中所有继承自java.lang.Exception类的异常都是检查型异常,所有继承自RuntimeException的异常都被称为�检查型异常。 **3) Java中的NullPointerException和ArrayIndexOutOfBoundException之间有什么相�之处?** -  在Java异常�试中这并�是一个很�行的问题,但会出现在��层次的�学者�试中,用�测试应�者对检查型异常和�检查型异常的概念是�熟悉。顺便说一下,该题的答案是,这两个异常都是�检查型异常,都继承自RuntimeException。该问题�能会引出�一个问题,�Java和C的数组有什么��之处,因为C里�的数组是没有大��制的,�对�会抛出ArrayIndexOutOfBoundException。 +在Java异常�试中这并�是一个很�行的问题,但会出现在��层次的�学者�试中,用�测试应�者对检查型异常和�检查型异常的概念是�熟悉。顺便说一下,该题的答案是,这两个异常都是�检查型异常,都继承自RuntimeException。该问题�能会引出�一个问题,�Java和C的数组有什么��之处,因为C里�的数组是没有大��制的,�对�会抛出ArrayIndexOutOfBoundException。 **4)在Java异常处�的过程中,你�循的那些最好的实践是什么?** -  这个问题在�试技术��是�常常�的一个问题。因为异常处�在项目设计中是�常关键的,所以精通异常处�是�分必�的。异常处�有很多最佳实践,下�列举集中,它们�高你代�的�壮性和�活性: +这个问题在�试技术��是�常常�的一个问题。因为异常处�在项目设计中是�常关键的,所以精通异常处�是�分必�的。异常处�有很多最佳实践,下�列举集中,它们�高你代�的�壮性和�活性: -  1) 调用方法的时候返回布尔值�代替返回null,这样�以 NullPointerException。由于空指针是java异常里最�心的异常 +  1) 调用方法的时候返回布尔值�代替返回null,这样�以NullPointerException。由于空指针是java异常里最�心的异常   2) catch�里别�写代�。空catch�是异常处�里的错误事件,因为它�是�获了异常,�没有任何处�或者�示。通常你起��打�出异常信�,当然你最好根�需求对异常信�进行处�。 @@ -809,32 +800,20 @@ finally中的异常会覆盖(消�)��try或者catch中的异常 **5) 既然我们�以用RuntimeException�处�错误,那么你认为为什么Java中还存在检查型异常?** -  这是一个有争议的问题,在回答该问题时你应当�心。虽然他们肯定愿��到你的观点,但其实他们最感兴趣的还是有说�力的�由。我认为其中一个�由是,存在检查型异常是一个设计上的决定,�到了诸如C++等比Java更早编程语言设计�验的影�。�大多数检查型异常�于java.io包内,这是�乎情�的,因为在你请求了�存在的系统资�的时候,一段强壮的程�必须能够优雅的处�这�情况。通过把IOException声明为检查型异常,Java 确�了你能够优雅的对异常进行处�。�一个�能的�由是,�以使用catch或finally�确�数���的系统资�(比如文件�述符)在你使用�尽早得到释放。 Joshua -Bloch编写的 [Effective Java 一书](http://www.amazon.com/dp/0321356683/?tag=javamysqlanta-20) 中多处涉�到了该�题,值得一读。 - -**6)  throw 和 throws这两个关键字在java中有什么��?** - -  一个java�学者应该掌�的�试问题。 throw 和 throws�看起�是很相似的尤其是在你还是一个java�学者的时候。尽管他们看起�相似,都是在处�异常时候使用到的。但在代�里的使用方法和用到的地方是��的。throws总是出现在一个函数头中,用�标明该�员函数�能抛出的��异常, 你也�以申明未检查的异常,但这�是编译器强制的。如果方法抛出了异常那么调用这个方法的时候就需�将这个异常处�。�一个关键字  throw 是用�抛出任�异常的,按照语法你�以抛出任� Throwable (i.e. Throwable -或任何Throwable的�生类) , throw�以中断程��行,因此�以用�代替return . 最常�的例�是用 throw 在一个空方法中需�return的地方抛出 UnSupportedOperationException 代�如下 : - - - - - -| 123 | `private``static` `void` `show() {``throw``new` `UnsupportedOperationException(``"Notyet implemented"``);``}` | -| --- | --- | - - - +这是一个有争议的问题,在回答该问题时你应当�心。虽然他们肯定愿��到你的观点,但其实他们最感兴趣的还是有说�力的�由。我认为其中一个�由是,存在检查型异常是一个设计上的决定,�到了诸如C++等比Java更早编程语言设计�验的影�。�大多数检查型异常�于java.io包内,这是�乎情�的,因为在你请求了�存在的系统资�的时候,一段强壮的程�必须能够优雅的处�这�情况。通过把IOException声明为检查型异常,Java 确�了你能够优雅的对异常进行处�。�一个�能的�由是,�以使用catch或finally�确�数���的系统资�(比如文件�述符)在你使用�尽早得到释放。Joshua +Bloch编写的[Effective Java 一书](http://www.amazon.com/dp/0321356683/?tag=javamysqlanta-20)中多处涉�到了该�题,值得一读。 +**6) throw 和 throws这两个关键字在java中有什么��?** -  �以看下这篇 [文章](http://javarevisited.blogspot.com/2012/02/difference-between-throw-and-throws-in.html)查看这两个关键字在java中更多的差异 。 +  一个java�学者应该掌�的�试问题。throw 和 throws�看起�是很相似的尤其是在你还是一个java�学者的时候。尽管他们看起�相似,都是在处�异常时候使用到的。但在代�里的使用方法和用到的地方是��的。throws总是出现在一个函数头中,用�标明该�员函数�能抛出的��异常, 你也�以申明未检查的异常,但这�是编译器强制的。如果方法抛出了异常那么调用这个方法的时候就需�将这个异常处�。�一个关键字 throw 是用�抛出任�异常的,按照语法你�以抛出任� Throwable(i.e. Throwable +或任何Throwable的�生类) , throw�以中断程��行,因此�以用�代替return . 最常�的例�是用 throw 在一个空方法中需�return的地方抛出 UnSupportedOperationException. +�以看下这篇[文章](http://javarevisited.blogspot.com/2012/02/difference-between-throw-and-throws-in.html)查看这两个关键字在java中更多的差异 。 **7) 什么是“异常链�?**   “异常链�是Java中�常�行的异常处�概念,是指在进行一个异常处�时抛出了�外一个异常,由此产生了一个异常链�。该技术大多用于将“ �检查异常� ( checked exception)�装�为“��检查异常�(unchecked exception)或者RuntimeException。顺便说一下,如果因为因为异常你决定抛出一个新的异常,你一定�包�原有的异常,这样,处�程���以通过getCause()和initCause()方法�访问异常最终的根�。 -**) 你曾�自定义实现过异常�?怎么写的?** +**8) 你曾�自定义实现过异常�?怎么写的?**   很显然,我们�大多数都写过自定义或者业务异常,�AccountNotFoundException。在�试过程中询问这个Java异常问题的主�原因是去�现你如何使用这个特性的。这�以更准确和精致的去处�异常,当然这也跟你选择checked 还是unchecked exception��相关。通过为�一个特定的情况创建一个特定的异常,你就为调用者更好的处�异常�供了更好的选择。相比通用异常(general exception),我更倾�更为精确的异常。大�的创建自定义异常会增加项目class的个数,因此,在自定义异常和通用异常之间维�一个平衡是�功的关键。 diff --git "a/docs/java/basic/11\343\200\201\350\247\243\350\257\273Java\344\270\255\347\232\204\345\233\236\350\260\203.md" "b/docs/java/basic/11\343\200\201\350\247\243\350\257\273Java\344\270\255\347\232\204\345\233\236\350\260\203.md" index 1af4d91..02ace9b 100644 --- "a/docs/java/basic/11\343\200\201\350\247\243\350\257\273Java\344\270\255\347\232\204\345\233\236\350\260\203.md" +++ "b/docs/java/basic/11\343\200\201\350\247\243\350\257\273Java\344\270\255\347\232\204\345\233\236\350\260\203.md" @@ -11,18 +11,6 @@ * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) - - ---- -title: 夯实Java基础系列11:深入�解Java中的回调机制 -date: 2019-9-11 15:56:26 # 文章生�时间,一般�改 -categories: - - Java技术江湖 - - Java基础 -tags: - - 回调机制 ---- - 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -73,49 +61,49 @@ tags: Java多线程中�以通过callable和future或futuretask结��获�线程执行�的返回值。实现方法是通过get方法�调用callable的call方法获�返回值。 其实这�方法本质上�是回调,回调�求的是任务完�以�被调用者主动回调调用者的接�。而这里是调用者主动使用get方法阻塞获�返回值。 - - public class 多线程中的回调 { - //这里简�地使用future和callable实现了线程执行完� - public static void main(String[] args) throws ExecutionException, InterruptedException { - ExecutorService executor = Executors.newCachedThreadPool(); - Future future = executor.submit(new Callable() { - @Override - public String call() throws Exception { - System.out.println("call"); - TimeUnit.SECONDS.sleep(1); - return "str"; - } - }); - //手动阻塞调用get通过call方法获得返回值。 - System.out.println(future.get()); - //需�手动关闭,�然线程池的线程会继续执行。 - executor.shutdown(); - - //使用futuretask�时作为线程执行�元和数�请求�元。 - FutureTask futureTask = new FutureTask(new Callable() { +```` +public class 多线程中的回调 { + //这里简�地使用future和callable实现了线程执行完� + public static void main(String[] args) throws ExecutionException, InterruptedException { + ExecutorService executor = Executors.newCachedThreadPool(); + Future future = executor.submit(new Callable() { @Override - public Integer call() throws Exception { - System.out.println("dasds"); - return new Random().nextInt(); + public String call() throws Exception { + System.out.println("call"); + TimeUnit.SECONDS.sleep(1); + return "str"; } }); - new Thread(futureTask).start(); - //阻塞获�返回值 - System.out.println(futureTask.get()); - } - @Test - public void test () { - Callable callable = new Callable() { - @Override - public Object call() throws Exception { - return null; - } - }; - FutureTask futureTask = new FutureTask(callable); + //手动阻塞调用get通过call方法获得返回值。 + System.out.println(future.get()); + //需�手动关闭,�然线程池的线程会继续执行。 + executor.shutdown(); - } - } + //使用futuretask�时作为线程执行�元和数�请求�元。 + FutureTask futureTask = new FutureTask(new Callable() { + @Override + public Integer call() throws Exception { + System.out.println("dasds"); + return new Random().nextInt(); + } + }); + new Thread(futureTask).start(); + //阻塞获�返回值 + System.out.println(futureTask.get()); +} +@Test +public void test () { + Callable callable = new Callable() { + @Override + public Object call() throws Exception { + return null; + } + }; + FutureTask futureTask = new FutureTask(callable); +} +} +```` ## Java回调机制实战 曾�自己�尔�说过回调机制,��约约能够懂一些��,但是当让自己写一个简�的示例程�时,自己就傻眼了。��工作�验的增加,自己�常�到这儿使用了回调,那儿使用了回调,自己是时候好好研究一下Java回调机制了。网上关于Java回调的文章一抓一大把,但是看完总是云里雾里,�知所云,特别是看到抓�别人的代�走两步时,总是现眼。于是自己决定写一篇关于Java机制的文章,以方便大家和自己更深入的学习Java回调机制。 @@ -138,22 +126,12 @@ Java多线程中�以通过callable和future或futuretask结��获�线程 �步调用时�图: - - - - -![](https://upload-images.jianshu.io/upload_images/3796264-6a5b5b898aa3930e.png?imageMogr2/auto-orient/strip|imageView2/2/w/1031/format/webp) - - - -�步调用时�图 - +![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230403210703.png) **1.1.1 底层�务类:BottomService.java** -``` - +```` package synchronization.demo; /** @@ -182,11 +160,11 @@ return param +" BottomService.bottom() execute -->"; } -``` + **1.1.2 上层�务接�: UpperService.java** -``` + package synchronization.demo; /** @@ -203,11 +181,11 @@ public String callBottomService(final String param); } -``` + **1.1.3 上层�务接�实现类:UpperServiceImpl.java** -``` + package synchronization.demo; /** @@ -244,11 +222,11 @@ return bottomService.bottom(param + " callBottomService.bottom() execute --> "); } -``` + **1.1.4 Test测试类:Test.java** -``` + package synchronization.demo; import java.util.Date; @@ -281,7 +259,7 @@ System.out.println("=============== callBottomService end ====================:" } -``` +```` **1.1.5 输出结果:** @@ -306,37 +284,37 @@ callBottomService start --> callBottomService.bottom() execute --> BottomServi 解答:回调更�是一个约定,就是如果我调用了b()方法,那么就必须�回调,而�需�显示调用 一�Java的回调-浅 我们用例��解释:�明和��相约一起去�早饭,但是��起的有点晚�先洗漱,等��洗漱完��,通知�明�一起去�饭。�明就是类A,��就是类B。一起去�饭这个事件就是方法a(),��去洗漱就是方法b()。 - - public class XiaoMing { - //�明和��一起�饭 - public void eatFood() { - XiaoLi xl = new XiaoLi(); - //A调用B的方法 - xl.washFace(); - } - - public void eat() { - System.out.print("�明和��一起去�大龙虾"); - } - } - 那么怎么让��洗漱完�在通知�明一起去�饭呢 - - public class XiaoMing { - //�明和��一起�饭 - public void eatFood() { - XiaoLi xl = new XiaoLi(); - //A调用B的方法 - xl.washFace(); - eat(); - } - - public void eat() { - System.out.print("�明和��一起去�大龙虾"); - } - } - +```` +public class XiaoMing { + //�明和��一起�饭 + public void eatFood() { + XiaoLi xl = new XiaoLi(); + //A调用B的方法 + xl.washFace(); + } + + public void eat() { + System.out.print("�明和��一起去�大龙虾"); + } +} +那么怎么让��洗漱完�在通知�明一起去�饭呢 + +public class XiaoMing { + //�明和��一起�饭 + public void eatFood() { + XiaoLi xl = new XiaoLi(); + //A调用B的方法 + xl.washFace(); + eat(); + } + + public void eat() { + System.out.print("�明和��一起去�大龙虾"); + } +} +```` �过上�已�说过了这个�是回调函数,所以�能这样�,正确的方�如下 - +```` public class XiaoLi{//�� public void washFace() { System.out.print("���洗漱"); @@ -345,7 +323,7 @@ callBottomService start --> callBottomService.bottom() execute --> BottomServi xm.eat();//洗漱完�,一起去�饭 } } - +```` 这样�就�以实现washFace()�时也能实现eat()。��洗漱完�,�通知�明一起去�饭,这就是回调。 二�Java的回调-中 @@ -354,50 +332,50 @@ callBottomService start --> callBottomService.bottom() execute --> BottomServi �明和��相约一起去�早饭,但是��起的有点晚�先洗漱,等��洗漱完��,通知�明�一起去�饭。�明就是类A,��就是类B。��的是我们新建一个�饭的接�EatRice,接�中有个抽象方法eat()。在�明中调用这个接�,并实现eat();��声明这个接�对象,并且调用这个接�的抽象方法。这里�能有点绕�,�过没关系,看看例�就很清楚了。 EatRice接�: +```` +public interface EatRice { + public void eat(String food); +} +�明: - public interface EatRice { - public void eat(String food); - } - �明: - - public class XiaoMing implements EatRice{//�明 - - //�明和��一起�饭 - public void eatFood() { - XiaoLi xl = new XiaoLi(); - //A调用B的方法 - xl.washFace("大龙虾", this);//this指的是�明这个类实现的EatRice接� - } - - @Override - public void eat(String food) { - // TODO Auto-generated method stub - System.out.println("�明和��一起去�" + food); - } - } - ��: - - public class XiaoLi{//�� - public void washFace(String food,EatRice er) { - System.out.println("���洗漱"); - //B调用了A的方法 - er.eat(food); - } - } - 测试Demo: - - public class demo { - public static void main(String args[]) { - XiaoMing xm = new XiaoMing(); - xm.eatFood(); - } - } +public class XiaoMing implements EatRice{//�明 + //�明和��一起�饭 + public void eatFood() { + XiaoLi xl = new XiaoLi(); + //A调用B的方法 + xl.washFace("大龙虾", this);//this指的是�明这个类实现的EatRice接� + } + + @Override + public void eat(String food) { + // TODO Auto-generated method stub + System.out.println("�明和��一起去�" + food); + } +} +��: + +public class XiaoLi{//�� + public void washFace(String food,EatRice er) { + System.out.println("���洗漱"); + //B调用了A的方法 + er.eat(food); + } +} +测试Demo: + +public class demo { + public static void main(String args[]) { + XiaoMing xm = new XiaoMing(); + xm.eatFood(); + } +} +```` 测试结果: 这样�就通过接�的形�实现了软编�。通过接�的形�我�以实现��洗漱完�,和�王一起去上网。代�如下 - +```` public class XiaoWang implements EatRice{//�王 //�王和��一起去上网 @@ -413,7 +391,7 @@ EatRice接�: System.out.println("�王和��一起去" + bar); } } - +```` ## 实例三:Tom�题 数学�师让Tom�一�题,并且Tom�题期间数学�师�用盯�Tom,而是在玩手机,等Tom把题目�完��把答案告诉�师。 @@ -425,64 +403,64 @@ EatRice接�: > 3 Tom需�数学�师的一个引用,以便Tom把答案给这��师,而�是隔�的体育�师。 回调接�,�以�解为�师接� +```` +//回调指的是A调用B��一件事,B�完以�将结果告诉给A,这期间A�以�别的事情。 +//这个接�中有一个方法,�为B�完题目�告诉A时使用的方法。 +//所以我们必须�供这个接�以便让B�回调。 +//回调接�, +public interface CallBack { + void tellAnswer(int res); +} +```` - //回调指的是A调用B��一件事,B�完以�将结果告诉给A,这期间A�以�别的事情。 - //这个接�中有一个方法,�为B�完题目�告诉A时使用的方法。 - //所以我们必须�供这个接�以便让B�回调。 - //回调接�, - public interface CallBack { - void tellAnswer(int res); - } - - 数学�师类 - - //�师类实例化回调接�,�学生写完题目之�通过�师的�供的方法进行回调。 - //那么学生如何调用到�师的方法呢,��在学生类的方法中传入�师的引用��。 - //而�师需�指定学生答题,所以也�传入学生的实例。 - public class Teacher implements CallBack{ - private Student student; - - Teacher(Student student) { - this.student = student; - } - - void askProblem (Student student, Teacher teacher) { - //main方法是主线程�行,为了实现异步回调,这里开�一个线程��作 - new Thread(new Runnable() { - @Override - public void run() { - student.resolveProblem(teacher); - } - }).start(); - //�师让学生�题以�,等待学生回答的这段时间,�以�别的事,比如玩手机.\ - //而�需��步等待,这就是回调的好处。 - //当然你�以说开�一个线程让学生�题就行了,但是这样无法让学生通知�师。 - //需��外的机制去实现通知过程。 - // 当然,多线程中的future和callable也�以实现数�获�的功能。 - for (int i = 1;i < 4;i ++) { - System.out.println("等学生回答问题的时候�师玩了 " + i + "秒的手机"); +```` + //�师类实例化回调接�,�学生写完题目之�通过�师的�供的方法进行回调。 + //那么学生如何调用到�师的方法呢,��在学生类的方法中传入�师的引用��。 + //而�师需�指定学生答题,所以也�传入学生的实例。 +public class Teacher implements CallBack{ + private Student student; + + Teacher(Student student) { + this.student = student; + } + + void askProblem (Student student, Teacher teacher) { + //main方法是主线程�行,为了实现异步回调,这里开�一个线程��作 + new Thread(new Runnable() { + @Override + public void run() { + student.resolveProblem(teacher); } - } - - @Override - public void tellAnswer(int res) { - System.out.println("the answer is " + res); + }).start(); + //�师让学生�题以�,等待学生回答的这段时间,�以�别的事,比如玩手机.\ + //而�需��步等待,这就是回调的好处。 + //当然你�以说开�一个线程让学生�题就行了,但是这样无法让学生通知�师。 + //需��外的机制去实现通知过程。 + // 当然,多线程中的future和callable也�以实现数�获�的功能。 + for (int i = 1;i < 4;i ++) { + System.out.println("等学生回答问题的时候�师玩了 " + i + "秒的手机"); } } - -学生接� + @Override + public void tellAnswer(int res) { + System.out.println("the answer is " + res); + } +} +```` +学生接� +```` //学生的接�,解决问题的方法中�传入�师的引用,�则无法完�对具体实例的回调。 //写为接�的好处就是,很多个学生都�以实现这个接�,并且�师在�问题时�以通过 //传入List���学生,�分方便。 public interface Student { void resolveProblem (Teacher teacher); } - +```` 学生Tom - +```` public class Tom implements Student{ @Override @@ -496,9 +474,9 @@ EatRice接�: e.printStackTrace(); } } - +```` 测试类 - +```` public class Test { public static void main(String[] args) { //测试 @@ -513,9 +491,7 @@ EatRice接�: // the answer is 111 } } - - - +```` ## �考文章 https://blog.csdn.net/fengye454545/article/details/80198446 diff --git "a/docs/java/basic/12\343\200\201\345\217\215\345\260\204.md" "b/docs/java/basic/12\343\200\201\345\217\215\345\260\204.md" index 0513f67..4eb6669 100644 --- "a/docs/java/basic/12\343\200\201\345\217\215\345\260\204.md" +++ "b/docs/java/basic/12\343\200\201\345\217\215\345\260\204.md" @@ -25,16 +25,6 @@ * [微信公众�](#微信公众�) * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) ---- -title: 夯实Java基础系列12:深入�解Java中的�射机制 -date: 2019-9-12 15:56:26 # 文章生�时间,一般�改 -categories: - - Java技术江湖 - - Java基础 -tags: - - Java�射 ---- - 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -61,11 +51,11 @@ Oracle官方对�射的解释是 > The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control. > ->  简而言之,通过�射,我们�以在�行时获得程�或程�集中�一个类型的�员和�员的信�。 +> 简而言之,通过�射,我们�以在�行时获得程�或程�集中�一个类型的�员和�员的信�。 > > 程�中一般的对象的类型都是在编译期就确定下�的,而Java�射机制�以动�地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们�以通过�射机制直接创建对象,�使这个对象的类型在编译期是未知的。 > ->  �射的核心是JVM在�行时�动�加载类或调用方法/访问属性,它�需�事先(写代�的时候或编译期)知��行对象是�。 +> �射的核心是JVM在�行时�动�加载类或调用方法/访问属性,它�需�事先(写代�的时候或编译期)知��行对象是�。 Java�射框架主��供以下功能: @@ -82,27 +72,15 @@ Java�射框架主��供以下功能: ## �射的主�用途 ->  很多人都认为�射在实际的Java开�应用中并�广泛,其实�然。 - ->  当我们在使用IDE(如Eclipse,IDEA)时,当我们输入一个对象或类并想调用它的属性或方法时,一按点�,编译器就会自动列出它的属性或方法,这里就会用到�射。 - ->  �射最��的用途就是开���通用框架。 +> 很多人都认为�射在实际的Java开�应用中并�广泛,其实�然。 ->  很多框架(比如Spring)都是�置化的(比如通过XML文件�置JavaBean,Action之类的),为了��框架的通用性,它们�能需�根��置文件加载��的对象或类,调用��的方法,这个时候就必须用到�射——�行时动�加载需�加载的对象。 +> 当我们在使用IDE(如Eclipse,IDEA)时,当我们输入一个对象或类并想调用它的属性或方法时,一按点�,编译器就会自动列出它的属性或方法,这里就会用到�射。 ->  举一个例�,在�用Struts 2框架的开�中我们一般会在struts.xml里去�置Action,比如: +> �射最��的用途就是开���通用框架。 - - /shop/shop-index.jsp - login.jsp - -�置文件与Action建立了一�映射关系,当View层�出请求时,请求会被StrutsPrepareAndExecuteFilter拦截,然�StrutsPrepareAndExecuteFilter会去动�地创建Action实例。 +> 很多框架(比如Spring)都是�置化的(比如通过XML文件�置JavaBean,Action之类的),为了��框架的通用性,它们�能需�根��置文件加载��的对象或类,调用��的方法,这个时候就必须用到�射——�行时动�加载需�加载的对象。 -——比如我们请求login.action,那么StrutsPrepareAndExecuteFilter就会去解�struts.xml文件,检索action中name为login的Action,并根�class属性创建SimpleLoginAction实例,并用invoke方法�调用execute方法,这个过程离�开�射。 - -> 对与框架开�人员�说,�射虽�但作用�常大,它是��容器实现的核心。而对于一般的开�者�说,�深入框架开�则用�射用的就会少一点,�过了解一下框架的底层机制有助于丰富自己的编程�想,也是很有益的。 +> 对于框架开�人员�说,�射虽�但作用�常大,它是��容器实现的核心。而对于一般的开�者�说,�深入框架开�则用�射用的就会少一点,�过了解一下框架的底层机制有助于丰富自己的编程�想,也是很有益的。 ## �射的基础:关于Class类 @@ -117,25 +95,26 @@ Java�射框架主��供以下功能: > 4�Class 对象�能由系统建立对象 > > 5�一个类在 JVM 中�会有一个Class实例 - - //总结一下就是,JDK有一个类��Class,这个类用��装所有Java类型,包括这些类的所有信�,JVM中类信�是放在方法区的。 - - //所有类在加载�,JVM会为其在堆中创建一个Class<类�称>的对象,并且�个类�会有一个Class对象,这个类的所有对象都�通过Class<类�称>�进行实例化。 - - //上�说的是JVM进行实例化的原�,当然实际上在Java写代�时�需�用 类�称就�以进行实例化了。 - - public final class Class implements java.io.Serializable, - GenericDeclaration, - Type, - AnnotatedElement { - 虚拟机会��唯一一 - //通过类�.class获得唯一的Class对象。 - Class cls = UserBean.class; - //通过integer.TYPEl�获�Class对象 - Class inti = Integer.TYPE; - //接�本质也是一个类,一样�以通过.class获� - Class userClass = User.class; - +> +```` +//总结一下就是,JDK有一个类��Class,这个类用��装所有Java类型,包括这些类的所有信�,JVM中类信�是放在方法区的。 + +//所有类在加载�,JVM会为其在堆中创建一个Class<类�称>的对象,并且�个类�会有一个Class对象,这个类的所有对象都�通过Class<类�称>�进行实例化。 + +//上�说的是JVM进行实例化的原�,当然实际上在Java写代�时�需�用 类�称就�以进行实例化了。 + +public final class Class implements java.io.Serializable, + GenericDeclaration, + Type, + AnnotatedElement { + //通过类�.class获得唯一的Class对象。 + Class cls = UserBean.class; + //通过integer.TYPEl�获�Class对象 + Class inti = Integer.TYPE; + //接�本质也是一个类,一样�以通过.class获� + Class userClass = User.class; +} +```` JAVA�射机制是在�行状�中,对于任�一个类,都能够知�这个类的所有属性和方法;对于任�一个对象,都能够调用它的任�一个方法和属性;这�动�获�的信�以�动�调用对象的方法的功能称为java语言的�射机制。 �想解剖一个类,必须先�获�到该类的字节�文件对象。而解剖使用的就是Class类中的方法.所以先�获�到�一个字节�文件对应的Class类型的对象. @@ -146,8 +125,7 @@ JAVA�射机制是在�行状�中,对于任�一个类,都能够知� 如图是类的正常加载过程:�射的原�在与class对象。 熟悉一下加载的时候:Class对象的由�是将class文件读入内存,并为之创建一个Class对象。 -![](https://img-blog.csdn.net/20170513133210763) - +![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230403211245.png) ## Java为什么需��射?�射�解决什么问题? Java中编译类型有两�: @@ -176,29 +154,31 @@ Array类:�供了动�创建数组,以�访问数组的元素的��方 1�获得Class对象方法有三� (1)使用Class类的forName��方法: - - public static Class forName(String className) - ``` - 在JDBC开�中常用此方法加载数�库驱动: - �使用全类��加载这个类,一般数�库驱动的�置信�会写在�置文件中。加载这个驱动��先导入jar包 - ```java - Class.forName(driver); +```` +public static Class forName(String className) +```` +在JDBC开�中常用此方法加载数�库驱动: +�使用全类��加载这个类,一般数�库驱动的�置信�会写在�置文件中。加载这个驱动��先导入jar包 +```` +Class.forName(driver); +```` (2)直接获��一个对象的class,比如: - - //Class是一个泛型表示,用于获�一个类的类型。 - Class klass = int.class; - Class classInt = Integer.TYPE; +```` +//Class是一个泛型表示,用于获�一个类的类型。 +Class klass = int.class; +Class classInt = Integer.TYPE; +```` (3)调用�个对象的getClass()方法,比如: - - StringBuilder str = new StringBuilder("123"); - Class klass = str.getClass(); - +```` +StringBuilder str = new StringBuilder("123"); +Class klass = str.getClass(); +```` ## 判断是�为�个类的实例 一般地,我们用instanceof关键字�判断是�为�个类的实例。�时我们也�以借助�射中Class对象的isInstance()方法�判断是�为�个类的实例,它是一个Native方法: - -==public native boolean isInstance(Object obj);== - +```` +public native boolean isInstance(Object obj); +```` ## 创建实例 通过�射�生�对象主�有两�方�。 @@ -206,20 +186,20 @@ Array类:�供了动�创建数组,以�访问数组的元素的��方 (1)使用Class对象的newInstance()方法�创建Class对象对应类的实例。 注�:利用newInstance创建对象:调用的类必须有无�的构造器 - - //Class代表任何类的一个类对象。 - //使用这个类对象�以为其他类进行实例化 - //因为jvm加载类以�自动在堆区生�一个对应的*.Class对象 - //该对象用于让JVM对进行所有*对象实例化。 - Class c = String.class; - - //Class 中的 ? 是通�符,其实就是表示任�符�泛类定义�件的类,和直接使用 Class - //效果基本一致,但是这样写更加规范,在�些类型转�时�以���必�的 unchecked 错误。 - - Object str = c.newInstance(); - +```` +//Class代表任何类的一个类对象。 +//使用这个类对象�以为其他类进行实例化 +//因为jvm加载类以�自动在堆区生�一个对应的*.Class对象 +//该对象用于让JVM对进行所有*对象实例化。 +Class c = String.class; + +//Class 中的 ? 是通�符,其实就是表示任�符�泛类定义�件的类,和直接使用 Class +//效果基本一致,但是这样写更加规范,在�些类型转�时�以���必�的 unchecked 错误。 + +Object str = c.newInstance(); +```` (2)先通过Class对象获�指定的Constructor对象,�调用Constructor对象的newInstance()方法�创建实例。这�方法�以用指定的构造器构造类的实例。 - +```` //获�String所对应的Class对象 Class c = String.class; //获�String类带一个String�数的构造器 @@ -227,33 +207,35 @@ Array类:�供了动�创建数组,以�访问数组的元素的��方 //根�构造器创建实例 Object obj = constructor.newInstance("23333"); System.out.println(obj); - +```` ## 获�方法 获��个Class对象的方法集�,主�有以下几个方法: getDeclaredMethods()方法返回类或接�声明的所有方法,==包括公共��护�默认(包)访问和�有方法,但�包括继承的方法==。 - - public Method[] getDeclaredMethods() throws SecurityException - +```` +public Method[] getDeclaredMethods() throws SecurityException +```` getMethods()方法返回�个类的所有公用(public)方法,==包括其继承类的公用方法。== - - public Method[] getMethods() throws SecurityException +```` +public Method[] getMethods() throws SecurityException +```` getMethod方法返回一个特定的方法,其中第一个�数为方法�称,��的�数为方法的�数对应Class的对象 - - - public Method getMethod(String name, Class... parameterTypes) +```` +public Method getMethod(String name, Class... parameterTypes) +```` �是这样�述的��能难以�解,我们用例���解这三个方法: 本文中的例�用到了以下这些类,用于�射的测试。 +```` //注解类,��用于表示方法,�以通过�射获�注解的内容。 //Java注解的实现是很多注框架实现注解�置的基础 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Invoke { } - +```` userbean的父类personbean - +```` public class PersonBean { private String name; @@ -266,20 +248,17 @@ userbean的父类personbean public void setName(String name) { this.name = name; } - - -​ } - +```` 接�user - +```` public interface User { public void login (); } - +```` userBean实现user接�,继承personbean - +```` public class UserBean extends PersonBean implements User{ @Override public void login() { @@ -318,100 +297,100 @@ userBean实现user接�,继承personbean System.out.println("I'm a private method"); } } - +```` 1 getMethods和getDeclaredMethods的区别 - - public class 动�加载类的�射 { - public static void main(String[] args) { - try { - Class clazz = Class.forName("com.javase.�射.UserBean"); - for (Field field : clazz.getDeclaredFields()) { - // field.setAccessible(true); - System.out.println(field); - } - //getDeclaredMethod*()获�的是类自身声明的所有方法,包�public�protected和private方法。 - System.out.println("------共有方法------"); - // getDeclaredMethod*()获�的是类自身声明的所有方法,包�public�protected和private方法。 - // getMethod*()获�的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的�从接�实现的所有public方法。 - for (Method method : clazz.getMethods()) { - String name = method.getName(); - System.out.println(name); - //打�出了UserBean.java的所有方法以�父类的方法 - } - System.out.println("------独�方法------"); - - for (Method method : clazz.getDeclaredMethods()) { - String name = method.getName(); - System.out.println(name); - } - } catch (ClassNotFoundException e) { - e.printStackTrace(); +```` +public class 动�加载类的�射 { + public static void main(String[] args) { + try { + Class clazz = Class.forName("com.javase.�射.UserBean"); + for (Field field : clazz.getDeclaredFields()) { +// field.setAccessible(true); + System.out.println(field); + } + //getDeclaredMethod*()获�的是类自身声明的所有方法,包�public�protected和private方法。 + System.out.println("------共有方法------"); +// getDeclaredMethod*()获�的是类自身声明的所有方法,包�public�protected和private方法。 +// getMethod*()获�的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的�从接�实现的所有public方法。 + for (Method method : clazz.getMethods()) { + String name = method.getName(); + System.out.println(name); + //打�出了UserBean.java的所有方法以�父类的方法 + } + System.out.println("------独�方法------"); + + for (Method method : clazz.getDeclaredMethods()) { + String name = method.getName(); + System.out.println(name); } + } catch (ClassNotFoundException e) { + e.printStackTrace(); } } +} - +```` 2 打�一个类的所有方法�详细信�: - - public class 打�所有方法 { - - public static void main(String[] args) { - Class userBeanClass = UserBean.class; - Field[] fields = userBeanClass.getDeclaredFields(); - //注�,打�方法时无法得到局部��的�称,因为jvm�知�它的类型 - Method[] methods = userBeanClass.getDeclaredMethods(); - for (Method method : methods) { - //�次获得方法的修饰符,返回类型和�称,外加方法中的�数 - String methodString = Modifier.toString(method.getModifiers()) + " " ; // private static - methodString += method.getReturnType().getSimpleName() + " "; // void - methodString += method.getName() + "("; // staticMethod - Class[] parameters = method.getParameterTypes(); - Parameter[] p = method.getParameters(); - - for (Class parameter : parameters) { - methodString += parameter.getSimpleName() + " " ; // String - } - methodString += ")"; - System.out.println(methodString); +```` +public class 打�所有方法 { + + public static void main(String[] args) { + Class userBeanClass = UserBean.class; + Field[] fields = userBeanClass.getDeclaredFields(); + //注�,打�方法时无法得到局部��的�称,因为jvm�知�它的类型 + Method[] methods = userBeanClass.getDeclaredMethods(); + for (Method method : methods) { + //�次获得方法的修饰符,返回类型和�称,外加方法中的�数 + String methodString = Modifier.toString(method.getModifiers()) + " " ; // private static + methodString += method.getReturnType().getSimpleName() + " "; // void + methodString += method.getName() + "("; // staticMethod + Class[] parameters = method.getParameterTypes(); + Parameter[] p = method.getParameters(); + + for (Class parameter : parameters) { + methodString += parameter.getSimpleName() + " " ; // String } - //注�方法�能获�到其类型,拿�到��� - /* public String getName() - public long getId() - public static void staticMethod(String int ) - public void publicMethod() - private void privateMethod()*/ + methodString += ")"; + System.out.println(methodString); } + //注�方法�能获�到其类型,拿�到��� +/* public String getName() + public long getId() + public static void staticMethod(String int ) + public void publicMethod() + private void privateMethod()*/ } - +} +```` ## 获�构造器信� 获�类构造器的用法与上述获�方法的用法类似。主�是通过Class类的getConstructor方法得到Constructor类的一个实例,而Constructor类有一个newInstance方法�以创建一个对象实例: - - public class 打�构造方法 { - public static void main(String[] args) { - // constructors - Class clazz = UserBean.class; - - Class userBeanClass = UserBean.class; - //获得所有的构造方法 - Constructor[] constructors = userBeanClass.getDeclaredConstructors(); - for (Constructor constructor : constructors) { - String s = Modifier.toString(constructor.getModifiers()) + " "; - s += constructor.getName() + "("; - //构造方法的�数类型 - Class[] parameters = constructor.getParameterTypes(); - for (Class parameter : parameters) { - s += parameter.getSimpleName() + ", "; - } - s += ")"; - System.out.println(s); - //打�结果//public com.javase.�射.UserBean(String, long, ) - +```` +public class 打�构造方法 { + public static void main(String[] args) { + // constructors + Class clazz = UserBean.class; + + Class userBeanClass = UserBean.class; + //获得所有的构造方法 + Constructor[] constructors = userBeanClass.getDeclaredConstructors(); + for (Constructor constructor : constructors) { + String s = Modifier.toString(constructor.getModifiers()) + " "; + s += constructor.getName() + "("; + //构造方法的�数类型 + Class[] parameters = constructor.getParameterTypes(); + for (Class parameter : parameters) { + s += parameter.getSimpleName() + ", "; } + s += ")"; + System.out.println(s); + //打�结果//public com.javase.�射.UserBean(String, long, ) + } } - +} +```` ## 获�类的�员��(字段)信� 主�是这几个方法,在此��赘述: @@ -419,140 +398,138 @@ getFiled: 访问公有的�员�� getDeclaredField:所有已声明的�员��。但�能得到其父类的�员�� getFileds和getDeclaredFields用法�上(�照Method) - public class 打��员�� { - public static void main(String[] args) { - Class userBeanClass = UserBean.class; - //获得该类的所有�员��,包括static private - Field[] fields = userBeanClass.getDeclaredFields(); - - for(Field field : fields) { - //private属性�使�用下�这个语�也�以访问 - // field.setAccessible(true); - - //因为类的�有域在�射中默认�访问,所以flag默认为true。 - String fieldString = ""; - fieldString += Modifier.toString(field.getModifiers()) + " "; // `private` - fieldString += field.getType().getSimpleName() + " "; // `String` - fieldString += field.getName(); // `userName` - fieldString += ";"; - System.out.println(fieldString); - - //打�结果 - // public String userName; - // protected int i; - // static int j; - // private int l; - // private long userId; - } - +```` +public class 打��员�� { + public static void main(String[] args) { + Class userBeanClass = UserBean.class; + //获得该类的所有�员��,包括static private + Field[] fields = userBeanClass.getDeclaredFields(); + + for(Field field : fields) { + //private属性�使�用下�这个语�也�以访问 +// field.setAccessible(true); + + //因为类的�有域在�射中默认�访问,所以flag默认为true。 + String fieldString = ""; + fieldString += Modifier.toString(field.getModifiers()) + " "; // `private` + fieldString += field.getType().getSimpleName() + " "; // `String` + fieldString += field.getName(); // `userName` + fieldString += ";"; + System.out.println(fieldString); + + //打�结果 +// public String userName; +// protected int i; +// static int j; +// private int l; +// private long userId; } - } + } +} +```` ## 调用方法 当我们从类中获�了一个方法�,我们就�以用invoke()方法�调用这个方法。invoke方法的原型为: - - public Object invoke(Object obj, Object... args) - throws IllegalAccessException, IllegalArgumentException, - InvocationTargetException - - public class 使用�射调用方法 { - public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { - Class userBeanClass = UserBean.class; - //获�该类所有的方法,包括��方法,实例方法。 - //此处也包括了�有方法,��过�有方法在用invoke访问之��设置访问�� - //也就是使用setAccessible使方法�访问,�则会抛出异常 - // // IllegalAccessException的解释是 - // * An IllegalAccessException is thrown when an application tries - // * to reflectively create an instance (other than an array), - // * set or get a field, or invoke a method, but the currently - // * executing method does not have access to the definition of - // * the specified class, field, method or constructor. - - // getDeclaredMethod*()获�的是类自身声明的所有方法,包�public�protected和private方法。 - // getMethod*()获�的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的�从接�实现的所有public方法。 - - //就是说,当这个类,域或者方法被设为�有访问,使用�射调用但是�没有��时会抛出异常。 - Method[] methods = userBeanClass.getDeclaredMethods(); // 获�所有�员方法 - for (Method method : methods) { - //�射�以获�方法上的注解,通过注解�进行判断 - if (method.isAnnotationPresent(Invoke.class)) { // 判断是�被 @Invoke 修饰 - //判断方法的修饰符是是static - if (Modifier.isStatic(method.getModifiers())) { // 如果是 static 方法 - //�射调用该方法 - //类方法�以直接调用,�必先实例化 - method.invoke(null, "wingjay",2); // 直接调用,并传入需�的�数 devName - } else { - //如果�是类方法,需�先获得一个实例�调用方法 - //传入构造方法需�的��类型 - Class[] params = {String.class, long.class}; - //获�该类指定类型的构造方法 - //如果没有这�类型的方法会报错 - Constructor constructor = userBeanClass.getDeclaredConstructor(params); // 获��数格�为 String,long 的构造函数 - //通过构造方法的实例�进行实例化 - Object userBean = constructor.newInstance("wingjay", 11); // 利用构造函数进行实例化,得到 Object - if (Modifier.isPrivate(method.getModifiers())) { - method.setAccessible(true); // 如果是 private 的方法,需�获�其调用�� - // Set the {@code accessible} flag for this object to - // * the indicated boolean value. A value of {@code true} indicates that - // * the reflected object should suppress Java language access - // * checking when it is used. A value of {@code false} indicates - // * that the reflected object should enforce Java language access checks. - //通过该方法�以设置其��或者���,�仅�以用于方法 - //��例�会介�将其用于�员�� - //打�结果 - // I'm a public method - // Hi wingjay, I'm a static methodI'm a private method - } - method.invoke(userBean); // 调用 method,无须�数 - - -​ - +```` +public Object invoke(Object obj, Object... args) + throws IllegalAccessException, IllegalArgumentException, + InvocationTargetException + +public class 使用�射调用方法 { + public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { + Class userBeanClass = UserBean.class; + //获�该类所有的方法,包括��方法,实例方法。 + //此处也包括了�有方法,��过�有方法在用invoke访问之��设置访问�� + //也就是使用setAccessible使方法�访问,�则会抛出异常 +// // IllegalAccessException的解释是 +// * An IllegalAccessException is thrown when an application tries +// * to reflectively create an instance (other than an array), +// * set or get a field, or invoke a method, but the currently +// * executing method does not have access to the definition of +// * the specified class, field, method or constructor. + +// getDeclaredMethod*()获�的是类自身声明的所有方法,包�public�protected和private方法。 +// getMethod*()获�的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的�从接�实现的所有public方法。 + + //就是说,当这个类,域或者方法被设为�有访问,使用�射调用但是�没有��时会抛出异常。 + Method[] methods = userBeanClass.getDeclaredMethods(); // 获�所有�员方法 + for (Method method : methods) { + //�射�以获�方法上的注解,通过注解�进行判断 + if (method.isAnnotationPresent(Invoke.class)) { // 判断是�被 @Invoke 修饰 + //判断方法的修饰符是是static + if (Modifier.isStatic(method.getModifiers())) { // 如果是 static 方法 + //�射调用该方法 + //类方法�以直接调用,�必先实例化 + method.invoke(null, "wingjay",2); // 直接调用,并传入需�的�数 devName + } else { + //如果�是类方法,需�先获得一个实例�调用方法 + //传入构造方法需�的��类型 + Class[] params = {String.class, long.class}; + //获�该类指定类型的构造方法 + //如果没有这�类型的方法会报错 + Constructor constructor = userBeanClass.getDeclaredConstructor(params); // 获��数格�为 String,long 的构造函数 + //通过构造方法的实例�进行实例化 + Object userBean = constructor.newInstance("wingjay", 11); // 利用构造函数进行实例化,得到 Object + if (Modifier.isPrivate(method.getModifiers())) { + method.setAccessible(true); // 如果是 private 的方法,需�获�其调用�� +// Set the {@code accessible} flag for this object to +// * the indicated boolean value. A value of {@code true} indicates that +// * the reflected object should suppress Java language access +// * checking when it is used. A value of {@code false} indicates +// * that the reflected object should enforce Java language access checks. + //通过该方法�以设置其��或者���,�仅�以用于方法 + //��例�会介�将其用于�员�� + //打�结果 +// I'm a public method +// Hi wingjay, I'm a static methodI'm a private method } + method.invoke(userBean); // 调用 method,无须�数 } } } } - +} +```` ## 利用�射创建数组 数组在Java里是比较特殊的一�类型,它�以赋值给一个Object Reference。下�我们看一看利用�射创建数组的例�: - - public class 用�射创建数组 { - public static void main(String[] args) { - Class cls = null; - try { - cls = Class.forName("java.lang.String"); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - Object array = Array.newInstance(cls,25); - //往数组里添加内容 - Array.set(array,0,"hello"); - Array.set(array,1,"Java"); - Array.set(array,2,"fuck"); - Array.set(array,3,"Scala"); - Array.set(array,4,"Clojure"); - //获��一项的内容 - System.out.println(Array.get(array,3)); - //Scala +```` +public class 用�射创建数组 { + public static void main(String[] args) { + Class cls = null; + try { + cls = Class.forName("java.lang.String"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); } - + Object array = Array.newInstance(cls,25); + //往数组里添加内容 + Array.set(array,0,"hello"); + Array.set(array,1,"Java"); + Array.set(array,2,"fuck"); + Array.set(array,3,"Scala"); + Array.set(array,4,"Clojure"); + //获��一项的内容 + System.out.println(Array.get(array,3)); + //Scala } +} +```` 其中的Array类为java.lang.reflect.Array类。我们通过Array.newInstance()创建数组对象,它的原型是: - - public static Object newInstance(Class componentType, int length) - throws NegativeArraySizeException { - return newArray(componentType, length); +```` +public static Object newInstance(Class componentType, int length) + throws NegativeArraySizeException { + return newArray(componentType, length); } +```` 而newArray()方法是一个Native方法,它在Hotspot JVM里的具体实现我们�边�研究,这里先把��贴出� +```` +private static native Object newArray(Class componentType, int length) + throws NegativeArraySizeException; - private static native Object newArray(Class componentType, int length) - throws NegativeArraySizeException; - - -​ +```` + ## Java�射常��试题 diff --git "a/docs/java/basic/13\343\200\201\346\263\233\345\236\213.md" "b/docs/java/basic/13\343\200\201\346\263\233\345\236\213.md" index 2251e75..d71286f 100644 --- "a/docs/java/basic/13\343\200\201\346\263\233\345\236\213.md" +++ "b/docs/java/basic/13\343\200\201\346\263\233\345\236\213.md" @@ -44,48 +44,45 @@ > > 泛型的本质是为了�数化类型(在�创建新的类型的情况下,通过泛型指定的��类型�控制形�具体�制的类型)。也就是说在泛型使用过程中,�作的数�类型被指定为一个�数,这��数类型�以用在类�接�和方法中,分别被称为泛型类�泛型接��泛型方法。 - - ### 一个栗� 一个被举了无数次的例�: - - List arrayList = new ArrayList(); - arrayList.add("aaaa"); - arrayList.add(100); - - for(int i = 0; i< arrayList.size();i++){ - String item = (String)arrayList.get(i); - Log.d("泛型测试","item = " + item); - } - +```` +List arrayList = new ArrayList(); +arrayList.add("aaaa"); +arrayList.add(100); + +for(int i = 0; i< arrayList.size();i++){ + String item = (String)arrayList.get(i); + Log.d("泛型测试","item = " + item); +} +```` 毫无疑问,程�的�行结果会以崩溃结�: -java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String + java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String ArrayList�以存放任�类型,例�中添加了一个String类型,添加了一个Integer类型,�使用时都以String的方�使用,因此程�崩溃了。为了解决类似这样的问题(在编译阶段就�以解决),泛型应�而生。 我们将第一行声明�始化list的代�更改一下,编译器会在编译阶段就能够帮我们�现类似这样的问题。 - +```` List arrayList = new ArrayList(); ... //arrayList.add(100); 在编译阶段,编译器就会报错 - +```` ### 特性 泛型�在编译阶段有效。看下�的代�: +```` +List stringArrayList = new ArrayList(); +List integerArrayList = new ArrayList(); - List stringArrayList = new ArrayList(); - List integerArrayList = new ArrayList(); - - Class classStringArrayList = stringArrayList.getClass(); - Class classIntegerArrayList = integerArrayList.getClass(); - - if(classStringArrayList.equals(classIntegerArrayList)){ - Log.d("泛型测试","类型相�"); - } - +Class classStringArrayList = stringArrayList.getClass(); +Class classIntegerArrayList = integerArrayList.getClass(); +if(classStringArrayList.equals(classIntegerArrayList)){ + Log.d("泛型测试","类型相�"); +} +```` > 通过上�的例��以�明,在编译之�程�会采�去泛型化的措施。也就是说Java中的泛型,�在编译阶段有效。在编译过程中,正确检验泛型结果�,会将泛型的相关信�擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转�的方法。也就是说,泛型信��会进入到�行时阶段。 > 对此总结�一��:泛型类型在逻辑上看以看�是多个��的类型,实际上都是相�的基本类型。 @@ -101,49 +98,49 @@ List arrayList = new ArrayList(); > 泛型类型用于类的定义中,被称为泛型类。通过泛型�以完�对一组类的�作对外开放相�的接�。最典型的就是��容器类,如:List�Set�Map。 > > 泛型类的最基本写法(这么看�能会有点晕,会在下�的例�中详解): - +```` class 类�称 <泛型标识:�以�便写任�标识�,标识指定的泛型的类型>{ private 泛型标识 /*(�员��类型)*/ var; ..... } - +```` 一个最普通的泛型类: //此处T�以�便写为任�标识,常�的如T�E�K�V等形�的�数常用于表示泛型 +```` +//在实例化泛型类时,必须指定T的具体类型 +public class Generic{ + //在类中声明的泛型整个类里�都�以用,除了��部分,因为泛型是实例化时声明的。 + //��区域的代�在编译时就已�确定,�与类相关 + class A { + T t; + } + //类里�的方法或类中�次声明��泛型是�许的,并且该泛型会覆盖掉父类的��泛型T + class B { + T t; + } + //��内部类也�以使用泛型,实例化时赋予泛型实际类型 + static class C { + T t; + } + public static void main(String[] args) { + //报错,�能使用T泛型,因为泛型T属于实例�属于类 +// T t = null; + } - //在实例化泛型类时,必须指定T的具体类型 - public class Generic{ - //在类中声明的泛型整个类里�都�以用,除了��部分,因为泛型是实例化时声明的。 - //��区域的代�在编译时就已�确定,�与类相关 - class A { - T t; - } - //类里�的方法或类中�次声明��泛型是�许的,并且该泛型会覆盖掉父类的��泛型T - class B { - T t; - } - //��内部类也�以使用泛型,实例化时赋予泛型实际类型 - static class C { - T t; - } - public static void main(String[] args) { - //报错,�能使用T泛型,因为泛型T属于实例�属于类 - // T t = null; - } - - //key这个�员��的类型为T,T的类型由外部指定 - private T key; - - public Generic(T key) { //泛型构造方法形�key的类型也为T,T的类型由外部指定 - this.key = key; - } - - public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定 - return key; - } + //key这个�员��的类型为T,T的类型由外部指定 + private T key; + + public Generic(T key) { //泛型构造方法形�key的类型也为T,T的类型由外部指定 + this.key = key; } + public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定 + return key; + } +} +```` > 12-27 09:20:04.432 13063-13063/? D/泛型测试: key is 123456 > 12-27 09:20:04.432 13063-13063/? D/泛型测试: key is key_vlaue @@ -151,22 +148,22 @@ List arrayList = new ArrayList(); > 定义的泛型类,就一定�传入泛型类型实�么?并�是这样,在使用泛型的时候如果传入泛型实�,则会根�传入的泛型实��相应的�制,此时泛型�会起到本应起到的�制作用。如果�传入泛型类型实�的�,在泛型类中使用泛型的方法或�员��定义的类型�以为任何的类型。 看一个例�: - - Generic generic = new Generic("111111"); - Generic generic1 = new Generic(4444); - Generic generic2 = new Generic(55.55); - Generic generic3 = new Generic(false); - - Log.d("泛型测试","key is " + generic.getKey()); - Log.d("泛型测试","key is " + generic1.getKey()); - Log.d("泛型测试","key is " + generic2.getKey()); - Log.d("泛型测试","key is " + generic3.getKey()); - - D/泛型测试: key is 111111 - D/泛型测试: key is 4444 - D/泛型测试: key is 55.55 - D/泛型测试: key is false - +```` +Generic generic = new Generic("111111"); +Generic generic1 = new Generic(4444); +Generic generic2 = new Generic(55.55); +Generic generic3 = new Generic(false); + +Log.d("泛型测试","key is " + generic.getKey()); +Log.d("泛型测试","key is " + generic1.getKey()); +Log.d("泛型测试","key is " + generic2.getKey()); +Log.d("泛型测试","key is " + generic3.getKey()); + +D/泛型测试: key is 111111 +D/泛型测试: key is 4444 +D/泛型测试: key is 55.55 +D/泛型测试: key is false +```` 注�: 泛型的类型�数�能是类类型,�能是简�类型。 �能对确切的泛型类型使用instanceof�作。如下�的�作是�法的,编译时会出错。 @@ -176,78 +173,78 @@ List arrayList = new ArrayList(); ### 泛型接� 泛型接�与泛型类的定义�使用基本相�。泛型接�常被用在��类的生产器中,�以看一个例�: - - //定义一个泛型接� - public interface Generator { - public T next(); - } - +```` +//定义一个泛型接� +public interface Generator { + public T next(); +} +```` 当实现泛型接�的类,未传入泛型实�时: - - /** - * 未传入泛型实�时,与泛型类的定义相�,在声明类的时候,需将泛型的声明也一起加到类中 - * �:class FruitGenerator implements Generator{ - * 如果�声明泛型,如:class FruitGenerator implements Generator,编译器会报错:"Unknown class" - */ - class FruitGenerator implements Generator{ - @Override - public T next() { - return null; - } +```` +/** + * 未传入泛型实�时,与泛型类的定义相�,在声明类的时候,需将泛型的声明也一起加到类中 + * �:class FruitGenerator implements Generator{ + * 如果�声明泛型,如:class FruitGenerator implements Generator,编译器会报错:"Unknown class" + */ +class FruitGenerator implements Generator{ + @Override + public T next() { + return null; } - +} +```` 当实现泛型接�的类,传入泛型实�时: - - /** - * 传入泛型实�时: - * 定义一个生产器实现这个接�,虽然我们�创建了一个泛型接�Generator - * 但是我们�以为T传入无数个实�,形�无数�类型的Generator接�。 - * 在实现类实现泛型接�时,如已将泛型类型传入实�类型,则所有使用泛型的地方都�替��传入的实�类型 - * �:Generator,public T next();中的的T都�替��传入的String类型。 - */ - public class FruitGenerator implements Generator { - - private String[] fruits = new String[]{"Apple", "Banana", "Pear"}; - - @Override - public String next() { - Random rand = new Random(); - return fruits[rand.nextInt(3)]; - } +```` +/** + * 传入泛型实�时: + * 定义一个生产器实现这个接�,虽然我们�创建了一个泛型接�Generator + * 但是我们�以为T传入无数个实�,形�无数�类型的Generator接�。 + * 在实现类实现泛型接�时,如已将泛型类型传入实�类型,则所有使用泛型的地方都�替��传入的实�类型 + * �:Generator,public T next();中的的T都�替��传入的String类型。 + */ +public class FruitGenerator implements Generator { + + private String[] fruits = new String[]{"Apple", "Banana", "Pear"}; + + @Override + public String next() { + Random rand = new Random(); + return fruits[rand.nextInt(3)]; } - +} +```` ### 泛型通�符 我们知�Ingeter是Number的一个�类,�时在特性章节中我们也验�过Generic与Generic实际上是相�的一�基本类型。那么问题�了,在使用Generic作为形�的方法中,能�使用Generic的实例传入呢?在逻辑上类似于Generic和Generic是��以看�具有父�关系的泛型类型呢? 为了弄清楚这个问题,我们使用Generic这个泛型类继续看下�的例�: +```` +public void showKeyValue1(Generic obj){ + Log.d("泛型测试","key value is " + obj.getKey()); +} - public void showKeyValue1(Generic obj){ - Log.d("泛型测试","key value is " + obj.getKey()); - } - - Generic gInteger = new Generic(123); - Generic gNumber = new Generic(456); - - showKeyValue(gNumber); - - // showKeyValue这个方法编译器会为我们报错:Generic - // cannot be applied to Generic - // showKeyValue(gInteger); +Generic gInteger = new Generic(123); +Generic gNumber = new Generic(456); +showKeyValue(gNumber); + +// showKeyValue这个方法编译器会为我们报错:Generic +// cannot be applied to Generic +// showKeyValue(gInteger); +```` 通过�示信�我们�以看到Generic�能被看作为`Generic的�类。由此�以看出:�一�泛型�以对应多个版本(因为�数类型是�确定的),��版本的泛型类实例是�兼容的。 回到上�的例�,如何解决上�的问题?总�能为了定义一个新的方法�处�Generic类型的类,这显然与java中的多��念相�背。因此我们需�一个在逻辑上�以表示�时是Generic和Generic父类的引用类型。由此类型通�符应�而生。 我们�以将上�的方法改一下: - - public void showKeyValue1(Generic obj){ - Log.d("泛型测试","key value is " + obj.getKey()); - +```` +public void showKeyValue1(Generic obj){ + Log.d("泛型测试","key value is " + obj.getKey()); +```` 类型通�符一般是使用?代替具体的类型实�,注�, 此处的?和Number�String�Integer一样都是一�实际的类型,�以把?看�所有类型的父类。是一�真实的类型。 �以解决当具体类型�确定的时候,这个通�符就是 ? ;当�作类型时,�需�使用类型的具体功能时,�使用Object类中的功能。那么�以用 ? 通�符�表未知类型 - +```` public void showKeyValue(Generic obj){ System.out.println(obj); } @@ -266,7 +263,7 @@ public void showKeyValue(Generic obj){ // showKeyValue这个方法编译器会为我们报错:Generic // cannot be applied to Generic // showKeyValue(gInteger); -。 +```` ### 泛型方法 @@ -274,167 +271,165 @@ public void showKeyValue(Generic obj){ 尤其是我们�到的大多数泛型类中的�员方法也都使用了泛型,有的甚至泛型类中也包��泛型方法,这样在�学者中�常容易将泛型方法�解错了。 泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。 +```` +/** + * 泛型方法的基本介� + * @param tClass 传入的泛型实� + * @return T 返回值为T类型 + * 说明: + * 1)public 与 返回值中间�常��,�以�解为声明此方法为泛型方法。 + * 2)�有声明了的方法�是泛型方法,泛型类中的使用了泛型的�员方法并�是泛型方法。 + * 3)表明该方法将使用泛型类型T,此时��以在方法中使用泛型类型T。 + * 4)与泛型类的定义一样,此处T�以�便写为任�标识,常�的如T�E�K�V等形�的�数常用于表示泛型。 + */ + public T genericMethod(Class tClass)throws InstantiationException , + IllegalAccessException{ + T instance = tClass.newInstance(); + return instance; + } - /** - * 泛型方法的基本介� - * @param tClass 传入的泛型实� - * @return T 返回值为T类型 - * 说明: - * 1)public 与 返回值中间�常��,�以�解为声明此方法为泛型方法。 - * 2)�有声明了的方法�是泛型方法,泛型类中的使用了泛型的�员方法并�是泛型方法。 - * 3)表明该方法将使用泛型类型T,此时��以在方法中使用泛型类型T。 - * 4)与泛型类的定义一样,此处T�以�便写为任�标识,常�的如T�E�K�V等形�的�数常用于表示泛型。 - */ - public T genericMethod(Class tClass)throws InstantiationException , - IllegalAccessException{ - T instance = tClass.newInstance(); - return instance; - } - - Object obj = genericMethod(Class.forName("com.test.test")); - +Object obj = genericMethod(Class.forName("com.test.test")); +```` ### 泛型方法的基本用法 光看上�的例�有的�学�能�然会�常迷糊,我们�通过一个例�,把我泛型方法�总结一下。 - - /** - * 这�是一个真正的泛型方法。 - * 首先在public与返回值之间的必��少,这表明这是一个泛型方法,并且声明了一个泛型T - * 这个T�以出现在这个泛型方法的任��置. - * 泛型的数�也�以为任�多个 - * 如:public K showKeyName(Generic container){ - * ... - * } - */ - - public class 泛型方法 { - @Test - public void test() { - test1(); - test2(new Integer(2)); - test3(new int[3],new Object()); - - //打�结果 - // null - // 2 - // [I@3d8c7aca - // java.lang.Object@5ebec15 - } - //该方法使用泛型T - public void test1() { - T t = null; - System.out.println(t); - } - //该方法使用泛型T - //并且�数和返回值都是T类型 - public T test2(T t) { - System.out.println(t); - return t; - } - - //该方法使用泛型T,E - //�数包括T,E - public void test3(T t, E e) { - System.out.println(t); - System.out.println(e); - } +```` +/** + * 这�是一个真正的泛型方法。 + * 首先在public与返回值之间的必��少,这表明这是一个泛型方法,并且声明了一个泛型T + * 这个T�以出现在这个泛型方法的任��置. + * 泛型的数�也�以为任�多个 + * 如:public K showKeyName(Generic container){ + * ... + * } + */ + + public class 泛型方法 { + @Test + public void test() { + test1(); + test2(new Integer(2)); + test3(new int[3],new Object()); + + //打�结果 + //null + //2 + //[I@3d8c7aca + //java.lang.Object@5ebec15 + } + //该方法使用泛型T + public void test1() { + T t = null; + System.out.println(t); + } + //该方法使用泛型T + //并且�数和返回值都是T类型 + public T test2(T t) { + System.out.println(t); + return t; } - -​ + //该方法使用泛型T,E + //�数包括T,E + public void test3(T t, E e) { + System.out.println(t); + System.out.println(e); + } +} +```` ### 类中的泛型方法 当然这并�是泛型方法的全部,泛型方法�以出现�任何地方和任何场景中使用。但是有一�情况是�常特殊的,当泛型方法出现在泛型类中时,我们�通过一个例�看一下 - - //注�泛型类先写类��写泛型,泛型方法先写泛型�写方法� - //类中声明的泛型在�员和方法中�用 - class A { - { - T t1 ; - } - A (T t){ - this.t = t; - } - T t; - - public void test1() { - System.out.println(this.t); - } - - public void test2(T t,E e) { - System.out.println(t); - System.out.println(e); - } +```` +//注�泛型类先写类��写泛型,泛型方法先写泛型�写方法� +//类中声明的泛型在�员和方法中�用 +class A { + { + T t1 ; } - @Test - public void run () { - A a = new A<>(1); - a.test1(); - a.test2(2,"ds"); - // 1 - // 2 - // ds + A (T t){ + this.t = t; } - - static class B { - T t; - public void go () { - System.out.println(t); - } + T t; + + public void test1() { + System.out.println(this.t); + } + + public void test2(T t,E e) { + System.out.println(t); + System.out.println(e); } +} +@Test +public void run () { + A a = new A<>(1); + a.test1(); + a.test2(2,"ds"); +// 1 +// 2 +// ds +} +static class B { + T t; + public void go () { + System.out.println(t); + } +} +```` ### 泛型方法与���数 �看一个泛型方法和���数的例�: - - public class 泛型和���数 { - @Test - public void test () { - printMsg("dasd",1,"dasd",2.0,false); - print("dasdas","dasdas", "aa"); - } - //普通���数�能适�一�类型 - public void print(String ... args) { - for(String t : args){ - System.out.println(t); - } +```` +public class 泛型和���数 { + @Test + public void test () { + printMsg("dasd",1,"dasd",2.0,false); + print("dasdas","dasdas", "aa"); + } + //普通���数�能适�一�类型 + public void print(String ... args) { + for(String t : args){ + System.out.println(t); } - //泛型的���数�以匹�所有类型的�数。。有点无敌 - public void printMsg( T... args){ - for(T t : args){ - System.out.println(t); - } + } + //泛型的���数�以匹�所有类型的�数。。有点无敌 + public void printMsg( T... args){ + for(T t : args){ + System.out.println(t); } - //打�结果: - //dasd - //1 - //dasd - //2.0 - //false - } + //打�结果: + //dasd + //1 + //dasd + //2.0 + //false +} +```` ### ��方法与泛型 ��方法有一�情况需�注�一下,那就是在类中的��方法使用泛型:��方法无法访问类上定义的泛型;如果��方法�作的引用数�类型�确定的时候,必须�将泛型定义在方法上。 �:如果��方法�使用泛型的�,必须将��方法也定义�泛型方法 。 +```` +public class StaticGenerator { + .... + .... + /** + * 如果在类中定义使用泛型的��方法,需�添加�外的泛型声明(将这个方法定义�泛型方法) + * �使��方法�使用泛型类中已�声明过的泛型也��以。 + * 如:public static void show(T t){..},此时编译器会�示错误信�: + "StaticGenerator cannot be refrenced from static context" + */ + public static void show(T t){ - public class StaticGenerator { - .... - .... - /** - * 如果在类中定义使用泛型的��方法,需�添加�外的泛型声明(将这个方法定义�泛型方法) - * �使��方法�使用泛型类中已�声明过的泛型也��以。 - * 如:public static void show(T t){..},此时编译器会�示错误信�: - "StaticGenerator cannot be refrenced from static context" - */ - public static void show(T t){ - - } } - +} +```` ## 泛型方法总结 泛型方法能使方法独立于类而产生�化,以下是一个基本的指导原则: @@ -445,90 +440,93 @@ public void showKeyValue(Generic obj){ 在使用泛型的时候,我们还�以为传入的泛型类型实�进行上下边界的�制,如:类型实��准传入��类型的父类或��类型的�类。 为泛型添加上边界,�传入的类型实�必须是指定类型的�类型 +```` +public class 泛型通�符与边界 { + public void showKeyValue(Generic obj){ + System.out.println("key value is " + obj.getKey()); + } + @Test + public void main() { + Generic gInteger = new Generic(123); + Generic gNumber = new Generic(456); + showKeyValue(gNumber); + //泛型中的�类也无法作为父类引用传入 +// showKeyValue(gInteger); + } + //直接使用?通�符�以接�任何类型作为泛型传入 + public void showKeyValueYeah(Generic obj) { + System.out.println(obj); + } + //�能传入number的�类或者number + public void showKeyValue1(Generic obj){ + System.out.println(obj); + } - public class 泛型通�符与边界 { - public void showKeyValue(Generic obj){ - System.out.println("key value is " + obj.getKey()); - } - @Test - public void main() { - Generic gInteger = new Generic(123); - Generic gNumber = new Generic(456); - showKeyValue(gNumber); - //泛型中的�类也无法作为父类引用传入 - // showKeyValue(gInteger); - } - //直接使用?通�符�以接�任何类型作为泛型传入 - public void showKeyValueYeah(Generic obj) { - System.out.println(obj); - } - //�能传入number的�类或者number - public void showKeyValue1(Generic obj){ - System.out.println(obj); - } - - //�能传入Integer的父类或者Integer - public void showKeyValue2(Generic obj){ - System.out.println(obj); - } - - @Test - public void testup () { - //这一行代�编译器会�示错误,因为String类型并�是Number类型的�类 - //showKeyValue1(generic1); - Generic generic1 = new Generic("11111"); - Generic generic2 = new Generic(2222); - Generic generic3 = new Generic(2.4f); - Generic generic4 = new Generic(2.56); - - showKeyValue1(generic2); - showKeyValue1(generic3); - showKeyValue1(generic4); - } - - @Test - public void testdown () { - - Generic generic1 = new Generic("11111"); - Generic generic2 = new Generic(2222); - Generic generic3 = new Generic(2); - // showKeyValue2(generic1);本行报错,因为String并�是Integer的父类 - showKeyValue2(generic2); - showKeyValue2(generic3); - } + //�能传入Integer的父类或者Integer + public void showKeyValue2(Generic obj){ + System.out.println(obj); + } + + @Test + public void testup () { + //这一行代�编译器会�示错误,因为String类型并�是Number类型的�类 + //showKeyValue1(generic1); + Generic generic1 = new Generic("11111"); + Generic generic2 = new Generic(2222); + Generic generic3 = new Generic(2.4f); + Generic generic4 = new Generic(2.56); + + showKeyValue1(generic2); + showKeyValue1(generic3); + showKeyValue1(generic4); } + @Test + public void testdown () { + + Generic generic1 = new Generic("11111"); + Generic generic2 = new Generic(2222); + Generic generic3 = new Generic(2); +// showKeyValue2(generic1);本行报错,因为String并�是Integer的父类 + showKeyValue2(generic2); + showKeyValue2(generic3); + } +} +```` == 关于泛型数组��一下 == 看到了很多文章中都会�起泛型数组,�过查看sun的说明文档,在java中是��能创建一个确切的泛型类型的数组�的。 - 也就是说下�的这个例�是��以的: - - List[] ls = new ArrayList[10]; - - 而使用通�符创建泛型数组是�以的,如下�这个例�: - - List[] ls = new ArrayList[10]; - - 这样也是�以的: - - List[] ls = new ArrayList[10]; +也就是说下�的这个例�是��以的: +```` +List[] ls = new ArrayList[10]; + +而使用通�符创建泛型数组是�以的,如下�这个例�: + +List[] ls = new ArrayList[10]; + +这样也是�以的: +List[] ls = new ArrayList[10]; +```` 下�使用Sun的一篇文档的一个例��说明这个问题: - List[] lsa = new List[10]; // Not really allowed. - Object o = lsa; - Object[] oa = (Object[]) o; - List li = new ArrayList(); - li.add(new Integer(3)); - oa[1] = li; // Unsound, but passes run time store check - String s = lsa[1].get(0); // Run-time error: ClassCastException. +```` +List[] lsa = new List[10]; // Not really allowed. +Object o = lsa; +Object[] oa = (Object[]) o; +List li = new ArrayList(); +li.add(new Integer(3)); +oa[1] = li; // Unsound, but passes run time store check +String s = lsa[1].get(0); // Run-time error: ClassCastException. +```` > 这�情况下,由于JVM泛型的擦除机制,在�行时JVM是�知�泛型信�的,所以�以给oa[1]赋上一个ArrayList而�会出现异常,但是在�出数�的时候���一次类型转�,所以就会出现ClassCastException,如果�以进行泛型数组的声明,上�说的这�情况在编译期将�会出现任何的警告和错误,�有在�行时�会出错。 > > 而对泛型数组的声明进行�制,对于这样的情况,�以在编译期�示代�有类型安全问题,比没有任何�示�强很多。 > 下�采用通�符的方�是被�许的:数组的类型��以是类型��,除�是采用通�符的方�,因为对于通�符的方�,最��出数�是��显�的类型转�的。 +```` List[] lsa = new List[10]; // OK, array of unbounded wildcard type. Object o = lsa; Object[] oa = (Object[]) o; @@ -536,6 +534,7 @@ public void showKeyValue(Generic obj){ li.add(new Integer(3)); oa[1] = li; // Correct. Integer i = (Integer) lsa[1].get(0); // OK +```` 最� @@ -580,13 +579,13 @@ return cache.put(key, value); 8. 你�以把List传递给一个接�List�数的方法�? 对任何一个�太熟悉泛型的人�说,这个Java泛型题目看起�令人疑惑,因为�看起�String是一�Object,所以 List应当�以用在需�List的地方,但是事实并�如此。真这样�的�会导致编译错误。如 果你�深一步考虑,你会�现Java这样�是有�义的,因为List�以存储任何类型的对象包括String, Integer等等,而List��能用�存储Strings。 - +```` List objectList; List stringList; objectList = stringList; //compilation error incompatible types - +```` 9. Array中�以用泛型�? 这�能是Java泛型�试题中最简�的一个了,当然��是你�知�Array事实上并�支�泛型,这也是为什么Joshua Bloch在Effective Java一书中建议使用List�代替Array,因为List�以�供编译期的类型安全��,而Array��能。 @@ -594,9 +593,9 @@ objectList = stringList; //compilation error incompatible types 10. 如何阻止Java中的类型未检查的警告? 如果你把泛型和原始类型混�起�使用,例如下列代�,Java 5的javac编译器会产生类型未检查的警告,例如 - +```` List rawList = new ArrayList() - +```` 注�: Hello.java使用了未检查或称为�安全的�作; 这�警告�以使用@SuppressWarnings(“unchecked�)注解��蔽。 @@ -609,9 +608,6 @@ https://www.cnblogs.com/dengchengchao/p/9717097.html https://www.cnblogs.com/cat520/p/9353291.html https://www.cnblogs.com/coprince/p/8603492.html - - - ## 微信公众� ### Java技术江湖 diff --git "a/docs/java/basic/14\343\200\201\346\236\232\344\270\276\347\261\273.md" "b/docs/java/basic/14\343\200\201\346\236\232\344\270\276\347\261\273.md" index 2891f98..e5219d4 100644 --- "a/docs/java/basic/14\343\200\201\346\236\232\344\270\276\347\261\273.md" +++ "b/docs/java/basic/14\343\200\201\346\236\232\344\270\276\347\261\273.md" @@ -94,136 +94,136 @@ ### 枚举类的具体使用 这部分内容�考https://blog.csdn.net/qq_27093465/article/details/52180865 #### 常� - - public class 常� { - } - enum Color { - Red, Green, Blue, Yellow - } - +```` +public class 常� { +} +enum Color { + Red, Green, Blue, Yellow +} +```` #### switch JDK1.6之�的switch语��支�int,char,enum类型,使用枚举,能让我们的代��读性更强。 - - public static void showColor(Color color) { - switch (color) { - case Red: - System.out.println(color); - break; - case Blue: - System.out.println(color); - break; - case Yellow: - System.out.println(color); - break; - case Green: - System.out.println(color); - break; - } - } - +```` +public static void showColor(Color color) { + switch (color) { + case Red: + System.out.println(color); + break; + case Blue: + System.out.println(color); + break; + case Yellow: + System.out.println(color); + break; + case Green: + System.out.println(color); + break; + } +} +```` #### �枚举中添加新方法 如果打算自定义自己的方法,那么必须在enum实例�列的最�添加一个分�。而且 Java �求必须先定义 enum 实例。 - - enum Color { - //�个颜色都是枚举类的一个实例,并且构造方法�和枚举类的格�相符�。 - //如果实例��有其他内容,实例�列结�时�加分�。 - Red("红色", 1), Green("绿色", 2), Blue("�色", 3), Yellow("黄色", 4); - String name; - int index; - Color(String name, int index) { - this.name = name; - this.index = index; - } - public void showAllColors() { - //values是Color实例的数组,在通过index和name�以获�对应的值。 - for (Color color : Color.values()) { - System.out.println(color.index + ":" + color.name); - } +```` +enum Color { + //�个颜色都是枚举类的一个实例,并且构造方法�和枚举类的格�相符�。 + //如果实例��有其他内容,实例�列结�时�加分�。 + Red("红色", 1), Green("绿色", 2), Blue("�色", 3), Yellow("黄色", 4); + String name; + int index; + Color(String name, int index) { + this.name = name; + this.index = index; + } + public void showAllColors() { + //values是Color实例的数组,在通过index和name�以获�对应的值。 + for (Color color : Color.values()) { + System.out.println(color.index + ":" + color.name); } } - +} +```` #### 覆盖枚举的方法 所有枚举类都继承自Enum类,所以�以�写该类的方法 下�给出一个toString()方法覆盖的例�。 - - @Override - public String toString() { - return this.index + ":" + this.name; - } - +```` +@Override +public String toString() { + return this.index + ":" + this.name; +} +```` #### 实现接� 所有的枚举都继承自java.lang.Enum类。由于Java �支�多继承,所以枚举对象�能�继承其他类。 - - enum Color implements Print{ - @Override - public void print() { - System.out.println(this.name); - } +```` +enum Color implements Print{ + @Override + public void print() { + System.out.println(this.name); } - +} +```` #### 使用接�组织枚举 �个实现接�,�组织枚举,简�讲,就是分类�。如果大�使用枚举的�,这么干,在写代�的时候,就很方便调用啦。 - - public class 用接�组织枚举 { - public static void main(String[] args) { - Food cf = chineseFood.dumpling; - Food jf = Food.JapaneseFood.fishpiece; - for (Food food : chineseFood.values()) { - System.out.println(food); - } - for (Food food : Food.JapaneseFood.values()) { - System.out.println(food); - } +```` +public class 用接�组织枚举 { + public static void main(String[] args) { + Food cf = chineseFood.dumpling; + Food jf = Food.JapaneseFood.fishpiece; + for (Food food : chineseFood.values()) { + System.out.println(food); } - } - interface Food { - enum JapaneseFood implements Food { - suse, fishpiece + for (Food food : Food.JapaneseFood.values()) { + System.out.println(food); } } - enum chineseFood implements Food { - dumpling, tofu +} +interface Food { + enum JapaneseFood implements Food { + suse, fishpiece } - +} +enum chineseFood implements Food { + dumpling, tofu +} +```` #### 枚举类集� java.util.EnumSet和java.util.EnumMap是两个枚举集�。EnumSet��集�中的元素���;EnumMap中的 key是enum类型,而value则�以是任�类型。 EnumSet在JDK中没有找到实现类,这里写一个EnumMap的例� - - public class 枚举类集� { - public static void main(String[] args) { - EnumMap map = new EnumMap(Color.class); - map.put(Color.Blue, "Blue"); - map.put(Color.Yellow, "Yellow"); - map.put(Color.Red, "Red"); - System.out.println(map.get(Color.Red)); - } +```` +public class 枚举类集� { + public static void main(String[] args) { + EnumMap map = new EnumMap(Color.class); + map.put(Color.Blue, "Blue"); + map.put(Color.Yellow, "Yellow"); + map.put(Color.Red, "Red"); + System.out.println(map.get(Color.Red)); } - +} +```` ## 使用枚举类的注�事项 -![image](https://img-blog.csdn.net/20170112172420090) +![image](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230403212903.png) 枚举类型对象之间的值比较,是�以使用==,直接�比较值,是�相等的,�是必须使用equals方法的哟。 因为枚举类Enum已��写了equals方法 - - /** - * Returns true if the specified object is equal to this - * enum constant. - * - * @param other the object to be compared for equality with this object. - * @return true if the specified object is equal to this - * enum constant. - */ - public final boolean equals(Object other) { - return this==other; - } - +```` +/** + * Returns true if the specified object is equal to this + * enum constant. + * + * @param other the object to be compared for equality with this object. + * @return true if the specified object is equal to this + * enum constant. + */ +public final boolean equals(Object other) { + return this==other; +} +```` ## 枚举类的实现原� 这部分�考https://blog.csdn.net/mhmyqn/article/details/48087247 @@ -235,46 +235,46 @@ EnumSet在JDK中没有找到实现类,这里写一个EnumMap的例� > Java在1.5中添加了java.lang.Enum抽象类,它是所有枚举类型基类。�供了一些基础属性和基础方法。�时,对把枚举用作Set和Map也�供了支�,�java.util.EnumSet和java.util.EnumMap。 接下�定义一个简�的枚举类 - - public enum Day { - MONDAY { - @Override - void say() { - System.out.println("MONDAY"); - } +```` +public enum Day { + MONDAY { + @Override + void say() { + System.out.println("MONDAY"); } - , TUESDAY { - @Override - void say() { - System.out.println("TUESDAY"); - } - }, FRIDAY("work"){ - @Override - void say() { - System.out.println("FRIDAY"); - } - }, SUNDAY("free"){ - @Override - void say() { - System.out.println("SUNDAY"); - } - }; - String work; - //没有构造�数时,�个实例�以看�常�。 - //使用构造�数时,�个实例都会�得�一样,�以看���的类型,所以编译�会生�实例个数对应的class。 - private Day(String work) { - this.work = work; + } + , TUESDAY { + @Override + void say() { + System.out.println("TUESDAY"); } - private Day() { - + }, FRIDAY("work"){ + @Override + void say() { + System.out.println("FRIDAY"); } - //枚举实例必须实现枚举类中的抽象方法 - abstract void say (); - + }, SUNDAY("free"){ + @Override + void say() { + System.out.println("SUNDAY"); + } + }; + String work; + //没有构造�数时,�个实例�以看�常�。 + //使用构造�数时,�个实例都会�得�一样,�以看���的类型,所以编译�会生�实例个数对应的class。 + private Day(String work) { + this.work = work; } + private Day() { -�编译结果 + } + //枚举实例必须实现枚举类中的抽象方法 + abstract void say (); +} +```` +�编译结果 +```` D:\MyTech\out\production\MyTech\com\javase\枚举类>javap Day.class Compiled from "Day.java" @@ -291,43 +291,43 @@ EnumSet在JDK中没有找到实现类,这里写一个EnumMap的例� com.javase.枚举类.Day(java.lang.String, int, java.lang.String, com.javase.枚举类.Day$1); static {}; } - +```` > �以看到,一个枚举在�过编译器编译过�,��了一个抽象类,它继承了java.lang.Enum;而枚举中定义的枚举常�,��了相应的public static final属性,而且其类型就抽象类的类型,�字就是枚举常�的�字. > > �时我们�以在Operator.class的相�路径下看到四个内部类的.class文件com/mikan/Day$1.class�com/mikan/Day$2.class�com/mikan/Day$3.class�com/mikan/Day$4.class,也就是说这四个命�字段分别使用了内部类�实现的;�时添加了两个方法values()和valueOf(String);我们定义的构造方法本��有一个�数,但���了三个�数;�时还生�了一个��代��。这些具体的内容接下�仔细看看。 下�分�一下字节�中的�部分,其中: - - InnerClasses: - static #23; //class com/javase/枚举类/Day$4 - static #18; //class com/javase/枚举类/Day$3 - static #14; //class com/javase/枚举类/Day$2 - static #10; //class com/javase/枚举类/Day$1 - +```` +InnerClasses: + static #23; //class com/javase/枚举类/Day$4 + static #18; //class com/javase/枚举类/Day$3 + static #14; //class com/javase/枚举类/Day$2 + static #10; //class com/javase/枚举类/Day$1 +```` 从中�以看到它有4个内部类,这四个内部类的详细信���会分�。 - - static {}; - descriptor: ()V - flags: ACC_STATIC - Code: - stack=5, locals=0, args_size=0 - 0: new #10 // class com/javase/枚举类/Day$1 - 3: dup - 4: ldc #11 // String MONDAY - 6: iconst_0 - 7: invokespecial #12 // Method com/javase/枚举类/Day$1."":(Ljava/lang/String;I)V - 10: putstatic #13 // Field MONDAY:Lcom/javase/枚举类/Day; - 13: new #14 // class com/javase/枚举类/Day$2 - 16: dup - 17: ldc #15 // String TUESDAY - 19: iconst_1 - 20: invokespecial #16 // Method com/javase/枚举类/Day$2."":(Ljava/lang/String;I)V - //��类似,这里�略 - } - +```` +static {}; + descriptor: ()V + flags: ACC_STATIC + Code: + stack=5, locals=0, args_size=0 + 0: new #10 // class com/javase/枚举类/Day$1 + 3: dup + 4: ldc #11 // String MONDAY + 6: iconst_0 + 7: invokespecial #12 // Method com/javase/枚举类/Day$1."":(Ljava/lang/String;I)V + 10: putstatic #13 // Field MONDAY:Lcom/javase/枚举类/Day; + 13: new #14 // class com/javase/枚举类/Day$2 + 16: dup + 17: ldc #15 // String TUESDAY + 19: iconst_1 + 20: invokespecial #16 // Method com/javase/枚举类/Day$2."":(Ljava/lang/String;I)V + //��类似,这里�略 +} +```` 其实编译器生�的这个��代���了如下工作:分别设置生�的四个公共��常�字段的值,�时编译器还生�了一个��字段$VALUES,�存的是枚举类型定义的所有枚举常� 编译器添加的values方法: - +```` public static com.javase.Day[] values(); flags: ACC_PUBLIC, ACC_STATIC Code: @@ -336,16 +336,17 @@ EnumSet在JDK中没有找到实现类,这里写一个EnumMap的例� 3: invokevirtual #3 // Method "[Lcom/mikan/Day;".clone:()Ljava/lang/Object; 6: checkcast #4 // class "[Lcom/javase/Day;" 9: areturn - 这个方法是一个公共的��方法,所以我们�以直接调用该方法(Day.values()),返回这个枚举值的数组,�外,这个方法的实现是,克隆在��代��中�始化的$VALUES字段的值,并把类型强转�Day[]类型返回。 +```` +这个方法是一个公共的��方法,所以我们�以直接调用该方法(Day.values()),返回这个枚举值的数组,�外,这个方法的实现是,克隆在��代��中�始化的$VALUES字段的值,并把类型强转�Day[]类型返回。 造方法为什么增加了两个�数? 有一个问题,构造方法我们明明�定义了一个�数,为什么生�的构造方法是三个�数呢? - 从Enum类中我们�以看到,为�个枚举都定义了两个属性,name和ordinal,name表示我们定义的枚举常�的�称,如FRIDAY�TUESDAY,而ordinal是一个顺��,根�定义的顺�分别赋予一个整形值,从0开始。在枚举常��始化时,会自动为�始化这两个字段,设置相应的值,所以�在构造方法中添加了两个�数。�: - - �外三个枚举常�生�的内部类基本上差�多,这里就���说明了。 +从Enum类中我们�以看到,为�个枚举都定义了两个属性,name和ordinal,name表示我们定义的枚举常�的�称,如FRIDAY�TUESDAY,而ordinal是一个顺��,根�定义的顺�分别赋予一个整形值,从0开始。在枚举常��始化时,会自动为�始化这两个字段,设置相应的值,所以�在构造方法中添加了两个�数。�: + +�外三个枚举常�生�的内部类基本上差�多,这里就���说明了。 > 我们�以从Enum类的代�中看到,定义的name和ordinal属性都是final的,而且大部分方法也都是final的,特别是clone�readObject�writeObject这三个方法,这三个方法和枚举通过��代���进行�始化一起。 diff --git "a/docs/java/basic/15\343\200\201Java\346\263\250\350\247\243\345\222\214\346\234\200\344\275\263\345\256\236\350\267\265.md" "b/docs/java/basic/15\343\200\201Java\346\263\250\350\247\243\345\222\214\346\234\200\344\275\263\345\256\236\350\267\265.md" index ab4a401..259a732 100644 --- "a/docs/java/basic/15\343\200\201Java\346\263\250\350\247\243\345\222\214\346\234\200\344\275\263\345\256\236\350\267\265.md" +++ "b/docs/java/basic/15\343\200\201Java\346\263\250\350\247\243\345\222\214\346\234\200\344\275\263\345\256\236\350\267\265.md" @@ -26,18 +26,6 @@ * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) - ---- -title: 夯实Java基础系列15:Java注解简介和最佳实践 -date: 2019-9-15 15:56:26 # 文章生�时间,一般�改 -categories: - - Java技术江湖 - - Java基础 -tags: - - annotation - - Java注解 ---- - 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -73,9 +61,7 @@ Annotation 中文译过�就是注解�标释的��,在 Java 中注解是 并且,往抽象地说,标签并�一定是一张纸,它�以是对人和事物的属性评价。也就是说,标签具备对于抽象事物的解释。 -![](https://img-blog.csdn.net/20170627213419176?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYnJpYmx1ZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) - - +![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230403213103.png) 所以,基于如此,我完�了自我的知识认知�级,我决定用标签�解释注解。 @@ -166,8 +152,8 @@ java.lang.annotation�供了四�元注解,专门注解其他的注解(在 JDK 内置注解 先�看几个 Java 内置的注解,让大家热热身。 - @Override 演示 - +@Override 演示 +```` class Parent { public void run() { } @@ -182,7 +168,9 @@ JDK 内置注解 public void run() { } } +```` @Deprecated 演示 +```` class Parent { /** @@ -201,7 +189,9 @@ class Parent { parent.run(); // 在编译器中此方法会显示过时标志 } } +```` @SuppressWarnings 演示 +```` class Parent { // 因为定义的 name 没有使用,那么编译器就会有警告,这时候使用此注解�以�蔽掉警告 @@ -209,8 +199,10 @@ class Parent { @SuppressWarnings("all") private String name; } - +```` @FunctionalInterface 演示 + +```` /** * 此注解是 Java8 �出的函数�接�,接�中��许有一个抽象方法 * 加上这个注解之�,类中多一个抽象方法或者少一个抽象方法都会报错 @@ -219,7 +211,7 @@ class Parent { interface Func { void run(); } - +```` ## 注解处�器实战 @@ -230,27 +222,30 @@ interface Func { 我们先�了解下如何通过在�行时使用�射获�在程�中的使用的注解信�。如下类注解和方法注解。 类注解 - Class aClass = ApiController.class; - Annotation[] annotations = aClass.getAnnotations(); - - for(Annotation annotation : annotations) { - if(annotation instanceof ApiAuthAnnotation) { - ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation; - System.out.println("name: " + apiAuthAnnotation.name()); - System.out.println("age: " + apiAuthAnnotation.age()); - } + +```` +Class aClass = ApiController.class; +Annotation[] annotations = aClass.getAnnotations(); + +for(Annotation annotation : annotations) { + if(annotation instanceof ApiAuthAnnotation) { + ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation; + System.out.println("name: " + apiAuthAnnotation.name()); + System.out.println("age: " + apiAuthAnnotation.age()); } - 方法注解 - Method method = ... //通过�射获�方法对象 - Annotation[] annotations = method.getDeclaredAnnotations(); - - for(Annotation annotation : annotations) { - if(annotation instanceof ApiAuthAnnotation) { - ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation; - System.out.println("name: " + apiAuthAnnotation.name()); - System.out.println("age: " + apiAuthAnnotation.age()); - } - } +} +方法注解 +Method method = ... //通过�射获�方法对象 +Annotation[] annotations = method.getDeclaredAnnotations(); + +for(Annotation annotation : annotations) { + if(annotation instanceof ApiAuthAnnotation) { + ApiAuthAnnotation apiAuthAnnotation = (ApiAuthAnnotation) annotation; + System.out.println("name: " + apiAuthAnnotation.name()); + System.out.println("age: " + apiAuthAnnotation.age()); + } +} +```` 此部分内容��考: 通过�射获�注解信� 注解处�器实战 @@ -260,33 +255,33 @@ interface Func { 接下���的事情: 写一个切�,拦截�览器访问带注解的接�,�出注解信�,判断年龄�确定是��以继续访问。 在 dispatcher-servlet.xml 文件中定义 aop 切� - - - - - - - - - +```` + + + + + + + + +```` 切�类处�逻辑�注解处�器代�如 - - @Component("apiAuthAspect") - public class ApiAuthAspect { - - public Object auth(ProceedingJoinPoint pjp) throws Throwable { - Method method = ((MethodSignature) pjp.getSignature()).getMethod(); - ApiAuthAnnotation apiAuthAnnotation = method.getAnnotation(ApiAuthAnnotation.class); - Integer age = apiAuthAnnotation.age(); - if (age > 18) { - return pjp.proceed(); - } else { - throw new RuntimeException("你未满18�,�止访问"); - } +```` +@Component("apiAuthAspect") +public class ApiAuthAspect { + + public Object auth(ProceedingJoinPoint pjp) throws Throwable { + Method method = ((MethodSignature) pjp.getSignature()).getMethod(); + ApiAuthAnnotation apiAuthAnnotation = method.getAnnotation(ApiAuthAnnotation.class); + Integer age = apiAuthAnnotation.age(); + if (age > 18) { + return pjp.proceed(); + } else { + throw new RuntimeException("你未满18�,�止访问"); } } - - +} +```` ## ��类型的注解 @@ -295,7 +290,7 @@ interface Func { 你�以在�行期访问类,方法或者��的注解信�,下是一个访问类注解的例�: ``` - Class aClass = TheClass.class; +Class aClass = TheClass.class; Annotation[] annotations = aClass.getAnnotations(); for(Annotation annotation : annotations){ diff --git "a/docs/java/basic/16\343\200\201JavaIO\346\265\201.md" "b/docs/java/basic/16\343\200\201JavaIO\346\265\201.md" index a405b7f..4403458 100644 --- "a/docs/java/basic/16\343\200\201JavaIO\346\265\201.md" +++ "b/docs/java/basic/16\343\200\201JavaIO\346\265\201.md" @@ -24,15 +24,6 @@ * [微信公众�](#微信公众�) * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) ---- -title: 夯实Java基础系列16:一文读懂Java IO�和常��试题 -date: 2019-9-16 15:56:26 # 文章生�时间,一般�改 -categories: - - Java技术江湖 - - Java基础 -tags: - - Java IO� ---- 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -60,7 +51,6 @@ tags: > 在这一�节,我会试�给出Java IO(java.io)包下所有类的概述。更具体地说,我会根�类的用途对类进行分组。这个分组将会使你在未�的工作中,进行类的用途判定时,或者是为�个特定用途选择类时�得更加容易。 -​ **输入和输出** 术语“输入�和“输出�有时候会有一点让人疑惑。一个应用程�的输入往往是�外一个应用程�的输出 @@ -174,7 +164,7 @@ java.io.InputStream类是所有Java IO输入�的基类。如果你正在开� 这使得RandomAccessFile�以覆盖一个文件的�些部分�或者追加内容到它的末尾�或者删除它的�些内容,当然它也�以从文件的任何�置开始读�文件。 下�是具体例�: - +```` @Test //文件�范例,打开一个文件的输入�,读�到字节数组,�写入�一个文件的输出� public void test1() { @@ -193,6 +183,7 @@ java.io.InputStream类是所有Java IO输入�的基类。如果你正在开� e.printStackTrace(); } } +```` ### 字符�和字节� Java IO的Reader和Writer除了基于字符之外,其他方�都与InputStream和OutputStream�常类似。他们被用于读写文本。InputStream和OutputStream是基于字节的,还记得�? @@ -204,46 +195,47 @@ Writer Writer类是Java IO中所有Writer的基类。�类包括BufferedWriter和PrintWriter等等。 这是一个简�的Java IO Reader的例�: +```` +Reader reader = new FileReader("c:\\data\\myfile.txt"); - Reader reader = new FileReader("c:\\data\\myfile.txt"); - - int data = reader.read(); - - while(data != -1){ - - char dataChar = (char) data; - - data = reader.read(); - - } +int data = reader.read(); + +while(data != -1){ + char dataChar = (char) data; + + data = reader.read(); + +} +```` 你通常会使用Reader的�类,而�会直接使用Reader。Reader的�类包括InputStreamReader,CharArrayReader,FileReader等等。�以查看Java IO概述�览完整的Reader表格。 **整�Reader与InputStream** 一个Reader�以和一个InputStream相结�。如果你有一个InputStream输入�,并且想从其中读�字符,�以把这个InputStream包装到InputStreamReader中。把InputStream传递到InputStreamReader的构造函数中: - - Reader reader = new InputStreamReader(inputStream); +```` +Reader reader = new InputStreamReader(inputStream); +```` 在构造函数中�以指定解�方�。 **Writer** Writer类是Java IO中所有Writer的基类。�类包括BufferedWriter和PrintWriter等等。这是一个Java IO Writer的例�: +```` +Writer writer = new FileWriter("c:\\data\\file-output.txt"); - Writer writer = new FileWriter("c:\\data\\file-output.txt"); - - writer.write("Hello World Writer"); - - writer.close(); +writer.write("Hello World Writer"); +writer.close(); +```` �样,你最好使用Writer的�类,�需�直接使用Writer,因为�类的实现更加明确,更能表现你的�图。常用�类包括OutputStreamWriter,CharArrayWriter,FileWriter等。Writer的write(int c)方法,会将传入�数的低16�写入到Writer中,忽略高16�的数�。 **整�Writer和OutputStream** 与Reader和InputStream类似,一个Writer�以和一个OutputStream相结�。把OutputStream包装到OutputStreamWriter中,所有写入到OutputStreamWriter的字符都将会传递给OutputStream。这是一个OutputStreamWriter的例�: - - Writer writer = new OutputStreamWriter(outputStream); - +```` +Writer writer = new OutputStreamWriter(outputStream); +```` ### IO管� Java IO中的管�为�行在�一个JVM中的两个线程�供了通信的能力。所以管�也�以作为数��以�目标媒介。 @@ -258,37 +250,38 @@ Java IO中的管�为�行在�一个JVM中的两个线程�供了通信的 Java IO管�示例 这是一个如何将PipedInputStream和PipedOutputStream关�起�的简�例�: - - //使用管��完�两个线程间的数�点对点传递 - @Test - public void test2() throws IOException { - PipedInputStream pipedInputStream = new PipedInputStream(); - PipedOutputStream pipedOutputStream = new PipedOutputStream(pipedInputStream); - new Thread(new Runnable() { - @Override - public void run() { - try { - pipedOutputStream.write("hello input".getBytes()); - pipedOutputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } +```` +//使用管��完�两个线程间的数�点对点传递 + @Test + public void test2() throws IOException { + PipedInputStream pipedInputStream = new PipedInputStream(); + PipedOutputStream pipedOutputStream = new PipedOutputStream(pipedInputStream); + new Thread(new Runnable() { + @Override + public void run() { + try { + pipedOutputStream.write("hello input".getBytes()); + pipedOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); } - }).start(); - new Thread(new Runnable() { - @Override - public void run() { - try { - byte []arr = new byte[128]; - while (pipedInputStream.read(arr) != -1) { - System.out.println(Arrays.toString(arr)); - } - pipedInputStream.close(); - } catch (IOException e) { - e.printStackTrace(); + } + }).start(); + new Thread(new Runnable() { + @Override + public void run() { + try { + byte []arr = new byte[128]; + while (pipedInputStream.read(arr) != -1) { + System.out.println(Arrays.toString(arr)); } + pipedInputStream.close(); + } catch (IOException e) { + e.printStackTrace(); } - }).start(); + } + }).start(); +```` 管�和线程 请记得,当使用两个相关�的管��时,务必将它们分�给��的线程。read()方法和write()方法调用时会导致�阻塞,这�味�如果你�试在一个线程中�时进行读和写,�能会导致线程死�。 @@ -304,7 +297,7 @@ Java中网络的内容或多或少的超出了Java IO的范畴。关于Java网 当两个进程之间建立了网络连接之�,他们通信的方�如��作文件一样:利用InputStream读�数�,利用OutputStream写入数�。����说,Java网络API用�在��进程之间建立网络连接,而Java IO则用�在建立了连接之�的进程之间交�数�。 基本上�味�如果你有一份能够对文件进行写入�些数�的代�,那么这些数�也�以很容易地写入到网络连接中去。你所需��的仅仅�是在代�中利用OutputStream替代FileOutputStream进行数�的写入。因为FileOutputStream是OuputStream的�类,所以这么�并没有什么问题。 - +```` //从网络中读�字节�也�以直接使用OutputStream public void test3() { //读�网络进程的输出� @@ -318,7 +311,7 @@ Java中网络的内容或多或少的超出了Java IO的范畴。关于Java网 //处�网络信� //do something with the OutputStream } - +```` ### 字节和字符数组 @@ -330,7 +323,7 @@ Java中网络的内容或多或少的超出了Java IO的范畴。关于Java网 ��的例�中,字符数组或字节数组是用�缓存数�的临时存储空间,�过它们�时也�以作为数���或者写入目的地。 举个例�: - +```` //字符数组和字节数组在io过程中的作用 public void test4() { //arr和brr分别作为数�� @@ -339,7 +332,7 @@ Java中网络的内容或多或少的超出了Java IO的范畴。关于Java网 byte []brr = {1,2,3,4,5}; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(brr); } - +```` ### System.in, System.out, System.err System.in, System.out, System.err这3个��样是常�的数���和数��目的地。使用最多的�能是在控制�程�里利用System.out将输出打�到控制�上。 @@ -358,7 +351,7 @@ JVM�动的时候通过Java�行时�始化这3个�,所以你�需�� System.out和System.err的简�例�: 这是一个System.out和System.err结�使用的简�示例: - +```` //测试System.in, System.out, System.err public static void main(String[] args) { int in = new Scanner(System.in).nextInt(); @@ -370,7 +363,7 @@ System.out和System.err的简�例�: // 10 // out } - +```` ### 字符�的Buffered和Filter @@ -437,8 +430,6 @@ Filter Stream是一�IO�主�作用是用�对存在的�增加一些� 在java.io包中主�由4个�用的filter Stream。两个字节filter stream,两个字符filter stream. 分别是FilterInputStream, FilterOutputStream, FilterReader and FilterWriter.这些类是抽象类,�能被实例化的。 - - ### 在文件拷�的时候,那一���用��更多的性能? 在字节�的时候,使用BufferedInputStream和BufferedOutputStream。 在字符�的时候,使用BufferedReader 和 BufferedWriter diff --git "a/docs/java/basic/17\343\200\201\345\244\232\347\272\277\347\250\213.md" "b/docs/java/basic/17\343\200\201\345\244\232\347\272\277\347\250\213.md" index e2cc758..3045d4e 100644 --- "a/docs/java/basic/17\343\200\201\345\244\232\347\272\277\347\250\213.md" +++ "b/docs/java/basic/17\343\200\201\345\244\232\347\272\277\347\250\213.md" @@ -19,15 +19,6 @@ * [微信公众�](#微信公众�) * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) ---- -title: 夯实Java基础系列17:一文�懂Java多线程使用方��实现原�以�常��试题 -date: 2019-9-17 15:56:26 # 文章生�时间,一般�改 -categories: - - Java技术江湖 - - Java基础 -tags: - - 多线程 ---- 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial diff --git "a/docs/java/basic/18\343\200\201\346\267\261\345\205\245\347\220\206\350\247\243\345\206\205\351\203\250\347\261\273.md" "b/docs/java/basic/18\343\200\201\346\267\261\345\205\245\347\220\206\350\247\243\345\206\205\351\203\250\347\261\273.md" index 0ce799d..adf7861 100644 --- "a/docs/java/basic/18\343\200\201\346\267\261\345\205\245\347\220\206\350\247\243\345\206\205\351\203\250\347\261\273.md" +++ "b/docs/java/basic/18\343\200\201\346\267\261\345\205\245\347\220\206\350\247\243\345\206\205\351\203\250\347\261\273.md" @@ -12,21 +12,10 @@ * [内部类�始化](#内部类�始化) * [内部类的�载](#内部类的�载) * [内部类的继承](#内部类的继承) - * [Java内部类的实现原�](#java内部类的实现原�) * [�考文章](#�考文章) * [微信公众�](#微信公众�) * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) ---- -title: 夯实Java基础系列18:深入�解Java内部类�其实现原� -date: 2019-9-18 15:56:26 # 文章生�时间,一般�改 -categories: - - Java技术江湖 - - Java基础 -tags: - - Java内部类 ---- - 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -58,8 +47,6 @@ tags: > > (4)外部类�能直接访问内部类的的�员,但�以通过内部类对象�访问 - -   内部类是外部类的一个�员,因此内部类�以自由地访问外部类的�员��,无论是�是private的。   因为当�个外围类的对象创建内部类的对象时,此内部类会�获一个��引用,它引用了实例化该内部对象的外围类对象。通过这个指针,�以访问外围类对象的全部状�。 @@ -121,125 +108,125 @@ tags: 3 外部类和它的内部类之间的关系 +```` +//本节讨论内部类以���访问��的控制 +//内部类�有在使用时�会被加载。 +//外部类B +public class B{ + int i = 1; + int j = 1; + static int s = 1; + static int ss = 1; + A a; + AA aa; + AAA aaa; + //内部类A + + public class A { +// static void go () { +// +// } +// static { +// +// } +// static int b = 1;//���内部类�能有���员��和��代��和��方法, + // 因为内部类在外部类加载时并�会被加载和�始化。 + //所以�会进行��代�的调用 + int i = 2;//外部类无法读�内部类的�员,而内部类�以直接访问外部类�员 - //本节讨论内部类以���访问��的控制 - //内部类�有在使用时�会被加载。 - //外部类B - public class B{ - int i = 1; - int j = 1; - static int s = 1; - static int ss = 1; - A a; - AA aa; - AAA aaa; - //内部类A - - public class A { - // static void go () { - // - // } - // static { - // - // } - // static int b = 1;//���内部类�能有���员��和��代��和��方法, - // 因为内部类在外部类加载时并�会被加载和�始化。 - //所以�会进行��代�的调用 - int i = 2;//外部类无法读�内部类的�员,而内部类�以直接访问外部类�员 - - public void test() { - System.out.println(j); - j = 2; - System.out.println(j); - System.out.println(s);//�以访问类的���员�� - } - public void test2() { - AA aa = new AA(); - AAA aaa = new AAA(); - } - - } - //��内部类S,�以被外部访问 - public static class S { - int i = 1;//访问�到�����。 - static int s = 0;//�以有���� - - public static void main(String[] args) { - System.out.println(s); - } - @Test - public void test () { - // System.out.println(j);//报错,��内部类�能读�外部类的����� - System.out.println(s); - System.out.println(ss); - s = 2; - ss = 2; - System.out.println(s); - System.out.println(ss); - } + public void test() { + System.out.println(j); + j = 2; + System.out.println(j); + System.out.println(s);//�以访问类的���员�� } - - //内部类AA,其实这里加protected相当于default - //因为外部类�调用内部类�能通过B。并且无法直接继承AA,所以必须在�包 - //的类中�能调用到(这里�考虑��内部类),那么就和default一样了。 - protected class AA{ - int i = 2;//内部类之间�共享�� - public void test (){ - A a = new A(); - AAA aaa = new AAA(); - //内部类之间�以互相访问。 - } + public void test2() { + AA aa = new AA(); + AAA aaa = new AAA(); } - //包外部�然无法访问,因为包没有继承关系,所以找�到这个类 - protected static class SS{ - int i = 2;//内部类之间�共享�� - public void test (){ - - //内部类之间�以互相访问。 - } - } - //�有内部类A,对外���,但对内部类和父类�� - private class AAA { - int i = 2;//内部类之间�共享�� - - public void test() { - A a = new A(); - AA aa = new AA(); - //内部类之间�以互相访问。 - } + + } + //��内部类S,�以被外部访问 + public static class S { + int i = 1;//访问�到�����。 + static int s = 0;//�以有���� + + public static void main(String[] args) { + System.out.println(s); } @Test - public void test(){ + public void test () { +// System.out.println(j);//报错,��内部类�能读�外部类的����� + System.out.println(s); + System.out.println(ss); + s = 2; + ss = 2; + System.out.println(s); + System.out.println(ss); + } + } + + //内部类AA,其实这里加protected相当于default + //因为外部类�调用内部类�能通过B。并且无法直接继承AA,所以必须在�包 + //的类中�能调用到(这里�考虑��内部类),那么就和default一样了。 + protected class AA{ + int i = 2;//内部类之间�共享�� + public void test (){ A a = new A(); - a.test(); - //内部类�以修改外部类的�员�� - //打�出 1 2 - B b = new B(); - + AAA aaa = new AAA(); + //内部类之间�以互相访问。 } } + //包外部�然无法访问,因为包没有继承关系,所以找�到这个类 + protected static class SS{ + int i = 2;//内部类之间�共享�� + public void test (){ + //内部类之间�以互相访问。 + } + } + //�有内部类A,对外���,但对内部类和父类�� + private class AAA { + int i = 2;//内部类之间�共享�� -​ - //�一个外部类 - class C { - @Test public void test() { - //首先,其他类内部类�能通过外部类�获�其实例。 - B.S s = new B.S(); - //��内部类�以直接通过B类直接获�,�需�B的实例,和���员��类似。 - //B.A a = new B.A(); - //当A�是��类时这行代�会报错。 - //需�使用B的实例�获�A的实例 - B b = new B(); - B.A a = b.new A(); - B.AA aa = b.new AA();//B和C�包,所以�以访问到AA - // B.AAA aaa = b.new AAA();AAA为�有内部类,外部类��� - //当A使用private修饰时,使用B的实例也无法获�A的实例,这一点和�有��是一样的。 - //所有普通的内部类与类中的一个��是类似的。��内部类则与���员类似。 + A a = new A(); + AA aa = new AA(); + //内部类之间�以互相访问。 } } + @Test + public void test(){ + A a = new A(); + a.test(); + //内部类�以修改外部类的�员�� + //打�出 1 2 + B b = new B(); + } +} +```` + +```` +//�一个外部类 +class C { + @Test + public void test() { + //首先,其他类内部类�能通过外部类�获�其实例。 + B.S s = new B.S(); + //��内部类�以直接通过B类直接获�,�需�B的实例,和���员��类似。 + //B.A a = new B.A(); + //当A�是��类时这行代�会报错。 + //需�使用B的实例�获�A的实例 + B b = new B(); + B.A a = b.new A(); + B.AA aa = b.new AA();//B和C�包,所以�以访问到AA +// B.AAA aaa = b.new AAA();AAA为�有内部类,外部类��� + //当A使用private修饰时,使用B的实例也无法获�A的实例,这一点和�有��是一样的。 + //所有普通的内部类与类中的一个��是类似的。��内部类则与���员类似。 + } +} +```` ## 内部类的加载 �能刚�的例�中没办法直观地看到内部类是如何加载的,接下�用例�展示一下内部类加载的过程。 @@ -277,43 +264,43 @@ tags: 需�注�的是: 局部内部类�能在定义该内部类的方法内实例化,��以在此方法外对其实例化。 +```` +public class 局部内部类 { + class A {//局部内部类就是写在方法里的类,�在方法执行时加载,一次性使用。 + public void test() { + class B { + public void test () { + class C { - public class 局部内部类 { - class A {//局部内部类就是写在方法里的类,�在方法执行时加载,一次性使用。 - public void test() { - class B { - public void test () { - class C { - - } } } } } - @Test - public void test () { - int i = 1; - final int j = 2; - class A { - @Test - public void test () { - System.out.println(i); - System.out.println(j); - } - } - A a = new A(); - System.out.println(a); - } - - static class B { - public static void test () { - //static class A报错,方法里�能定义��内部类。 - //因为�有在方法调用时�能进行类加载和�始化。 - + } + @Test + public void test () { + int i = 1; + final int j = 2; + class A { + @Test + public void test () { + System.out.println(i); + System.out.println(j); } } + A a = new A(); + System.out.println(a); } + static class B { + public static void test () { + //static class A报错,方法里�能定义��内部类。 + //因为�有在方法调用时�能进行类加载和�始化。 + + } + } +} +```` ### 匿�内部类 简�地说:匿�内部类就是没有�字的内部类,并且,匿�内部类是局部内部类的一�特殊形�。什么情况下需�使用匿�内部类?如果满足下�的一些�件,使用匿�内部类是比较�适的: @@ -336,61 +323,61 @@ tags: >6  因匿�内部类为局部内部类,所以局部内部类的所有�制都对其生效。 一个匿�内部类的例�: +```` +public class 匿�内部类 { + +} +interface D{ + void run (); +} +abstract class E{ + E (){ - public class 匿�内部类 { - - } - interface D{ - void run (); - } - abstract class E{ - E (){ - - } - abstract void work(); } - class A { - - @Test - public void test (int k) { - //利用接�写出一个实现该接�的类的实例。 - //有且仅有一个实例,这个类无法�用。 - new Runnable() { - @Override - public void run() { - // k = 1;报错,当外部方法中的局部��在内部类使用中必须改为final类型。 - //因为方外部法中�使改�了这个��也�会�映到内部类中。 - //所以对于内部类�讲这�是一个常�。 - System.out.println(100); - System.out.println(k); - } - }; - new D(){ - //实现接�的匿�类 - int i =1; - @Override - public void run() { - System.out.println("run"); - System.out.println(i); - System.out.println(k); - } - }.run(); - new E(){ - //继承抽象类的匿�类 - int i = 1; - void run (int j) { - j = 1; - } - - @Override - void work() { - - } - }; + abstract void work(); +} +class A { + + @Test + public void test (int k) { + //利用接�写出一个实现该接�的类的实例。 + //有且仅有一个实例,这个类无法�用。 + new Runnable() { + @Override + public void run() { +// k = 1;报错,当外部方法中的局部��在内部类使用中必须改为final类型。 + //因为方外部法中�使改�了这个��也�会�映到内部类中。 + //所以对于内部类�讲这�是一个常�。 + System.out.println(100); + System.out.println(k); } - + }; + new D(){ + //实现接�的匿�类 + int i =1; + @Override + public void run() { + System.out.println("run"); + System.out.println(i); + System.out.println(k); + } + }.run(); + new E(){ + //继承抽象类的匿�类 + int i = 1; + void run (int j) { + j = 1; + } + + @Override + void work() { + + } + }; } +} +```` ### 匿�内部类里的final 使用的形�为何�为final @@ -401,37 +388,36 @@ tags: > 为什么必须�为final呢? > > 首先我们知�在内部类编译�功�,它会产生一个class文件,该class文件与外部类并�是�一class文件,仅仅��留对外部类的引用。当外部类传入的�数需�被内部类调用时,从java程�的角度�看是直接被调用: -> -> - public class OuterClass { - public void display(final String name,String age){ - class InnerClass{ - void display(){ - System.out.println(name); - } +```` +public class OuterClass { + public void display(final String name,String age){ + class InnerClass{ + void display(){ + System.out.println(name); } } } - +} +```` 从上�代�中看好�name�数应该是被内部类直接调用?其实�然,在java编译之�实际的�作如下: - - public class OuterClass$InnerClass { - public InnerClass(String name,String age){ - this.InnerClass$name = name; - this.InnerClass$age = age; - } +```` +public class OuterClass$InnerClass { + public InnerClass(String name,String age){ + this.InnerClass$name = name; + this.InnerClass$age = age; + } -​ - public void display(){ - System.out.println(this.InnerClass$name + "----" + this.InnerClass$age ); - } + + public void display(){ + System.out.println(this.InnerClass$name + "----" + this.InnerClass$age ); } - +} +```` 所以从上�代��看,内部类并�是直接调用方法传递的�数,而是利用自身的构造器对传入的�数进行备份,自己内部方法调用的实际上时自己的属性而�是外部方法传递进�的�数。 -> 直到这里还没有解释为什么是final +> 直到这里还没有解释为什么是final > 在内部类中的属性和外部方法的�数两者从外表上看是�一个东西,但实际上��是,所以他们两者是�以任��化的,也就是说在内部类中我对属性的改�并�会影�到外部的形�,而然这从程�员的角度�看这是��行的。 > @@ -444,63 +430,62 @@ tags: ## 内部类�始化 我们一般都是利用构造器�完��个实例的�始化工作的,但是匿�内部类是没有构造器的�那怎么��始化匿�内部类呢?使用构造代���利用构造代��能够达到为匿�内部类创建一个构造器的效果。 - - public class OutClass { - public InnerClass getInnerClass(final int age,final String name){ - return new InnerClass() { - int age_ ; - String name_; - //构造代��完��始化工作 - { - if(0 < age && age < 200){ - age_ = age; - name_ = name; - } - } - public String getName() { - return name_; +```` +public class OutClass { + public InnerClass getInnerClass(final int age,final String name){ + return new InnerClass() { + int age_ ; + String name_; + //构造代��完��始化工作 + { + if(0 < age && age < 200){ + age_ = age; + name_ = name; } - - public int getAge() { - return age_; - } - }; - } - - -​ + } + public String getName() { + return name_; + } + + public int getAge() { + return age_; + } + }; + } +```` + ## 内部类的�载 +如果你创建了一个内部类,然�继承其外围类并�新定义此内部类时,会�生什么呢?也就是说,内部类�以被�载�?这看起�似乎是个很有用的点�,但是“�载�内部类就好�它是外围类的一个方法,其实并�起什么作用: +```` +class Egg { + private Yolk y; + + protected class Yolk { + public Yolk() { + System.out.println("Egg.Yolk()"); + } + } + + public Egg() { + System.out.println("New Egg()"); + y = new Yolk(); + } +} + +public class BigEgg extends Egg { + public class Yolk { + public Yolk() { + System.out.println("BigEgg.Yolk()"); + } + } + + public static void main(String[] args) { + new BigEgg(); + } +} -  如果你创建了一个内部类,然�继承其外围类并�新定义此内部类时,会�生什么呢?也就是说,内部类�以被�载�?这看起�似乎是个很有用的点�,但是“�载�内部类就好�它是外围类的一个方法,其实并�起什么作用: - - - class Egg { - private Yolk y; - - protected class Yolk { - public Yolk() { - System.out.println("Egg.Yolk()"); - } - } - - public Egg() { - System.out.println("New Egg()"); - y = new Yolk(); - } - } - - public class BigEgg extends Egg { - public class Yolk { - public Yolk() { - System.out.println("BigEgg.Yolk()"); - } - } - - public static void main(String[] args) { - new BigEgg(); - } - } +```` �制代� 输出结果为: New Egg() @@ -512,7 +497,7 @@ tags: ## 内部类的继承 因为内部类的构造器�用到其外围类对象的引用,所以在你继承一个内部类的时候,事情�得有点��。问题在于,那个“秘密的�外围类对象的引用必须被�始化,而在被继承的类中并�存在��接的缺�对象。�解决这个问题,需使用专门的语法�明确说清它们之间的关�: - +```` class WithInner { class Inner { Inner(){ @@ -533,10 +518,11 @@ tags: InheritInner ii = new InheritInner(wi); } } -�制代� -输出结果为: -this is a constructor in WithInner.Inner -this is a constructor in InheritInner +```` + �制代� + 输出结果为: + this is a constructor in WithInner.Inner + this is a constructor in InheritInner �以看到,InheritInner �继承自内部类,而�是外围类。但是当�生�一个构造器时,缺�的构造器并�算好,而且你�能�是传递一个指�外围类对象的引用。此外,你必须在构造器内使用如下语法: enclosingClassReference.super(); @@ -544,38 +530,6 @@ enclosingClassReference.super(); 有关匿�内部类实现回调,事件驱动,委托等机制的文章将在下一节讲述。 -## Java内部类的实现原� - -内部类为什么能够访问外部类的�员? - -定义内部类如下: - -![Java 内部类](http://p3.pstatp.com/large/pgc-image/1539338093053104f5529ec) - -使用javap命令进行�编译。 - -编译�得到Main.class Main$Inner.class两个文件,�编译Main$Inner.class文件如下: - -![Java 内部类](http://p1.pstatp.com/large/pgc-image/1539338144888f57662c7bc) - -�以看到,内部类其实拥有外部类的一个引用,在构造函数中将外部类的引用传递进�。 - -匿�内部类为什么�能访问局部的final��? - -其实�以这样想,当方法执行完毕�,局部��的生命周期就结�了,而局部内部类对象的生命周期�能还没有结�,那么在局部内部类中访问局部��就��能了,所以将局部��改为final,改�其生命周期。 - -编写代�如下: - -![Java 内部类](http://p1.pstatp.com/large/pgc-image/15393408957685bcddd1c64) - -这段代�编译为Main.class Main$1.class两个文件,�编译Main$1.class文件如下: - -![Java 内部类](http://p3.pstatp.com/large/pgc-image/1539341219661a629a53b8c) - -�以看到,java将编译时已�确定的值直接�制,进行替�,将无法确定的值放到了内部类的常�池中,并在构造函数中将其从常�池�出到字段中。 - -�以看出,java将局部��m直接进行�制,所以其并�是原�的值,若在内部类中将m更改,局部��的m值�会�,就会出现数��一致,所以java就将其�制为final,使其�能进行更改,这样数��一致的问题就解决了。 - ## �考文章 https://www.cnblogs.com/hujingnb/p/10181621.html diff --git "a/docs/java/basic/19\343\200\201Java\351\233\206\345\220\210\346\241\206\346\236\266\346\242\263\347\220\206.md" "b/docs/java/basic/19\343\200\201Java\351\233\206\345\220\210\346\241\206\346\236\266\346\242\263\347\220\206.md" index 8ad5827..c5c96e2 100644 --- "a/docs/java/basic/19\343\200\201Java\351\233\206\345\220\210\346\241\206\346\236\266\346\242\263\347\220\206.md" +++ "b/docs/java/basic/19\343\200\201Java\351\233\206\345\220\210\346\241\206\346\236\266\346\242\263\347\220\206.md" @@ -61,8 +61,7 @@ tags: 在编写java程�中,我们最常用的除了八�基本数�类型,String对象外还有一个集�类,在我们的的程�中到处充斥�集�类的身影� -![image](https://img-blog.csdnimg.cn/20190222094403579.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3p6dzE1MzE0MzkwOTA=,size_16,color_FFFFFF,t_70) - +![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230403214433.png) java中集�大家�的�员实在是太丰富了,有常用的ArrayList�HashMap�HashSet,也有�常用的Stack�Queue,有线程安全的Vector�HashTable,也有线程�安全的LinkedList�TreeMap等等� ![](https://images0.cnblogs.com/blog/381060/201312/28124707-3a873160808e457686d67c118af6fa70.png) @@ -90,63 +89,63 @@ java中集�大家�的�员实在是太丰富了,有常用的ArrayList�H 在Java中所有实现了Collection接�的类都必须�供两套标准的构造函数,一个是无�,用于创建一个空的Collection,一个是带有Collection�数的有�构造函数,用于创建一个新的Collection,这个新的Collection与传入进�的Collection具备相�的元素。 //�求实现基本的增删改查方法,并且需�能够转�为数组类型 +```` +public class Collection接� { + class collect implements Collection { - public class Collection接� { - class collect implements Collection { - - @Override - public int size() { - return 0; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean contains(Object o) { - return false; - } - - @Override - public Iterator iterator() { - return null; - } - - @Override - public Object[] toArray() { - return new Object[0]; - } - - @Override - public boolean add(Object o) { - return false; - } - - @Override - public boolean remove(Object o) { - return false; - } - - @Override - public boolean addAll(Collection c) { - return false; - } - - @Override - public void clear() { - - } - //�略部分代� - - @Override - public Object[] toArray(Object[] a) { - return new Object[0]; - } + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object o) { + return false; + } + + @Override + public Iterator iterator() { + return null; + } + + @Override + public Object[] toArray() { + return new Object[0]; + } + + @Override + public boolean add(Object o) { + return false; + } + + @Override + public boolean remove(Object o) { + return false; + } + + @Override + public boolean addAll(Collection c) { + return false; } - } + @Override + public void clear() { + + } +//�略部分代� + + @Override + public Object[] toArray(Object[] a) { + return new Object[0]; + } + } +} +```` ## List接� > List接�为Collection直接接�。List所代表的是有�的Collection,�它用��特定的�入顺��维护元素顺�。用户�以对列表中�个元素的�入�置进行精确地控制,�时�以根�元素的整数索引(在列表中的�置)访问元素,并�索列表中的元素。实现List接�的集�主�有:ArrayList�LinkedList�Vector�Stack。 @@ -173,84 +172,84 @@ java中集�大家�的�员实在是太丰富了,有常用的ArrayList�H > > 2.4�Stack > Stack继承自Vector,实现一个�进先出的堆栈。Stack�供5个�外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是�为空,search方法检测一个元素在堆栈中的�置。Stack刚创建�是空栈。。 +```` +public class List接� { + //下�是List的继承关系,由于List接�规定了包括诸如索引查询,迭代器的实现,所以实现List接�的类都会有这些方法。 + //所以�管是ArrayList和LinkedList底层都�以使用数组�作,但一般��供这样外部调用方法。 + // public interface Iterable +// public interface Collection extends Iterable +// public interface List extends Collection + class MyList implements List { + + @Override + public int size() { + return 0; + } - public class List接� { - //下�是List的继承关系,由于List接�规定了包括诸如索引查询,迭代器的实现,所以实现List接�的类都会有这些方法。 - //所以�管是ArrayList和LinkedList底层都�以使用数组�作,但一般��供这样外部调用方法。 - // public interface Iterable - // public interface Collection extends Iterable - // public interface List extends Collection - class MyList implements List { - - @Override - public int size() { - return 0; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean contains(Object o) { - return false; - } - - @Override - public Iterator iterator() { - return null; - } - - @Override - public Object[] toArray() { - return new Object[0]; - } - - @Override - public boolean add(Object o) { - return false; - } - - @Override - public boolean remove(Object o) { - return false; - } - - @Override - public void clear() { - - } - - //�略部分代� - - @Override - public Object get(int index) { - return null; - } - - @Override - public ListIterator listIterator() { - return null; - } - - @Override - public ListIterator listIterator(int index) { - return null; - } - - @Override - public List subList(int fromIndex, int toIndex) { - return null; - } - - @Override - public Object[] toArray(Object[] a) { - return new Object[0]; - } + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object o) { + return false; + } + + @Override + public Iterator iterator() { + return null; + } + + @Override + public Object[] toArray() { + return new Object[0]; + } + + @Override + public boolean add(Object o) { + return false; + } + + @Override + public boolean remove(Object o) { + return false; + } + + @Override + public void clear() { + + } + + //�略部分代� + + @Override + public Object get(int index) { + return null; } - } + @Override + public ListIterator listIterator() { + return null; + } + + @Override + public ListIterator listIterator(int index) { + return null; + } + + @Override + public List subList(int fromIndex, int toIndex) { + return null; + } + + @Override + public Object[] toArray(Object[] a) { + return new Object[0]; + } + } +} +```` ## Set接� > Set是一��包括��元素的Collection。它维�它自己的内部排�,所以�机访问没有任何�义。与List一样,它�样�行null的存在但是仅有一个。由于Set接�的特殊性,所有传入Set集�中的元素都必须��,�时�注�任何��对象,如果在对集�中元素进行�作时,导致e1.equals(e2)==true,则必定会产生�些问题。实现了Set接�的集�有:EnumSet�HashSet�TreeSet。 @@ -261,83 +260,84 @@ java中集�大家�的�员实在是太丰富了,有常用的ArrayList�H > 3.2�HashSet > HashSet堪称查询速度最快的集�,因为其内部是以HashCode�实现的。它内部元素的顺�是由哈希��决定的,所以它���set 的迭代顺�;特别是它���该顺��久��。 - public class Set接� { - // Set接�规定将set看�一个集�,并且使用和数组类似的增删改查方�,�时�供iterator迭代器 - // public interface Set extends Collection - // public interface Collection extends Iterable - // public interface Iterable - class MySet implements Set { - - @Override - public int size() { - return 0; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean contains(Object o) { - return false; - } - - @Override - public Iterator iterator() { - return null; - } - - @Override - public Object[] toArray() { - return new Object[0]; - } - - @Override - public boolean add(Object o) { - return false; - } - - @Override - public boolean remove(Object o) { - return false; - } - - @Override - public boolean addAll(Collection c) { - return false; - } - - @Override - public void clear() { - - } - - @Override - public boolean removeAll(Collection c) { - return false; - } - - @Override - public boolean retainAll(Collection c) { - return false; - } - - @Override - public boolean containsAll(Collection c) { - return false; - } - - @Override - public Object[] toArray(Object[] a) { - return new Object[0]; - } +```` +public class Set接� { + // Set接�规定将set看�一个集�,并且使用和数组类似的增删改查方�,�时�供iterator迭代器 + // public interface Set extends Collection + // public interface Collection extends Iterable + // public interface Iterable + class MySet implements Set { + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object o) { + return false; + } + + @Override + public Iterator iterator() { + return null; + } + + @Override + public Object[] toArray() { + return new Object[0]; + } + + @Override + public boolean add(Object o) { + return false; + } + + @Override + public boolean remove(Object o) { + return false; } - } + @Override + public boolean addAll(Collection c) { + return false; + } + + @Override + public void clear() { + + } + + @Override + public boolean removeAll(Collection c) { + return false; + } + + @Override + public boolean retainAll(Collection c) { + return false; + } + + @Override + public boolean containsAll(Collection c) { + return false; + } + + @Override + public Object[] toArray(Object[] a) { + return new Object[0]; + } + } +} +```` ## Map接� -> Map与List�Set接���,它是由一系列键值对组�的集�,�供了key到Value的映射。�时它也没有继承Collection。在Map中它��了key与value之间的一一对应关系。也就是说一个key对应一个value,所以它�能存在相�的key值,当然value值�以相�。实现map的有:HashMap�TreeMap�HashTable�Properties�EnumMap。 +> Map与List�Set接���,它是由一系列键值对组�的集�,�供了key到Value的映射。�时它也没有继承Collection。在Map中它��了key与value之间的一一对应关系。也就是说一个key对应一个value,所以它�能存在相�的key值,当然value值�以相�。实现map的有:HashMap�TreeMap�HashTable�Properties�EnumMap。 > 4.1�HashMap > 以哈希表数�结构实现,查找对象时通过哈希函数计算其�置,它是为快速查询而设计的,其内部定义了一个hash表数组(Entry[] table),元素会通过哈希转�函数将元素的哈希地�转��数组中存放的索引,如果有冲�,则使用散列链表的形�将所有相�哈希地�的元素串起�,�能通过查看HashMap.Entry的��它是一个�链表结构。 @@ -347,152 +347,152 @@ java中集�大家�的�员实在是太丰富了,有常用的ArrayList�H > > 4.3�HashTable > 也是以哈希表数�结构实现的,解决冲�时与HashMap也一样也是采用了散列链表的形�,�过性能比HashMap�低 +```` +public class Map接� { + //Map接�是最上层接�,Map接�实现类必须实现put和get等哈希�作。 + //并且��供keyset和values,以�entryset等查询结构。 + //public interface Map + class MyMap implements Map { + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public Object get(Object key) { + return null; + } + + @Override + public Object put(Object key, Object value) { + return null; + } + + @Override + public Object remove(Object key) { + return null; + } + + @Override + public void putAll(Map m) { + + } + + @Override + public void clear() { - public class Map接� { - //Map接�是最上层接�,Map接�实现类必须实现put和get等哈希�作。 - //并且��供keyset和values,以�entryset等查询结构。 - //public interface Map - class MyMap implements Map { - - @Override - public int size() { - return 0; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean containsKey(Object key) { - return false; - } - - @Override - public boolean containsValue(Object value) { - return false; - } - - @Override - public Object get(Object key) { - return null; - } - - @Override - public Object put(Object key, Object value) { - return null; - } - - @Override - public Object remove(Object key) { - return null; - } - - @Override - public void putAll(Map m) { - - } - - @Override - public void clear() { - - } - - @Override - public Set keySet() { - return null; - } - - @Override - public Collection values() { - return null; - } - - @Override - public Set entrySet() { - return null; - } } - } + @Override + public Set keySet() { + return null; + } + + @Override + public Collection values() { + return null; + } + + @Override + public Set entrySet() { + return null; + } + } +} +```` ## Queue > 队列,它主�分为两大类,一类是阻塞�队列,队列满了以���入元素则会抛出异常,主�包括ArrayBlockQueue�PriorityBlockingQueue�LinkedBlockingQueue。�一�队列则是�端队列,支�在头�尾两端�入和移除元素,主�包括:ArrayDeque�LinkedBlockingDeque�LinkedList。 +```` +public class Queue接� { + //queue接�是对队列的一个实现,需��供队列的进队出队等方法。一般使用linkedlist作为实现类 + class MyQueue implements Queue { + + @Override + public int size() { + return 0; + } - public class Queue接� { - //queue接�是对队列的一个实现,需��供队列的进队出队等方法。一般使用linkedlist作为实现类 - class MyQueue implements Queue { - - @Override - public int size() { - return 0; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean contains(Object o) { - return false; - } - - @Override - public Iterator iterator() { - return null; - } - - @Override - public Object[] toArray() { - return new Object[0]; - } - - @Override - public Object[] toArray(Object[] a) { - return new Object[0]; - } - - @Override - public boolean add(Object o) { - return false; - } - - @Override - public boolean remove(Object o) { - return false; - } - - //�略部分代� - @Override - public boolean offer(Object o) { - return false; - } - - @Override - public Object remove() { - return null; - } - - @Override - public Object poll() { - return null; - } - - @Override - public Object element() { - return null; - } - - @Override - public Object peek() { - return null; - } + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object o) { + return false; + } + + @Override + public Iterator iterator() { + return null; + } + + @Override + public Object[] toArray() { + return new Object[0]; + } + + @Override + public Object[] toArray(Object[] a) { + return new Object[0]; + } + + @Override + public boolean add(Object o) { + return false; + } + + @Override + public boolean remove(Object o) { + return false; + } + + //�略部分代� + @Override + public boolean offer(Object o) { + return false; } - } + @Override + public Object remove() { + return null; + } + + @Override + public Object poll() { + return null; + } + + @Override + public Object element() { + return null; + } + + @Override + public Object peek() { + return null; + } + } +} +```` ## 关于Java集�的�抄 这部分内容转自我�� 江�白衣 的�客:http://calvin1978.blogcn.com/articles/collection.html diff --git "a/docs/java/basic/20\343\200\201javac\345\222\214javap.md" "b/docs/java/basic/20\343\200\201javac\345\222\214javap.md" index dde513d..de74810 100644 --- "a/docs/java/basic/20\343\200\201javac\345\222\214javap.md" +++ "b/docs/java/basic/20\343\200\201javac\345\222\214javap.md" @@ -31,15 +31,6 @@ * [微信公众�](#微信公众�) * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) ---- -title: 夯实Java基础系列20:从IDE的实现原��起,谈谈那些年我们用过的Java命令 -date: 2019-9-20 15:56:26 # 文章生�时间,一般�改 -categories: - - Java技术江湖 - - Java基础 -tags: - - Java命令行 ---- 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -81,119 +72,119 @@ java�供了JavaCompiler,我们�以通过它�编译java�文件为class 通过上�一个查找class,得到Class对象�,�以通过newInstance()或构造器的newInstance()得到对象。然�得到Method,最�调用方法,传入相关�数��。 示例代�: - - public class MyIDE { - - public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { - // 定义java代�,并�存到文件(Test.java) - StringBuilder sb = new StringBuilder(); - sb.append("package com.tommy.core.test.reflect;\n"); - sb.append("public class Test {\n"); - sb.append(" private String name;\n"); - sb.append(" public Test(String name){\n"); - sb.append(" this.name = name;\n"); - sb.append(" System.out.println(\"hello,my name is \" + name);\n"); - sb.append(" }\n"); - sb.append(" public String sayHello(String name) {\n"); - sb.append(" return \"hello,\" + name;\n"); - sb.append(" }\n"); - sb.append("}\n"); - - System.out.println(sb.toString()); - - String baseOutputDir = "F:\\output\\classes\\"; - String baseDir = baseOutputDir + "com\\tommy\\core\\test\\reflect\\"; - String targetJavaOutputPath = baseDir + "Test.java"; - // �存为java文件 - FileWriter fileWriter = new FileWriter(targetJavaOutputPath); - fileWriter.write(sb.toString()); - fileWriter.flush(); - fileWriter.close(); - - // 编译为class文件 - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - StandardJavaFileManager manager = compiler.getStandardFileManager(null,null,null); - List files = new ArrayList<>(); - files.add(new File(targetJavaOutputPath)); - Iterable compilationUnits = manager.getJavaFileObjectsFromFiles(files); - - // 编译 - // 设置编译选项,�置class文件输出路径 - Iterable options = Arrays.asList("-d",baseOutputDir); - JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, options, null, compilationUnits); - // 执行编译任务 - task.call(); - - -​ -​ // 通过�射得到对象 -​ // Class clazz = Class.forName("com.tommy.core.test.reflect.Test"); -​ // 使用自定义的类加载器加载class -​ Class clazz = new MyClassLoader(baseOutputDir).loadClass("com.tommy.core.test.reflect.Test"); -​ // 得到构造器 -​ Constructor constructor = clazz.getConstructor(String.class); -​ // 通过构造器new一个对象 -​ Object test = constructor.newInstance("jack.tsing"); -​ // 得到sayHello方法 -​ Method method = clazz.getMethod("sayHello", String.class); -​ // 调用sayHello方法 -​ String result = (String) method.invoke(test, "jack.ma"); -​ System.out.println(result); -​ } -​ } - +```` +public class MyIDE { + + public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { + // 定义java代�,并�存到文件(Test.java) + StringBuilder sb = new StringBuilder(); + sb.append("package com.tommy.core.test.reflect;\n"); + sb.append("public class Test {\n"); + sb.append(" private String name;\n"); + sb.append(" public Test(String name){\n"); + sb.append(" this.name = name;\n"); + sb.append(" System.out.println(\"hello,my name is \" + name);\n"); + sb.append(" }\n"); + sb.append(" public String sayHello(String name) {\n"); + sb.append(" return \"hello,\" + name;\n"); + sb.append(" }\n"); + sb.append("}\n"); + + System.out.println(sb.toString()); + + String baseOutputDir = "F:\\output\\classes\\"; + String baseDir = baseOutputDir + "com\\tommy\\core\\test\\reflect\\"; + String targetJavaOutputPath = baseDir + "Test.java"; + // �存为java文件 + FileWriter fileWriter = new FileWriter(targetJavaOutputPath); + fileWriter.write(sb.toString()); + fileWriter.flush(); + fileWriter.close(); + + // 编译为class文件 + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager manager = compiler.getStandardFileManager(null,null,null); + List files = new ArrayList<>(); + files.add(new File(targetJavaOutputPath)); + Iterable compilationUnits = manager.getJavaFileObjectsFromFiles(files); + + // 编译 + // 设置编译选项,�置class文件输出路径 + Iterable options = Arrays.asList("-d",baseOutputDir); + JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, options, null, compilationUnits); + // 执行编译任务 + task.call(); + + + + // 通过�射得到对象 +// Class clazz = Class.forName("com.tommy.core.test.reflect.Test"); + // 使用自定义的类加载器加载class + Class clazz = new MyClassLoader(baseOutputDir).loadClass("com.tommy.core.test.reflect.Test"); + // 得到构造器 + Constructor constructor = clazz.getConstructor(String.class); + // 通过构造器new一个对象 + Object test = constructor.newInstance("jack.tsing"); + // 得到sayHello方法 + Method method = clazz.getMethod("sayHello", String.class); + // 调用sayHello方法 + String result = (String) method.invoke(test, "jack.ma"); + System.out.println(result); + } +} +```` 自定义类加载器代�: +```` + +public class MyClassLoader extends ClassLoader { + private String baseDir; + public MyClassLoader(String baseDir) { + this.baseDir = baseDir; + } + @Override + protected Class findClass(String name) throws ClassNotFoundException { + String fullClassFilePath = this.baseDir + name.replace("\\.","/") + ".class"; + File classFilePath = new File(fullClassFilePath); + if (classFilePath.exists()) { + FileInputStream fileInputStream = null; + ByteArrayOutputStream byteArrayOutputStream = null; + try { + fileInputStream = new FileInputStream(classFilePath); + byte[] data = new byte[1024]; + int len = -1; + byteArrayOutputStream = new ByteArrayOutputStream(); + while ((len = fileInputStream.read(data)) != -1) { + byteArrayOutputStream.write(data,0,len); + } -​ -​ public class MyClassLoader extends ClassLoader { -​ private String baseDir; -​ public MyClassLoader(String baseDir) { -​ this.baseDir = baseDir; -​ } -​ @Override -​ protected Class findClass(String name) throws ClassNotFoundException { -​ String fullClassFilePath = this.baseDir + name.replace("\\.","/") + ".class"; -​ File classFilePath = new File(fullClassFilePath); -​ if (classFilePath.exists()) { -​ FileInputStream fileInputStream = null; -​ ByteArrayOutputStream byteArrayOutputStream = null; -​ try { -​ fileInputStream = new FileInputStream(classFilePath); -​ byte[] data = new byte[1024]; -​ int len = -1; -​ byteArrayOutputStream = new ByteArrayOutputStream(); -​ while ((len = fileInputStream.read(data)) != -1) { -​ byteArrayOutputStream.write(data,0,len); -​ } -​ - return defineClass(name,byteArrayOutputStream.toByteArray(),0,byteArrayOutputStream.size()); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (null != fileInputStream) { - try { - fileInputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } + return defineClass(name,byteArrayOutputStream.toByteArray(),0,byteArrayOutputStream.size()); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (null != fileInputStream) { + try { + fileInputStream.close(); + } catch (IOException e) { + e.printStackTrace(); } - - if (null != byteArrayOutputStream) { - try { - byteArrayOutputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } + } + + if (null != byteArrayOutputStream) { + try { + byteArrayOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); } } } - return super.findClass(name); } - } - + return super.findClass(name); + } +} +```` ## javac命令�窥 注:以下红色标记的�数在下文中有所讲解。 @@ -316,7 +307,7 @@ javac:如果当�你�编译的java文件中引用了其它的类(比如说 > 这里展示一个web项目的.classpath Xml代� - +```` @@ -328,7 +319,7 @@ Xml代� …… - +```` > XML文档包�一个根元素,就是classpath,类路径,那么这里�包�了什么信�呢?�元素是classpathentry,kind属性区别了� 类信�,src��,con你看看��的path就知�是JRE容器的信�。lib是项目�赖的第三方类库,output是src编译�的�置。 > 既然是web项目,那么就是WEB-INF/classes目录,�能用MyEclipse的�学会说他们那里是WebRoot或者是WebContext而�是webapp,有区别么?回答:完全没有� @@ -393,27 +384,27 @@ Xml代� 举个例�, - - public class A - { - public static void main(String[] args) { - B b = new B(); - b.print(); - } +```` +public class A +{ + public static void main(String[] args) { + B b = new B(); + b.print(); } +} -​ -​ -​ public class B -​ { -​ public void print() -​ { -​ System.out.println("old"); -​ } -​ } +public class B +{ + public void print() + { + System.out.println("old"); + } +} +```` + 目录结构如下: @@ -451,19 +442,19 @@ sourcepath //此处为当�目录 这里我用�实现一下这个功能,�设项目�称为project,此目录为当�目录,且在src/com目录中有一个Main.java文件。‘ -​ -​ package com; -​ public class Main -​ { -​ public static void main(String[] args) { -​ System.out.println("Hello"); -​ } -​ } +```` + package com; + public class Main + { + public static void main(String[] args) { + System.out.println("Hello"); + } + } -​ -​ -​ javac -d bin src/com/Main.java +```` + +javac -d bin src/com/Main.java 上�的语�将Main.class生�在bin/com目录下。 @@ -472,23 +463,23 @@ sourcepath //此处为当�目录 •如果有文件为A.java(其中有类A),且在类A中使用了类B,类B在B.java中,则编译A.java时,默认会自动编译B.java,且生�B.class。 •implicit:none:�自动生���引用的类文件。 •implicit:class(默认):自动生���引用的类文件。 - - public class A - { - public static void main(String[] args) { - B b = new B(); - } - } - - public class B - { +```` +public class A +{ + public static void main(String[] args) { + B b = new B(); } - - 如果使用: +} +public class B +{ +} +```` +如果使用: -​ -​ javac -implicit:none A.java + + +javac -implicit:none A.java 则�会生� B.class。 @@ -578,18 +569,18 @@ src/com/yp/test/HelloWorld.java build/ -``` +```` ├─build └─src └─com └─yp └─test HelloWorld.java -``` +```` java文件�常简� - +```` package com.yp.test; public class HelloWorld { @@ -597,12 +588,14 @@ java文件�常简� System.out.println("helloWorld"); } } +```` + 编译: javac src/com/yp/test/HelloWorld.java -d build -d 表示编译到 build文件夹下 -``` +```` 查看build文件夹 ├─build │ └─com @@ -615,10 +608,11 @@ javac src/com/yp/test/HelloWorld.java -d build └─yp └─test HelloWorld.java -``` +```` �行文件 + > E:\codeplace\n_learn\java\javacmd> java com/yp/test/HelloWorld.class > 错误: 找�到或无法加载主类 build.com.yp.test.HelloWorld.class > @@ -677,27 +671,28 @@ javac src/com/yp/test/HelloWorld.java -d build 先下一个jar包 这里直接下 log4j - * main函数改� - - import com.yp.test.entity.Cat; - import org.apache.log4j.Logger; - - public class HelloWorld { - - static Logger log = Logger.getLogger(HelloWorld.class); - - public static void main(String[] args) { - Cat c = new Cat("keyboard"); - log.info("这是log4j"); - System.out.println("hello," + c.getName()); - } - +* main函数改� + +```` +import com.yp.test.entity.Cat; +import org.apache.log4j.Logger; + +public class HelloWorld { + + static Logger log = Logger.getLogger(HelloWorld.class); + + public static void main(String[] args) { + Cat c = new Cat("keyboard"); + log.info("这是log4j"); + System.out.println("hello," + c.getName()); } +} +```` 现的文件是这样的 -``` +```` ├─build ├─lib │ log4j-1.2.17.jar @@ -710,8 +705,7 @@ javac src/com/yp/test/HelloWorld.java -d build │ └─entity Cat.java -``` - +```` 这个时候 javac命令�接上 -cp ./lib/*.jar E:\codeplace\n_learn\java\javacmd>javac -encoding "utf8" src/com/yp/test/HelloWorld.java -sourcepath src -d build -g -cp ./lib/*.jar @@ -729,21 +723,22 @@ javac src/com/yp/test/HelloWorld.java -d build 由于没有 log4j的�置文件,所以�示上�的问题,往 build 里�加上 log4j.xml - - - - - - - - - - - - - - - +```` + + + + + + + + + + + + + + +```` ��行 E:\codeplace\n_learn\java\javacmd>java -cp lib/log4j-1.2.17.jar;build com.yp.tes t.HelloWorld @@ -757,7 +752,7 @@ ok 一个简�的java 工程就�行完了 但是 貌似有些��, 需�手动键入 java文件 以�相应的jar包 很是麻烦, so �以用 shell �脚本�简化相关�作 shell 文件整�如下: - +```` #!/bin/bash echo "build start" @@ -788,6 +783,7 @@ shell 文件整�如下: #�行 通过-cp指定所有的引用jar包,指定入�函数�行 java -cp $BIN_PATH$jarfile com.zuiapps.danmaku.server.Main +```` > 有一点需�注�的是, javac -d $BIN_PATH/ -cp $jarfile @$SRC_FILE_LIST_PATH > 在�编译的文件很多时候,一个个敲命令会显得很长,也�方便修改, @@ -805,7 +801,7 @@ shell 文件整�如下: 1.需�� 编译时设置的bin目录和 所有jar包加入到 classpath 中去 -​ + ## javap 的使用 > javap是jdk自带的一个工具,�以对代��编译,也�以查看java编译器生�的字节�。 @@ -815,37 +811,37 @@ shell 文件整�如下: > > > javap命令分解一个class文件,它根�options�决定到底输出什么。如果没有使用options,那么javap将会输出包,类里的protected和public域以�类里的所有方法。javap将会把它们输出在标准输出上。�看这个例�,先编译(javac)下�这个类。 - - import java.awt.*; - import java.applet.*; - - public class DocFooter extends Applet { - String date; - String email; - - public void init() { - resize(500,100); - date = getParameter("LAST_UPDATED"); - email = getParameter("EMAIL"); - } - } - +```` +import java.awt.*; +import java.applet.*; + +public class DocFooter extends Applet { + String date; + String email; + + public void init() { + resize(500,100); + date = getParameter("LAST_UPDATED"); + email = getParameter("EMAIL"); + } +} +```` 在命令行上键入javap DocFooter�,输出结果如下 Compiled from "DocFooter.java" - - public class DocFooter extends java.applet.Applet { - java.lang.String date; - java.lang.String email; - public DocFooter(); - public void init(); - } - +```` +public class DocFooter extends java.applet.Applet { + java.lang.String date; + java.lang.String email; + public DocFooter(); + public void init(); +} +```` 如果加入了-c,�javap -c DocFooter,那么输出结果如下 Compiled from "DocFooter.java" - +```` public class DocFooter extends java.applet.Applet { java.lang.String date; @@ -876,6 +872,7 @@ Compiled from "DocFooter.java" 29: return } +```` 上�输出的内容就是字节�。 用法摘� diff --git "a/docs/java/basic/21\343\200\201Java8\346\226\260\347\211\271\346\200\247\347\273\210\346\236\201\346\214\207\345\215\227.md" "b/docs/java/basic/21\343\200\201Java8\346\226\260\347\211\271\346\200\247\347\273\210\346\236\201\346\214\207\345\215\227.md" index 14b4137..157f61c 100644 --- "a/docs/java/basic/21\343\200\201Java8\346\226\260\347\211\271\346\200\247\347\273\210\346\236\201\346\214\207\345\215\227.md" +++ "b/docs/java/basic/21\343\200\201Java8\346\226\260\347\211\271\346\200\247\347\273\210\346\236\201\346\214\207\345\215\227.md" @@ -19,15 +19,6 @@ * [微信公众�](#微信公众�) * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) ---- -title: 夯实Java基础系列21:Java8新特性终�指� -date: 2019-9-21 15:56:26 # 文章生�时间,一般�改 -categories: - - Java技术江湖 - - Java基础 -tags: - - Java8 ---- 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -48,8 +39,7 @@ tags: 这是一个Java8新增特性的总结图。接下�让我们一次实践一下这些新特性� -![image](https://img2018.cnblogs.com/blog/493447/201906/493447-20190604133048748-2090946599.png) - +![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230403215737.png) ## Java语言新特性 ### Lambda表达� @@ -100,13 +90,14 @@ java.lang.Runnable与java.util.concurrent.Callable是函数�接�最典型的 在实际使用过程中,函数�接�是容易出错的:如有�个人在接�定义中增加了�一个方法,这时,这个接�就��是函数�的了,并且编译过程也会失败。 为了克�函数�接�的这�脆弱性并且能够明确声明接�作为函数�接�的�图,Java8增加了一�特殊的注解@FunctionalInterface(Java8中所有类库的已有接�都添加了@FunctionalInterface注解)。让我们看一下这�函数�接�的定义: - +```` @FunctionalInterface public interface Functional { void method(); } +```` 需�记�的一件事是:默认方法与��方法并�影�函数�接�的契约,�以任�使用: - +```` @FunctionalInterface public interface FunctionalDefaultMethods { void method(); @@ -114,82 +105,83 @@ public interface FunctionalDefaultMethods { default void defaultMethod() { } } +```` Lambda是Java 8最大的�点。它具有�引越�越多程�员到Java平�上的潜力,并且能够在纯Java语言环境中�供一�优雅的方��支�函数�编程。更多详情�以�考官方文档。 下�看一个例�: +```` +public class lambda和函数�编程 { + @Test + public void test1() { + List names = Arrays.asList("peter", "anna", "mike", "xenia"); - public class lambda和函数�编程 { - @Test - public void test1() { - List names = Arrays.asList("peter", "anna", "mike", "xenia"); - - Collections.sort(names, new Comparator() { - @Override - public int compare(String a, String b) { - return b.compareTo(a); - } - }); - System.out.println(Arrays.toString(names.toArray())); - } - - @Test - public void test2() { - List names = Arrays.asList("peter", "anna", "mike", "xenia"); - - Collections.sort(names, (String a, String b) -> { + Collections.sort(names, new Comparator() { + @Override + public int compare(String a, String b) { return b.compareTo(a); - }); - - Collections.sort(names, (String a, String b) -> b.compareTo(a)); - - Collections.sort(names, (a, b) -> b.compareTo(a)); - System.out.println(Arrays.toString(names.toArray())); - } - + } + }); + System.out.println(Arrays.toString(names.toArray())); } - - static void add(double a,String b) { - System.out.println(a + b); - } - @Test - public void test5() { - D d = (a,b) -> add(a,b); - // interface D { - // void get(int i,String j); - // } - //这里�求,add的两个�数和get的两个�数��并且返回类型也�相等,�则报错 - // static void add(double a,String b) { - // System.out.println(a + b); - // } - } - - @FunctionalInterface - interface D { - void get(int i,String j); - } -接下�看看Lambda和匿�内部类的区别 + @Test + public void test2() { + List names = Arrays.asList("peter", "anna", "mike", "xenia"); -匿�内部类�然是一个类,�是�需�我们显�指定类�,编译器会自动为该类��。比如有如下形�的代�: + Collections.sort(names, (String a, String b) -> { + return b.compareTo(a); + }); - public class LambdaTest { - public static void main(String[] args) { - new Thread(new Runnable() { - @Override - public void run() { - System.out.println("Hello World"); - } - }).start(); - } + Collections.sort(names, (String a, String b) -> b.compareTo(a)); + + Collections.sort(names, (a, b) -> b.compareTo(a)); + System.out.println(Arrays.toString(names.toArray())); } +} + + static void add(double a,String b) { + System.out.println(a + b); + } + @Test + public void test5() { + D d = (a,b) -> add(a,b); +// interface D { +// void get(int i,String j); +// } + //这里�求,add的两个�数和get的两个�数��并且返回类型也�相等,�则报错 +// static void add(double a,String b) { +// System.out.println(a + b); +// } + } + + @FunctionalInterface + interface D { + void get(int i,String j); + } +```` +接下�看看Lambda和匿�内部类的区别 + +匿�内部类�然是一个类,�是�需�我们显�指定类�,编译器会自动为该类��。比如有如下形�的代�: +```` +public class LambdaTest { + public static void main(String[] args) { + new Thread(new Runnable() { + @Override + public void run() { + System.out.println("Hello World"); + } + }).start(); + } +} +```` 编译之�将会产生两个 class 文件: LambdaTest.class LambdaTest$1.class 使用 javap -c LambdaTest.class 进一步分� LambdaTest.class 的字节�,部分结果如下: - +```` public static void main(java.lang.String[]); Code: 0: new #2 // class java/lang/Thread @@ -200,28 +192,28 @@ Lambda是Java 8最大的�点。它具有�引越�越多程�员到Java平 11: invokespecial #5 // Method java/lang/Thread."":(Ljava/lang/Runnable;)V 14: invokevirtual #6 // Method java/lang/Thread.start:()V 17: return - +```` �以�现在 4: new #3 这一行创建了匿�内部类的对象。 而对于 Lambda表达�的实现, 接下�我们将上�的示例代�使用 Lambda 表达�实现,代�如下: - - public class LambdaTest { - public static void main(String[] args) { - new Thread(() -> System.out.println("Hello World")).start(); - } +```` +public class LambdaTest { + public static void main(String[] args) { + new Thread(() -> System.out.println("Hello World")).start(); } - +} +```` 此时编译��会产生一个文件 LambdaTest.class,��看看通过 javap 对该文件�编译�的结果: - - public static void main(java.lang.String[]); - Code: - 0: new #2 // class java/lang/Thread - 3: dup - 4: invokedynamic #3, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; - 9: invokespecial #4 // Method java/lang/Thread."":(Ljava/lang/Runnable;)V - 12: invokevirtual #5 // Method java/lang/Thread.start:()V - 15: return - +```` +public static void main(java.lang.String[]); +Code: + 0: new #2 // class java/lang/Thread + 3: dup + 4: invokedynamic #3, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; + 9: invokespecial #4 // Method java/lang/Thread."":(Ljava/lang/Runnable;)V + 12: invokevirtual #5 // Method java/lang/Thread.start:()V + 15: return +```` 从上�的结果我们�现 Lambda 表达�被�装�了主类的一个�有方法,并通过 invokedynamic 指令进行调用。 因此,我们�以得出结论:Lambda 表达�是通过 invokedynamic 指令实现的,并且书写 Lambda 表达��会产生新的类。 @@ -238,50 +230,50 @@ lambda表达�是如何符� Java 类型系统的?�个lambda对应于一 我们�以使用任�的接�作为lambda表达�,��这个接��包�一个抽象方法。为了��你的接�满足需求,你需�增加@FunctionalInterface注解。编译器知�这个注解,一旦你试图给这个接�增加第二个抽象方法声明时,它将抛出一个编译器错误。 下�举几个例� - - public class 函数�接�使用 { - @FunctionalInterface - interface A { - void say(); - default void talk() { - - } - } - @Test - public void test1() { - A a = () -> System.out.println("hello"); - a.say(); - } - - @FunctionalInterface - interface B { - void say(String i); - } - public void test2() { - //下�两个是等价的,都是通过B接��引用一个方法,而方法�以直接使用::�作为方法引用 - B b = System.out::println; - B b1 = a -> Integer.parseInt("s");//这里的a其实��别的也行,�是将方法传给接�作为其方法实现 - B b2 = Integer::valueOf;//i与方法传入�数的��类型一直时,�以直接替� - B b3 = String::valueOf; - //B b4 = Integer::parseInt;类型�符,无法使用 - - } - @FunctionalInterface - interface C { - int say(String i); - } - public void test3() { - C c = Integer::parseInt;//方法�数和接�方法的�数一样,�以替�。 - int i = c.say("1"); - //当我把C接�的int替�为void时就会报错,因为返回类型�一致。 - System.out.println(i); - //综上所述,lambda表达��供了一�简便的表达方�,�以将一个方法传到接�中。 - //函数�接�是��供一个抽象方法的接�,其方法由lambda表达�注入,�需�写实现类, - //也�需�写匿�内部类,�以�去很多代�,比如实现runnable接�。 - //函数�编程就是指把方法当�一个�数或引用�进行�作。除了普通方法以外,��方法,构造方法也是�以这样�作的。 +```` +public class 函数�接�使用 { + @FunctionalInterface + interface A { + void say(); + default void talk() { + } } + @Test + public void test1() { + A a = () -> System.out.println("hello"); + a.say(); + } + + @FunctionalInterface + interface B { + void say(String i); + } + public void test2() { + //下�两个是等价的,都是通过B接��引用一个方法,而方法�以直接使用::�作为方法引用 + B b = System.out::println; + B b1 = a -> Integer.parseInt("s");//这里的a其实��别的也行,�是将方法传给接�作为其方法实现 + B b2 = Integer::valueOf;//i与方法传入�数的��类型一直时,�以直接替� + B b3 = String::valueOf; + //B b4 = Integer::parseInt;类型�符,无法使用 + } + @FunctionalInterface + interface C { + int say(String i); + } + public void test3() { + C c = Integer::parseInt;//方法�数和接�方法的�数一样,�以替�。 + int i = c.say("1"); + //当我把C接�的int替�为void时就会报错,因为返回类型�一致。 + System.out.println(i); + //综上所述,lambda表达��供了一�简便的表达方�,�以将一个方法传到接�中。 + //函数�接�是��供一个抽象方法的接�,其方法由lambda表达�注入,�需�写实现类, + //也�需�写匿�内部类,�以�去很多代�,比如实现runnable接�。 + //函数�编程就是指把方法当�一个�数或引用�进行�作。除了普通方法以外,��方法,构造方法也是�以这样�作的。 + } +} +```` 请记�如果@FunctionalInterface 这个注解被��,此代��然有效。 ### 方法引用 @@ -290,7 +282,7 @@ Lambda表达�和方法引用 有了函数�接�之�,就�以使用Lambda表达�和方法引用了。其实函数�接�的表中的函数�述符就是Lambda表达�,在函数�接�中Lambda表达�相当于匿�内部类的效果。 举个简�的例�: - +```` public class TestLambda { public static void execute(Runnable runnable) { @@ -310,7 +302,7 @@ public class TestLambda { execute(() -> System.out.println("run")); } } - +```` �以看到,相比于使用匿�内部类的方�,Lambda表达��以使用更少的代�但是有更清晰的表述。注�,Lambda表达�也�是完全等价于匿�内部类的, 两者的��点在于this的指�和本地��的�蔽上。 方法引用�以看作Lambda表达�的更简�的一�表达形�,使用::�作符,方法引用主�有三类: @@ -351,31 +343,31 @@ public class TestLambda { ### 接�的默认方法 Java 8 使我们能够使用default 关键字给接�增加�抽象的方法实现。这个特性也被�� 扩展方法(Extension Methods)。如下例所示: - - public class 接�的默认方法 { - class B implements A { - // void a(){}实现类方法�能�� - } - interface A { - //�以有多个默认方法 - public default void a(){ - System.out.println("a"); - } - public default void b(){ - System.out.println("b"); - } - //报错static和default�能�时使用 - // public static default void c(){ - // System.out.println("c"); - // } +```` +public class 接�的默认方法 { + class B implements A { +// void a(){}实现类方法�能�� + } + interface A { + //�以有多个默认方法 + public default void a(){ + System.out.println("a"); } - public void test() { - B b = new B(); - b.a(); - + public default void b(){ + System.out.println("b"); } + //报错static和default�能�时使用 +// public static default void c(){ +// System.out.println("c"); +// } } + public void test() { + B b = new B(); + b.a(); + } +} +```` 默认方法出现的原因是为了对原有接�的扩展,有了默认方法之�就�怕因改动原有的接�而对已�使用这些接�的程�造�的代��兼容的影�。 在Java8中也对一些接�增加了一些默认方法,比如Map接�等等。一般�说,使用默认方法的场景有两个:�选方法和行为的多继承。 默认方法的使用相对�说比较简�,唯一�注�的点是如何处�默认方法的冲�。关于如何处�默认方法的冲��以�考以下三�规则: @@ -385,7 +377,7 @@ Java 8 使我们能够使用default 关键字给接�增加�抽象的方法 如果无法��第一�规则进行判断,那么�接�的优先级更高:函数签�相�时,优先选择拥有最具体实现的默认方法的接�。�如果B继承了A,那么B就比A更具体。 最�,如果还是无法判断,继承了多个接�的类必须通过显�覆盖和调用期望的方法,显�地选择使用哪一个默认方法的实现。那么如何显�地指定呢: - +```` public class C implements B, A { public void hello() { @@ -393,43 +385,46 @@ Java 8 使我们能够使用default 关键字给接�增加�抽象的方法 } } +```` 使用X.super.m(..)显�地调用希望调用的方法。 Java 8用默认方法与��方法这两个新概念�扩展接�的声明。默认方法使接�有点�Traits(Scala中特�(trait)类似于Java中的Interface,但它�以包�实现代�,也就是目�Java8新增的功能),但与传统的接��有些�一样,它�许在已有的接�中添加新方法,而�时���了与旧版本代�的兼容性。 默认方法与抽象方法��之处在于抽象方法必须�求实现,但是默认方法则没有这个�求。相�,�个接�都必须�供一个所谓的默认实现,这样所有的接�实现者将会默认继承它(如果有必�的�,�以覆盖这个默认实现)。让我们看看下�的例�: - - private interface Defaulable { - // Interfaces now allow default methods, the implementer may or - // may not implement (override) them. - default String notRequired() { - return "Default implementation"; - } - } - - private static class DefaultableImpl implements Defaulable { - } +```` +private interface Defaulable { + // Interfaces now allow default methods, the implementer may or + // may not implement (override) them. + default String notRequired() { + return "Default implementation"; + } +} - private static class OverridableImpl implements Defaulable { - @Override - public String notRequired() { - return "Overridden implementation"; - } +private static class DefaultableImpl implements Defaulable { +} + +private static class OverridableImpl implements Defaulable { + @Override + public String notRequired() { + return "Overridden implementation"; } +} +```` Defaulable接�用关键字default声明了一个默认方法notRequired(),Defaulable接�的实现者之一DefaultableImpl实现了这个接�,并且让默认方法��原样。Defaulable接�的�一个实现者OverridableImpl用自己的方法覆盖了默认方法。 Java 8带�的�一个有趣的特性是接��以声明(并且�以�供实现)��方法。例如: - +```` private interface DefaulableFactory { // Interfaces now allow static methods static Defaulable create( Supplier< Defaulable > supplier ) { return supplier.get(); } } +```` 下�的一�段代�片段把上�的默认方法与��方法��到一起。 - +```` public static void main( String[] args ) { Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new ); System.out.println( defaulable.notRequired() ); @@ -437,6 +432,7 @@ Java 8带�的�一个有趣的特性是接��以声明(并且�以� defaulable = DefaulableFactory.create( OverridableImpl::new ); System.out.println( defaulable.notRequired() ); } +```` 这个程�的控制�输出如下: Default implementation @@ -450,58 +446,57 @@ Overridden implementation 自从Java 5引入了注解机制,这一特性就�得�常�行并且广为使用。然而,使用注解的一个�制是相�的注解在�一�置�能声明一次,�能声明多次。Java 8打破了这�规则,引入了��注解机制,这样相�的注解�以在�一地方声明多次。 ��注解机制本身必须用@Repeatable注解。事实上,这并�是语言层�上的改�,更多的是编译器的技巧,底层的原�����。让我们看一个快速入门的例�: - - package com.javacodegeeks.java8.repeatable.annotations; +```` +package com.javacodegeeks.java8.repeatable.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +public class RepeatingAnnotations { + @Target( ElementType.TYPE ) + @Retention( RetentionPolicy.RUNTIME ) + public @interface Filters { + Filter[] value(); + } - import java.lang.annotation.ElementType; - import java.lang.annotation.Repeatable; - import java.lang.annotation.Retention; - import java.lang.annotation.RetentionPolicy; - import java.lang.annotation.Target; + @Target( ElementType.TYPE ) + @Retention( RetentionPolicy.RUNTIME ) + @Repeatable( Filters.class ) + public @interface Filter { + String value(); + }; - public class RepeatingAnnotations { - @Target( ElementType.TYPE ) - @Retention( RetentionPolicy.RUNTIME ) - public @interface Filters { - Filter[] value(); - } - - @Target( ElementType.TYPE ) - @Retention( RetentionPolicy.RUNTIME ) - @Repeatable( Filters.class ) - public @interface Filter { - String value(); - }; - - @Filter( "filter1" ) - @Filter( "filter2" ) - public interface Filterable { - } - - public static void main(String[] args) { - for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) { - System.out.println( filter.value() ); - } + @Filter( "filter1" ) + @Filter( "filter2" ) + public interface Filterable { + } + + public static void main(String[] args) { + for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) { + System.out.println( filter.value() ); } } +} +```` 正如我们看到的,这里有个使用@Repeatable( Filters.class )注解的注解类Filter,Filters仅仅是Filter注解的数组,但Java编译器并�想让程�员�识到Filters的存在。这样,接�Filterable就拥有了两次Filter(并没有�到Filter)注解。 �时,�射相关的API�供了新的函数getAnnotationsByType()�返回��注解的类型(请注�Filterable.class.getAnnotation( Filters.class )�编译器处��将会返回Filters的实例)。 程�输出结果如下: -filter1 -filter2 + filter1 + filter2 更多详情请�考官方文档 - - ## Java编译器的新特性 ### 方法�数�字�以�射获� 很长一段时间里,Java程�员一直在�明��的方�使得方法�数的�字能�留在Java字节�中,并且能够在�行时获�它们(比如,Paranamer类库)。最终,在Java 8中把这个强烈�求的功能添加到语言层�(通过�射API与Parameter.getName()方法)与字节�文件(通过新版的javac的–parameters选项)中。 - +```` package com.javacodegeeks.java8.parameter.names; import java.lang.reflect.Method; @@ -515,6 +510,7 @@ public class ParameterNames { } } } +```` 如果�使用–parameters�数�编译这个类,然��行这个类,会得到下�的输出: Parameter: arg0 @@ -531,7 +527,7 @@ Java 8 通过增加大�新类,扩展已有类的功能的方��改善对 Optional实际上是个容器:它�以�存类型T的值,或者仅仅�存null。Optional�供很多有用的方法,这样我们就�用显�进行空值检测。更多详情请�考官方文档。 我们下�用两个�例��演示如何使用Optional类:一个�许为空值,一个��许为空值。 - +```` public class 空指针Optional { public static void main(String[] args) { @@ -554,7 +550,7 @@ Optional实际上是个容器:它�以�存类型T的值,或者仅仅� //输出Optional.empty。 } } - +```` 如果Optional类的实例为�空值的�,isPresent()返回true,�从返回false。为了防止Optional为空值,orElseGet()方法通过回调函数�产生一个默认值。map()函数对当�Optional的值进行转化,然�返回一个新的Optional实例。orElse()方法和orElseGet()方法类似,但是orElse接�一个默认值而�是一个回调函数。下�是这个程�的输出: Full Name is set? false @@ -581,14 +577,15 @@ Hey Tom! Stream API�大简化了集�框架的处�(但它的处�的范围�仅仅�于集�框架的处�,这点��我们会看到)。让我们以一个简�的Task类为例进行介�: Task类有一个分数的概念(或者说是伪��度),其次是还有一个值�以为OPEN或CLOSED的状�.让我们引入一个Task的�集�作为演示例�: - +```` final Collection< Task > tasks = Arrays.asList( new Task( Status.OPEN, 5 ), new Task( Status.OPEN, 13 ), new Task( Status.CLOSED, 8 ) ); +```` 我们下��讨论的第一个问题是所有状�为OPEN的任务一共有多少分数?在Java 8以�,一般的解决方�用foreach循环,但是在Java 8里�我们�以使用stream:一串支�连续�并行�集�作的元素。 - +```` // Calculate total points of all active tasks using sum() final long totalPointsOfOpenTasks = tasks .stream() @@ -597,9 +594,10 @@ Task类有一个分数的概念(或者说是伪��度),其次是还有 .sum(); System.out.println( "Total points: " + totalPointsOfOpenTasks ); +```` 程�在控制�上的输出如下: -Total points: 18 + Total points: 18 这里有几个注�事项。 @@ -617,7 +615,7 @@ Total points: 18 stream�一个有价值的地方是能够原生支�并行处�。让我们�看看这个算task分数和的例�。 stream�一个有价值的地方是能够原生支�并行处�。让我们�看看这个算task分数和的例�。 - +```` // Calculate total points of all tasks final double totalPoints = tasks .stream() @@ -626,23 +624,28 @@ stream�一个有价值的地方是能够原生支�并行处�。让我们 .reduce( 0, Integer::sum ); System.out.println( "Total points (all tasks): " + totalPoints ); +```` 这个例�和第一个例�很相似,但这个例�的��之处在于这个程�是并行�行的,其次使用reduce方法�算最终的结果。 下�是这个例�在控制�的输出: Total points (all tasks): 26.0 �常会有这个一个需求:我们需�按照��准则�对集�中的元素进行分组。Stream也�以处�这样的需求,下�是一个例�: - +```` // Group tasks by their status final Map< Status, List< Task > > map = tasks .stream() .collect( Collectors.groupingBy( Task::getStatus ) ); System.out.println( map ); +```` + 这个例�的控制�输出如下: -{CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]} + {CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]} + 让我们�计算整个集�中�个task分数(或��)的平�值�结�task的例�。 +```` // Calculate the weight of each tasks (as percent of total points) final Collection< String > result = tasks .stream() // Stream< String > @@ -655,15 +658,19 @@ Total points (all tasks): 26.0 .collect( Collectors.toList() ); // List< String > System.out.println( result ); +```` + 下�是这个例�的控制�输出: [19%, 50%, 30%] 最�,就����到的,Stream API�仅仅处�Java集�框架。�从文本文件中�行读�数�这样典型的I/O�作也很适�用Stream API�处�。下�用一个例��应�这一点。 - +```` final Path path = new File( filename ).toPath(); try( Stream< String > lines = Files.lines( path, StandardCharsets.UTF_8 ) ) { lines.onClose( () -> System.out.println("Done!") ).forEach( System.out::println ); } +```` + 对一个stream对象调用onClose方法会返回一个在原有功能基础上新增了关闭功能的stream对象,当对stream对象调用close()方法时,与关闭相关的处�器就会执行。 Stream API�Lambda表达�与方法引用在接�默认方法与��方法的��下是Java 8对现代软件开�范�的回应。更多详情请�考官方文档。 @@ -674,19 +681,19 @@ Java 8通过�布新的Date-Time API (JSR 310)�进一步加强对日期与时 这�情况直接导致了Joda-Time——一个�替�标准日期/时间处�且功能�常强大的Java API的诞生。Java 8新的Date-Time API (JSR 310)在很大程度上�到Joda-Time的影�,并且��了其精髓。新的java.time包涵盖了所有处�日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的�作。在设计新版API时,�分注�与旧版API的兼容性:��许有任何的改�(从java.util.Calendar中得到的深刻教训)。如果需�修改,会返回这个类的一个新实例。 让我们用例��看一下新版API主�类的使用方法。第一个是Clock类,它通过指定一个时区,然�就�以获�到当�的时刻,日期与时间。Clock�以替�System.currentTimeMillis()与TimeZone.getDefault()。 - +```` // Get the system clock as UTC offset final Clock clock = Clock.systemUTC(); System.out.println( clock.instant() ); System.out.println( clock.millis() ); - +```` 下�是程�在控制�上的输出: 2014-04-12T15:19:29.282Z 1397315969360 我们需�关注的其他类是LocaleDate与LocalTime。LocaleDate��有ISO-8601格�且无时区信�的日期部分。相应的,LocaleTime��有ISO-8601格�且无时区信�的时间部分。LocaleDate与LocalTime都�以从Clock中得到。 - +```` // Get the local date and local time final LocalDate date = LocalDate.now(); final LocalDate dateFromClock = LocalDate.now( clock ); @@ -700,7 +707,7 @@ Java 8通过�布新的Date-Time API (JSR 310)�进一步加强对日期与时 System.out.println( time ); System.out.println( timeFromClock ); - +```` 下�是程�在控制�上的输出: 2014-04-12 @@ -715,7 +722,7 @@ Java 8通过�布新的Date-Time API (JSR 310)�进一步加强对日期与时 2014-04-12T08:47:01.017-07:00[America/Los_Angeles] 最�,让我们看一下Duration类:在秒与纳秒级别上的一段时间。Duration使计算两个日期间的���的�分简�。下�让我们看一个这方�的例�。 - +```` // Get duration between two dates final LocalDateTime from = LocalDateTime.of( 2014, Month.APRIL, 16, 0, 0, 0 ); final LocalDateTime to = LocalDateTime.of( 2015, Month.APRIL, 16, 23, 59, 59 ); @@ -723,7 +730,7 @@ Java 8通过�布新的Date-Time API (JSR 310)�进一步加强对日期与时 final Duration duration = Duration.between( from, to ); System.out.println( "Duration in days: " + duration.toDays() ); System.out.println( "Duration in hours: " + duration.toHours() ); - +```` 上�的例�计算了两个日期2014年4月16�与2014年4月16�之间的过程。下�是程�在控制�上的输出: Duration in days: 365 @@ -733,7 +740,7 @@ Duration in hours: 8783 ### 并行(parallel)数组 Java 8增加了大�的新方法�对数组进行并行处�。�以说,最��的是parallelSort()方法,因为它�以在多核机器上�大�高数组排�的速度。下�的例�展示了新方法(parallelXxx)的使用。 - +```` package com.javacodegeeks.java8.parallel.arrays; import java.util.Arrays; @@ -755,7 +762,7 @@ Java 8增加了大�的新方法�对数组进行并行处�。�以说, System.out.println(); } } - +```` 上�的代�片段使用了parallelSetAll()方法�对一个有20000个元素的数组进行�机赋值。然�,调用parallelSort方法。这个程�首先打�出�10个元素的值,之�对整个数组排�。这个程�在控制�上的输出如下(请注�数组元素是�机生产的): Unsorted: 591217 891976 443951 424479 766825 351964 242997 642839 119108 552378 @@ -766,7 +773,7 @@ Sorted: 39 220 263 268 325 607 655 678 723 793 在Java8之�,我们会使用JDK�供的Future接��进行一些异步的�作,其实CompletableFuture也是实现了Future接�, 并且基于ForkJoinPool�执行任务,因此本质上�讲,CompletableFuture�是对原有API的�装, 而使用CompletableFuture与原�的Future的��之处在于�以将两个Future组�起�,或者如果两个Future是有�赖关系的,�以等第一个执行完毕��实行第二个等特性。 **先�看看基本的使用方�:** - +```` public Future getPriceAsync(final String product) { final CompletableFuture futurePrice = new CompletableFuture<>(); new Thread(() -> { @@ -775,13 +782,14 @@ Sorted: 39 220 263 268 325 607 655 678 723 793 }).start(); return futurePrice; } +```` 得到Future之�就�以使用get方法�获�结果,CompletableFuture�供了一些工厂方法�简化这些API,并且使用函数�编程的方��使用这些API,例如: Fufure price = CompletableFuture.supplyAsync(() -> calculatePrice(product)); 代�是�是一下�简�了许多呢。之�说了,CompletableFuture�以组�多个Future,�管是Future之间有�赖的,还是没有�赖的。 **如果第二个请求�赖于第一个请求的结果,那么�以使用thenCompose方法�组�两个Future** - +```` public List findPriceAsync(String product) { List> priceFutures = tasks.stream() .map(task -> CompletableFuture.supplyAsync(() -> task.getPrice(product),executor)) @@ -791,24 +799,26 @@ Fufure price = CompletableFuture.supplyAsync(() -> calculatePrice(produc return priceFutures.stream().map(CompletableFuture::join).collect(Collectors.toList()); } +```` 上�这段代�使用了thenCompose�组�两个CompletableFuture。supplyAsync方法第二个�数接�一个自定义的Executor。 首先使用CompletableFuture执行一个任务,调用getPrice方法,得到一个Future,之�使用thenApply方法,将Future的结果应用parse方法, 之��使用执行完parse之�的结果作为�数�执行一个applyCount方法,然�收集�一个CompletableFuture的List, 最��使用一个�,调用CompletableFuture的join方法,这是为了等待所有的异步任务执行完毕,获得最�的结果。 注�,这里必须使用两个�,如果在一个�里调用join方法,那么由于Stream的延迟特性,所有的�作还是会串行的执行,并�是异步的。 **��看一个两个Future之间没有�赖关系的例�:** - +```` Future futurePriceInUsd = CompletableFuture.supplyAsync(() -> shop.getPrice(“price1�)) .thenCombine(CompletableFuture.supplyAsync(() -> shop.getPrice(“price2�)), (s1, s2) -> s1 + s2); +```` 这里有两个异步的任务,使用thenCombine方法�组�两个Future,thenCombine方法的第二个�数就是用��并两个Future方法返回值的�作函数。 有时候,我们并�需�等待所有的异步任务结�,�需�其中的一个完�就�以了,CompletableFuture也�供了这样的方法: - +```` //�设getStream方法返回一个Stream> CompletableFuture[] futures = getStream(“listen�).map(f -> f.thenAccept(System.out::println)).toArray(CompletableFuture[]::new); //等待其中的一个执行完毕 CompletableFuture.anyOf(futures).join(); 使用anyOf方法��应CompletableFuture的completion事件。 - +```` ## Java虚拟机(JVM)的新特性 PermGen空间被移除了,�而代之的是Metaspace(JEP 122)。JVM选项-XX:PermSize与-XX:MaxPermSize分别被-XX:MetaSpaceSize与-XX:MaxMetaspaceSize所代替。 diff --git "a/docs/java/basic/22\343\200\201\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226.md" "b/docs/java/basic/22\343\200\201\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226.md" index 6de5ffb..c668e69 100644 --- "a/docs/java/basic/22\343\200\201\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226.md" +++ "b/docs/java/basic/22\343\200\201\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226.md" @@ -12,15 +12,6 @@ * [微信公众�](#微信公众�) * [Java技术江湖](#java技术江湖) * [个人公众�:黄�斜](#个人公众�:黄�斜) ---- -title: 夯实Java基础系列22:一文读懂Java�列化和��列化 -date: 2019-9-22 15:56:26 # 文章生�时间,一般�改 -categories: - - Java技术江湖 - - Java基础 -tags: - - Java�列化 ---- 本系列文章将整�到我在GitHub上的《Java�试指�》仓库,更多精彩内容请到我的仓库里查看 > https://github.com/h2pl/Java-Tutorial @@ -37,7 +28,6 @@ tags: - 本文�考 http://www.importnew.com/17964.html和 https://www.ibm.com/developerworks/cn/java/j-lo-serial/ @@ -86,96 +76,93 @@ Java为了方便开�人员将Java对象进行�列化���列化�供了 如果��列化的类有父类,�想�时将在父类中定义过的���久化下�,那么父类也应该集�java.io.Serializable接�。 下�是一个实现了java.io.Serializable接�的类 +```` +public class �列化和��列化 { + public static void main(String[] args) { - public class �列化和��列化 { - - -​ -​ public static void main(String[] args) { -​ - } - //注�,内部类�能进行�列化,因为它�赖于外部类 - @Test - public void test() throws IOException { - A a = new A(); - a.i = 1; - a.s = "a"; - FileOutputStream fileOutputStream = null; - FileInputStream fileInputStream = null; - try { - //将obj写入文件 - fileOutputStream = new FileOutputStream("temp"); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); - objectOutputStream.writeObject(a); - fileOutputStream.close(); - //通过文件读�obj - fileInputStream = new FileInputStream("temp"); - ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); - A a2 = (A) objectInputStream.readObject(); - fileInputStream.close(); - System.out.println(a2.i); - System.out.println(a2.s); - //打�结果和�列化之�相� - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } } - - class A implements Serializable { - - int i; - String s; + //注�,内部类�能进行�列化,因为它�赖于外部类 + @Test + public void test() throws IOException { + A a = new A(); + a.i = 1; + a.s = "a"; + FileOutputStream fileOutputStream = null; + FileInputStream fileInputStream = null; + try { + //将obj写入文件 + fileOutputStream = new FileOutputStream("temp"); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + objectOutputStream.writeObject(a); + fileOutputStream.close(); + //通过文件读�obj + fileInputStream = new FileInputStream("temp"); + ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); + A a2 = (A) objectInputStream.readObject(); + fileInputStream.close(); + System.out.println(a2.i); + System.out.println(a2.s); + //打�结果和�列化之�相� + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } } +} + +class A implements Serializable { + int i; + String s; +} +```` **Externalizable接�** 除了Serializable 之外,java中还�供了�一个�列化接�Externalizable 为了了解Externalizable接�和Serializable接�的区别,先�看代�,我们把上�的代�改�使用Externalizable的形�。 +```` +class B implements Externalizable { + //必须�有公开无�构造函数。�则报错 + public B() { - class B implements Externalizable { - //必须�有公开无�构造函数。�则报错 - public B() { - - } - int i; - String s; - @Override - public void writeExternal(ObjectOutput out) throws IOException { - - } - - @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - - } } - - @Test - public void test2() throws IOException, ClassNotFoundException { - B b = new B(); - b.i = 1; - b.s = "a"; - //将obj写入文件 - FileOutputStream fileOutputStream = new FileOutputStream("temp"); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); - objectOutputStream.writeObject(b); - fileOutputStream.close(); - //通过文件读�obj - FileInputStream fileInputStream = new FileInputStream("temp"); - ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); - B b2 = (B) objectInputStream.readObject(); - fileInputStream.close(); - System.out.println(b2.i); - System.out.println(b2.s); - //打�结果为0和null,��始值,没有被赋值 - //0 - //null - } + int i; + String s; + @Override + public void writeExternal(ObjectOutput out) throws IOException { + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + + } +} + +@Test + public void test2() throws IOException, ClassNotFoundException { + B b = new B(); + b.i = 1; + b.s = "a"; + //将obj写入文件 + FileOutputStream fileOutputStream = new FileOutputStream("temp"); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + objectOutputStream.writeObject(b); + fileOutputStream.close(); + //通过文件读�obj + FileInputStream fileInputStream = new FileInputStream("temp"); + ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); + B b2 = (B) objectInputStream.readObject(); + fileInputStream.close(); + System.out.println(b2.i); + System.out.println(b2.s); + //打�结果为0和null,��始值,没有被赋值 + //0 + //null + } +```` 通过上�的实例�以�现,对B类进行�列化���列化之�得到的对象的所有属性的值都��了默认值。也就是说,之�的那个对象的状�并没有被�久化下�。这就是Externalizable接�和Serializable接�的区别: Externalizable继承了Serializable,该接�中定义了两个抽象方法:writeExternal()与readExternal()。 @@ -184,54 +171,56 @@ Externalizable继承了Serializable,该接�中定义了两个抽象方法: > 还有一点值得注�:在使用Externalizable进行�列化的时候,在读�对象时,会调用被�列化类的无�构造器去创建一个新的对象,然��将被�存对象的字段的值分别填充到新对象中。所以,实现Externalizable接�的类必须��供一个public的无�的构造器。 - class C implements Externalizable { - int i; - int j; - String s; - public C() { - - } - //实现下�两个方法�以选择�列化中需�被�制的�员。 - //并且,写入顺�和读�顺��一致,�则报错。 - //�以写入多个�类型��,顺���一致��。 - @Override - public void writeExternal(ObjectOutput out) throws IOException { - out.writeInt(i); - out.writeInt(j); - out.writeObject(s); - } - - @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - i = in.readInt(); - j = in.readInt(); - s = (String) in.readObject(); - } +```` +class C implements Externalizable { + int i; + int j; + String s; + public C() { + } - - @Test - public void test3() throws IOException, ClassNotFoundException { - C c = new C(); - c.i = 1; - c.j = 2; - c.s = "a"; - //将obj写入文件 - FileOutputStream fileOutputStream = new FileOutputStream("temp"); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); - objectOutputStream.writeObject(c); - fileOutputStream.close(); - //通过文件读�obj - FileInputStream fileInputStream = new FileInputStream("temp"); - ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); - C c2 = (C) objectInputStream.readObject(); - fileInputStream.close(); - System.out.println(c2.i); - System.out.println(c2.j); - System.out.println(c2.s); - //打�结果为0和null,��始值,没有被赋值 - //0 - //null - } + //实现下�两个方法�以选择�列化中需�被�制的�员。 + //并且,写入顺�和读�顺��一致,�则报错。 + //�以写入多个�类型��,顺���一致��。 + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(i); + out.writeInt(j); + out.writeObject(s); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + i = in.readInt(); + j = in.readInt(); + s = (String) in.readObject(); + } +} + +@Test +public void test3() throws IOException, ClassNotFoundException { + C c = new C(); + c.i = 1; + c.j = 2; + c.s = "a"; + //将obj写入文件 + FileOutputStream fileOutputStream = new FileOutputStream("temp"); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + objectOutputStream.writeObject(c); + fileOutputStream.close(); + //通过文件读�obj + FileInputStream fileInputStream = new FileInputStream("temp"); + ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); + C c2 = (C) objectInputStream.readObject(); + fileInputStream.close(); + System.out.println(c2.i); + System.out.println(c2.j); + System.out.println(c2.s); + //打�结果为0和null,��始值,没有被赋值 + //0 + //null +} +```` ## �列化ID @@ -241,87 +230,89 @@ Externalizable继承了Serializable,该接�中定义了两个抽象方法: 问题:C 对象的全类路径�设为 com.inout.Test,在 A 和 B 端都有这么一个类文件,功能代�完全一致。也都实现了 Serializable 接�,但是��列化时总是�示��功。 解决:虚拟机是��许��列化,�仅�决于类路径和功能代�是�一致,一个�常��的一点是两个类的�列化 ID 是�一致(就是 private static final long serialVersionUID = 1L)。清� 1 中,虽然两个类的功能代�完全一致,但是�列化 ID ��,他们无法相互�列化和��列化。 - - package com.inout; - - import java.io.Serializable; - - public class A implements Serializable { - - private static final long serialVersionUID = 1L; - - private String name; - - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } +```` +package com.inout; + +import java.io.Serializable; + +public class A implements Serializable { + + private static final long serialVersionUID = 1L; + + private String name; + + public String getName() + { + return name; } - - package com.inout; - - import java.io.Serializable; - - public class A implements Serializable { - - private static final long serialVersionUID = 2L; - - private String name; - - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } - } + + public void setName(String name) + { + this.name = name; + } +} + +package com.inout; + +import java.io.Serializable; + +public class A implements Serializable { + + private static final long serialVersionUID = 2L; + + private String name; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } +} +```` ### ������与�列化 清� 2 中的 main 方法,将对象�列化�,修改����的数值,�将�列化对象读�出�,然�通过读�出�的对象获得����的数值并打�出�。�照清� 2,这个 System.out.println(t.staticVar) 语�输出的是 10 还是 5 呢? - - public class Test implements Serializable { - - private static final long serialVersionUID = 1L; - - public static int staticVar = 5; - - public static void main(String[] args) { - try { - //�始时staticVar为5 - ObjectOutputStream out = new ObjectOutputStream( - new FileOutputStream("result.obj")); - out.writeObject(new Test()); - out.close(); - - //�列化�修改为10 - Test.staticVar = 10; - - ObjectInputStream oin = new ObjectInputStream(new FileInputStream( - "result.obj")); - Test t = (Test) oin.readObject(); - oin.close(); - - //�读�,通过t.staticVar打�新的值 - System.out.println(t.staticVar); - - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } +```` +public class Test implements Serializable { + + private static final long serialVersionUID = 1L; + + public static int staticVar = 5; + + public static void main(String[] args) { + try { + //�始时staticVar为5 + ObjectOutputStream out = new ObjectOutputStream( + new FileOutputStream("result.obj")); + out.writeObject(new Test()); + out.close(); + + //�列化�修改为10 + Test.staticVar = 10; + + ObjectInputStream oin = new ObjectInputStream(new FileInputStream( + "result.obj")); + Test t = (Test) oin.readObject(); + oin.close(); + + //�读�,通过t.staticVar打�新的值 + System.out.println(t.staticVar); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); } } +} +```` 最�的输出是 10,对于无法�解的读者认为,打�的 staticVar 是从读�的对象里获得的,应该是�存时的状��对。之所以打� 10 的原因在于�列化时,并��存����,这其实比较容易�解,�列化�存的是对象的状�,����属于类的状�,因此 �列化并��存����。 @@ -334,6 +325,7 @@ ArrayList的�列化 带�这个问题,我们�看java.util.ArrayList的�� +```` public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable { @@ -341,26 +333,27 @@ ArrayList的�列化 transient Object[] elementData; // non-private to simplify nested class access private int size; } +```` 笔者�略了其他�员��,从上�的代�中�以知�ArrayList实现了java.io.Serializable接�,那么我们就�以对它进行�列化���列化。 因为elementData是transient的(1.8好�改掉了这一点),所以我们认为这个�员���会被�列化而�留下�。我们写一个Demo,验�一下我们的想法: - - public class ArrayList的�列化 { - public static void main(String[] args) throws IOException, ClassNotFoundException { - ArrayList list = new ArrayList(); - list.add("a"); - list.add("b"); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("arr")); - objectOutputStream.writeObject(list); - objectOutputStream.close(); - ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("arr")); - ArrayList list1 = (ArrayList) objectInputStream.readObject(); - objectInputStream.close(); - System.out.println(Arrays.toString(list.toArray())); - //�列化�功,里�的元素����。 - } - +```` +public class ArrayList的�列化 { + public static void main(String[] args) throws IOException, ClassNotFoundException { + ArrayList list = new ArrayList(); + list.add("a"); + list.add("b"); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("arr")); + objectOutputStream.writeObject(list); + objectOutputStream.close(); + ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("arr")); + ArrayList list1 = (ArrayList) objectInputStream.readObject(); + objectInputStream.close(); + System.out.println(Arrays.toString(list.toArray())); + //�列化�功,里�的元素����。 + } +```` 了解ArrayList的人都知�,ArrayList底层是通过数组实现的。那么数组elementData其实就是用��存列表中的元素的。通过该属性的声明方�我们知�,他是无法通过�列化�久化下�的。那么为什么code 4的结果�通过�列化和��列化把List中的元素�留下�了呢? **writeObject和readObject方法** @@ -376,50 +369,48 @@ ArrayList的�列化 > 用户自定义的 writeObject 和 readObject 方法�以�许用户控制�列化的过程,比如�以在�列化的过程中动�改��列化的数值。 �看一下这两个方法的具体实现: +```` +private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + elementData = EMPTY_ELEMENTDATA; - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - elementData = EMPTY_ELEMENTDATA; - - // Read in size, and any hidden stuff - s.defaultReadObject(); - - // Read in capacity - s.readInt(); // ignored - - if (size > 0) { - // be like clone(), allocate array based upon size not capacity - ensureCapacityInternal(size); - - Object[] a = elementData; - // Read in all elements in the proper order. - for (int i=0; i