diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index e85bf95..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1,6 +0,0 @@
-* text=auto
-*.js linguist-language=java
-*.css linguist-language=java
-*.html linguist-language=java
-
-
diff --git a/.gitignore b/.gitignore
index 517ec8a..e233607 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@ out
gen
/target/
+
+
diff --git a/ReadMe.md b/ReadMe.md
index b382ce2..84572da 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -1,4 +1,21 @@
-本仓库为ã€�Java工程师技术指å�—ã€‘åŠ›æ±‚æ‰“é€ æœ€å®Œæ•´æœ€å®žç”¨çš„Java工程师å¦ä¹ 指å�—ï¼�
+
+
+
+
+
+
+åŠ›æ±‚æ‰“é€ æœ€å®Œæ•´æœ€å®žç”¨çš„Java工程师å¦ä¹ 指å�—ï¼�
è¿™äº›æ–‡ç« å’Œæ€»ç»“éƒ½æ˜¯æˆ‘è¿‘å‡ å¹´å¦ä¹ Java总结和整ç�†å‡ºæ�¥çš„,é�žå¸¸å®žç”¨ï¼Œå¯¹äºŽå¦ä¹ Javaå�Žç«¯çš„æœ‹å�‹æ�¥è¯´åº”该是最全é�¢æœ€å®Œæ•´çš„æŠ€æœ¯ä»“库。
我é� ç�€è¿™äº›å†…容进行å¤�ä¹ ï¼Œæ‹¿åˆ°äº†BATç‰å¤§åŽ‚çš„offer,这个仓库也已ç»�帮助了很多的Javaå¦ä¹ è€…ï¼Œå¦‚æžœå¯¹ä½ æœ‰ç”¨ï¼Œå¸Œæœ›èƒ½ç»™ä¸ªstar支æŒ�我,谢谢ï¼�
@@ -9,366 +26,467 @@
-
+
-
-推è��使用 https://how2playlife.com/ 在线阅读,在线阅读内容本仓库å�Œæ¥ä¸€è‡´ã€‚è¿™ç§�æ–¹å¼�阅读的优势在于:左侧边æ �有目录,阅读体验更好。
-
-
-## 目录
-
-- [Java基础](#Java基础)
- - [基础知识](#基础知识)
- - [容器](#容器)
- - [设计模�](#设计模�)
-- [JavaWeb](#JavaWeb)
- - [Srping](#Spring)
- - [SpringMVC](#SpringMVC)
- - [SpringBoot](#SpringBoot)
-- [Java进阶](#Java进阶)
- - [并�](#并�)
- - [JVM](#JVM)
- - [Java网络编程](#Java网络编程)
-- [计算机基础](#计算机基础)
- - [计算机网络](#计算机网络)
- - [�作系统](#�作系统)
- - [Linux相关](#linux相关)
- - [数�结构与算法](#数�结构与算法)
- - [数�结构](#数�结构)
- - [算法](#算法)
-- [数�库](#数�库)
- - [MySQL](#MySQL)
-- [缓å˜](#缓å˜)
- - [Redis](#Redis)
-- [消�队列](#消�队列)
- - [Kafka](#Kafka)
-- [大�端](#大�端)
-- [分布�](#分布�)
- - [�论](#�论)
- - [实战](#实战)
-- [�试指�](#�试指�)
- - [æ ¡æ‹›æŒ‡å�—](#æ ¡æ‹›æŒ‡å�—)
- - [��](#��)
-- [工具](#工具)
- - [Git](#git)
-- [资料](#资料)
- - [书�](#书�)
-- [待办](#待办)
-- [说明](#说明)
-- [微信公众�](#微信公众�)
-
-## Java基础
-
-### 基础知识
-
-* [��对象基础](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)
-
-### 容器
-
-* [Java集�类总结](docs/java/collection/Java集�类总结.md)
-* [Java集�详解1:一文读懂ArrayList,Vector与Stack使用方法和实现原�](docs/java/collection/Java集�详解1:一文读懂ArrayList,Vector与Stack使用方法和实现原�.md)
-* [Java集�详解2:Queue和LinkedList](docs/java/collection/Java集�详解2:Queue和LinkedList.md)
-* [Java集�详解3:Iterator,fail-fast机制与比较器](docs/java/collection/Java集�详解3:Iterator,fail-fast机制与比较器.md)
-* [Java集�详解4:HashMap和HashTable](docs/java/collection/Java集�详解4:HashMap和HashTable.md)
-* [Java集å�ˆè¯¦è§£5:深入ç�†è§£LinkedHashMapå’ŒLRU缓å˜](docs/java/collection/Java集å�ˆè¯¦è§£5:深入ç�†è§£LinkedHashMapå’ŒLRU缓å˜.md)
-* [Java集å�ˆè¯¦è§£6:TreeMapå’Œçº¢é»‘æ ‘](docs/java/collection/Java集å�ˆè¯¦è§£6:TreeMapå’Œçº¢é»‘æ ‘.md)
-* [Java集�详解7:HashSet,TreeSet与LinkedHashSet](docs/java/collection/Java集�详解7:HashSet,TreeSet与LinkedHashSet.md)
-* [Java集�详解8:Java集�类细节精讲](docs/java/collection/Java集�详解8:Java集�类细节精讲.md)
-
-### 设计模�
-
-* [设计模å¼�å¦ä¹ 总结](docs/java/design-parttern/设计模å¼�å¦ä¹ 总结.md)
-* [åˆ�探Java设计模å¼�1:创建型模å¼�(工厂,å�•例ç‰ï¼‰.md](docs/java/design-parttern/åˆ�探Java设计模å¼�1:创建型模å¼�(工厂,å�•例ç‰ï¼‰.md)
-* [åˆ�探Java设计模å¼�2:结构型模å¼�(代ç�†æ¨¡å¼�,适é…�器模å¼�ç‰ï¼‰.md](docs/java/design-parttern/åˆ�探Java设计模å¼�2:结构型模å¼�(代ç�†æ¨¡å¼�,适é…�器模å¼�ç‰ï¼‰.md)
-* [åˆ�探Java设计模å¼�3:行为型模å¼�(ç–略,观察者ç‰ï¼‰.md](docs/java/design-parttern/åˆ�探Java设计模å¼�3:行为型模å¼�(ç–略,观察者ç‰ï¼‰.md)
-* [åˆ�探Java设计模å¼�4:JDKä¸çš„设计模å¼�.md](docs/java/design-parttern/åˆ�探Java设计模å¼�4:JDKä¸çš„设计模å¼�.md)
-* [�探Java设计模�5:Spring涉�到的9�设计模�.md](docs/java/design-parttern/�探Java设计模�5:Spring涉�到的9�设计模�.md)
-
-## JavaWeb
-
-* [走进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技术世界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)
-* [走进JavaWeb技术世界8:浅�Tomcat9请求处��程与�动部署过程](docs/java-web/走进JavaWeb技术世界8:浅�Tomcat9请求处��程与�动部署过程.md)
-* [走进JavaWeb技术世界9:Java日志系统的诞生与�展](docs/java-web/走进JavaWeb技术世界9:Java日志系统的诞生与�展.md)
-* [走进JavaWeb技术世界10:从JavaBean讲到Spring](docs/java-web/走进JavaWeb技术世界10:从JavaBean讲到Spring.md)
-* [走进JavaWeb技术世界11:�元测试框架Junit](docs/java-web/走进JavaWeb技术世界11:�元测试框架Junit.md)
-* [走进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技术世界16:�简�置的SpringBoot](docs/java-web/走进JavaWeb技术世界16:�简�置的SpringBoot.md)
-
-### Spring
-
-* [Springæº�ç �剖æž�1:Spring概述](docs/java-web/Spring/Springæº�ç �剖æž�1:Spring概述.md)
-* [Springæº�ç �剖æž�2:åˆ�探Spring IOCæ ¸å¿ƒæµ�程](docs/java-web/Spring/Springæº�ç �剖æž�2:åˆ�探Spring%20IOCæ ¸å¿ƒæµ�程.md)
-* [Springæº�ç �剖æž�3:Spring IOCå®¹å™¨çš„åŠ è½½è¿‡ç¨‹ ](docs/java-web/Spring/Springæº�ç �剖æž�3:Spring%20IOCå®¹å™¨çš„åŠ è½½è¿‡ç¨‹.md)
-* [Springæº�ç �剖æž�4ï¼šæ‡’åŠ è½½çš„å�•例Bean获å�–过程分æž�](docs/java-web/Spring/Springæº�ç �剖æž�4ï¼šæ‡’åŠ è½½çš„å�•例Bean获å�–过程分æž�.md)
-* [Springæº�ç �剖æž�5:JDKå’Œcglib动æ€�代ç�†åŽŸç�†è¯¦è§£ ](docs/java-web/Spring/Springæº�ç �剖æž�5:JDKå’Œcglib动æ€�代ç�†åŽŸç�†è¯¦è§£.md)
-* [Springæº�ç �剖æž�6:Spring AOP概述](docs/java-web/Spring/Springæº�ç �剖æž�6:Spring%20AOP概述.md)
-* [Springæº�ç �剖æž�7:AOP实现原ç�†è¯¦è§£ ](docs/java-web/Spring/Springæº�ç �剖æž�7:AOP实现原ç�†è¯¦è§£.md)
-* [Springæº�ç �剖æž�8:Spring事务概述](docs/java-web/Spring/Springæº�ç �剖æž�8:Spring事务概述.md)
-* [Springæº�ç �剖æž�9:Spring事务æº�ç �剖æž�](docs/java-web/Spring/Springæº�ç �剖æž�9:Spring事务æº�ç �剖æž�.md)
-
-### 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)
-
-### SpringBoot
-
-todo
-
-### SpringCloud
-
-todo
-
-## Java进阶
-
-### 并�
-
-* [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)
-
-### JVM
-
-* [JVM总结](docs/java/jvm/JVM总结.md)
-* [深入ç�†è§£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虚拟机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虚拟机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)
-* [深入�解JVM虚拟机12:JVM性能管�神器VisualVM介�与实战](docs/java/jvm/深入�解JVM虚拟机12:JVM性能管�神器VisualVM介�与实战.md)
-* [深入�解JVM虚拟机13:�谈四�引用�GC实践](docs/java/jvm/深入�解JVM虚拟机13:�谈四�引用�GC实践.md)
-* [深入�解JVM虚拟机14:GC调优�路与常用工具](docs/java/jvm/深入�解JVM虚拟机:GC调优�路与常用工具.md)
-
-### 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基础
+
+## 基础知识
+* [��对象基础](docs/Java/basic/��对象基础.md)
+* [Java基本数�类型](docs/Java/basic/Java基本数�类型.md)
+* [string和包装类](docs/Java/basic/string和包装类.md)
+* [final关键å—特性](docs/Java/basic/final关键å—特性.md)
+* [Java类和包](docs/Java/basic/Java类和包.md)
+* [抽象类和接�](docs/Java/basic/抽象类和接�.md)
+* [代ç �å�—和代ç �执行顺åº�](docs/Java/basic/代ç �å�—和代ç �执行顺åº�.md)
+* [Java自动拆箱装箱里��的秘密](docs/Java/basic/Java自动拆箱装箱里��的秘密.md)
+* [Javaä¸çš„Class类和Objectç±»](docs/Java/basic/Javaä¸çš„Class类和Objectç±».md)
+* [Java异常](docs/Java/basic/Java异常.md)
+* [解读Javaä¸çš„回调](docs/Java/basic/解读Javaä¸çš„回调.md)
+* [�射](docs/Java/basic/�射.md)
+* [泛型](docs/Java/basic/泛型.md)
+* [枚举类](docs/Java/basic/枚举类.md)
+* [Java注解和最佳实践](docs/Java/basic/Java注解和最佳实践.md)
+* [JavaIO�](docs/Java/basic/JavaIO�.md)
+* [多线程](docs/Java/basic/多线程.md)
+* [深入�解内部类](docs/Java/basic/深入�解内部类.md)
+* [javacå’Œjavap](docs/Java/basic/javacå’Œjavap.md)
+* [Java8新特性终�指�](docs/Java/basic/Java8新特性终�指�.md)
+* [�列化和��列化](docs/Java/basic/�列化和��列化.md)
+* [继承�装多�的实现原�](docs/Java/basic/继承�装多�的实现原�.md)
+
+## 集�类
+
+* [Java集�类总结](docs/Java/collection/Java集�类总结.md)
+* [Java集�详解:一文读懂ArrayList,Vector与Stack使用方法和实现原�](docs/Java/collection/Java集�详解:一文读懂ArrayList,Vector与Stack使用方法和实现原�.md)
+* [Java集�详解:Queue和LinkedList](docs/Java/collection/Java集�详解:Queue和LinkedList.md)
+* [Java集�详解:Iterator,fail-fast机制与比较器](docs/Java/collection/Java集�详解:Iterator,fail-fast机制与比较器.md)
+* [Java集�详解:HashMap和HashTable](docs/Java/collection/Java集�详解:HashMap和HashTable.md)
+* [Java集å�ˆè¯¦è§£ï¼šæ·±å…¥ç�†è§£LinkedHashMapå’ŒLRU缓å˜](docs/Java/collection/Java集å�ˆè¯¦è§£ï¼šæ·±å…¥ç�†è§£LinkedHashMapå’ŒLRU缓å˜.md)
+* [Java集å�ˆè¯¦è§£ï¼šTreeMapå’Œçº¢é»‘æ ‘](docs/Java/collection/Java集å�ˆè¯¦è§£ï¼šTreeMapå’Œçº¢é»‘æ ‘.md)
+* [Java集�详解:HashSet,TreeSet与LinkedHashSet](docs/Java/collection/Java集�详解:HashSet,TreeSet与LinkedHashSet.md)
+* [Java集�详解:Java集�类细节精讲](docs/Java/collection/Java集�详解:Java集�类细节精讲.md)
+
+# JavaWeb
+
+* [走进JavaWeb技术世界:JavaWeb的由�和基础知识](docs/JavaWeb/走进JavaWeb技术世界:JavaWeb的由�和基础知识.md)
+* [走进JavaWeb技术世界:JSP与Servlet的曾�与现在](docs/JavaWeb/走进JavaWeb技术世界:JSP与Servlet的曾�与现在.md)
+* [èµ°è¿›JavaWeb技术世界:JDBCçš„è¿›åŒ–ä¸Žè¿žæŽ¥æ± æŠ€æœ¯](docs/JavaWeb/èµ°è¿›JavaWeb技术世界:JDBCçš„è¿›åŒ–ä¸Žè¿žæŽ¥æ± æŠ€æœ¯.md)
+* [走进JavaWeb技术世界:Servlet工作原�详解](docs/JavaWeb/走进JavaWeb技术世界:Servlet工作原�详解.md)
+* [走进JavaWeb技术世界:�探Tomcat的HTTP请求过程](docs/JavaWeb/走进JavaWeb技术世界:�探Tomcat的HTTP请求过程.md)
+* [走进JavaWeb技术世界:Tomcat5总体架构剖�](docs/JavaWeb/走进JavaWeb技术世界:Tomcat5总体架构剖�.md)
+* [走进JavaWeb技术世界:Tomcat和其他WEB容器的区别](docs/JavaWeb/走进JavaWeb技术世界:Tomcat和其他WEB容器的区别.md)
+* [走进JavaWeb技术世界:浅�Tomcat9请求处��程与�动部署过程](docs/JavaWeb/走进JavaWeb技术世界:浅�Tomcat9请求处��程与�动部署过程.md)
+* [走进JavaWeb技术世界:Java日志系统的诞生与�展](docs/JavaWeb/走进JavaWeb技术世界:Java日志系统的诞生与�展.md)
+* [走进JavaWeb技术世界:从JavaBean讲到Spring](docs/JavaWeb/走进JavaWeb技术世界:从JavaBean讲到Spring.md)
+* [走进JavaWeb技术世界:�元测试框架Junit](docs/JavaWeb/走进JavaWeb技术世界:�元测试框架Junit.md)
+* [走进JavaWeb技术世界:从手动编译打包到项目构建工具Maven](docs/JavaWeb/走进JavaWeb技术世界:从手动编译打包到项目构建工具Maven.md)
+* [走进JavaWeb技术世界:Hibernate入门�典与注解�开�](docs/JavaWeb/走进JavaWeb技术世界:Hibernate入门�典与注解�开�.md)
+* [走进JavaWeb技术世界:Mybatis入门](docs/JavaWeb/走进JavaWeb技术世界:Mybatis入门.md)
+* [走进JavaWeb技术世界:深入浅出Mybatis基本原�](docs/JavaWeb/走进JavaWeb技术世界:深入浅出Mybatis基本原�.md)
+* [走进JavaWeb技术世界:�简�置的SpringBoot](docs/JavaWeb/走进JavaWeb技术世界:�简�置的SpringBoot.md)
+
+# Java进阶
+
+## 并�编程
+
+* [Java并�指�:并�基础与Java多线程](docs/Java/concurrency/Java并�指�:并�基础与Java多线程.md)
+* [Javaå¹¶å�‘指å�—:深入ç�†è§£Javaå†…å˜æ¨¡åž‹JMM](docs/Java/concurrency/Javaå¹¶å�‘指å�—:深入ç�†è§£Javaå†…å˜æ¨¡åž‹JMM.md)
+* [Javaå¹¶å�‘指å�—:并å�‘三大问题与volatile关键å—,CASæ“�作](docs/Java/concurrency/Javaå¹¶å�‘指å�—:并å�‘三大问题与volatile关键å—,CASæ“�作.md)
+* [Javaå¹¶å�‘指å�—:Javaä¸çš„é”�Lockå’Œsynchronized](docs/Java/concurrency/Javaå¹¶å�‘指å�—:Javaä¸çš„é”�Lockå’Œsynchronized.md)
+* [Javaå¹¶å�‘指å�—:JMMä¸çš„final关键å—è§£æž�](docs/Java/concurrency/Javaå¹¶å�‘指å�—:JMMä¸çš„final关键å—è§£æž�.md)
+* [Javaå¹¶å�‘指å�—:Javaå†…å˜æ¨¡åž‹JMM总结](docs/Java/concurrency/Javaå¹¶å�‘指å�—:Javaå†…å˜æ¨¡åž‹JMM总结.md)
+* [Javaå¹¶å�‘指å�—:JUCçš„æ ¸å¿ƒç±»AQS详解](docs/Java/concurrency/Javaå¹¶å�‘指å�—:JUCçš„æ ¸å¿ƒç±»AQS详解.md)
+* [Javaå¹¶å�‘指å�—:AQSä¸çš„公平é”�与é�žå…¬å¹³é”�,Condtion](docs/Java/concurrency/Javaå¹¶å�‘指å�—:AQSä¸çš„公平é”�与é�žå…¬å¹³é”�,Condtion.md)
+* [Java并�指�:AQS共享模�与并�工具类的实现](docs/Java/concurrency/Java并�指�:AQS共享模�与并�工具类的实现.md)
+* [Javaå¹¶å�‘指å�—:Java读写é”�ReentrantReadWriteLockæº�ç �分æž�](docs/Java/concurrency/Javaå¹¶å�‘指å�—:Java读写é”�ReentrantReadWriteLockæº�ç �分æž�.md)
+* [Java并�指�:解读Java阻塞队列BlockingQueue](docs/Java/concurrency/Java并�指�:解读Java阻塞队列BlockingQueue.md)
+* [Javaå¹¶å�‘指å�—:深度解读javaçº¿ç¨‹æ± è®¾è®¡æ€�想å�Šæº�ç �实现](docs/Java/concurrency/Javaå¹¶å�‘指å�—:深度解读Javaçº¿ç¨‹æ± è®¾è®¡æ€�想å�Šæº�ç �实现.md)
+* [Javaå¹¶å�‘指å�—:Javaä¸çš„HashMapå’ŒConcurrentHashMap全解æž�](docs/Java/concurrency/Javaå¹¶å�‘指å�—:Javaä¸çš„HashMapå’ŒConcurrentHashMap全解æž�.md)
+* [Javaå¹¶å�‘指å�—:JUCä¸å¸¸ç”¨çš„Unsafeå’ŒLocksupport](docs/Java/concurrency/Javaå¹¶å�‘指å�—:JUCä¸å¸¸ç”¨çš„Unsafeå’ŒLocksupport.md)
+* [Java并�指�:ForkJoin并�框架与工作窃�算法剖�](docs/Java/concurrency/Java并�指�:ForkJoin并�框架与工作窃�算法剖�.md)
+* [Javaå¹¶å�‘编程å¦ä¹ 总结](docs/Java/concurrency/Javaå¹¶å�‘编程å¦ä¹ 总结.md)
+
+## JVM
+
+* [JVM总结](docs/Java/JVM/JVM总结.md)
+* [深入ç�†è§£JVM虚拟机:JVM内å˜çš„结构与消失的永久代](docs/Java/JVM/深入ç�†è§£JVM虚拟机:JVM内å˜çš„结构与消失的永久代.md)
+* [深入�解JVM虚拟机:JVM垃圾回收基本原�和算法](docs/Java/JVM/深入�解JVM虚拟机:JVM垃圾回收基本原�和算法.md)
+* [深入�解JVM虚拟机:垃圾回收器详解](docs/Java/JVM/深入�解JVM虚拟机:垃圾回收器详解.md)
+* [深入ç�†è§£JVM虚拟机:Javaclass介ç»�与解æž�实践](docs/Java/JVM/深入ç�†è§£JVM虚拟机:Javaå—节ç �介ç»�与解æž�实践.md)
+* [深入ç�†è§£JVM虚拟机:虚拟机å—节ç �执行引擎](docs/Java/JVM/深入ç�†è§£JVM虚拟机:虚拟机å—节ç �执行引擎.md)
+* [深入ç�†è§£JVM虚拟机:深入ç�†è§£JVMç±»åŠ è½½æœºåˆ¶](docs/Java/JVM/深入ç�†è§£JVM虚拟机:深入ç�†è§£JVMç±»åŠ è½½æœºåˆ¶.md)
+* [深入ç�†è§£JVM虚拟机:JNDI,OSGI,Tomcatç±»åŠ è½½å™¨å®žçŽ°](docs/Java/JVM/深入ç�†è§£JVM虚拟机:JNDI,OSGI,Tomcatç±»åŠ è½½å™¨å®žçŽ°.md)
+* [深入了解JVM虚拟机:Java的编译期优化与�行期优化](docs/Java/JVM/深入�解JVM虚拟机:Java的编译期优化与�行期优化.md)
+* [深入ç�†è§£JVM虚拟机:JVM监控工具与诊æ–实践](docs/Java/JVM/深入ç�†è§£JVM虚拟机:JVM监控工具与诊æ–实践.md)
+* [深入�解JVM虚拟机:JVM常用�数以�调优实践](docs/Java/JVM/深入�解JVM虚拟机:JVM常用�数以�调优实践.md)
+* [深入ç�†è§£JVM虚拟机:Java内å˜å¼‚常原ç�†ä¸Žå®žè·µ](docs/Java/JVM/深入ç�†è§£JVM虚拟机:Java内å˜å¼‚常原ç�†ä¸Žå®žè·µ.md)
+* [深入�解JVM虚拟机:JVM性能管�神器VisualVM介�与实战](docs/Java/JVM/深入�解JVM虚拟机:JVM性能管�神器VisualVM介�与实战.md)
+* [深入�解JVM虚拟机:�谈四�引用�GC实践](docs/Java/JVM/深入�解JVM虚拟机:�谈四�引用�GC实践.md)
+* [深入�解JVM虚拟机:GC调优�路与常用工具](docs/Java/JVM/深入�解JVM虚拟机:GC调优�路与常用工具.md)
+
+## Java网络编程
+
+* [Java网络编程和NIO详解:JAVA ä¸åŽŸç”Ÿçš„ socket 通信机制](docs/Java/network/Java网络编程与NIO详解:JAVAä¸åŽŸç”Ÿçš„socket通信机制.md)
+* [Java网络编程与NIO详解:JAVA NIO ä¸€æ¥æ¥æž„建IO多路å¤�用的请求模型](docs/Java/network/Java网络编程与NIO详解:JavaNIOä¸€æ¥æ¥æž„建IO多路å¤�用的请求模型.md)
+* [Java网络编程和NIO详解:IO模型与Java网络编程模型](docs/Java/network/Java网络编程与NIO详解:IO模型与Java网络编程模型.md)
+* [Java网络编程与NIO详解:浅æž�NIO包ä¸çš„BufferChannelå’ŒSelector](docs/Java/network/Java网络编程与NIO详解:浅æž�NIO包ä¸çš„BufferChannelå’ŒSelector.md)
+* [Java网络编程和NIO详解:Javaé�žé˜»å¡žIO和异æ¥IO](docs/Java/network/Java网络编程与NIO详解:Javaé�žé˜»å¡žIO和异æ¥IO.md)
+* [Java网络编程与NIO详解:LinuxEpoll实现原�详解](docs/Java/network/Java网络编程与NIO详解:LinuxEpoll实现原�详解.md.md)
+* [Java网络编程与NIO详解:浅谈Linuxä¸Selector的实现原ç�†](docs/Java/network/Java网络编程与NIO详解:浅谈Linuxä¸Selector的实现原ç�†.md)
+* [Java网络编程与NIO详解:浅�mmap和DirectBuffer](docs/Java/network/Java网络编程与NIO详解:浅�mmap和DirectBuffer.md)
+* [Java网络编程与NIO详解:基于NIO的网络编程框架Netty](docs/Java/network/Java网络编程与NIO详解:基于NIO的网络编程框架Netty.md)
+* [Java网络编程与NIO详解:Java网络编程与NIO详解](docs/Java/network/Java网络编程与NIO详解:深度解读Tomcatä¸çš„NIO模型.md)
+* [Java网络编程与NIO详解:Tomcatä¸çš„Connectoræº�ç �分æž�(NIO)](docs/Java/network/Java网络编程与NIO详解:Tomcatä¸çš„Connectoræº�ç �分æž�(NIO).md)
+
+# Spring全家桶
+
+## Spring
+
+* [SpringAOP的概念与作用](docs/Spring全家桶/Spring/Spring常�注解.md)
+* [SpringBean的定义与管ç�†ï¼ˆæ ¸å¿ƒï¼‰](docs/Spring全家桶/Spring/Spring常è§�注解.md)
+* [Springä¸å¯¹äºŽæ•°æ�®åº“的访问](docs/Spring全家桶/Spring/Spring常è§�注解.md)
+* [Springä¸å¯¹äºŽæ ¡éªŒåŠŸèƒ½çš„æ”¯æŒ�](docs/Spring全家桶/Spring/Spring常è§�注解.md)
+* [Springä¸çš„Environment环境å�˜é‡�](docs/Spring全家桶/Spring/Spring常è§�注解.md)
+* [Springä¸çš„事件处ç�†æœºåˆ¶](docs/Spring全家桶/Spring/Spring常è§�注解.md)
+* [Springä¸çš„资æº�管ç�†](docs/Spring全家桶/Spring/Spring常è§�注解.md)
+* [Springä¸çš„é…�置元数æ�®ï¼ˆç®¡ç�†é…�置的基本数æ�®ï¼‰](docs/Spring全家桶/Spring/Spring常è§�注解.md)
+* [Spring事务基本用法](docs/Spring全家桶/Spring/Spring常�注解.md)
+* [Spring�集](docs/Spring全家桶/Spring/Spring常�注解.md)
+* [Spring容器与IOC](docs/Spring全家桶/Spring/Spring常�注解.md)
+* [Spring常�注解](docs/Spring全家桶/Spring/Spring常�注解.md)
+* [Spring概述](docs/Spring全家桶/Spring/Spring常�注解.md)
+* [第一个Spring应用](docs/Spring全家桶/Spring/Spring常�注解.md)
+
+## Springæº�ç �分æž�
+
+### 综�
+* [Springæº�ç �剖æž�:åˆ�探SpringIOCæ ¸å¿ƒæµ�程](docs/Spring全家桶/Springæº�ç �分æž�/Springæº�ç �剖æž�:åˆ�探SpringIOCæ ¸å¿ƒæµ�程.md)
+* [Springæº�ç �剖æž�:SpringIOCå®¹å™¨çš„åŠ è½½è¿‡ç¨‹ ](docs/Spring全家桶/Springæº�ç �分æž�/Springæº�ç �剖æž�:SpringIOCå®¹å™¨çš„åŠ è½½è¿‡ç¨‹.md)
+* [Springæº�ç �剖æž�ï¼šæ‡’åŠ è½½çš„å�•例Bean获å�–过程分æž�](docs/Spring全家桶/Springæº�ç �分æž�/Springæº�ç �剖æž�ï¼šæ‡’åŠ è½½çš„å�•例Bean获å�–过程分æž�.md)
+* [Springæº�ç �剖æž�:JDKå’Œcglib动æ€�代ç�†åŽŸç�†è¯¦è§£ ](docs/Spring全家桶/Springæº�ç �分æž�/Springæº�ç �剖æž�:JDKå’Œcglib动æ€�代ç�†åŽŸç�†è¯¦è§£.md)
+* [Springæº�ç �剖æž�:SpringAOP概述](docs/Spring全家桶/Springæº�ç �分æž�/Springæº�ç �剖æž�:SpringAOP概述.md)
+* [Springæº�ç �剖æž�:AOP实现原ç�†è¯¦è§£ ](docs/Spring全家桶/Springæº�ç �分æž�/Springæº�ç �剖æž�:AOP实现原ç�†è¯¦è§£.md)
+* [Springæº�ç �剖æž�:Spring事务概述](docs/Spring全家桶/Springæº�ç �分æž�/Springæº�ç �剖æž�:Spring事务概述.md)
+* [Springæº�ç �剖æž�:Spring事务æº�ç �剖æž�](docs/Spring全家桶/Springæº�ç �分æž�/Springæº�ç �剖æž�:Spring事务æº�ç �剖æž�.md)
+
+### AOP
+* [AnnotationAwareAspectJAutoProxyCreator 分æž�(上)](docs/Spring全家桶/Springæº�ç �分æž�/SpringAOP/AnnotationAwareAspectJAutoProxyCreator分æž�(上).md)
+* [AnnotationAwareAspectJAutoProxyCreator 分æž�(下)](docs/Spring全家桶/Springæº�ç �分æž�/SpringAOP/AnnotationAwareAspectJAutoProxyCreator分æž�(下).md)
+* [AOP示例demoå�Š@EnableAspectJAutoProxy](docs/Spring全家桶/Springæº�ç �分æž�/SpringAOP/AOP示例demoå�Š@EnableAspectJAutoProxy.md)
+* [SpringAop(四):jdk 动æ€�代ç�†](docs/Spring全家桶/Springæº�ç �分æž�/SpringAOP/SpringAop(四):jdk动æ€�代ç�†.md)
+* [SpringAop(五):cglib 代ç�†](docs/Spring全家桶/Springæº�ç �分æž�/SpringAOP/SpringAop(五):cglib代ç�†.md)
+* [SpringAop(å…):aop 总结](docs/Spring全家桶/Springæº�ç �分æž�/SpringAOP/SpringAop(å…):aop总结.md)
+
+### 事务
+* [spring 事务(一):认识事务组件](docs/Spring全家桶/Springæº�ç �分æž�/Spring事务/Spring事务(一):认识事务组件.md)
+* [spring 事务(二):事务的执行æµ�程](docs/Spring全家桶/Springæº�ç �分æž�/Spring事务/Spring事务(二):事务的执行æµ�程.md)
+* [spring äº‹åŠ¡ï¼ˆä¸‰ï¼‰ï¼šäº‹åŠ¡çš„éš”ç¦»çº§åˆ«ä¸Žä¼ æ’æ–¹å¼�的处ç�†](docs/Spring全家桶/Springæº�ç �分æž�/Spring事务/Springäº‹åŠ¡ï¼ˆä¸‰ï¼‰ï¼šäº‹åŠ¡çš„éš”ç¦»çº§åˆ«ä¸Žä¼ æ’æ–¹å¼�的处ç�†01.md)
+* [spring äº‹åŠ¡ï¼ˆå››ï¼‰ï¼šäº‹åŠ¡çš„éš”ç¦»çº§åˆ«ä¸Žä¼ æ’æ–¹å¼�的处ç�†](docs/Spring全家桶/Springæº�ç �分æž�/Spring事务/Springäº‹åŠ¡ï¼ˆå››ï¼‰ï¼šäº‹åŠ¡çš„éš”ç¦»çº§åˆ«ä¸Žä¼ æ’æ–¹å¼�的处ç�†02.md)
+* [spring äº‹åŠ¡ï¼ˆäº”ï¼‰ï¼šäº‹åŠ¡çš„éš”ç¦»çº§åˆ«ä¸Žä¼ æ’æ–¹å¼�的处ç�†](docs/Spring全家桶/Springæº�ç �分æž�/Spring事务/Springäº‹åŠ¡ï¼ˆäº”ï¼‰ï¼šäº‹åŠ¡çš„éš”ç¦»çº§åˆ«ä¸Žä¼ æ’æ–¹å¼�的处ç�†03.md)
+* [spring 事务(å…ï¼‰ï¼šäº‹åŠ¡çš„éš”ç¦»çº§åˆ«ä¸Žä¼ æ’æ–¹å¼�的处ç�†](docs/Spring全家桶/Springæº�ç �分æž�/Spring事务/Spring事务(å…ï¼‰ï¼šäº‹åŠ¡çš„éš”ç¦»çº§åˆ«ä¸Žä¼ æ’æ–¹å¼�的处ç�†04.md)
+
+### �动�程
+* [springå�¯åЍæµ�程(一):å�¯åЍæµ�程概览](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(一):å�¯åЍæµ�程概览.md)
+* [springå�¯åЍæµ�程(二):ApplicationContext 的创建](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(二):ApplicationContext的创建.md)
+* [springå�¯åЍæµ�程(三):包的扫æ��æµ�程](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(三):包的扫æ��æµ�程.md)
+* [springå�¯åЍæµ�程(四):å�¯åЍå‰�的准备工作](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(四):å�¯åЍå‰�的准备工作.md)
+* [springå�¯åЍæµ�程(五):执行 BeanFactoryPostProcessor](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(五):执行BeanFactoryPostProcessor.md)
+* [springå�¯åЍæµ�程(å…):注册 BeanPostProcessor](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(å…):注册BeanPostProcessor.md)
+* [springå�¯åЍæµ�程(七):国际化与事件处ç�†](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(七):国际化与事件处ç�†.md)
+* [springå�¯åЍæµ�程(八):完æˆ� BeanFactory çš„åˆ�始化](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(八):完æˆ�BeanFactoryçš„åˆ�始化.md)
+* [springå�¯åЍæµ�程(ä¹�):å�•例 bean 的创建](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(ä¹�):å�•例bean的创建.md)
+* [springå�¯åЍæµ�程(å��):å�¯åŠ¨å®Œæˆ�的处ç�†](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(å��):å�¯åŠ¨å®Œæˆ�的处ç�†.md)
+* [springå�¯åЍæµ�程(å��一):å�¯åЍæµ�程总结](docs/Spring全家桶/Springæº�ç �分æž�/Springå�¯åЍæµ�程/Springå�¯åЍæµ�程(å��一):å�¯åЍæµ�程总结.md)
+
+### 组件分�
+* [spring 组件之 ApplicationContext](docs/Spring全家桶/Springæº�ç �分æž�/Spring组件分æž�/Spring组件之ApplicationContext.md)
+* [spring 组件之 BeanDefinition](docs/Spring全家桶/Springæº�ç �分æž�/Spring组件分æž�/Spring组件之BeanDefinition.md)
+* [Spring 组件之 BeanFactory](docs/Spring全家桶/Springæº�ç �分æž�/Spring组件分æž�/Spring组件之BeanFactory.md)
+* [spring 组件之 BeanFactoryPostProcessor](docs/Spring全家桶/Springæº�ç �分æž�/Spring组件分æž�/Spring组件之BeanFactoryPostProcessor.md)
+* [spring 组件之 BeanPostProcessor](docs/Spring全家桶/Springæº�ç �分æž�/Spring组件分æž�/Spring组件之BeanPostProcessor.md)
+
+### ��机制探秘
+
+* [ConfigurationClassPostProcessor(一):处ç�† @ComponentScan 注解](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/ConfigurationClassPostProcessor(一):处ç�†@ComponentScan注解.md)
+* [ConfigurationClassPostProcessor(三):处ç�† @Import 注解](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/ConfigurationClassPostProcessor(三):处ç�†@Import注解.md)
+* [ConfigurationClassPostProcessor(二):处ç�† @Bean 注解](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/ConfigurationClassPostProcessor(二):处ç�†@Bean注解.md)
+* [ConfigurationClassPostProcessor(四):处ç�† @Conditional 注解](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/ConfigurationClassPostProcessor(四):处ç�†@Conditional注解.md)
+* [Spring 探秘之 AOP 的执行顺åº�](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/Spring探秘之AOP的执行顺åº�.md)
+* [Spring 探秘之 Spring 事件机制](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/Spring探秘之Spring事件机制.md)
+* [spring 探秘之循环ä¾�赖的解决(一):ç�†è®ºåŸºçŸ³](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/Spring探秘之循环ä¾�赖的解决(一):ç�†è®ºåŸºçŸ³.md)
+* [spring 探秘之循环ä¾�赖的解决(二):æº�ç �分æž�](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/Spring探秘之循环ä¾�赖的解决(二):æº�ç �分æž�.md)
+* [spring 探秘之监å�¬å™¨æ³¨è§£ @EventListener](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/spring探秘之监å�¬å™¨æ³¨è§£@EventListener.md)
+* [spring 探秘之组å�ˆæ³¨è§£çš„处ç�†](docs/Spring全家桶/Springæº�ç �分æž�/Springé‡�è¦�机制探秘/Spring探秘之组å�ˆæ³¨è§£çš„处ç�†.md)
+
+## SpringMVC
+
+* [SpringMVCä¸çš„国际化功能](docs/Spring全家桶/SpringMVC/SpringMVCä¸çš„国际化功能.md)
+* [SpringMVCä¸çš„异常处ç�†å™¨](docs/Spring全家桶/SpringMVC/SpringMVCä¸çš„异常处ç�†å™¨.md)
+* [SpringMVCä¸çš„æ‹¦æˆªå™¨](docs/Spring全家桶/SpringMVC/SpringMVCä¸çš„æ‹¦æˆªå™¨.md)
+* [SpringMVCä¸çš„视图解æž�器](docs/Spring全家桶/SpringMVC/SpringMVCä¸çš„视图解æž�器.md)
+* [SpringMVCä¸çš„过滤器Filter](docs/Spring全家桶/SpringMVC/SpringMVCä¸çš„过滤器Filter.md)
+* [SpringMVC基本介�与快速入门](docs/Spring全家桶/SpringMVC/SpringMVC基本介�与快速入门.md)
+* [SpringMVCå¦‚ä½•å®žçŽ°æ–‡ä»¶ä¸Šä¼ ](docs/Spring全家桶/SpringMVC/SpringMVCå¦‚ä½•å®žçŽ°æ–‡ä»¶ä¸Šä¼ .md)
+* [SpringMVCä¸çš„常用功能](docs/Spring全家桶/SpringMVC/SpringMVCä¸çš„常用功能.md)
+
+## SpringMVCæº�ç �分æž�
+
+* [SpringMVCæº�ç �分æž�:SpringMVC概述](docs/Spring全家桶/SpringMVCæº�ç �分æž�/SpringMVCæº�ç �分æž�:SpringMVC概述.md)
+* [SpringMVCæº�ç �分æž�:SpringMVC设计ç�†å¿µä¸ŽDispatcherServlet](docs/Spring全家桶/SpringMVCæº�ç �分æž�/SpringMVCæº�ç �分æž�:SpringMVC设计ç�†å¿µä¸ŽDispatcherServlet.md)
+* [SpringMVCæº�ç �分æž�:DispatcherServletçš„åˆ�始化与请求转å�‘ ](docs/Spring全家桶/SpringMVCæº�ç �分æž�/SpringMVCæº�ç �分æž�:DispatcherServletçš„åˆ�始化与请求转å�‘.md)
+* [SpringMVCæº�ç �分æž�:DispatcherServlet如何找到æ£ç¡®çš„Controller ](docs/Spring全家桶/SpringMVCæº�ç �分æž�/SpringMVCæº�ç �分æž�:DispatcherServlet如何找到æ£ç¡®çš„Controller.md)
+* [SpringMVCæº�ç �剖æž�:消æ�¯è½¬æ�¢å™¨HttpMessageConverter与@ResponseBody注解](docs/Spring全家桶/SpringMVC/SpringMVCæº�ç �剖æž�:消æ�¯è½¬æ�¢å™¨HttpMessageConverter与@ResponseBody注解.md)
+* [DispatcherServlet åˆ�始化æµ�程 ](docs/Spring全家桶/SpringMVCæº�ç �分æž�/DispatcherServletåˆ�始化æµ�程.md)
+* [RequestMapping åˆ�始化æµ�程 ](docs/Spring全家桶/SpringMVCæº�ç �分æž�/RequestMappingåˆ�始化æµ�程.md)
+* [Spring 容器å�¯åЍ Tomcat ](docs/Spring全家桶/SpringMVCæº�ç �分æž�/Spring容器å�¯åЍTomcat.md)
+* [SpringMVC demo 与@EnableWebMvc 注解 ](docs/Spring全家桶/SpringMVCæº�ç �分æž�/SpringMVCçš„Demo与@EnableWebMvc注解.md)
+* [SpringMVC 整体æº�ç �结构总结 ](docs/Spring全家桶/SpringMVCæº�ç �分æž�/SpringMVC整体æº�ç �结构总结.md)
+* [请求执行æµ�程(一)之获å�– Handler ](docs/Spring全家桶/SpringMVCæº�ç �分æž�/请求执行æµ�程(一)之获å�–Handler.md)
+* [请求执行æµ�程(二)之执行 Handler 方法 ](docs/Spring全家桶/SpringMVCæº�ç �分æž�/请求执行æµ�程(二)之执行Handler方法.md)
+
+## SpringBoot
+
+* [SpringBoot系列:SpringBoot的�世今生](docs/Spring全家桶/SpringBoot/SpringBoot的�世今生.md)
+* [ç»™ä½ ä¸€ä»½SpringBoot知识清å�•.md](docs/Spring全家桶/SpringBoot/ç»™ä½ ä¸€ä»½SpringBoot知识清å�•.md)
+* [Spring常�注解使用指�(包�Spring+SpringMVC+SpringBoot)](docs/Spring全家桶/SpringBoot/Spring常�注解使用指�(包�Spring+SpringMVC+SpringBoot).md)
+* [SpringBootä¸çš„æ—¥å¿—管ç�†](docs/Spring全家桶/SpringBoot/SpringBootä¸çš„æ—¥å¿—管ç�†.md)
+* [SpringBoot常�注解](docs/Spring全家桶/SpringBoot/SpringBoot常�注解.md)
+* [SpringBoot应用也�以部署到外部Tomcat](docs/Spring全家桶/SpringBoot/SpringBoot应用也�以部署到外部Tomcat.md)
+* [SpringBoot生产环境工具Actuator](docs/Spring全家桶/SpringBoot/SpringBoot生产环境工具Actuator.md)
+* [SpringBoot的Starter机制](docs/Spring全家桶/SpringBoot/SpringBoot的Starter机制.md)
+* [SpringBoot的�世今生](docs/Spring全家桶/SpringBoot/SpringBoot的�世今生.md)
+* [SpringBoot的基本使用](docs/Spring全家桶/SpringBoot/SpringBoot的基本使用.md)
+* [SpringBoot的�置文件管�](docs/Spring全家桶/SpringBoot/SpringBoot的�置文件管�.md)
+* [SpringBoot自带的çƒéƒ¨ç½²å·¥å…·](docs/Spring全家桶/SpringBoot/SpringBoot自带的çƒéƒ¨ç½²å·¥å…·.md)
+* [SpringBootä¸çš„任务调度与@Async](docs/Spring全家桶/SpringBoot/SpringBootä¸çš„任务调度与@Async.md)
+* [基于SpringBootä¸çš„å¼€æº�监控工具SpringBootAdmin](docs/Spring全家桶/SpringBoot/基于SpringBootä¸çš„å¼€æº�监控工具SpringBootAdmin.md)
+
+## SpringBootæº�ç �分æž�
+* [@SpringBootApplication 注解](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/@SpringBootApplication注解.md)
+* [springboot web应用(一):servlet 组件的注册æµ�程](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBootWeb应用(一):servlet组件的注册æµ�程.md)
+* [springboot web应用(二):WebMvc 装é…�过程](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBootWeb应用(二):WebMvc装é…�过程.md)
+
+* [SpringBoot å�¯åЍæµ�程(一):准备 SpringApplication](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBootå�¯åЍæµ�程(一):准备SpringApplication.md)
+* [SpringBoot å�¯åЍæµ�程(二):准备è¿�行环境](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBootå�¯åЍæµ�程(二):准备è¿�行环境.md)
+* [SpringBoot å�¯åЍæµ�程(三):准备IOC容器](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBootå�¯åЍæµ�程(三):准备IOC容器.md)
+* [springboot å�¯åЍæµ�程(四):å�¯åЍIOC容器](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBootå�¯åЍæµ�程(四):å�¯åЍIOC容器.md)
+* [springboot å�¯åЍæµ�程(五):完æˆ�å�¯åЍ](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBootå�¯åЍæµ�程(五):完æˆ�å�¯åЍ.md)
+* [springboot å�¯åЍæµ�程(å…):å�¯åЍæµ�程总结](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBootå�¯åЍæµ�程(å…):å�¯åЍæµ�程总结.md)
+
+* [springboot 自动装é…�ï¼ˆä¸€ï¼‰ï¼šåŠ è½½è‡ªåŠ¨è£…é…�ç±»](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBoot自动装é…�ï¼ˆä¸€ï¼‰ï¼šåŠ è½½è‡ªåŠ¨è£…é…�ç±».md)
+* [springboot 自动装é…�(二):æ�¡ä»¶æ³¨è§£](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBoot自动装é…�(二):æ�¡ä»¶æ³¨è§£.md)
+* [springboot 自动装é…�(三):自动装é…�顺åº�](docs/Spring全家桶/SpringBootæº�ç �è§£æž�/SpringBoot自动装é…�(三):自动装é…�顺åº�.md)
+
+## SpringCloud
+* [SpringCloud概述](docs/Spring全家桶/SpringCloud/SpringCloud概述.md)
+* [Spring Cloud Config](docs/Spring全家桶/SpringCloud/SpringCloudConfig.md)
+* [Spring Cloud Consul](docs/Spring全家桶/SpringCloud/SpringCloudConsul.md)
+* [Spring Cloud Eureka](docs/Spring全家桶/SpringCloud/SpringCloudEureka.md)
+* [Spring Cloud Gateway](docs/Spring全家桶/SpringCloud/SpringCloudGateway.md)
+* [Spring Cloud Hystrix](docs/Spring全家桶/SpringCloud/SpringCloudHystrix.md)
+* [Spring Cloud LoadBalancer](docs/Spring全家桶/SpringCloud/SpringCloudLoadBalancer.md)
+* [Spring Cloud OpenFeign](docs/Spring全家桶/SpringCloud/SpringCloudOpenFeign.md)
+* [Spring Cloud Ribbon](docs/Spring全家桶/SpringCloud/SpringCloudRibbon.md)
+* [Spring Cloud Sleuth](docs/Spring全家桶/SpringCloud/SpringCloudSleuth.md)
+* [Spring Cloud Zuul](docs/Spring全家桶/SpringCloud/SpringCloudZuul.md)
+
+## SpringCloud æº�ç �分æž�
+* [Spring Cloud Configæº�ç �分æž�](docs/Spring全家桶/SpringCloudæº�ç �分æž�/SpringCloudConfigæº�ç �分æž�.md)
+* [Spring Cloud Eurekaæº�ç �分æž�](docs/Spring全家桶/SpringCloudæº�ç �分æž�/SpringCloudEurekaæº�ç �分æž�.md)
+* [Spring Cloud Gatewayæº�ç �分æž�](docs/Spring全家桶/SpringCloudæº�ç �分æž�/SpringCloudGatewayæº�ç �分æž�.md)
+* [Spring Cloud Hystrixæº�ç �分æž�](docs/Spring全家桶/SpringCloudæº�ç �分æž�/SpringCloudHystrixæº�ç �分æž�.md)
+* [Spring Cloud LoadBalanceræº�ç �分æž�](docs/Spring全家桶/SpringCloudæº�ç �分æž�/SpringCloudLoadBalanceræº�ç �分æž�.md)
+* [Spring Cloud OpenFeignæº�ç �分æž�](docs/Spring全家桶/SpringCloudæº�ç �分æž�/SpringCloudOpenFeignæº�ç �分æž�.md)
+* [Spring Cloud Ribbonæº�ç �分æž�](docs/Spring全家桶/SpringCloudæº�ç �分æž�/SpringCloudRibbonæº�ç �分æž�.md)
+
+## SpringCloud Alibaba
+* [SpringCloud Alibaba概览](docs/Spring全家桶/SpringCloudAlibaba/SpringCloudAlibaba概览.md)
+* [SpringCloud Alibaba nacos](docs/Spring全家桶/SpringCloudAlibaba/SpringCloudAlibabaNacos.md)
+* [SpringCloud Alibaba RocketMQ](docs/Spring全家桶/SpringCloudAlibaba/SpringCloudAlibabaRocketMQ.md)
+* [SpringCloud Alibaba sentinel](docs/Spring全家桶/SpringCloudAlibaba/SpringCloudAlibabaSentinel.md)
+* [SpringCloud Alibaba skywalking](docs/Spring全家桶/SpringCloudAlibaba/SpringCloudAlibabaSkywalking.md)
+* [SpringCloud Alibaba seata](docs/Spring全家桶/SpringCloudAlibaba/SpringCloudAlibabaSeata.md)
+
+## SpringCloud Alibabaæº�ç �分æž�
+* [Spring Cloud Seataæº�ç �分æž�](docs/Spring全家桶/SpringCloudAlibabaæº�ç �分æž�/SpringCloudSeataæº�ç �分æž�.md)
+* [Spring Cloud Sentinelæº�ç �分æž�](docs/Spring全家桶/SpringCloudAlibabaæº�ç �分æž�/SpringCloudSentinelæº�ç �分æž�.md)
+* [SpringCloudAlibaba nacosæº�ç �分æž�:概览](docs/Spring全家桶/SpringCloudAlibabaæº�ç �分æž�/SpringCloudAlibabaNacosæº�ç �分æž�:概览.md)
+* [SpringCloudAlibaba nacosæº�ç �分æž�:æœ�务å�‘现](docs/Spring全家桶/SpringCloudAlibabaæº�ç �分æž�/SpringCloudAlibabaNacosæº�ç �分æž�:æœ�务å�‘现.md)
+* [SpringCloudAlibaba nacosæº�ç �分æž�:æœ�务注册](docs/Spring全家桶/SpringCloudAlibabaæº�ç �分æž�/SpringCloudAlibabaNacosæº�ç �分æž�:æœ�务注册.md)
+* [SpringCloudAlibaba nacosæº�ç �分æž�:é…�ç½®ä¸å¿ƒ](docs/Spring全家桶/SpringCloudAlibabaæº�ç �分æž�/SpringCloudAlibabaNacosæº�ç �分æž�:é…�ç½®ä¸å¿ƒ.md)
+* [Spring Cloud RocketMQæº�ç �分æž�](docs/Spring全家桶/SpringCloudAlibabaæº�ç �分æž�/SpringCloudRocketMQæº�ç �分æž�.md)
+
+# 设计模�
+
+* [设计模å¼�å¦ä¹ 总结](docs/Java/design-parttern/设计模å¼�å¦ä¹ 总结.md)
+* [åˆ�探Java设计模å¼�:创建型模å¼�(工厂,å�•例ç‰ï¼‰.md](docs/Java/design-parttern/åˆ�探Java设计模å¼�:创建型模å¼�(工厂,å�•例ç‰ï¼‰.md)
+* [åˆ�探Java设计模å¼�:结构型模å¼�(代ç�†æ¨¡å¼�,适é…�器模å¼�ç‰ï¼‰.md](docs/Java/design-parttern/åˆ�探Java设计模å¼�:结构型模å¼�(代ç�†æ¨¡å¼�,适é…�器模å¼�ç‰ï¼‰.md)
+* [åˆ�探Java设计模å¼�:行为型模å¼�(ç–略,观察者ç‰ï¼‰.md](docs/Java/design-parttern/åˆ�探Java设计模å¼�:行为型模å¼�(ç–略,观察者ç‰ï¼‰.md)
+* [åˆ�探Java设计模å¼�:JDKä¸çš„设计模å¼�.md](docs/Java/design-parttern/åˆ�探Java设计模å¼�:JDKä¸çš„设计模å¼�.md)
+* [�探Java设计模�:Spring涉�到的�设计模�.md](docs/Java/design-parttern/�探Java设计模�:Spring涉�到的�设计模�.md)
+
+
+# 计算机基础
+
+## 计算机网络
todo
-### �作系统
+## �作系统
todo
-#### Linux相关
+## Linux相关
todo
-### 数�结构与算法
+## 数�结构与算法
todo
-#### 数�结构
+## 数�结构
todo
-#### 算法
+## 算法
todo
-## 数�库
+# 数�库
todo
-### MySQL
+## 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æ•°æ�®åº“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)
-* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“6:浅谈MySQLçš„ä¸äº‹åŠ¡ä¸Žé”�](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“6:浅谈MySQLçš„ä¸äº‹åŠ¡ä¸Žé”�.md)
-* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“7:详解MyIsam与InnoDB引擎的é”�实现](docs/database/é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“7:详解MyIsam与InnoDB引擎的é”�实现.md)
-* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“8:MySQL的事务隔离级别实战](docs/database/é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“8:MySQL的事务隔离级别实战.md)
-* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“9:Innodbä¸çš„事务隔离级别和é”�的关系](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“9:Innodbä¸çš„事务隔离级别和é”�的关系.md)
-* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“10:MySQL里的那些日志们](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“10:MySQL里的那些日志们.md)
-* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“11:以Java的视角æ�¥è�Šè�ŠSQL注入](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“11:以Java的视角æ�¥è�Šè�ŠSQL注入.md)
-* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“12:从实践sqlè¯å�¥ä¼˜åŒ–开始](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“12:从实践sqlè¯å�¥ä¼˜åŒ–开始.md)
-* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“13:Mysql主从å¤�制,读写分离,分表分库ç–略与实践](docs/database/é‡�æ–°å¦ä¹ Mysqlæ•°æ�®13:Mysql主从å¤�制,读写分离,分表分库ç–略与实践.md)
-
-
-## 缓å˜
-
-### Redis
+* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“ï¼šæ— åºŸè¯�MySQL入门](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“ï¼šæ— åºŸè¯�MySQL入门.md)
+* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“:『浅入浅出ã€�MySQLå’ŒInnoDB](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:『浅入浅出ã€�MySQLå’ŒInnoDB.md)
+* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“:Mysqlå˜å‚¨å¼•擎与数æ�®å˜å‚¨åŽŸç�†](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:Mysqlå˜å‚¨å¼•擎与数æ�®å˜å‚¨åŽŸç�†.md)
+* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“:Mysql索引实现原ç�†å’Œç›¸å…³æ•°æ�®ç»“构算法](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:Mysql索引实现原ç�†å’Œç›¸å…³æ•°æ�®ç»“构算法.md)
+* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“ï¼šæ ¹æ�®MySQL索引原ç�†è¿›è¡Œåˆ†æž�与优化](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“ï¼šæ ¹æ�®MySQL索引原ç�†è¿›è¡Œåˆ†æž�与优化.md)
+* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:浅谈MySQLçš„ä¸äº‹åŠ¡ä¸Žé”�](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:浅谈MySQLçš„ä¸äº‹åŠ¡ä¸Žé”�.md)
+* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“:详解MyIsam与InnoDB引擎的é”�实现](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:详解MyIsam与InnoDB引擎的é”�实现.md)
+* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“:MySQL的事务隔离级别实战](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:MySQL的事务隔离级别实战.md)
+* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:Innodbä¸çš„事务隔离级别和é”�的关系](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:Innodbä¸çš„事务隔离级别和é”�的关系.md)
+* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:MySQL里的那些日志们](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:MySQL里的那些日志们.md)
+* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:以Java的视角æ�¥è�Šè�ŠSQL注入](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:以Java的视角æ�¥è�Šè�ŠSQL注入.md)
+* [é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:从实践sqlè¯å�¥ä¼˜åŒ–开始](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:从实践sqlè¯å�¥ä¼˜åŒ–开始.md)
+* [é‡�æ–°å¦ä¹ Mysqlæ•°æ�®åº“:Mysql主从å¤�制,读写分离,分表分库ç–略与实践](docs/database/é‡�æ–°å¦ä¹ MySQLæ•°æ�®åº“:Mysql主从å¤�制,读写分离,分表分库ç–略与实践.md)
+
+
+# 缓å˜
+
+## Redis
* [Redis原�与实践总结](docs/cache/Redis原�与实践总结.md)
* [探索Redis设计与实现开篇:什么是Redis](docs/cache/探索Redis设计与实现开篇:什么是Redis.md)
-* [探索Redis设计与实现1:Redis 的基础数�结构概览](docs/cache/探索Redis设计与实现1:Redis%20的基础数�结构概览.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)
-* [探索Redis设计与实现5:Redis内部数�结构详解——quicklist](docs/cache/探索Redis设计与实现5:Redis内部数�结构详解——quicklist.md)
-* [探索Redis设计与实现6:Redis内部数�结构详解——skiplist](docs/cache/探索Redis设计与实现6:Redis内部数�结构详解——skiplist.md)
-* [探索Redis设计与实现7:Redis内部数�结构详解——intset](docs/cache/探索Redis设计与实现7:Redis内部数�结构详解——intset.md)
-* [探索Redis设计与实现8:连接底层与表�的数�结构robj](docs/cache/探索Redis设计与实现8:连接底层与表�的数�结构robj.md)
-* [探索Redis设计与实现9:数æ�®åº“redisDbä¸Žé”®è¿‡æœŸåˆ é™¤ç–ç•¥](docs/cache/探索Redis设计与实现9:数æ�®åº“redisDbä¸Žé”®è¿‡æœŸåˆ é™¤ç–ç•¥.md)
-* [探索Redis设计与实现10:Redis的事件驱动模型与命令执行过程](docs/cache/探索Redis设计与实现10:Redis的事件驱动模型与命令执行过程.md)
-* [探索Redis设计与实现11:使用快照和AOFå°†Redisæ•°æ�®æŒ�久化到硬盘ä¸](docs/cache/探索Redis设计与实现11:使用快照和AOFå°†Redisæ•°æ�®æŒ�久化到硬盘ä¸.md)
-* [探索Redis设计与实现12:浅�Redis主从�制](docs/cache/探索Redis设计与实现12:浅�Redis主从�制.md)
-* [探索Redis设计与实现13:Redis集群机制�一个Redis架构演进实例](docs/cache/探索Redis设计与实现13:Redis集群机制�一个Redis架构演进实例.md)
-* [探索Redis设计与实现14:Redis事务浅�与ACID特性介�](docs/cache/探索Redis设计与实现14:Redis事务浅�与ACID特性介�.md)
-* [探索Redis设计与实现15:Redis分布��进化� ](docs/cache/探索Redis设计与实现15:Redis分布��进化�.md )
-
-## 消�队列
-
-### Kafka
-
-## 大�端
-* [�端技术�谈开篇:云计算,大数�与AI的故事](docs/big-backEnd/�端技术�谈开篇:云计算,大数�与AI的故事.md)
-* [�端技术�谈1:�索引擎基础倒排索引](docs/big-backEnd/�端技术�谈1:�索引擎基础倒排索引.md)
-* [�端技术�谈2:�索引擎工作原�](docs/big-backEnd/�端技术�谈2:�索引擎工作原�.md)
-* [�端技术�谈3:Lucene基础原�与实践](docs/big-backEnd/�端技术�谈3:Lucene基础原�与实践.md)
-* [�端技术�谈4:Elasticsearch与solr入门实践](docs/big-backEnd/�端技术�谈4:Elasticsearch与solr入门实践.md)
-* [�端技术�谈5:云计算的�世今生](docs/big-backEnd/�端技术�谈5:云计算的�世今生.md)
-* [�端技术�谈6:白�虚拟化技术](docs/big-backEnd/�端技术�谈6:白�虚拟化技术.md )
-* [�端技术�谈7:OpenStack的基石KVM](docs/big-backEnd/�端技术�谈7:OpenStack的基石KVM.md)
-* [�端技术�谈8:OpenStack架构设计](docs/big-backEnd/�端技术�谈8:OpenStack架构设计.md)
-* [å�Žç«¯æŠ€æœ¯æ�‚è°ˆ9:先æ�žæ‡‚Dockeræ ¸å¿ƒæ¦‚å¿µå�§](docs/big-backEnd/å�Žç«¯æŠ€æœ¯æ�‚è°ˆ9:先æ�žæ‡‚Dockeræ ¸å¿ƒæ¦‚å¿µå�§.md)
-* [å�Žç«¯æŠ€æœ¯æ�‚è°ˆ10:Docker æ ¸å¿ƒæŠ€æœ¯ä¸Žå®žçŽ°åŽŸç�†](docs/big-backEnd/å�Žç«¯æŠ€æœ¯æ�‚è°ˆ10:Docker%20æ ¸å¿ƒæŠ€æœ¯ä¸Žå®žçŽ°åŽŸç�†.md)
-* [å�Žç«¯æŠ€æœ¯æ�‚è°ˆ11:å��分钟ç�†è§£Kubernetesæ ¸å¿ƒæ¦‚å¿µ](docs/big-backEnd/å�Žç«¯æŠ€æœ¯æ�‚è°ˆ11:å��分钟ç�†è§£Kubernetesæ ¸å¿ƒæ¦‚å¿µ.md)
-* [å�Žç«¯æŠ€æœ¯æ�‚è°ˆ12:æ�‹ä¸€æ�‹å¤§æ•°æ�®ç ”å�‘的基本概念](docs/big-backEnd/å�Žç«¯æŠ€æœ¯æ�‚è°ˆ12:æ�‹ä¸€æ�‹å¤§æ•°æ�®ç ”å�‘的基本概念.md)
-
-## 分布�
-### �论
-* [分布�系统�论基础开篇:从放弃到入门](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:分布�系统的一些基本概念 ](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 )
-
-
-## �试指�
+* [探索Redis设计与实现:Redis的基础数�结构概览](docs/cache/探索Redis设计与实现:Redis的基础数�结构概览.md)
+* [探索Redis设计与实现:Redis内部数�结构详解——dict](docs/cache/探索Redis设计与实现:Redis内部数�结构详解——dict.md)
+* [探索Redis设计与实现:Redis内部数�结构详解——sds](docs/cache/探索Redis设计与实现:Redis内部数�结构详解——sds.md)
+* [探索Redis设计与实现:Redis内部数�结构详解——ziplist](docs/cache/探索Redis设计与实现:Redis内部数�结构详解——ziplist.md)
+* [探索Redis设计与实现:Redis内部数�结构详解——quicklist](docs/cache/探索Redis设计与实现:Redis内部数�结构详解——quicklist.md)
+* [探索Redis设计与实现:Redis内部数�结构详解——skiplist](docs/cache/探索Redis设计与实现:Redis内部数�结构详解——skiplist.md)
+* [探索Redis设计与实现:Redis内部数�结构详解——intset](docs/cache/探索Redis设计与实现:Redis内部数�结构详解——intset.md)
+* [探索Redis设计与实现:连接底层与表�的数�结构robj](docs/cache/探索Redis设计与实现:连接底层与表�的数�结构robj.md)
+* [探索Redis设计与实现:数æ�®åº“redisDbä¸Žé”®è¿‡æœŸåˆ é™¤ç–ç•¥](docs/cache/探索Redis设计与实现:数æ�®åº“redisDbä¸Žé”®è¿‡æœŸåˆ é™¤ç–ç•¥.md)
+* [探索Redis设计与实现:Redis的事件驱动模型与命令执行过程](docs/cache/探索Redis设计与实现:Redis的事件驱动模型与命令执行过程.md)
+* [探索Redis设计与实现:使用快照和AOFå°†Redisæ•°æ�®æŒ�久化到硬盘ä¸](docs/cache/探索Redis设计与实现:使用快照和AOFå°†Redisæ•°æ�®æŒ�久化到硬盘ä¸.md)
+* [探索Redis设计与实现:浅�Redis主从�制](docs/cache/探索Redis设计与实现:浅�Redis主从�制.md)
+* [探索Redis设计与实现:Redis集群机制�一个Redis架构演进实例](docs/cache/探索Redis设计与实现:Redis集群机制�一个Redis架构演进实例.md)
+* [探索Redis设计与实现:Redis事务浅�与ACID特性介�](docs/cache/探索Redis设计与实现:Redis事务浅�与ACID特性介�.md)
+* [探索Redis设计与实现:Redis分布��进化� ](docs/cache/探索Redis设计与实现:Redis分布��进化�.md )
+
+# 消�队列
+
+## Kafka
+* [消�队列kafka详解:Kafka快速上手(Java版)](docs/mq/kafka/消�队列kafka详解:Kafka快速上手(Java版).md)
+* [消æ�¯é˜Ÿåˆ—kafka详解:Kafka一æ�¡æ¶ˆæ�¯å˜åˆ°broker的过程](docs/mq/kafka/消æ�¯é˜Ÿåˆ—kafka详解:Kafka一æ�¡æ¶ˆæ�¯å˜åˆ°broker的过程.md)
+* [消�队列kafka详解:消�队列kafka详解:Kafka介�](docs/mq/kafka/消�队列kafka详解:Kafka介�.md)
+* [消�队列kafka详解:Kafka原�分�总结篇](docs/mq/kafka/消�队列kafka详解:Kafka原�分�总结篇.md)
+* [消�队列kafka详解:Kafka常�命令��置总结](docs/mq/kafka/消�队列kafka详解:Kafka常�命令��置总结.md)
+* [消�队列kafka详解:Kafka架构介�](docs/mq/kafka/消�队列kafka详解:Kafka架构介�.md)
+* [消�队列kafka详解:Kafka的集群工作原�](docs/mq/kafka/消�队列kafka详解:Kafka的集群工作原�.md)
+* [消�队列kafka详解:Kafka��知识点+�试题大全](docs/mq/kafka/消�队列kafka详解:Kafka��知识点+�试题大全.md)
+* [消�队列kafka详解:如何实现延迟队列](docs/mq/kafka/消�队列kafka详解:如何实现延迟队列.md)
+* [消æ�¯é˜Ÿåˆ—kafka详解:如何实现æ»ä¿¡é˜Ÿåˆ—](docs/mq/kafka/消æ�¯é˜Ÿåˆ—kafka详解:如何实现æ»ä¿¡é˜Ÿåˆ—.md)
+
+## RocketMQ
+* [RocketMQ系列:事务消�(最终一致性)](docs/mq/RocketMQ/RocketMQ系列:事务消�(最终一致性).md)
+* [RocketMQ系列:基本概念](docs/mq/RocketMQ/RocketMQ系列:基本概念.md)
+* [RocketMQ系列:广æ’与延迟消æ�¯](docs/mq/RocketMQ/RocketMQ系列:广æ’与延迟消æ�¯.md)
+* [RocketMQ系列:批���与过滤](docs/mq/RocketMQ/RocketMQ系列:批���与过滤.md)
+* [RocketMQ系列:消�的生产与消费](docs/mq/RocketMQ/RocketMQ系列:消�的生产与消费.md)
+* [RocketMQ系列:环境æ�建](docs/mq/RocketMQ/RocketMQ系列:环境æ�建.md)
+* [RocketMQ系列:顺�消费](docs/mq/RocketMQ/RocketMQ系列:顺�消费.md)
+
+# 大�端
+* [�端技术�谈开篇:云计算,大数�与AI的故事](docs/backend/�端技术�谈开篇:云计算,大数�与AI的故事.md)
+* [�端技术�谈:�索引擎基础倒排索引](docs/backend/�端技术�谈:�索引擎基础倒排索引.md)
+* [�端技术�谈:�索引擎工作原�](docs/backend/�端技术�谈:�索引擎工作原�.md)
+* [�端技术�谈:Lucene基础原�与实践](docs/backend/�端技术�谈:Lucene基础原�与实践.md)
+* [�端技术�谈:Elasticsearch与solr入门实践](docs/backend/�端技术�谈:Elasticsearch与solr入门实践.md)
+* [�端技术�谈:云计算的�世今生](docs/backend/�端技术�谈:云计算的�世今生.md)
+* [�端技术�谈:白�虚拟化技术](docs/backend/�端技术�谈:白�虚拟化技术.md )
+* [�端技术�谈:OpenStack的基石KVM](docs/backend/�端技术�谈:OpenStack的基石KVM.md)
+* [�端技术�谈:OpenStack架构设计](docs/backend/�端技术�谈:OpenStack架构设计.md)
+* [å�Žç«¯æŠ€æœ¯æ�‚谈:先æ�žæ‡‚Dockeræ ¸å¿ƒæ¦‚å¿µå�§](docs/backend/å�Žç«¯æŠ€æœ¯æ�‚谈:先æ�žæ‡‚Dockeræ ¸å¿ƒæ¦‚å¿µå�§.md)
+* [å�Žç«¯æŠ€æœ¯æ�‚谈:Docker æ ¸å¿ƒæŠ€æœ¯ä¸Žå®žçŽ°åŽŸç�†](docs/backend/å�Žç«¯æŠ€æœ¯æ�‚谈:Docker%æ ¸å¿ƒæŠ€æœ¯ä¸Žå®žçŽ°åŽŸç�†.md)
+* [å�Žç«¯æŠ€æœ¯æ�‚谈:å��分钟ç�†è§£Kubernetesæ ¸å¿ƒæ¦‚å¿µ](docs/backend/å�Žç«¯æŠ€æœ¯æ�‚谈:å��分钟ç�†è§£Kubernetesæ ¸å¿ƒæ¦‚å¿µ.md)
+* [å�Žç«¯æŠ€æœ¯æ�‚谈:æ�‹ä¸€æ�‹å¤§æ•°æ�®ç ”å�‘的基本概念](docs/backend/å�Žç«¯æŠ€æœ¯æ�‚谈:æ�‹ä¸€æ�‹å¤§æ•°æ�®ç ”å�‘的基本概念.md)
+
+# 分布�
+## 分布��论
+* [分布�系统�论基础:一致性PC和PC ](docs/distributed/basic/分布�系统�论基础:一致性PC和PC.md)
+* [分布�系统�论基础:CAP ](docs/distributed/basic/分布�系统�论基础:CAP.md)
+* [分布�系统�论基础:时间时钟和事件顺�](docs/distributed/basic/分布�系统�论基础:时间时钟和事件顺�.md)
+* [分布�系统�论基础:Paxos](docs/distributed/basic/分布�系统�论基础:Paxos.md)
+* [分布�系统�论基础:选举多数派和租约](docs/distributed/basic/分布�系统�论基础:选举多数派和租约.md)
+* [分布�系统�论基础:RaftZab ](docs/distributed/basic/分布�系统�论基础:RaftZab.md)
+* [分布�系统�论进阶:Paxos��和优化 ](docs/distributed/basic/分布�系统�论进阶:Paxos��和优化.md)
+* [分布�系统�论基础:zookeeper分布��调�务 ](docs/distributed/basic/分布�系统�论基础:zookeeper分布��调�务.md)
+* [分布��论总结](docs/distributed/分布�技术实践总结.md)
+
+## 分布�技术
+* [�懂分布�技术:分布�系统的一些基本概念](docs/distributed/practice/�懂分布�技术:分布�系统的一些基本概念.md )
+* [�懂分布�技术:分布�一致性�议与Paxos,Raft算法](docs/distributed/practice/�懂分布�技术:分布�一致性�议与Paxos,Raft算法.md)
+* [�懂分布�技术:�探分布��调�务zookeeper](docs/distributed/practice/�懂分布�技术:�探分布��调�务zookeeper.md )
+* [�懂分布�技术:ZAB�议概述与选主�程详解](docs/distributed/practice/�懂分布�技术:ZAB�议概述与选主�程详解.md )
+* [�懂分布�技术:Zookeeper的�置与集群管�实战](docs/distributed/practice/�懂分布�技术:Zookeeper的�置与集群管�实战.md)
+* [�懂分布�技术:Zookeeper典型应用场景�实践](docs/distributed/practice/�懂分布�技术:Zookeeper典型应用场景�实践.md )
+* [�懂分布�技术:LVS实现负载�衡的原�与实践 ](docs/distributed/practice/�懂分布�技术:LVS实现负载�衡的原�与实践.md )
+* [�懂分布�技术:分布�session解决方案与一致性hash](docs/distributed/practice/�懂分布�技术:分布�session解决方案与一致性hash.md)
+* [�懂分布�技术:分布�ID生�方案 ](docs/distributed/practice/�懂分布�技术:分布�ID生�方案.md )
+* [æ�žæ‡‚分布å¼�技术:缓å˜çš„那些事](docs/distributed/practice/æ�žæ‡‚分布å¼�技术:缓å˜çš„那些事.md)
+* [æ�žæ‡‚分布å¼�技术:SpringBoot使用注解集æˆ�Redis缓å˜](docs/distributed/practice/æ�žæ‡‚分布å¼�技术:SpringBoot使用注解集æˆ�Redis缓å˜.md)
+* [æ�žæ‡‚分布å¼�æŠ€æœ¯ï¼šç¼“å˜æ›´æ–°çš„套路 ](docs/distributed/practice/æ�žæ‡‚分布å¼�æŠ€æœ¯ï¼šç¼“å˜æ›´æ–°çš„套路.md )
+* [æ�žæ‡‚分布å¼�技术:浅谈分布å¼�é”�çš„å‡ ç§�方案 ](docs/distributed/practice/æ�žæ‡‚分布å¼�技术:浅谈分布å¼�é”�çš„å‡ ç§�方案.md )
+* [�懂分布�技术:浅�分布�事务](docs/distributed/practice/�懂分布�技术:浅�分布�事务.md )
+* [�懂分布�技术:分布�事务常用解决方案 ](docs/distributed/practice/�懂分布�技术:分布�事务常用解决方案.md )
+* [�懂分布�技术:使用RocketMQ事务消�解决分布�事务 ](docs/distributed/practice/�懂分布�技术:使用RocketMQ事务消�解决分布�事务.md )
+* [æ�žæ‡‚分布å¼�技术:消æ�¯é˜Ÿåˆ—å› ä½•è€Œç”Ÿ](docs/distributed/practice/æ�žæ‡‚分布å¼�技术:消æ�¯é˜Ÿåˆ—å› ä½•è€Œç”Ÿ.md)
+* [�懂分布�技术:浅谈分布�消�技术Kafka](docs/distributed/practice/�懂分布�技术:浅谈分布�消�技术Kafka.md )
+* [分布�技术实践总结](docs/distributed/分布��论总结.md)
+
+# �试指�
todo
-### æ ¡æ‹›æŒ‡å�—
+## æ ¡æ‹›æŒ‡å�—
todo
-### ��
+## ��
todo
-## 工具
+# 工具
todo
-## 资料
+# 资料
todo
-### 书�
+## 书�
todo
-## 待办
+# 待办
springbootå’Œspringcloud
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师技术å¦ä¹ 资料:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-**Java进阶架构师资料:** 关注公众å�·å�Žå›žå¤� **â€�架构师“** å�³å�¯é¢†å�– Java基础ã€�进阶ã€�项目和架构师ç‰å…�è´¹å¦ä¹ 资料,更有数æ�®åº“ã€�分布å¼�ã€�å¾®æœ�务ç‰çƒé—¨æŠ€æœ¯å¦ä¹ 视频,内容丰富,兼顾原ç�†å’Œå®žè·µï¼Œå�¦å¤–ä¹Ÿå°†èµ é€�作者原创的Javaå¦ä¹ 指å�—ã€�Java程åº�员é�¢è¯•指å�—ç‰å¹²è´§èµ„æº�
-
-
-
-### 个人公众�:程�员黄�斜
-​
-黄å°�斜是 985 硕士,阿里巴巴Java工程师,在自å¦ç¼–程ã€�技术求è�Œã€�Javaå¦ä¹ ç‰æ–¹é�¢æœ‰ä¸°å¯Œç»�验和独到è§�解,希望帮助到更多想è¦�从事互è�”网行业的程åº�员们。
-​
-作者专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼Œçƒè¡·äºŽåˆ†äº«ç¨‹åº�员干货ã€�å¦ä¹ ç»�验ã€�求è�Œå¿ƒå¾—,以å�Šè‡ªå¦ç¼–程和JavaæŠ€æœ¯æ ˆçš„ç›¸å…³å¹²è´§ã€‚
-​
-黄å°�斜是一个斜æ� é�’年,å�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�,希望和更多的程åº�员交朋å�‹ï¼Œä¸€èµ·è¿›æ¥å’Œæˆ�é•¿ï¼�
-
-**原创电å�书:** 关注微信公众å�·ã€�程åº�员黄å°�斜】å�Žå›žå¤� **"原创电å�书"** å�³å�¯é¢†å�–我原创的电å�书《è�œé¸Ÿç¨‹åº�员修炼手册:从技术å°�白到阿里巴巴Java工程师》这份电å�书总结了我2å¹´çš„Javaå¦ä¹ 之路,包括å¦ä¹ 方法ã€�技术总结ã€�求è�Œç»�验和é�¢è¯•技巧ç‰å†…容,已ç»�帮助很多的程åº�员拿到了心仪的offerï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·ã€�程åº�员黄å°�斜】å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–,包括Javaã€�pythonã€�C++ã€�大数æ�®ã€�机器å¦ä¹ ã€�å‰�端ã€�ç§»åŠ¨ç«¯ç‰æ–¹å�‘的技术资料。
+# 微信公众�
-
+## Java技术江湖
+如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】
+
diff --git a/_config.yml b/_config.yml
deleted file mode 100644
index 34ac42a..0000000
--- a/_config.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-theme: jekyll-theme-cayman
-
diff --git a/backup.md b/backup.md
deleted file mode 100644
index f2fb131..0000000
--- a/backup.md
+++ /dev/null
@@ -1,81 +0,0 @@
-## 声明
-
-**关于仓库**
-
-本仓库是笔者在准备 2018 å¹´ç§‹æ‹›å¤�ä¹ è¿‡ç¨‹ä¸çš„å¦ä¹ 总结,内容以Javaå�Žç«¯çš„知识总结为主,其ä¸å¤§éƒ¨åˆ†éƒ½æ˜¯ç¬”è€…æ ¹æ�®è‡ªå·±çš„ç�†è§£åŠ ä¸Šä¸ªäººå�šå®¢æ€»ç»“而æ�¥çš„。
-
-其䏿œ‰å°‘数内容å�¯èƒ½ä¼šåŒ…å�«çžŽXX说,è¯å�¥ä¸�通顺,内容ä¸�å…¨é�¢ç‰å�„æ–¹é�¢é—®é¢˜ï¼Œè¿˜è¯·è§�谅。
-
-æ¯�ç¯‡æ–‡ç« éƒ½ä¼šæœ‰ç¬”è€…æ›´åŠ è¯¦ç»†çš„ä¸€ç³»åˆ—å�šå®¢å�¯ä¾›å�‚è€ƒï¼Œè¿™äº›æ–‡ç« ä¹Ÿè¢«æˆ‘å�‘表在CSDN技术å�šå®¢ä¸Šï¼Œæ•´ç�†æˆ�å�šå®¢ä¸“æ �,欢迎查看â”�(*`∀´*)ノ亻!
-
-详细内容请�我的CSDN技术�客:https://blog.csdn.net/a724888
-
-**æ›´å¤šæ ¡æ‹›å¹²è´§å’ŒæŠ€æœ¯æ–‡ç« è¯·å…³æ³¨æˆ‘çš„å…¬ä¼—å�·ï¼šé»„å°�æ–œ**
-
-| â… | â…¡ | â…¢ | â…£ | â…¤ | â…¥ | â…¦ | â…§ | â…¨ |
-| :----------------------------: | :--------------------------------------: | :------------------------: | :----------------------------------------: | :--------------------------: | :---------------------------------: | :-----------------------------------------: | :----------------------------------: | :--------------------------------------------: |
-| 算法[:pencil2:](#算法-pencil2) | �作系统[:computer:](#�作系统-computer) | 网络[:cloud:](#网络-cloud) | 数�库[:floppy_disk:](#数�库-floppy_disk) | Java[:couple:](#Java-couple) | JavaWeb [:coffee:](#JavaWeb-coffee) | 分布� [:sweat_drops:](#分布�-sweat_drops) | 设计模�[:hammer:](#设计模�-hammer) | Hadoop[:speak_no_evil:](#Hadoop-speak_no_evil) |
-
-## 算法 :pencil2:
-
-> [剑指offer算法总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/%E5%89%91%E6%8C%87offer.md)
-
-> [LeetCode刷题指�](https://github.com/h2pl/Java-Tutorial/blob/master/md/LeetCode%E5%88%B7%E9%A2%98%E6%8C%87%E5%8D%97.md)
-
-## �作系统 :computer:
-
-> [æ“�作系统å¦ä¹ 总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%AD%A6%E4%B9%A0%E6%80%BB%E7%BB%93.md)
-
-> [Linuxå†…æ ¸ä¸ŽåŸºç¡€å‘½ä»¤å¦ä¹ 总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/Linux%E5%86%85%E6%A0%B8%E4%B8%8E%E5%9F%BA%E7%A1%80%E5%91%BD%E4%BB%A4%E5%AD%A6%E4%B9%A0%E6%80%BB%E7%BB%93.md)
-
-## 网络 :cloud:
-
-> [计算机网络å¦ä¹ 总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E5%AD%A6%E4%B9%A0%E6%80%BB%E7%BB%93.md)
-
-## 数�库 :floppy_disk:
-
-> [Mysql原�与实践总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/Mysql%E5%8E%9F%E7%90%86%E4%B8%8E%E5%AE%9E%E8%B7%B5%E6%80%BB%E7%BB%93.md)
-
-> [Redis原�与实践总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/Redis%E5%8E%9F%E7%90%86%E4%B8%8E%E5%AE%9E%E8%B7%B5%E6%80%BB%E7%BB%93.md)
-
-## Java :couple:
-
-> [Javaæ ¸å¿ƒæŠ€æœ¯æ€»ç»“](https://github.com/h2pl/Java-Tutorial/blob/master/md/Java%E6%A0%B8%E5%BF%83%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93.md)
-
-> [Java集�类总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/Java%E9%9B%86%E5%90%88%E7%B1%BB%E6%80%BB%E7%BB%93.md)
-
-> [Java并�技术总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/Java%E5%B9%B6%E5%8F%91%E6%80%BB%E7%BB%93.md)
-
-> [JVM原ç�†å¦ä¹ 总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/JVM%E6%80%BB%E7%BB%93.md)
-
-> [Java网络与NIO总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/Java%E7%BD%91%E7%BB%9C%E4%B8%8ENIO%E6%80%BB%E7%BB%93.md)
-
-## JavaWeb :coffee:
-
-> [JavaWeb技术å¦ä¹ 总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/JavaWeb%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93.md)
-
-> [Spring与SpringMVCæº�ç �è§£æž�](https://github.com/h2pl/Java-Tutorial/blob/master/md/Spring%E4%B8%8ESpringMVC%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%E6%80%BB%E7%BB%93.md)
-
-## 分布� :sweat_drops:
-
-> [分布å¼�ç�†è®ºå¦ä¹ 总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/%E5%88%86%E5%B8%83%E5%BC%8F%E7%90%86%E8%AE%BA%E6%80%BB%E7%BB%93.md)
-
-> [分布å¼�技术å¦ä¹ 总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/%E5%88%86%E5%B8%83%E5%BC%8F%E6%8A%80%E6%9C%AF%E5%AE%9E%E8%B7%B5%E6%80%BB%E7%BB%93.md)
-
-## 设计模� :hammer:
-> [设计模å¼�å¦ä¹ 总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E5%AD%A6%E4%B9%A0%E6%80%BB%E7%BB%93.md)
-
-## Hadoop :speak_no_evil:
-
-> [Hadoop生æ€�å¦ä¹ 总结](https://github.com/h2pl/Java-Tutorial/blob/master/md/Hadoop%E7%94%9F%E6%80%81%E6%80%BB%E7%BB%93.md)
-
-
-
-**关于转载**
-
-转载的时候请注明一下出处就行啦。
-
-å�¦å¤–æˆ‘è¿™ä¸ªä»“åº“çš„æ ¼å¼�模仿的是@CyC2018 大佬的仓库
-
-并且其ä¸ä¸€ç¯‡LeetCode刷题指å�—也是forkè¿™ä½�大佬而æ�¥çš„。我å�ªæ˜¯è‡ªå·±åˆ·äº†ä¸€é��ç„¶å�Žç¨�å¾®åŠ äº†ä¸€äº›è§£æž�,站在大佬肩膀上。
-
diff --git "a/docs/java/jvm/JVM\346\200\273\347\273\223.md" "b/docs/Java/JVM/JVM\346\200\273\347\273\223.md"
similarity index 86%
rename from "docs/java/jvm/JVM\346\200\273\347\273\223.md"
rename to "docs/Java/JVM/JVM\346\200\273\347\273\223.md"
index 2762768..60b89e6 100644
--- "a/docs/java/jvm/JVM\346\200\273\347\273\223.md"
+++ "b/docs/Java/JVM/JVM\346\200\273\347\273\223.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [JVM介ç»�å’Œæº�ç �](#jvm介ç»�å’Œæº�ç �)
* [JVMå†…å˜æ¨¡åž‹](#jvmå†…å˜æ¨¡åž‹)
@@ -11,9 +11,7 @@
* [编译期优化和�行期优化](#编译期优化和�行期优化)
* [JVM的垃圾回收](#jvm的垃圾回收)
* [JVM的�优化](#jvm的�优化)
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
---
@@ -153,20 +151,4 @@ g1收集器和cms的收集方å¼�类似,但是g1å°†å †å†…å˜åˆ’分æˆ�了大å°�
在Javaå¹¶å�‘ä¸è®²è¿°äº†synchronizedé‡�é‡�级é”�以å�Šé”�优化的方法,包括轻é‡�级é”�,å��å�‘é”�,自旋é”�ç‰ã€‚详细内容å�¯ä»¥å�‚考我的专æ �:Javaå¹¶å�‘技术指å�—
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
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\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.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\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
new file mode 100644
index 0000000..ceda305
--- /dev/null
+++ "b/docs/Java/JVM/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232GC\350\260\203\344\274\230\346\200\235\350\267\257\344\270\216\345\270\270\347\224\250\345\267\245\345\205\267.md"
@@ -0,0 +1,838 @@
+# 目录
+
+* [æ ¸å¿ƒæ¦‚å¿µ(Core Concepts)](#æ ¸å¿ƒæ¦‚å¿µcore-concepts)
+ * [Latency(延迟)](#latency延迟)
+ * [Throughput(���)](#throughput���)
+ * [Capacity(系统容�)](#capacity系统容�)
+* [相关示例](#相关示例)
+ * [Tuning for Latency(è°ƒä¼˜å»¶è¿ŸæŒ‡æ ‡)](#tuning-for-latencyè°ƒä¼˜å»¶è¿ŸæŒ‡æ ‡)
+ * [Tuning for Throughput(���调优)](#tuning-for-throughput���调优)
+ * [Tuning for Capacity(调优系统容�)](#tuning-for-capacity调优系统容�)
+ * [6\. GC 调优(工具篇) - GC�考手册](#6-gc-调优工具篇---gc�考手册)
+ * [JMX API](#jmx-api)
+ * [JVisualVM](#jvisualvm)
+ * [jstat](#jstat)
+ * [GC日志(GC logs)](#gc日志gc-logs)
+ * [GCViewer](#gcviewer)
+ * [分�器(Profilers)](#分�器profilers)
+ * [hprof](#hprof)
+ * [Java VisualVM](#java-visualvm)
+ * [AProf](#aprof)
+ * [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
+
+
+
+æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
+> https://github.com/h2pl/Java-Tutorial
+
+喜欢的�麻烦点下Star哈
+
+æ–‡ç« é¦–å�‘于我的个人å�šå®¢ï¼š
+> www.how2playlife.com
+
+本文是微信公众å�·ã€�Java技术江湖】的《深入ç�†è§£JVM虚拟机》其ä¸ä¸€ç¯‡ï¼Œæœ¬æ–‡éƒ¨åˆ†å†…容æ�¥æº�于网络,为了把本文主题讲得清晰é€�彻,也整å�ˆäº†å¾ˆå¤šæˆ‘认为ä¸�错的技术å�šå®¢å†…容,引用其ä¸äº†ä¸€äº›æ¯”较好的å�šå®¢æ–‡ç« ,如有侵æ�ƒï¼Œè¯·è�”系作者。
+该系列å�šæ–‡ä¼šå‘Šè¯‰ä½ å¦‚ä½•ä»Žå…¥é—¨åˆ°è¿›é˜¶ï¼Œä¸€æ¥æ¥åœ°å¦ä¹ JVM基础知识,并上手进行JVM调优实战,JVM是æ¯�一个Java工程师必须è¦�å¦ä¹ å’Œç�†è§£çš„çŸ¥è¯†ç‚¹ï¼Œä½ å¿…é¡»è¦�掌æ�¡å…¶å®žçŽ°åŽŸç�†ï¼Œæ‰�能更完整地了解整个Java技术体系,形æˆ�è‡ªå·±çš„çŸ¥è¯†æ¡†æž¶ã€‚ä¸ºäº†æ›´å¥½åœ°æ€»ç»“å’Œæ£€éªŒä½ çš„å¦ä¹ æˆ�æžœï¼Œæœ¬ç³»åˆ—æ–‡ç« ä¹Ÿä¼šæ��ä¾›æ¯�个知识点对应的é�¢è¯•题以å�Šå�‚è€ƒç”æ¡ˆã€‚
+
+å¦‚æžœå¯¹æœ¬ç³»åˆ—æ–‡ç« æœ‰ä»€ä¹ˆå»ºè®®ï¼Œæˆ–è€…æ˜¯æœ‰ä»€ä¹ˆç–‘é—®çš„è¯�,也å�¯ä»¥å…³æ³¨å…¬ä¼—å�·ã€�Java技术江湖】è�”ç³»ä½œè€…ï¼Œæ¬¢è¿Žä½ å�‚与本系列å�šæ–‡çš„åˆ›ä½œå’Œä¿®è®¢ã€‚
+
+
+
+> **说明**:
+>
+> **Capacity**: 性能,能力,系统容é‡�; æ–‡ä¸ç¿»è¯‘为â€�**系统容é‡�**“; æ„�为硬件é…�置。
+
+您应该已ç»�阅读了å‰�é�¢çš„ç« èŠ‚:
+
+1. 垃圾收集简介 - GC�考手册
+2. Javaä¸çš„垃圾收集 - GCå�‚考手册
+3. GC 算法(基础篇) - GC�考手册
+4. GC 算法(实现篇) - GC�考手册
+
+GC调优(Tuning Garbage Collection)和其他性能调优是å�Œæ ·çš„原ç�†ã€‚åˆ�å¦è€…å�¯èƒ½ä¼šè¢« 200 多个 GCå�‚数弄得一头雾水, ç„¶å�Žéš�ä¾¿è°ƒæ•´å‡ ä¸ªæ�¥è¯•试结果,å�ˆæˆ–è€…ä¿®æ”¹å‡ è¡Œä»£ç �æ�¥æµ‹è¯•。其实å�ªè¦�å�‚照下é�¢çš„æ¥éª¤ï¼Œå°±èƒ½ä¿�è¯�ä½ çš„è°ƒä¼˜æ–¹å�‘æ£ç¡®:
+
+1. åˆ—å‡ºæ€§èƒ½è°ƒä¼˜æŒ‡æ ‡(State your performance goals)
+2. 执行测试(Run tests)
+3. 检查结果(Measure the results)
+4. ä¸Žç›®æ ‡è¿›è¡Œå¯¹æ¯”(Compare the results with the goals)
+5. 如果达ä¸�åˆ°æŒ‡æ ‡, 修改é…�ç½®å�‚æ•°, ç„¶å�Žç»§ç»æµ‹è¯•(go back to running tests)
+
+第一æ¥, 我们需è¦�å�šçš„事情就是: 制定明确的GCæ€§èƒ½æŒ‡æ ‡ã€‚å¯¹æ‰€æœ‰æ€§èƒ½ç›‘æŽ§å’Œç®¡ç�†æ�¥è¯´, 有三个维度是通用的:
+
+* Latency(延迟)
+* Throughput(���)
+* Capacity(系统容�)
+
+我们先讲解基本概念,ç„¶å�Žå†�æ¼”ç¤ºå¦‚ä½•ä½¿ç”¨è¿™äº›æŒ‡æ ‡ã€‚å¦‚æžœæ‚¨å¯¹ 延迟ã€�å�žå��é‡�和系统容é‡�ç‰æ¦‚念很熟悉, å�¯ä»¥è·³è¿‡è¿™ä¸€å°�节。
+
+### æ ¸å¿ƒæ¦‚å¿µ(Core Concepts)
+
+我们先�看一家工厂的装��水线。工人在�水线将现�的组件按顺�拼接,组装�自行车。通过实地观测, 我们�现从组件进入生产线,到�一端组装�自行车需�4�时。
+
+
+ç»§ç»è§‚察,我们还å�‘现,æ¤å�Žæ¯�分钟就有1辆自行车完æˆ�组装, æ¯�天24å°�æ—¶,一直如æ¤ã€‚将这个模型简化, 并忽略维护窗å�£æœŸå�Žå¾—出结论:**è¿™æ�¡æµ�水线æ¯�å°�æ—¶å�¯ä»¥ç»„装60辆自行车**。
+
+> **说明**: 时间窗�/窗�期,请类比车站�票的窗�,是一段规定/�定��件事的时间段。
+
+通过这两�测�方法, 就知�了生产线的相关性能信�:**延迟**与**���**:
+
+* 生产线的延迟:**4�时**
+* 生产线的���:**60辆/�时**
+
+请注æ„�, è¡¡é‡�延迟的时间å�•ä½�æ ¹æ�®å…·ä½“需è¦�而确定 —— 从纳秒(nanosecond)åˆ°å‡ å�ƒå¹´(millennia)都有å�¯èƒ½ã€‚系统的å�žå��é‡�是æ¯�个å�•ä½�时间内完æˆ�çš„æ“�作。æ“�作(Operations)一般是特定系统相关的东西。在本例ä¸,选择的时间å�•ä½�是å°�æ—¶, æ“�作就是对自行车的组装。
+
+掌æ�¡äº†å»¶è¿Ÿå’Œå�žå��é‡�两个概念之å�Ž, 让我们对这个工厂æ�¥è¿›è¡Œå®žé™…的调优。自行车的需求在一段时间内都很稳定, 生产线组装自行车有四个å°�时延迟, 而å�žå��é‡�åœ¨å‡ ä¸ªæœˆä»¥æ�¥éƒ½å¾ˆç¨³å®š: 60辆/å°�时。å�‡è®¾æŸ�个销售团队çª�然业绩暴涨, å¯¹è‡ªè¡Œè½¦çš„éœ€æ±‚å¢žåŠ äº†1å€�。客户æ¯�天需è¦�的自行车ä¸�å†�是 60 * 24 = 1440辆, 而是 2*1440 = 2880辆/天。è€�æ�¿å¯¹å·¥åŽ‚çš„äº§èƒ½ä¸�满æ„�,想è¦�å�šäº›è°ƒæ•´ä»¥æ��å�‡äº§èƒ½ã€‚
+
+看起æ�¥æ€»ç»�ç�†å¾ˆå®¹æ˜“得出æ£ç¡®çš„判æ–, 系统的延迟没法å�进行处ç�† —— 他关注的是æ¯�天的自行车生产总é‡�。得出这个结论以å�Ž, å�‡è‹¥å·¥åŽ‚èµ„é‡‘å……è¶³, 那么应该立å�³é‡‡å�–措施, 改善å�žå��é‡�ä»¥å¢žåŠ äº§èƒ½ã€‚
+
+我们很快会看到, 这家工厂有两æ�¡ç›¸å�Œçš„生产线。æ¯�æ�¡ç”Ÿäº§çº¿ä¸€åˆ†é’Ÿå�¯ä»¥ç»„装一辆æˆ�å“�自行车。 å�¯ä»¥æƒ³è±¡ï¼Œæ¯�天生产的自行车数é‡�ä¼šå¢žåŠ ä¸€å€�。达到 2880辆/天。è¦�注æ„�的是, ä¸�需è¦�å‡�少自行车的装é…�æ—¶é—´ —— 从开始到结æ�Ÿä¾�然需è¦� 4 å°�时。
+
+
+
+å·§å�ˆçš„æ˜¯ï¼Œè¿™æ ·è¿›è¡Œçš„æ€§èƒ½ä¼˜åŒ–,å�Œæ—¶å¢žåŠ äº†å�žå��é‡�和产能。一般æ�¥è¯´ï¼Œæˆ‘们会先测é‡�当å‰�的系统性能, å†�è®¾å®šæ–°ç›®æ ‡, å�ªä¼˜åŒ–系统的æŸ�个方é�¢æ�¥æ»¡è¶³æ€§èƒ½æŒ‡æ ‡ã€‚
+
+在这里å�šäº†ä¸€ä¸ªå¾ˆé‡�è¦�的决定 —— è¦�å¢žåŠ å�žå��é‡�,而ä¸�是å‡�å°�å»¶è¿Ÿã€‚åœ¨å¢žåŠ å�žå��é‡�çš„å�Œæ—¶, 也需è¦�å¢žåŠ ç³»ç»Ÿå®¹é‡�。比起原æ�¥çš„æƒ…况, 现在需è¦�两æ�¡æµ�水线æ�¥ç”Ÿäº§å‡ºæ‰€éœ€çš„自行车。在这ç§�情况下, å¢žåŠ ç³»ç»Ÿçš„å�žå��é‡�å¹¶ä¸�是å…�费的, 需è¦�水平扩展, ä»¥æ»¡è¶³å¢žåŠ çš„å�žå��é‡�需求。
+
+在处ç�†æ€§èƒ½é—®é¢˜æ—¶, 应该考虑到还有å�¦ä¸€ç§�看似ä¸�相关的解决办法。å�‡å¦‚生产线的延迟从1分钟é™�低为30ç§’,那么å�žå��é‡�å�Œæ ·å�¯ä»¥å¢žé•¿ 1 å€�。
+
+或者是é™�低延迟, 或者是客户é�žå¸¸æœ‰é’±ã€‚软件工程里有一ç§�相似的说法 —— æ¯�个性能问题背å�Ž,总有两ç§�ä¸�å�Œçš„解决办法。 å�¯ä»¥ç”¨æ›´å¤šçš„æœºå™¨, 或者是花精力æ�¥æ”¹å–„性能低下的代ç �。
+
+#### Latency(延迟)
+
+GCçš„å»¶è¿ŸæŒ‡æ ‡ç”±ä¸€èˆ¬çš„å»¶è¿Ÿéœ€æ±‚å†³å®šã€‚å»¶è¿ŸæŒ‡æ ‡é€šå¸¸å¦‚ä¸‹æ‰€è¿°:
+
+* 所有交易必须在10秒内得到�应
+* 90%的订�付款�作必须在3秒以内处�完�
+* 推�商�必须在 100 ms 内展示到用户��
+
+é�¢å¯¹è¿™ç±»æ€§èƒ½æŒ‡æ ‡æ—¶, 需è¦�ç¡®ä¿�在交易过程ä¸, GCæš‚å�œä¸�能å� 用太多时间,å�¦åˆ™å°±æ»¡è¶³ä¸�äº†æŒ‡æ ‡ã€‚â€œä¸�能å� 用太多â€� çš„æ„�æ€�需è¦�视具体情况而定, 还è¦�è€ƒè™‘åˆ°å…¶ä»–å› ç´ , 比如外部数æ�®æº�的交互时间(round-trips), é”�竞争(lock contention), 以å�Šå…¶ä»–的安全点ç‰ç‰ã€‚
+
+å�‡è®¾æ€§èƒ½éœ€æ±‚为:`90%`的交易è¦�在`1000ms`以内完æˆ�, æ¯�次交易最长ä¸�能超过`10ç§’`。 æ ¹æ�®ç»�验, å�‡è®¾GCæš‚å�œæ—¶é—´æ¯”例ä¸�能超过10%。 也就是说, 90%çš„GCæš‚å�œå¿…须在`100ms`内结æ�Ÿ, 也ä¸�能有超过`1000ms`çš„GCæš‚å�œã€‚为简å�•èµ·è§�, 我们忽略在å�Œä¸€æ¬¡äº¤æ˜“过程ä¸å�‘生多次GCå�œé¡¿çš„å�¯èƒ½æ€§ã€‚
+
+有了æ£å¼�的需求,下一æ¥å°±æ˜¯æ£€æŸ¥æš‚å�œæ—¶é—´ã€‚有许多工具å�¯ä»¥ä½¿ç”¨, 在接下æ�¥çš„6\. GC 调优(工具篇)
+
+
+
+```
+2015-06-04T13:34:16.974-0200: 2.578: [Full GC (Ergonomics)
+ [PSYoungGen: 93677K->70109K(254976K)]
+ [ParOldGen: 499597K->511230K(761856K)]
+ 593275K->581339K(1016832K),
+ [Metaspace: 2936K->2936K(1056768K)]
+ , 0.0713174 secs]
+ [Times: user=0.21 sys=0.02, real=0.07 secs
+```
+
+
+
+这表示一次GC暂�, 在`2015-06-04T13:34:16`这个时刻触�. 对应于JVM�动之�的`2,578 ms`。
+
+æ¤äº‹ä»¶å°†åº”用线程暂å�œäº†`0.0713174`秒。虽然花费的总时间为 210 ms, ä½†å› ä¸ºæ˜¯å¤šæ ¸CPU机器, 所以最é‡�è¦�çš„æ•°å—æ˜¯åº”用线程被暂å�œçš„æ€»æ—¶é—´, 这里使用的是并行GC, 所以暂å�œæ—¶é—´å¤§çº¦ä¸º`70ms`。 这次GC的暂å�œæ—¶é—´å°�于`100ms`的阈值,满足需求。
+
+ç»§ç»åˆ†æž�, 从所有GCæ—¥å¿—ä¸æ��å�–出暂å�œç›¸å…³çš„æ•°æ�®, 汇总之å�Žå°±å�¯ä»¥å¾—知是å�¦æ»¡è¶³éœ€æ±‚。
+
+#### Throughput(���)
+
+å�žå��é‡�å’Œå»¶è¿ŸæŒ‡æ ‡æœ‰å¾ˆå¤§åŒºåˆ«ã€‚å½“ç„¶ä¸¤è€…éƒ½æ˜¯æ ¹æ�®ä¸€èˆ¬å�žå��é‡�需求而得出的。一般å�žå��é‡�需求(Generic requirements for throughput) ç±»ä¼¼è¿™æ ·:
+
+* 解决方案�天必须处� 100万个订�
+* 解决方案必须支�1000个登录用户,�时在5-10秒内执行�个�作: A�B或C
+* �周对所有客户进行统计, 时间�能超过6�时,时间窗�为�周日晚12点到次日6点之间。
+
+å�¯ä»¥çœ‹å‡º,å�žå��é‡�需求ä¸�是针对å�•个æ“�作的, 而是在给定的时间内, 系统必须完æˆ�多少个æ“�作。和延迟需求类似, GC调优也需è¦�确定GC行为所消耗的总时间。æ¯�个系统能接å�—的时间ä¸�å�Œ, 一般æ�¥è¯´, GCå� 用的总时间比ä¸�能超过`10%`。
+
+现在�设需求为: �分钟处� 1000 笔交易。�时, �分钟GC暂�的总时间�能超过6秒(�10%)。
+
+有了æ£å¼�的需求, 下一æ¥å°±æ˜¯èŽ·å�–相关的信æ�¯ã€‚ä¾�然是从GCæ—¥å¿—ä¸æ��å�–æ•°æ�®, å�¯ä»¥çœ‹åˆ°ç±»ä¼¼è¿™æ ·çš„ä¿¡æ�¯:
+
+
+
+```
+2015-06-04T13:34:16.974-0200: 2.578: [Full GC (Ergonomics)
+ [PSYoungGen: 93677K->70109K(254976K)]
+ [ParOldGen: 499597K->511230K(761856K)]
+ 593275K->581339K(1016832K),
+ [Metaspace: 2936K->2936K(1056768K)],
+ 0.0713174 secs]
+ [Times: user=0.21 sys=0.02, real=0.07 secs
+```
+
+
+
+æ¤æ—¶æˆ‘们对 用户耗时(user)和系统耗时(sys)感兴趣, 而ä¸�关心实际耗时(real)。在这里, 我们关心的时间为`0.23s`(user + sys = 0.21 + 0.02 s), 这段时间内, GCæš‚å�œå� 用了 cpu 资æº�。 é‡�è¦�的是, 系统è¿�è¡Œåœ¨å¤šæ ¸æœºå™¨ä¸Š, 转æ�¢ä¸ºå®žé™…çš„å�œé¡¿æ—¶é—´(stop-the-world)为`0.0713174ç§’`, 下é�¢çš„计算会用到这个数å—。
+
+��出有用的信��, 剩下��的就是统计�分钟内GC暂�的总时间。看看是�满足需求: �分钟内总的暂�时间�得超过6000毫秒(6秒)。
+
+#### Capacity(系统容�)
+
+系统容é‡�(Capacity)需求,是在达æˆ�å�žå��é‡�å’Œå»¶è¿ŸæŒ‡æ ‡çš„æƒ…å†µä¸‹,对硬件环境的é¢�外约æ�Ÿã€‚这类需求大多是æ�¥æº�于计算资æº�或者预算方é�¢çš„åŽŸå› ã€‚ä¾‹å¦‚:
+
+* 系统必须能部署到å°�于512 MB内å˜çš„Android设备上
+* 系统必须部署在Amazon**EC2**实例上, é…�ç½®ä¸�得超过**c3.xlarge(4æ ¸8GB)**。
+* �月的 Amazon EC2 账��得超过`$12,000`
+
+å› æ¤, 在满足延迟和å�žå��é‡�需求的基础上必须考虑系统容é‡�。å�¯ä»¥è¯´, å�‡è‹¥æœ‰æ— é™�的计算资æº�å�¯ä¾›æŒ¥éœ�, 那么任何 延迟和å�žå��é‡�æŒ‡æ ‡ 都ä¸�æˆ�问题, 但现实情况是, 预算(budget)和其他约æ�Ÿé™�制了å�¯ç”¨çš„资æº�。
+
+### 相关示例
+
+介ç»�完性能调优的三个维度å�Ž, 我们æ�¥è¿›è¡Œå®žé™…çš„æ“�作以达æˆ�GCæ€§èƒ½æŒ‡æ ‡ã€‚
+
+请看下é�¢çš„代ç �:
+
+
+
+```
+//imports skipped for brevity
+public class Producer implements Runnable {
+
+ private static ScheduledExecutorService executorService
+ = Executors.newScheduledThreadPool(2);
+
+ private Deque deque;
+ private int objectSize;
+ private int queueSize;
+
+ public Producer(int objectSize, int ttl) {
+ this.deque = new ArrayDeque();
+ this.objectSize = objectSize;
+ this.queueSize = ttl * 1000;
+ }
+
+ @Override
+ public void run() {
+ for (int i = 0; i < 100; i++) {
+ deque.add(new byte[objectSize]);
+ if (deque.size() > queueSize) {
+ deque.poll();
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ throws InterruptedException {
+ executorService.scheduleAtFixedRate(
+ new Producer(200 * 1024 * 1024 / 1000, 5),
+ 0, 100, TimeUnit.MILLISECONDS
+ );
+ executorService.scheduleAtFixedRate(
+ new Producer(50 * 1024 * 1024 / 1000, 120),
+ 0, 100, TimeUnit.MILLISECONDS);
+ TimeUnit.MINUTES.sleep(10);
+ executorService.shutdownNow();
+ }
+}
+```
+
+
+
+这段程åº�代ç �, æ¯� 100毫秒 æ��交两个作业(job)æ�¥ã€‚æ¯�个作业都模拟特定的生命周期: 创建对象, ç„¶å�Žåœ¨é¢„定的时间释放, 接ç�€å°±ä¸�管了, ç”±GCæ�¥è‡ªåŠ¨å›žæ”¶å� 用的内å˜ã€‚
+
+在�行这个示例程�时,通过以下JVM�数打开GC日志记录:
+
+
+
+```
+-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
+```
+
+
+
+è¿˜åº”è¯¥åŠ ä¸ŠJVMå�‚æ•°`-Xloggc`以指定GC日志的å˜å‚¨ä½�ç½®,ç±»ä¼¼è¿™æ ·:
+
+
+
+```
+-Xloggc:C:\\Producer_gc.log
+```
+
+
+
+* 1
+* 2
+
+在日志文件ä¸å�¯ä»¥çœ‹åˆ°GC的行为, 类似下é�¢è¿™æ ·:
+
+
+
+```
+2015-06-04T13:34:16.119-0200: 1.723: [GC (Allocation Failure)
+ [PSYoungGen: 114016K->73191K(234496K)]
+ 421540K->421269K(745984K),
+ 0.0858176 secs]
+ [Times: user=0.04 sys=0.06, real=0.09 secs]
+
+2015-06-04T13:34:16.738-0200: 2.342: [GC (Allocation Failure)
+ [PSYoungGen: 234462K->93677K(254976K)]
+ 582540K->593275K(766464K),
+ 0.2357086 secs]
+ [Times: user=0.11 sys=0.14, real=0.24 secs]
+
+2015-06-04T13:34:16.974-0200: 2.578: [Full GC (Ergonomics)
+ [PSYoungGen: 93677K->70109K(254976K)]
+ [ParOldGen: 499597K->511230K(761856K)]
+ 593275K->581339K(1016832K),
+ [Metaspace: 2936K->2936K(1056768K)],
+ 0.0713174 secs]
+ [Times: user=0.21 sys=0.02, real=0.07 secs]
+```
+
+
+
+基于日志ä¸çš„ä¿¡æ�¯, å�¯ä»¥é€šè¿‡ä¸‰ä¸ªä¼˜åŒ–ç›®æ ‡æ�¥æ��å�‡æ€§èƒ½:
+
+1. 确�最�情况下,GC暂�时间�超过预定阀值
+2. 确�线程暂�的总时间�超过预定阀值
+3. 在确ä¿�达到延迟和å�žå��é‡�æŒ‡æ ‡çš„æƒ…å†µä¸‹, é™�低硬件é…�置以å�Šæˆ�本。
+
+为æ¤, 用三ç§�ä¸�å�Œçš„é…�ç½®, 将代ç �è¿�行10分钟, 得到了三ç§�ä¸�å�Œçš„结果, 汇总如下:
+
+
+| **å †å†…å˜å¤§å°�(Heap)** | **GC算法(GC Algorithm)** | **有效时间比(Useful work)** | **最长å�œé¡¿æ—¶é—´(Longest pause)** |
+| -Xmx12g | -XX:+UseConcMarkSweepGC | 89.8% | **560 ms** |
+| -Xmx12g | -XX:+UseParallelGC | 91.5% | 1,104 ms |
+| -Xmx8g | -XX:+UseConcMarkSweepGC | 66.3% | 1,610 ms |
+
+使用ä¸�å�Œçš„GC算法,å’Œä¸�å�Œçš„内å˜é…�ç½®,è¿�行相å�Œçš„代ç �, 以测é‡�GCæš‚å�œæ—¶é—´ä¸Ž 延迟ã€�å�žå��é‡�的关系。实验的细节和结果在å�Žé�¢ç« 节详细介ç»�。
+
+注æ„�, 为了尽é‡�简å�•, 示例ä¸å�ªæ”¹å�˜äº†å¾ˆå°‘的输入å�‚æ•°, æ¤å®žéªŒä¹Ÿæ²¡æœ‰åœ¨ä¸�å�ŒCPUæ•°é‡�或者ä¸�å�Œçš„å †å¸ƒå±€ä¸‹è¿›è¡Œæµ‹è¯•ã€‚
+
+#### Tuning for Latency(è°ƒä¼˜å»¶è¿ŸæŒ‡æ ‡)
+
+å�‡è®¾æœ‰ä¸€ä¸ªéœ€æ±‚,**æ¯�次作业必须在 1000ms 内处ç�†å®Œæˆ�**。我们知é�“, 实际的作业处ç�†å�ªéœ€è¦�100 ms,简化å�Žï¼Œ 两者相å‡�å°±å�¯ä»¥ç®—出对 GCæš‚å�œçš„延迟è¦�求。现在需求å�˜æˆ�:**GCæš‚å�œä¸�能超过900ms**ã€‚è¿™ä¸ªé—®é¢˜å¾ˆå®¹æ˜“æ‰¾åˆ°ç”æ¡ˆ, å�ªéœ€è¦�è§£æž�GC日志文件, 并找出GCæš‚å�œä¸æœ€å¤§çš„那个暂å�œæ—¶é—´å�³å�¯ã€‚
+
+��看测试所用的三个�置:
+
+
+| **å †å†…å˜å¤§å°�(Heap)** | **GC算法(GC Algorithm)** | **有效时间比(Useful work)** | **最长å�œé¡¿æ—¶é—´(Longest pause)** |
+| -Xmx12g | -XX:+UseConcMarkSweepGC | 89.8% | **560 ms** |
+| -Xmx12g | -XX:+UseParallelGC | 91.5% | 1,104 ms |
+| -Xmx8g | -XX:+UseConcMarkSweepGC | 66.3% | 1,610 ms |
+
+å�¯ä»¥çœ‹åˆ°,其䏿œ‰ä¸€ä¸ªé…�置达到了è¦�求。è¿�行的å�‚数为:
+
+
+
+```
+java -Xmx12g -XX:+UseConcMarkSweepGC Producer
+```
+
+
+
+对应的GC日志ä¸,æš‚å�œæ—¶é—´æœ€å¤§ä¸º`560 ms`, è¿™è¾¾åˆ°äº†å»¶è¿ŸæŒ‡æ ‡`900 ms`çš„è¦�求。如果还满足å�žå��é‡�和系统容é‡�需求的è¯�,å°±å�¯ä»¥è¯´æˆ�功达æˆ�了GCè°ƒä¼˜ç›®æ ‡, 调优结æ�Ÿã€‚
+
+#### Tuning for Throughput(���调优)
+
+å�‡å®šå�žå��é‡�æŒ‡æ ‡ä¸º:**æ¯�å°�时完æˆ� 1300万次æ“�作处ç�†**。å�Œæ ·æ˜¯ä¸Šé�¢çš„é…�ç½®, 其䏿œ‰ä¸€ç§�é…�置满足了需求:
+
+
+| **å †å†…å˜å¤§å°�(Heap)** | **GC算法(GC Algorithm)** | **有效时间比(Useful work)** | **最长å�œé¡¿æ—¶é—´(Longest pause)** |
+| -Xmx12g | -XX:+UseConcMarkSweepGC | 89.8% | 560 ms |
+| -Xmx12g | -XX:+UseParallelGC | **91.5%** | 1,104 ms |
+| -Xmx8g | -XX:+UseConcMarkSweepGC | 66.3% | 1,610 ms |
+
+æ¤é…�置对应的命令行å�‚数为:
+
+
+
+```
+java -Xmx12g -XX:+UseParallelGC Producer
+```
+
+
+
+* å�¯ä»¥çœ‹åˆ°,GCå� 用了 8.5%çš„CPUæ—¶é—´,剩下的`91.5%`是有效的计算时间。为简å�•èµ·è§�, 忽略示例ä¸çš„其他安全点。现在需è¦�考虑:
+
+1. æ¯�个CPUæ ¸å¿ƒå¤„ç�†ä¸€æ¬¡ä½œä¸šéœ€è¦�耗时`100ms`
+2. å› æ¤, 一分钟内æ¯�ä¸ªæ ¸å¿ƒå�¯ä»¥æ‰§è¡Œ 60,000 次æ“�作(**æ¯�个job完æˆ�100次æ“�作**)
+3. 一å°�时内, ä¸€ä¸ªæ ¸å¿ƒå�¯ä»¥æ‰§è¡Œ 360万次æ“�作
+4. 有四个CPUå†…æ ¸, 则æ¯�å°�æ—¶å�¯ä»¥æ‰§è¡Œ: 4 x 3.6M = 1440万次æ“�作
+
+�论上,通过简�的计算就�以得出结论, ��时�以执行的�作数为:`14.4 M * 91.5% = 13,176,000`次, 满足需求。
+
+值得一æ��的是, å�‡è‹¥è¿˜è¦�æ»¡è¶³å»¶è¿ŸæŒ‡æ ‡, 那就有问题了, 最å��情况下, GCæš‚å�œæ—¶é—´ä¸º`1,104 ms`, 最大延迟时间是å‰�一ç§�é…�置的两å€�。
+
+#### Tuning for Capacity(调优系统容�)
+
+å�‡è®¾éœ€è¦�将软件部署到æœ�务器上(commodity-class hardware), é…�置为`4æ ¸10G`ã€‚è¿™æ ·çš„è¯�, 系统容é‡�çš„è¦�求就å�˜æˆ�: æœ€å¤§çš„å †å†…å˜ç©ºé—´ä¸�能超过`8GB`。有了这个需求, 我们需è¦�调整为第三套é…�置进行测试:
+
+
+| **å †å†…å˜å¤§å°�(Heap)** | **GC算法(GC Algorithm)** | **有效时间比(Useful work)** | **最长å�œé¡¿æ—¶é—´(Longest pause)** |
+| -Xmx12g | -XX:+UseConcMarkSweepGC | 89.8% | 560 ms |
+| -Xmx12g | -XX:+UseParallelGC | 91.5% | 1,104 ms |
+| **-Xmx8g** | -XX:+UseConcMarkSweepGC | 66.3% | 1,610 ms |
+
+程��以通过如下�数执行:
+
+
+
+```
+java -Xmx8g -XX:+UseConcMarkSweepGC Producer
+```
+
+
+
+* 测试结果是延迟大幅增长, å�žå��é‡�å�Œæ ·å¤§å¹…é™�低:
+* 现在,GCå� 用了更多的CPU资æº�, 这个é…�ç½®å�ªæœ‰`66.3%`的有效CPUæ—¶é—´ã€‚å› æ¤,这个é…�置让å�žå��é‡�从最好的情况**13,176,000 æ“�作/å°�æ—¶**下é™�到**ä¸�è¶³ 9,547,200次æ“�作/å°�æ—¶**.
+* 最�情况下的延迟��了**1,610 ms**, 而��是**560ms**。
+
+通过对这三个维度的介ç»�, ä½ åº”è¯¥äº†è§£, ä¸�是简å�•的进行“性能(performance)â€�优化, 而是需è¦�从三ç§�ä¸�å�Œçš„维度æ�¥è¿›è¡Œè€ƒè™‘, 测é‡�, 并调优延迟和å�žå��é‡�, æ¤å¤–还需è¦�考虑系统容é‡�的约æ�Ÿã€‚
+
+请继ç»é˜…è¯»ä¸‹ä¸€ç« :6\. GC 调优(工具篇) - GCå�‚考手册
+
+原文链接:[GC Tuning: Basics](https://plumbr.eu/handbook/gc-tuning)
+
+翻译时间: 2016年02月06日
+
+## 6\. GC 调优(工具篇) - GC�考手册
+
+2017年02月23日 18:56:02
+
+阅读数:6469
+
+进行GC性能调优时, 需è¦�明确了解, 当å‰�çš„GC行为对系统和用户有多大的影å“�。有多ç§�监控GC的工具和方法, æœ¬ç« å°†é€�一介ç»�常用的工具。
+
+您应该已ç»�阅读了å‰�é�¢çš„ç« èŠ‚:
+
+1. 垃圾收集简介 - GC�考手册
+2. Javaä¸çš„垃圾收集 - GCå�‚考手册
+3. GC 算法(基础篇) - GC�考手册
+4. GC 算法(实现篇) - GC�考手册
+5. GC 调优(基础篇) - GC�考手册
+
+JVM 在程åº�执行的过程ä¸, æ��供了GC行为的原生数æ�®ã€‚那么, 我们就å�¯ä»¥åˆ©ç”¨è¿™äº›åŽŸç”Ÿæ•°æ�®æ�¥ç”Ÿæˆ�å�„ç§�报告。原生数æ�®(_raw data_) 包括:
+
+* å�„ä¸ªå†…å˜æ± 的当å‰�使用情况,
+* å�„ä¸ªå†…å˜æ± 的总容é‡�,
+* æ¯�次GCæš‚å�œçš„æŒ�ç»æ—¶é—´,
+* GCæš‚å�œåœ¨å�„个阶段的æŒ�ç»æ—¶é—´ã€‚
+
+å�¯ä»¥é€šè¿‡è¿™äº›æ•°æ�®ç®—出å�„ç§�æŒ‡æ ‡, 例如: 程åº�的内å˜åˆ†é…�率, æ��å�‡çއç‰ç‰ã€‚æœ¬ç« ä¸»è¦�介ç»�如何获å�–原生数æ�®ã€‚ å�Žç»çš„ç« èŠ‚å°†å¯¹é‡�è¦�çš„æ´¾ç”ŸæŒ‡æ ‡(derived metrics)展开讨论, 并引入GC性能相关的è¯�题。
+
+## JMX API
+
+从 JVM è¿�行时获å�–GC行为数æ�®, 最简å�•çš„åŠžæ³•æ˜¯ä½¿ç”¨æ ‡å‡†[JMX API 接å�£](https://docs.oracle.com/javase/tutorial/jmx/index.html). JMX是获å�– JVM内部è¿�行时状æ€�ä¿¡æ�¯ çš„æ ‡å‡†API. å�¯ä»¥ç¼–写程åº�代ç �, 通过 JMX API æ�¥è®¿é—®æœ¬ç¨‹åº�所在的JVM,也å�¯ä»¥é€šè¿‡JMX客户端执行(远程)访问。
+
+最常è§�çš„ JMX客户端是[JConsole](http://docs.oracle.com/javase/7/docs/technotes/guides/management/jconsole.html)å’Œ[JVisualVM](http://docs.oracle.com/javase/7/docs/technotes/tools/share/jvisualvm.html)(å�¯ä»¥å®‰è£…å�„ç§�æ�’ä»¶,å��分强大)ã€‚ä¸¤ä¸ªå·¥å…·éƒ½æ˜¯æ ‡å‡†JDK的一部分, 而且很容易使用. 如果使用的是 JDK 7u40 å�Šæ›´é«˜ç‰ˆæœ¬, 还å�¯ä»¥ä½¿ç”¨å�¦ä¸€ä¸ªå·¥å…·:[Java Mission Control](http://www.oracle.com/technetwork/java/javaseproducts/mission-control/java-mission-control-1998576.html)( 大致翻译为 Java控制ä¸å¿ƒ,`jmc.exe`)。
+
+> JVisualVM安装MBeansæ�’ä»¶çš„æ¥éª¤: 通过 工具(T) – æ�’ä»¶(G) – å�¯ç”¨æ�’ä»¶ – 勾选VisualVM-MBeans – 安装 – ä¸‹ä¸€æ¥ â€“ ç‰å¾…安装完æˆ�…… å…¶ä»–æ�’件的安装过程基本一致。
+
+所有 JMX客户端都是独立的程åº�,å�¯ä»¥è¿žæŽ¥åˆ°ç›®æ ‡JVMä¸Šã€‚ç›®æ ‡JVMå�¯ä»¥åœ¨æœ¬æœº, 也å�¯èƒ½æ˜¯è¿œç«¯JVM. 如果è¦�连接远端JVM, åˆ™ç›®æ ‡JVMå�¯åŠ¨æ—¶å¿…é¡»æŒ‡å®šç‰¹å®šçš„çŽ¯å¢ƒå�˜é‡�,以开å�¯è¿œç¨‹JMX连接/以å�Šç«¯å�£å�·ã€‚ 示例如下:
+
+
+
+```
+java -Dcom.sun.management.jmxremote.port=5432 com.yourcompany.YourApp
+```
+
+
+
+在æ¤å¤„, JVM 打开端å�£`5432`以支æŒ�JMX连接。
+
+通过 JVisualVM 连接到æŸ�个JVM以å�Ž, 切æ�¢åˆ° MBeans æ ‡ç¾, 展开 “java.lang/GarbageCollectorâ€� . å°±å�¯ä»¥çœ‹åˆ°GC行为信æ�¯, 下图是 JVisualVM ä¸çš„æˆªå›¾:
+
+
+
+下图是Java Mission Control ä¸çš„æˆªå›¾:
+
+
+
+从以上截图ä¸å�¯ä»¥çœ‹åˆ°ä¸¤æ¬¾åžƒåœ¾æ”¶é›†å™¨ã€‚å…¶ä¸ä¸€æ¬¾è´Ÿè´£æ¸…ç�†å¹´è½»ä»£(**PS Scavenge**),å�¦ä¸€æ¬¾è´Ÿè´£æ¸…ç�†è€�年代(**PS MarkSweep**); åˆ—è¡¨ä¸æ˜¾ç¤ºçš„就是垃圾收集器的å��称。å�¯ä»¥çœ‹åˆ° , jmc 的功能和展示数æ�®çš„æ–¹å¼�更强大。
+
+对所有的垃圾收集器, 通过 JMX API 获�的信�包括:
+
+* **CollectionCount**: 垃圾收集器执行的GC总次数,
+* **CollectionTime**: 收集器è¿�行时间的累计。这个值ç‰äºŽæ‰€æœ‰GC事件æŒ�ç»æ—¶é—´çš„æ€»å’Œ,
+* **LastGcInfo**: 最近一次GC事件的详细信æ�¯ã€‚包括 GC事件的æŒ�ç»æ—¶é—´(duration), 开始时间(startTime) å’Œ 结æ�Ÿæ—¶é—´(endTime), 以å�Šå�„ä¸ªå†…å˜æ± 在最近一次GC之å‰�和之å�Žçš„使用情况,
+* **MemoryPoolNames**: å�„ä¸ªå†…å˜æ± çš„å��ç§°,
+* **Name**: 垃圾收集器的�称
+* **ObjectName**: ç”±JMX规范定义的 MBeançš„å��å—,,
+* **Valid**: æ¤æ”¶é›†å™¨æ˜¯å�¦æœ‰æ•ˆã€‚本人å�ªè§�过 “`true`“的情况 (^_^)
+
+æ ¹æ�®ç»�验, 这些信æ�¯å¯¹GC的性能æ�¥è¯´,ä¸�能得出什么结论. å�ªæœ‰ç¼–写程åº�, 获å�–GC相关的 JMX ä¿¡æ�¯æ�¥è¿›è¡Œç»Ÿè®¡å’Œåˆ†æž�。 在下文å�¯ä»¥çœ‹åˆ°, 一般也ä¸�怎么关注 MBean , 但 MBean 对于ç�†è§£GC的原ç�†å€’是挺有用的。
+
+## JVisualVM
+
+
+
+Visual GC æ�’件常用æ�¥ç›‘控本机è¿�行的Java程åº�, 比如开å�‘者和性能调优专家ç»�å¸¸ä¼šä½¿ç”¨æ¤æ�’ä»¶, 以快速获å�–程åº�è¿�行时的GCä¿¡æ�¯ã€‚
+
+
+
+左侧的图表展示了å�„ä¸ªå†…å˜æ± 的使用情况: Metaspace/永久代, è€�年代, Eden区以å�Šä¸¤ä¸ªå˜æ´»åŒºã€‚
+
+在å�³è¾¹, 顶部的两个图表与 GCæ— å…³, 显示的是 JIT编译时间 å’Œ ç±»åŠ è½½æ—¶é—´ã€‚ä¸‹é�¢çš„6ä¸ªå›¾æ˜¾ç¤ºçš„æ˜¯å†…å˜æ± 的历å�²è®°å½•, æ¯�ä¸ªå†…å˜æ± çš„GC次数,GC总时间, 以å�Šæœ€å¤§å€¼ï¼Œå³°å€¼, 当å‰�使用情况。
+
+å†�下é�¢æ˜¯ HistoGram, 显示了年轻代对象的年龄分布。至于对象的年龄监控(objects tenuring monitoring), æœ¬ç« ä¸�进行讲解。
+
+与纯粹的JMX工具相比, VisualGC æ�’ä»¶æ��供了更å�‹å¥½çš„界é�¢, 如果没有其他è¶�手的工具, 请选择VisualGC. æœ¬ç« æŽ¥ä¸‹æ�¥ä¼šä»‹ç»�其他工具, 这些工具å�¯ä»¥æ��供更多的信æ�¯, 以å�Šæ›´å¥½çš„视角. 当然, 在“Profilers(分æž�器)â€�一节ä¸ï¼Œä¹Ÿä¼šä»‹ç»� JVisualVM 的适用场景 —— 如: 分é…�分æž�(allocation profiling), 所以我们ç»�ä¸�会贬低哪一款工具, 关键还得看实际情况。
+
+## jstat
+
+[jstat](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html)ä¹Ÿæ˜¯æ ‡å‡†JDKæ��供的一款监控工具(Java Virtual Machine statistics monitoring tool),å�¯ä»¥ç»Ÿè®¡å�„ç§�æŒ‡æ ‡ã€‚æ—¢å�¯ä»¥è¿žæŽ¥åˆ°æœ¬åœ°JVM,也å�¯ä»¥è¿žåˆ°è¿œç¨‹JVM. 查看支æŒ�çš„æŒ‡æ ‡å’Œå¯¹åº”é€‰é¡¹å�¯ä»¥æ‰§è¡Œ “`jstat -options`â€� 。例如:
+
+
+
+```
++-----------------+---------------------------------------------------------------+
+| Option | Displays... |
++-----------------+---------------------------------------------------------------+
+|class | Statistics on the behavior of the class loader |
+|compiler | Statistics on the behavior of the HotSpot Just-In-Time com- |
+| | piler |
+|gc | Statistics on the behavior of the garbage collected heap |
+|gccapacity | Statistics of the capacities of the generations and their |
+| | corresponding spaces. |
+|gccause | Summary of garbage collection statistics (same as -gcutil), |
+| | with the cause of the last and current (if applicable) |
+| | garbage collection events. |
+|gcnew | Statistics of the behavior of the new generation. |
+|gcnewcapacity | Statistics of the sizes of the new generations and its corre- |
+| | sponding spaces. |
+|gcold | Statistics of the behavior of the old and permanent genera- |
+| | tions. |
+|gcoldcapacity | Statistics of the sizes of the old generation. |
+|gcpermcapacity | Statistics of the sizes of the permanent generation. |
+|gcutil | Summary of garbage collection statistics. |
+|printcompilation | Summary of garbage collection statistics. |
++-----------------+---------------------------------------------------------------+
+```
+
+
+
+* jstat 对于快速确定GC行为是å�¦å�¥åº·é�žå¸¸æœ‰ç”¨ã€‚å�¯åŠ¨æ–¹å¼�为: “`jstat -gc -t PID 1s`â€� , å…¶ä¸,PID 就是è¦�监视的Java进程ID。å�¯ä»¥é€šè¿‡`jps`命令查看æ£åœ¨è¿�行的Java进程列表。
+
+
+
+```
+jps
+
+jstat -gc -t 2428 1s
+```
+
+
+
+以上命令的结果, 是 jstat æ¯�ç§’å�‘æ ‡å‡†è¾“å‡ºè¾“å‡ºä¸€è¡Œæ–°å†…å®¹, 比如:
+
+
+
+```
+Timestamp S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
+200.0 8448.0 8448.0 8448.0 0.0 67712.0 67712.0 169344.0 169344.0 21248.0 20534.3 3072.0 2807.7 34 0.720 658 133.684 134.404
+201.0 8448.0 8448.0 8448.0 0.0 67712.0 67712.0 169344.0 169343.2 21248.0 20534.3 3072.0 2807.7 34 0.720 662 134.712 135.432
+202.0 8448.0 8448.0 8102.5 0.0 67712.0 67598.5 169344.0 169343.6 21248.0 20534.3 3072.0 2807.7 34 0.720 667 135.840 136.559
+203.0 8448.0 8448.0 8126.3 0.0 67712.0 67702.2 169344.0 169343.6 21248.0 20547.2 3072.0 2807.7 34 0.720 669 136.178 136.898
+204.0 8448.0 8448.0 8126.3 0.0 67712.0 67702.2 169344.0 169343.6 21248.0 20547.2 3072.0 2807.7 34 0.720 669 136.178 136.898
+205.0 8448.0 8448.0 8134.6 0.0 67712.0 67712.0 169344.0 169343.5 21248.0 20547.2 3072.0 2807.7 34 0.720 671 136.234 136.954
+206.0 8448.0 8448.0 8134.6 0.0 67712.0 67712.0 169344.0 169343.5 21248.0 20547.2 3072.0 2807.7 34 0.720 671 136.234 136.954
+207.0 8448.0 8448.0 8154.8 0.0 67712.0 67712.0 169344.0 169343.5 21248.0 20547.2 3072.0 2807.7 34 0.720 673 136.289 137.009
+208.0 8448.0 8448.0 8154.8 0.0 67712.0 67712.0 169344.0 169343.5 21248.0 20547.2 3072.0 2807.7 34 0.720 673 136.289 137.009
+```
+
+
+
+�微解释一下上�的内容。�考[jstat manpage](http://www.manpagez.com/man/1/jstat/), 我们�以知�:
+
+* jstat 连接到 JVM 的时间, 是JVMå�¯åЍå�Žçš„ 200秒。æ¤ä¿¡æ�¯ä»Žç¬¬ä¸€è¡Œçš„ “**Timestamp**â€� 列得知。继ç»çœ‹ä¸‹ä¸€è¡Œ, jstat æ¯�秒钟从JVM 接收一次信æ�¯, 也就是命令行å�‚æ•°ä¸ â€œ`1s`â€� çš„å�«ä¹‰ã€‚
+* 从第一行的 “**YGC**â€� 列得知年轻代共执行了34次GC, ç”± “**FGC**â€� åˆ—å¾—çŸ¥æ•´ä¸ªå †å†…å˜å·²ç»�执行了 658次 full GC。
+* 年轻代的GC耗时总共为`0.720 秒`, 显示在“**YGCT**� 这一列。
+* Full GC 的总计耗时为`133.684 ç§’`, 由“**FGCT**â€�列得知。 这立马就å�¸å¼•了我们的目光, 总的JVM è¿�行时间å�ªæœ‰ 200 ç§’,**但其䏿œ‰ 66% 的部分被 Full GC 消耗了**。
+
+�看下一行, 问题就更明显了。
+
+* 在接下�的一秒内共执行了 4 次 Full GC。�� “**FGC**� 列.
+* è¿™4次 Full GC æš‚å�œå� 用了差ä¸�多 1秒的时间(æ ¹æ�®**FGCT**列的差得知)。与第一行相比, Full GC 耗费了`928 毫秒`, å�³`92.8%`的时间。
+* æ ¹æ�® “**OC**å’Œ “**OU**â€� 列得知,**整个è€�年代的空间**为`169,344.0 KB`(“OC“), 在 4 次 Full GC å�Žä¾�ç„¶å� 用了`169,344.2 KB`(“OU“)。用了`928ms`的时间å�´å�ªé‡Šæ”¾äº† 800 å—节的内å˜, 怎么看都觉得很ä¸�æ£å¸¸ã€‚
+
+å�ªçœ‹è¿™ä¸¤è¡Œçš„内容, 就知é�“程åº�出了很严é‡�的问题。继ç»åˆ†æž�下一行, å�¯ä»¥ç¡®å®šé—®é¢˜ä¾�ç„¶å˜åœ¨,而且å�˜å¾—更糟。
+
+JVMå‡ ä¹Žå®Œå…¨å�¡ä½�了(stalled), å› ä¸ºGCå� 用了90%以上的计算资æº�。GC之å�Ž, 所有的è€�代空间ä»�然还在å� 用。事实上, 程åº�在一分钟以å�Žå°±æŒ‚了, 抛出了 “[java.lang.OutOfMemoryError: GC overhead limit exceeded](https://plumbr.eu/outofmemoryerror/gc-overhead-limit-exceeded)â€� 错误。
+
+�以看到, 通过 jstat 能很快�现对JVM�康�为�利的GC行为。一般�说, �看 jstat 的输出就能快速�现以下问题:
+
+* 最�一列 “**GCT**�, 与JVM的总�行时间 “**Timestamp**� 的比值, 就是GC 的开销。如果�一秒内, “**GCT**� 的值都会明显增大, 与总�行时间相比, 就暴露出GC开销过大的问题. ��系统对GC开销有��的容�度, 由性能需求决定, 一般�讲, 超过`10%`的GC开销都是有问题的。
+* “**YGC**� 和 “**FGC**� 列的快速�化往往也是有问题的�兆。频�的GC暂�会累积,并导致更多的线程�顿(stop-the-world pauses), 进而影����。
+* 如果看到 “**OU**â€� 列ä¸,è€�年代的使用é‡�约ç‰äºŽè€�年代的最大容é‡�(**OC**), 并且ä¸�é™�低的è¯�, 就表示虽然执行了è€�年代GC, ä½†åŸºæœ¬ä¸Šå±žäºŽæ— æ•ˆGC。
+
+## GC日志(GC logs)
+
+通过日志内容也å�¯ä»¥å¾—到GC相关的信æ�¯ã€‚å› ä¸ºGC日志模å�—内置于JVMä¸, 所以日志ä¸åŒ…å�«äº†å¯¹GC活动最全é�¢çš„æ��述。 è¿™å°±æ˜¯äº‹å®žä¸Šçš„æ ‡å‡†, å�¯ä½œä¸ºGC性能评估和优化的最真实数æ�®æ�¥æº�。
+
+GC日志一般输出到文件之ä¸, 是纯 text æ ¼å¼�çš„, 当然也å�¯ä»¥æ‰“å�°åˆ°æŽ§åˆ¶å�°ã€‚有多个å�¯ä»¥æŽ§åˆ¶GC日志的JVMå�‚数。例如,å�¯ä»¥æ‰“å�°æ¯�次GCçš„æŒ�ç»æ—¶é—´, 以å�Šç¨‹åº�æš‚å�œæ—¶é—´(`-XX:+PrintGCApplicationStoppedTime`), 还有GC清ç�†äº†å¤šå°‘引用类型(`-XX:+PrintReferenceGC`)。
+
+è¦�打å�°GC日志, 需è¦�在å�¯åŠ¨è„šæœ¬ä¸æŒ‡å®šä»¥ä¸‹å�‚æ•°:
+
+
+
+```
+-XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:
+```
+
+
+
+以上å�‚数指示JVM: 将所有GC事件打å�°åˆ°æ—¥å¿—文件ä¸, 输出æ¯�次GC的日期和时间戳。ä¸�å�ŒGC算法输出的内容略有ä¸�å�Œ. ParallelGC è¾“å‡ºçš„æ—¥å¿—ç±»ä¼¼è¿™æ ·:
+
+
+
+```
+199.879: [Full GC (Ergonomics) [PSYoungGen: 64000K->63998K(74240K)] [ParOldGen: 169318K->169318K(169472K)] 233318K->233317K(243712K), [Metaspace: 20427K->20427K(1067008K)], 0.1473386 secs] [Times: user=0.43 sys=0.01, real=0.15 secs]
+200.027: [Full GC (Ergonomics) [PSYoungGen: 64000K->63998K(74240K)] [ParOldGen: 169318K->169318K(169472K)] 233318K->233317K(243712K), [Metaspace: 20427K->20427K(1067008K)], 0.1567794 secs] [Times: user=0.41 sys=0.00, real=0.16 secs]
+200.184: [Full GC (Ergonomics) [PSYoungGen: 64000K->63998K(74240K)] [ParOldGen: 169318K->169318K(169472K)] 233318K->233317K(243712K), [Metaspace: 20427K->20427K(1067008K)], 0.1621946 secs] [Times: user=0.43 sys=0.00, real=0.16 secs]
+200.346: [Full GC (Ergonomics) [PSYoungGen: 64000K->63998K(74240K)] [ParOldGen: 169318K->169318K(169472K)] 233318K->233317K(243712K), [Metaspace: 20427K->20427K(1067008K)], 0.1547695 secs] [Times: user=0.41 sys=0.00, real=0.15 secs]
+200.502: [Full GC (Ergonomics) [PSYoungGen: 64000K->63999K(74240K)] [ParOldGen: 169318K->169318K(169472K)] 233318K->233317K(243712K), [Metaspace: 20427K->20427K(1067008K)], 0.1563071 secs] [Times: user=0.42 sys=0.01, real=0.16 secs]
+200.659: [Full GC (Ergonomics) [PSYoungGen: 64000K->63999K(74240K)] [ParOldGen: 169318K->169318K(169472K)] 233318K->233317K(243712K), [Metaspace: 20427K->20427K(1067008K)], 0.1538778 secs] [Times: user=0.42 sys=0.00, real=0.16 secs]
+```
+
+
+
+在 “04\. GC算法:实现篇â€� ä¸è¯¦ç»†ä»‹ç»�äº†è¿™äº›æ ¼å¼�, 如果对æ¤ä¸�了解, å�¯ä»¥å…ˆé˜…è¯»è¯¥ç« èŠ‚ã€‚
+
+分�以上日志内容, �以得知:
+
+* 这部分日志截�自JVM�动�200秒左�。
+* æ—¥å¿—ç‰‡æ®µä¸æ˜¾ç¤º, 在`780毫秒`以内, å› ä¸ºåžƒåœ¾å›žæ”¶ 导致了5次 Full GC æš‚å�œ(åŽ»æŽ‰ç¬¬å…æ¬¡æš‚å�œ,è¿™æ ·æ›´ç²¾ç¡®ä¸€äº›)。
+* 这些暂å�œäº‹ä»¶çš„æ€»æŒ�ç»æ—¶é—´æ˜¯`777毫秒`, å� 总è¿�行时间的**99.6%**。
+* 在GC完æˆ�之å�Ž, å‡ ä¹Žæ‰€æœ‰çš„è€�年代空间(`169,472 KB`)ä¾�然被å� 用(`169,318 KB`)。
+
+通过日志信æ�¯å�¯ä»¥ç¡®å®š, 该应用的GC情况é�žå¸¸ç³Ÿç³•。JVMå‡ ä¹Žå®Œå…¨å�œæ»ž, å› ä¸ºGCå� 用了超过`99%`çš„CPU时间。 而GC的结果是, è€�年代空间ä»�然被å� 满, 这进一æ¥è‚¯å®šäº†æˆ‘们的结论。 示例程åº�å’Œjstat å°�节ä¸çš„æ˜¯å�Œä¸€ä¸ª, å‡ åˆ†é’Ÿä¹‹å�Žç³»ç»Ÿå°±æŒ‚了, 抛出 “[java.lang.OutOfMemoryError: GC overhead limit exceeded](https://plumbr.eu/outofmemoryerror/gc-overhead-limit-exceeded)â€� 错误, ä¸�用说, 问题是很严é‡�çš„.
+
+从æ¤ç¤ºä¾‹å�¯ä»¥çœ‹å‡º, GC日志对监控GC行为和JVM是å�¦å¤„于å�¥åº·çжæ€�é�žå¸¸æœ‰ç”¨ã€‚一般情况下, 查看 GC 日志就å�¯ä»¥å¿«é€Ÿç¡®å®šä»¥ä¸‹ç—‡çж:
+
+* GC开销太大。如果GCæš‚å�œçš„æ€»æ—¶é—´å¾ˆé•¿, 就会æ�Ÿå®³ç³»ç»Ÿçš„å�žå��é‡�。ä¸�å�Œçš„系统å…�许ä¸�å�Œæ¯”例的GC开销, 但一般认为, æ£å¸¸èŒƒå›´åœ¨`10%`以内。
+* æž�个别的GC事件暂å�œæ—¶é—´è¿‡é•¿ã€‚当æŸ�次GCæš‚å�œæ—¶é—´å¤ªé•¿, 就会影å“�ç³»ç»Ÿçš„å»¶è¿ŸæŒ‡æ ‡. å¦‚æžœå»¶è¿ŸæŒ‡æ ‡è§„å®šäº¤æ˜“å¿…é¡»åœ¨`1,000 ms`内完æˆ�, 那就ä¸�能容å¿�任何超过`1000毫秒`çš„GCæš‚å�œã€‚
+* è€�年代的使用é‡�超过é™�制。如果è€�年代空间在 Full GC 之å�Žä»�然接近全满, 那么GCå°±æˆ�为了性能瓶颈, å�¯èƒ½æ˜¯å†…å˜å¤ªå°�, 也å�¯èƒ½æ˜¯å˜åœ¨å†…å˜æ³„æ¼�。这ç§�症状会让GC的开销暴增。
+
+å�¯ä»¥çœ‹åˆ°,GC日志ä¸çš„ä¿¡æ�¯é�žå¸¸è¯¦ç»†ã€‚但除了这些简å�•çš„å°�程åº�, 生产系统一般都会生æˆ�大é‡�çš„GC日志, 纯é� 人工是很难阅读和进行解æž�的。
+
+## GCViewer
+
+我们å�¯ä»¥è‡ªå·±ç¼–写解æž�器, æ�¥å°†åºžå¤§çš„GC日志解æž�为直观易读的图形信æ�¯ã€‚ 但很多时候自己写程åº�也ä¸�是个好办法, å› ä¸ºå�„ç§�GC算法的å¤�æ�‚性, 导致日志信æ�¯æ ¼å¼�互相之间ä¸�太兼容。那么神器æ�¥äº†:[GCViewer](https://github.com/chewiebug/GCViewer)。
+
+[GCViewer](https://github.com/chewiebug/GCViewer)是一款开æº�çš„GC日志分æž�工具。项目的 GitHub 主页对å�„é¡¹æŒ‡æ ‡è¿›è¡Œäº†å®Œæ•´çš„æ��è¿°. 下é�¢æˆ‘们介ç»�æœ€å¸¸ç”¨çš„ä¸€äº›æŒ‡æ ‡ã€‚
+
+ç¬¬ä¸€æ¥æ˜¯èŽ·å�–GC日志文件。这些日志文件è¦�能够å��æ˜ ç³»ç»Ÿåœ¨æ€§èƒ½è°ƒä¼˜æ—¶çš„å…·ä½“åœºæ™¯. å�‡è‹¥è¿�è�¥éƒ¨é—¨(operational department)å��馈: æ¯�周五下å�ˆ,系统就è¿�行缓慢, ä¸�管GC是ä¸�是主è¦�åŽŸå› , 分æž�周一早晨的日志是没有多少æ„�义的。
+
+获�到日志文件之�, 就�以用 GCViewer 进行分�, 大致会看到类似下�的图形界�:
+
+
+
+使用的命令行大致如下:
+
+
+
+```
+java -jar gcviewer_1.3.4.jar gc.log
+```
+
+
+
+当然, 如果ä¸�想打开程åº�界é�¢,也å�¯ä»¥åœ¨å�Žé�¢åŠ ä¸Šå…¶ä»–å�‚æ•°,直接将分æž�结果输出到文件。
+
+命令大致如下:
+
+
+
+```
+java -jar gcviewer_1.3.4.jar gc.log summary.csv chart.png
+```
+
+
+
+以上命令将信æ�¯æ±‡æ€»åˆ°å½“å‰�目录下的 Excel 文件`summary.csv`之ä¸, 将图形信æ�¯ä¿�å˜ä¸º`chart.png`文件。
+
+点击下载:gcviewer的jar包�使用示例
+
+上图ä¸, Chart 区域是对GC事件的图形化展示。包括å�„ä¸ªå†…å˜æ± 的大å°�å’ŒGC事件。上图ä¸, å�ªæœ‰ä¸¤ä¸ªå�¯è§†åŒ–æŒ‡æ ‡: è“�色线æ�¡è¡¨ç¤ºå †å†…å˜çš„使用情况, 黑色的Bar则表示æ¯�次GCæš‚å�œæ—¶é—´çš„é•¿çŸã€‚
+
+从图ä¸å�¯ä»¥çœ‹åˆ°, 内å˜ä½¿ç”¨é‡�增长很快。一分钟左å�³å°±è¾¾åˆ°äº†å †å†…å˜çš„æœ€å¤§å€¼. å †å†…å˜å‡ 乎全部被消耗, ä¸�能顺利分é…�新对象, 并引å�‘频ç¹�çš„ Full GC 事件. 这说明程åº�å�¯èƒ½å˜åœ¨å†…å˜æ³„露, 或者å�¯åŠ¨æ—¶æŒ‡å®šçš„å†…å˜ç©ºé—´ä¸�足。
+
+从图ä¸è¿˜å�¯ä»¥çœ‹åˆ° GCæš‚å�œçš„频率和æŒ�ç»æ—¶é—´ã€‚`30ç§’`之å�Ž, GCå‡ ä¹Žä¸�é—´æ–地è¿�行,最长的暂å�œæ—¶é—´è¶…过`1.4ç§’`。
+
+在å�³è¾¹æœ‰ä¸‰ä¸ªé€‰é¡¹å�¡ã€‚“`**Summary**`(摘è¦�)â€� 䏿¯”较有用的是 “`Throughput`â€�(å�žå��é‡�百分比) å’Œ “`Number of GC pauses`â€�(GCæš‚å�œçš„æ¬¡æ•°), 以å�Šâ€œ`Number of full GC pauses`â€�(Full GC æš‚å�œçš„æ¬¡æ•°). å�žå��é‡�显示了有效工作的时间比例, 剩下的部分就是GC的消耗。
+
+以上示例ä¸çš„å�žå��é‡�为`**6.28%**`。这æ„�味ç�€æœ‰`**93.72%**`
+
+下一个有��的地方是“**Pause**�(暂�)选项�:
+
+
+
+“`Pause`â€� 展示了GCæš‚å�œçš„æ€»æ—¶é—´,å¹³å�‡å€¼,最å°�值和最大值, 并且将 total 与minor/major æš‚å�œåˆ†å¼€ç»Ÿè®¡ã€‚如果è¦�优化程åº�çš„å»¶è¿ŸæŒ‡æ ‡, 这些统计å�¯ä»¥å¾ˆå¿«åˆ¤æ–出暂å�œæ—¶é—´æ˜¯å�¦è¿‡é•¿ã€‚å�¦å¤–, 我们å�¯ä»¥å¾—出明确的信æ�¯: 累计暂å�œæ—¶é—´ä¸º`634.59 ç§’`, GCæš‚å�œçš„æ€»æ¬¡æ•°ä¸º`3,938 次`, 这在`11分钟/660ç§’`的总è¿�行时间里那ä¸�是一般的高。
+
+更详细的GCæš‚å�œæ±‡æ€»ä¿¡æ�¯, 请查看主界é�¢ä¸çš„ “**Event details**â€� æ ‡ç¾:
+
+
+
+从“**Event details**â€� æ ‡ç¾ä¸, å�¯ä»¥çœ‹åˆ°æ—¥å¿—䏿‰€æœ‰é‡�è¦�çš„GC事件汇总:`普通GCå�œé¡¿`å’Œ`Full GC å�œé¡¿æ¬¡æ•°`, 以å�Š`å¹¶å�‘执行数`,`é�ž stop-the-world 事件`ç‰ã€‚æ¤ç¤ºä¾‹ä¸, å�¯ä»¥çœ‹åˆ°ä¸€ä¸ªæ˜Žæ˜¾çš„地方, Full GC æš‚å�œä¸¥é‡�å½±å“�了å�žå��é‡�和延迟, ä¾�æ�®æ˜¯:`3,928 次 Full GC`, æš‚å�œäº†`634ç§’`。
+
+å�¯ä»¥çœ‹åˆ°, GCViewer 能用图形界é�¢å¿«é€Ÿå±•现异常的GC行为。一般æ�¥è¯´, 图åƒ�化信æ�¯èƒ½è¿…速æ�示以下症状:
+
+* 低å�žå��é‡�。当应用的å�žå��é‡�下é™�到ä¸�能容å¿�çš„åœ°æ¥æ—¶, 有用工作的总时间就大é‡�å‡�å°‘. 具体有多大的 “容å¿�度â€�(tolerable) å�–决于具体场景。按照ç»�验, 低于 90% çš„æœ‰æ•ˆæ—¶é—´å°±å€¼å¾—è¦æƒ•了, å�¯èƒ½éœ€è¦�好好优化下GC。
+* å�•次GC的暂å�œæ—¶é—´è¿‡é•¿ã€‚å�ªè¦�有一次GCå�œé¡¿æ—¶é—´è¿‡é•¿,就会影å“�程åº�çš„å»¶è¿ŸæŒ‡æ ‡. 例如, 延迟需求规定必须在 1000 ms以内完æˆ�交易, 那就ä¸�能容å¿�任何一次GCæš‚å�œè¶…过1000毫秒。
+* å †å†…å˜ä½¿ç”¨çŽ‡è¿‡é«˜ã€‚å¦‚æžœè€�年代空间在 Full GC 之å�Žä»�然接近全满, 程åº�性能就会大幅é™�低, å�¯èƒ½æ˜¯èµ„æº�ä¸�è¶³æˆ–è€…å†…å˜æ³„æ¼�。这ç§�症状会对å�žå��é‡�产生严é‡�å½±å“�。
+
+业界良心 —— 图形化展示的GC日志信æ�¯ç»�对是我们é‡�磅推è��的。ä¸�用去阅读冗长而å�ˆå¤�æ�‚çš„GC日志,通过容易ç�†è§£çš„图形, 也å�¯ä»¥å¾—到å�Œæ ·çš„ä¿¡æ�¯ã€‚
+
+## 分�器(Profilers)
+
+下é�¢ä»‹ç»�分æž�器([profilers](http://zeroturnaround.com/rebellabs/developer-productivity-report-2015-java-performance-survey-results/3/), Oracle官方翻译是:`æŠ½æ ·å™¨`)。相对于å‰�é�¢çš„工具, 分æž�器å�ªå…³å¿ƒGCä¸çš„一部分领域. 本节我们也å�ªå…³æ³¨åˆ†æž�器相关的GC功能。
+
+首先è¦å‘Š â€”â€” ä¸�è¦�认为分æž�器适用于所有的场景。分æž�器有时确实作用很大, 比如检测代ç �ä¸çš„CPUçƒç‚¹æ—¶ã€‚但æŸ�些情况使用分æž�器ä¸�一定是个好方案。
+
+对GC调优æ�¥è¯´ä¹Ÿæ˜¯ä¸€æ ·çš„。è¦�检测是å�¦å› 为GC而引起延迟或å�žå��é‡�问题时, ä¸�需è¦�使用分æž�器. å‰�é�¢æ��到的工具(`jstat`或 原生/å�¯è§†åŒ–GC日志)就能更好更快地检测出是å�¦å˜åœ¨GC问题. ç‰¹åˆ«æ˜¯ä»Žç”Ÿäº§çŽ¯å¢ƒä¸æ”¶é›†æ€§èƒ½æ•°æ�®æ—¶, 最好ä¸�è¦�使用分æž�器, å› ä¸ºæ€§èƒ½å¼€é”€é�žå¸¸å¤§ã€‚
+
+如果确实需è¦�对GC进行优化, 那么分æž�器就å�¯ä»¥æ´¾ä¸Šç”¨åœºäº†, å�¯ä»¥å¯¹ Object 的创建信æ�¯ä¸€ç›®äº†ç„¶. æ�¢ä¸ªè§’度看, 如果GCæš‚å�œçš„åŽŸå› ä¸�在æŸ�ä¸ªå†…å˜æ± ä¸, 那就å�ªä¼šæ˜¯å› 为创建对象太多了。 所有分æž�器都能够跟踪对象分é…�(via allocation profiling), æ ¹æ�®å†…å˜åˆ†é…�的轨迹, è®©ä½ çŸ¥é�“**实际驻留在内å˜ä¸çš„æ˜¯å“ªäº›å¯¹è±¡**。
+
+分é…�分æž�能定ä½�到在哪个地方创建了大é‡�的对象. 使用分æž�器辅助进行GC调优的好处是, 能确定哪ç§�类型的对象最å� 用内å˜, 以å�Šå“ªäº›çº¿ç¨‹åˆ›å»ºäº†æœ€å¤šçš„对象。
+
+下�我们通过实例介�3�分�分�器:`**hprof**`,`**JVisualV**`**M**和`**AProf**`。实际上还有很多分�器�供选择, 有商业产�,也有�费工具, 但其功能和应用基本上都是类似的。
+
+### hprof
+
+[hprof 分æž�器](http://docs.oracle.com/javase/8/docs/technotes/samples/hprof.html)内置于JDK之ä¸ã€‚ 在å�„ç§�环境下都å�¯ä»¥ä½¿ç”¨, 一般优先使用这款工具。
+
+è¦�让`hprof`和程åº�一起è¿�行, 需è¦�修改å�¯åŠ¨è„šæœ¬, ç±»ä¼¼è¿™æ ·:
+
+
+
+```
+java -agentlib:hprof=heap=sites com.yourcompany.YourApplication
+```
+
+
+
+在程åº�退出时,会将分é…�ä¿¡æ�¯dump(转储)到工作目录下的`java.hprof.txt`文件ä¸ã€‚使用文本编辑器打开, å¹¶æ�œç´¢ “**SITES BEGIN**â€� 关键å—, å�¯ä»¥çœ‹åˆ°:
+
+
+
+```
+SITES BEGIN (ordered by live bytes) Tue Dec 8 11:16:15 2015
+ percent live alloc'ed stack class
+ rank self accum bytes objs bytes objs trace name
+ 1 64.43% 4.43% 8370336 20121 27513408 66138 302116 int[]
+ 2 3.26% 88.49% 482976 20124 1587696 66154 302104 java.util.ArrayList
+ 3 1.76% 88.74% 241704 20121 1587312 66138 302115 eu.plumbr.demo.largeheap.ClonableClass0006
+ ... 部分�略 ...
+
+SITES END
+```
+
+
+
+从以上片段å�¯ä»¥çœ‹åˆ°, allocations æ˜¯æ ¹æ�®æ¯�次创建的对象数é‡�æ�¥æŽ’åº�çš„ã€‚ç¬¬ä¸€è¡Œæ˜¾ç¤ºæ‰€æœ‰å¯¹è±¡ä¸æœ‰`**64.43%**`的对象是整型数组(`int[]`), åœ¨æ ‡è¯†ä¸º`302116`çš„ä½�置创建。æ�œç´¢ “**TRACE 302116**â€� å�¯ä»¥çœ‹åˆ°:
+
+
+
+```
+TRACE 302116:
+ eu.plumbr.demo.largeheap.ClonableClass0006.(GeneratorClass.java:11)
+ sun.reflect.GeneratedConstructorAccessor7.newInstance(:Unknown line)
+ sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
+ java.lang.reflect.Constructor.newInstance(Constructor.java:422)
+```
+
+
+
+现在, 知é�“有`64.43%`的对象是整数数组, 在`ClonableClass0006`ç±»çš„æž„é€ å‡½æ•°ä¸, 第11行的ä½�ç½®, 接下æ�¥å°±å�¯ä»¥ä¼˜åŒ–代ç �, 以å‡�å°‘GC的压力。
+
+### Java VisualVM
+
+æœ¬ç« å‰�é�¢çš„第一部分, 在监控 JVM çš„GC行为工具时介ç»�了 JVisualVM , 本节介ç»�其在分é…�分æž�上的应用。
+
+JVisualVM 通过GUI的方å¼�连接到æ£åœ¨è¿�行的JVM。 è¿žæŽ¥ä¸Šç›®æ ‡JVM之å�Ž :
+
+1. 打开 “工具â€� –> “选项â€� è�œå�•, 点击**性能分æž�(Profiler)**æ ‡ç¾, 新增é…�ç½®, 选择 Profiler 内å˜, ç¡®ä¿�勾选了 “Record allocations stack tracesâ€�(记录分é…�æ ˆè·Ÿè¸ª)。
+2. 勾选 “Settingsâ€�(设置) å¤�选框, 在内å˜è®¾ç½®æ ‡ç¾ä¸‹,修改预设é…�置。
+3. 点击 “Memoryâ€�(内å˜) 按钮开始进行内å˜åˆ†æž�。
+4. 让程��行一段时间,以收集关于对象分�的足够信�。
+5. �击下方的 “Snapshot�(快照) 按钮。�以获�收集到的快照信�。
+
+
+
+完æˆ�上é�¢çš„æ¥éª¤å�Ž, å�¯ä»¥å¾—åˆ°ç±»ä¼¼è¿™æ ·çš„ä¿¡æ�¯:
+
+
+
+上图按照æ¯�个类被创建的对象数é‡�多少æ�¥æŽ’åº�。看第一行å�¯ä»¥çŸ¥é�“, 创建的最多的对象是`int[]`数组. é¼ æ ‡å�³é”®å�•击这行, å°±å�¯ä»¥çœ‹åˆ°è¿™äº›å¯¹è±¡éƒ½åœ¨å“ªäº›åœ°æ–¹åˆ›å»ºçš„:
+
+
+
+与`hprof`相比, JVisualVM æ›´åŠ å®¹æ˜“ä½¿ç”¨ —— 比如上é�¢çš„æˆªå›¾ä¸, 在一个地方就å�¯ä»¥çœ‹åˆ°æ‰€æœ‰`int[]`的分é…�ä¿¡æ�¯, 所以多次在å�Œä¸€å¤„代ç �进行分é…�的情况就很容易å�‘现。
+
+### AProf
+
+最é‡�è¦�的一款分æž�器,是由 Devexperts å¼€å�‘çš„[**AProf**](https://code.devexperts.com/display/AProf/About+Aprof)。 内å˜åˆ†é…�分æž�器 AProf 也被打包为 Java agent 的形å¼�。
+
+用 AProf 分æž�应用程åº�, 需è¦�修改 JVM å�¯åŠ¨è„šæœ¬,ç±»ä¼¼è¿™æ ·:
+
+
+
+```
+java -javaagent:/path-to/aprof.jar com.yourcompany.YourApplication
+```
+
+
+
+é‡�å�¯åº”用之å�Ž, 工作目录下会生æˆ�一个`aprof.txt`æ–‡ä»¶ã€‚æ¤æ–‡ä»¶æ¯�分钟更新一次, 包å�«è¿™æ ·çš„ä¿¡æ�¯:
+
+
+
+```
+========================================================================================================================
+TOTAL allocation dump for 91,289 ms (0h01m31s)
+Allocated 1,769,670,584 bytes in 24,868,088 objects of 425 classes in 2,127 locations
+========================================================================================================================
+
+Top allocation-inducing locations with the data types allocated from them
+------------------------------------------------------------------------------------------------------------------------
+eu.plumbr.demo.largeheap.ManyTargetsGarbageProducer.newRandomClassObject: 1,423,675,776 (80.44%) bytes in 17,113,721 (68.81%) objects (avg size 83 bytes)
+ int[]: 711,322,976 (40.19%) bytes in 1,709,911 (6.87%) objects (avg size 416 bytes)
+ char[]: 369,550,816 (20.88%) bytes in 5,132,759 (20.63%) objects (avg size 72 bytes)
+ java.lang.reflect.Constructor: 136,800,000 (7.73%) bytes in 1,710,000 (6.87%) objects (avg size 80 bytes)
+ java.lang.Object[]: 41,079,872 (2.32%) bytes in 1,710,712 (6.87%) objects (avg size 24 bytes)
+ java.lang.String: 41,063,496 (2.32%) bytes in 1,710,979 (6.88%) objects (avg size 24 bytes)
+ java.util.ArrayList: 41,050,680 (2.31%) bytes in 1,710,445 (6.87%) objects (avg size 24 bytes)
+ ... cut for brevity ...
+```
+
+
+
+上é�¢çš„输出是按照`size`进行排åº�的。å�¯ä»¥çœ‹å‡º,`80.44%`çš„ bytes å’Œ`68.81%`çš„ objects 是在`ManyTargetsGarbageProducer.newRandomClassObject()`方法ä¸åˆ†é…�的。 å…¶ä¸,**int[]**数组å� 用了`40.19%`的内å˜, 是最大的一个。
+
+ç»§ç»å¾€ä¸‹çœ‹, 会å�‘现`allocation traces`(分é…�痕迹)相关的内容, 也是以 allocation size 排åº�çš„:
+
+
+
+```
+Top allocated data types with reverse location traces
+------------------------------------------------------------------------------------------------------------------------
+int[]: 725,306,304 (40.98%) bytes in 1,954,234 (7.85%) objects (avg size 371 bytes)
+ eu.plumbr.demo.largeheap.ClonableClass0006.: 38,357,696 (2.16%) bytes in 92,206 (0.37%) objects (avg size 416 bytes)
+ java.lang.reflect.Constructor.newInstance: 38,357,696 (2.16%) bytes in 92,206 (0.37%) objects (avg size 416 bytes)
+ eu.plumbr.demo.largeheap.ManyTargetsGarbageProducer.newRandomClassObject: 38,357,280 (2.16%) bytes in 92,205 (0.37%) objects (avg size 416 bytes)
+ java.lang.reflect.Constructor.newInstance: 416 (0.00%) bytes in 1 (0.00%) objects (avg size 416 bytes)
+... cut for brevity ...
+```
+
+
+
+å�¯ä»¥çœ‹åˆ°,`int[]`数组的分é…�, 在`ClonableClass0006`æž„é€ å‡½æ•°ä¸ç»§ç»å¢žå¤§ã€‚
+
+å’Œå…¶ä»–å·¥å…·ä¸€æ ·,`AProf`æ�露了 分é…�的大å°�以å�Šä½�置信æ�¯(`allocation size and locations`), 从而能够快速找到最耗内å˜çš„部分。在我们看æ�¥,**AProf**是最有用的分é…�分æž�器, å› ä¸ºå®ƒå�ªä¸“注于内å˜åˆ†é…�, 所以å�šå¾—最好。 当然, 这款工具是开æº�å…�费的, 资æº�开销也最å°�。
+
+请继ç»é˜…è¯»ä¸‹ä¸€ç« :7\. GC 调优(实战篇) - GCå�‚考手册
+
+原文链接:[GC Tuning: Tooling](https://plumbr.eu/handbook/gc-tuning-measuring)
+
+翻译时间: 2016年02月06日
+
+## å�‚考文ç«
+
+
+
+
+
+
+
+
+
+https://blog.csdn.net/android_hl/article/details/53228348
+
+
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\272\357\274\232JNDI\357\274\214OSGI\357\274\214Tomcat\347\261\273\345\212\240\350\275\275\345\231\250\345\256\236\347\216\260.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\272\357\274\232JNDI\357\274\214OSGI\357\274\214Tomcat\347\261\273\345\212\240\350\275\275\345\231\250\345\256\236\347\216\260.md"
new file mode 100644
index 0000000..6c1b066
--- /dev/null
+++ "b/docs/Java/JVM/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JNDI\357\274\214OSGI\357\274\214Tomcat\347\261\273\345\212\240\350\275\275\345\231\250\345\256\236\347\216\260.md"
@@ -0,0 +1,372 @@
+# 目录
+ * [æ‰“ç ´å�Œäº²å§”派模型](#æ‰“ç ´å�Œäº²å§”派模型)
+ * [JNDI](#jndi)
+ * [JNDI 的�解](#[jndi-的�解])
+ * [OSGI](#osgi)
+ * [1.如何æ£ç¡®çš„ç�†è§£å’Œè®¤è¯†OSGI技术?](#1如何æ£ç¡®çš„ç�†è§£å’Œè®¤è¯†osgi技术?)
+ * [Tomcatç±»åŠ è½½å™¨ä»¥å�Šåº”用间class隔离与共享](#tomcatç±»åŠ è½½å™¨ä»¥å�Šåº”用间class隔离与共享)
+ * [ç±»åŠ è½½å™¨](#ç±»åŠ è½½å™¨)
+ * [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
+
+
+
+本文转自互è�”网,侵åˆ
+
+æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
+> https://github.com/h2pl/Java-Tutorial
+
+喜欢的�麻烦点下Star哈
+
+æ–‡ç« å°†å�Œæ¥åˆ°æˆ‘的个人å�šå®¢ï¼š
+> www.how2playlife.com
+
+本文是微信公众å�·ã€�Java技术江湖】的《深入ç�†è§£JVM虚拟机》其ä¸ä¸€ç¯‡ï¼Œæœ¬æ–‡éƒ¨åˆ†å†…容æ�¥æº�于网络,为了把本文主题讲得清晰é€�彻,也整å�ˆäº†å¾ˆå¤šæˆ‘认为ä¸�错的技术å�šå®¢å†…容,引用其ä¸äº†ä¸€äº›æ¯”较好的å�šå®¢æ–‡ç« ,如有侵æ�ƒï¼Œè¯·è�”系作者。
+
+该系列å�šæ–‡ä¼šå‘Šè¯‰ä½ å¦‚ä½•ä»Žå…¥é—¨åˆ°è¿›é˜¶ï¼Œä¸€æ¥æ¥åœ°å¦ä¹ JVM基础知识,并上手进行JVM调优实战,JVM是æ¯�一个Java工程师必须è¦�å¦ä¹ å’Œç�†è§£çš„çŸ¥è¯†ç‚¹ï¼Œä½ å¿…é¡»è¦�掌æ�¡å…¶å®žçŽ°åŽŸç�†ï¼Œæ‰�能更完整地了解整个Java技术体系,形æˆ�自己的知识框架。
+
+ä¸ºäº†æ›´å¥½åœ°æ€»ç»“å’Œæ£€éªŒä½ çš„å¦ä¹ æˆ�æžœï¼Œæœ¬ç³»åˆ—æ–‡ç« ä¹Ÿä¼šæ��ä¾›æ¯�个知识点对应的é�¢è¯•题以å�Šå�‚è€ƒç”æ¡ˆã€‚
+
+å¦‚æžœå¯¹æœ¬ç³»åˆ—æ–‡ç« æœ‰ä»€ä¹ˆå»ºè®®ï¼Œæˆ–è€…æ˜¯æœ‰ä»€ä¹ˆç–‘é—®çš„è¯�,也å�¯ä»¥å…³æ³¨å…¬ä¼—å�·ã€�Java技术江湖】è�”ç³»ä½œè€…ï¼Œæ¬¢è¿Žä½ å�‚与本系列å�šæ–‡çš„åˆ›ä½œå’Œä¿®è®¢ã€‚
+
+
+
+## æ‰“ç ´å�Œäº²å§”派模型
+
+### JNDI
+
+### JNDI 的�解
+
+
+JNDI是 Java 命å��与文件夹接å�£ï¼ˆJava Naming and Directory Interface),在J2EEè§„èŒƒä¸æ˜¯é‡�è¦�的规范之ä¸çš„一个,ä¸�少专家觉得,没有é€�å½»ç�†è§£JNDIçš„æ„�ä¹‰å’Œä½œç”¨ï¼Œå°±æ²¡æœ‰çœŸæ£æŽŒæ�¡J2EE特别是EJB的知识。
+
+那么,JNDI究竟起什么作用?//带ç�€é—®é¢˜çœ‹æ–‡ç« 是最有效的
+
+�了解JNDI的作用,我们能够从“�设�用JNDI我们如何�?用了JNDI�我们�将如何�?�这个问题�探讨。
+
+没有JNDI的�法:
+
+程åº�猿开å�‘时,知é�“è¦�å¼€å�‘訪问MySQLæ•°æ�®åº“的应用,于是将一个对 MySQL JDBC 驱动程åº�类的引用进行了编ç �,并通过使用适当的 JDBC URL 连接到数æ�®åº“。
+å°±åƒ�以下代ç �è¿™æ ·ï¼š
+
+````
+ 1. Connectionconn=null;
+ 2. try{
+ 3. Class.forName("com.mysql.jdbc.Driver",
+ 4. true,Thread.currentThread().getContextClassLoader());
+ 5. conn=DriverManager.
+ 6. getConnection("jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue");
+ 7. ......
+ 8. conn.close();
+ 9. }catch(Exceptione){
+ 10. e.printStackTrace();
+ 11. }finally{
+ 12. if(conn!=null){
+ 13. try{
+ 14. conn.close();
+ 15. }catch(SQLExceptione){}
+ 16. }
+ 17. }
+````
+
+
+è¿™æ˜¯ä¼ ç»Ÿçš„å�šæ³•ï¼Œä¹Ÿæ˜¯æ›¾ç»�é�žJava程åº�猿(如Delphiã€�VBç‰ï¼‰å¸¸è§�çš„å�šæ³•ã€‚
+
+è¿™ç§�å�šæ³•ä¸€èˆ¬åœ¨å°�规模的开å�‘过程ä¸ä¸�会产生问题,仅仅è¦�程åº�猿熟悉Javaè¯è¨€ã€�了解JDBC技术和MySQL,能够é�žå¸¸å¿«å¼€å�‘出对应的应用程åº�。
+
+没有JNDIçš„å�𿳕å˜åœ¨çš„问题:
+
+ 1ã€�æ•°æ�®åº“serverå��ç§°MyDBServer ã€�usernameå’Œå�£ä»¤éƒ½å�¯èƒ½é¡»è¦�改å�˜ï¼Œç”±æ¤å¼•å�‘JDBC URLé¡»è¦�改动;
+ 2�数�库�能改用别的产�,如改用DB2或者Oracle,引�JDBC驱动程�包和类�须�改动;
+ 3ã€�éš�ç�€å®žé™…ä½¿ç”¨ç»ˆç«¯çš„æ·»åŠ ï¼ŒåŽŸé…�ç½®çš„è¿žæŽ¥æ± å�ƒæ•°å�¯èƒ½é¡»è¦�调整;
+ 4�......
+
+解决的方法:
+
+程åº�猿应该ä¸�é¡»è¦�关心“详细的数æ�®åº“å�Žå�°æ˜¯ä»€ä¹ˆï¼ŸJDBC驱动程åº�是什么?JDBC URLæ ¼å¼�是什么?訪问数æ�®åº“çš„usernameå’Œå�£ä»¤æ˜¯ä»€ä¹ˆï¼Ÿâ€�ç‰ç‰è¿™äº›é—®é¢˜ã€‚
+
+程åº�猿编写的程åº�应该没有对 JDBC驱动程åº�的引用,没有serverå��称,没实username称或å�£ä»¤ —— 甚至没有数æ�®åº“æ± æˆ–è¿žæŽ¥ç®¡ç�†ã€‚
+
+而是把这些问题交给J2EE容器(比方weblogic)��置和管�,程�猿仅仅须�对这些�置和管�进行引用就�以。
+
+ç”±æ¤ï¼Œå°±æœ‰äº†JNDI。
+
+//看的出æ�¥ã€‚æ˜¯ä¸ºäº†ä¸€ä¸ªæœ€æœ€æ ¸å¿ƒçš„é—®é¢˜ï¼šæ˜¯ä¸ºäº†è§£è€¦ï¼Œæ˜¯ä¸ºäº†å¼€å�‘å‡ºæ›´åŠ å�¯ç»´æŠ¤ã€�å�¯æ‰©å±•//的系统
+
+用了JNDI之�的�法:
+首先。在在J2EE容器ä¸é…�ç½®JNDIå�ƒæ•°ï¼Œå®šä¹‰ä¸€ä¸ªæ•°æ�®æº�。也就是JDBC引用å�ƒæ•°ï¼Œç»™è¿™ä¸ªæ•°æ�®æº�设置一个å��称;然å�Žï¼Œåœ¨ç¨‹åº�ä¸ï¼Œé€šè¿‡æ•°æ�®æº�å��称引用数æ�®æº�从而訪问å�Žå�°æ•°æ�®åº“。
+
+//红色的å—能够看出。JNDI是由j2ee容器æ��供的功能
+
+详细�作例如以下(以JBoss为例):
+1��置数��
+在JBoss 的 D:\jboss420GA\docs\examples\jca 文件夹以下。有�常多��数�库引用的数��定义模�。
+
+将当ä¸çš„ mysql-ds.xml 文件Copyåˆ°ä½ ä½¿ç”¨çš„server下,如 D:\jboss420GA\server\default\deploy。
+改动 mysql-ds.xml 文件的内容,使之能通过JDBCæ£ç¡®è¨ªé—®ä½ çš„MySQLæ•°æ�®åº“。例如以下:
+
+
+
+````
+
+
+
+MySqlDS
+jdbc:mysql://localhost:3306/lw
+com.mysql.jdbc.Driver
+root
+rootpassword
+
+org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter
+
+
+mySQL
+
+
+
+````
+
+
+这里,定义了一个å��为MySqlDS的数æ�®æº�。其å�ƒæ•°åŒ…å�«JDBCçš„URL。驱动类å��,usernameå�Šå¯†ç �ç‰ã€‚
+
+2ã€�在程åº�ä¸å¼•用数æ�®æº�:
+
+````
+1. Connectionconn=null;
+2. try{
+3. Contextctx=newInitialContext();
+4. ObjectdatasourceRef=ctx.lookup("java:MySqlDS");//引用数��
+5. DataSourceds=(Datasource)datasourceRef;
+6. conn=ds.getConnection();
+7. ......
+8. c.close();
+9. }catch(Exceptione){
+10. e.printStackTrace();
+11. }finally{
+12. if(conn!=null){
+13. try{
+14. conn.close();
+15. }catch(SQLExceptione){}
+16. }
+17. }
+````
+
+
+直接使用JDBC或者通过JNDI引用数æ�®æº�的编程代ç �é‡�ç›¸å·®æ— å‡ ï¼Œå�¯æ˜¯å¦‚今的程åº�能够ä¸�用关心详细JDBCå�ƒæ•°äº†ã€‚
+
+//解藕了。�扩展了
+在系统部署å�Žã€‚å�‡è®¾æ•°æ�®åº“的相关å�ƒæ•°å�˜æ›´ã€‚ä»…ä»…é¡»è¦�å�ˆä¸€æ¬¡é…�ç½® mysql-ds.xml 改动当ä¸çš„JDBCå�ƒæ•°ï¼Œä»…ä»…è¦�ä¿�è¯�æ•°æ�®æº�çš„å��ç§°ä¸�å�˜ï¼Œé‚£ä¹ˆç¨‹åº�æº�ç �å°±æ— éœ€æ”¹åŠ¨ã€‚
+
+ç”±æ¤å�¯è§�。JNDIé�¿å…�了程åº�与数æ�®åº“之间的紧耦å�ˆï¼Œä½¿åº”ç”¨æ›´åŠ æ˜“äºŽé…�ç½®ã€�易于部署。
+
+JNDI的扩展:
+JNDI在满足了数æ�®æº�é…�置的è¦�æ±‚çš„åŸºç¡€ä¸Šã€‚è¿˜è¿›ä¸€æ¥æ‰©å……了作用:全部与系统外部的资æº�的引用,都能够通过JNDI定义和引用。
+
+//注�什么�资�
+
+所以,在J2EE规范ä¸ï¼ŒJ2EE ä¸çš„资æº�å¹¶ä¸�å±€é™�于 JDBC æ•°æ�®æº�。
+
+引用的类型有é�žå¸¸å¤šï¼Œå½“ä¸åŒ…å�«èµ„æº�引用(已ç»�讨论过)ã€�环境实体和 EJB 引用。
+
+特别是 EJB 引用,它暴露了 JNDI 在 J2EE ä¸çš„å�¦å¤–一项关键角色:查找其它应用程åº�组件。
+
+EJB çš„ JNDI 引用é�žå¸¸ç›¸ä¼¼äºŽ JDBC 资æº�的引用。在æœ�务趋于转æ�¢çš„环境ä¸ï¼Œè¿™æ˜¯ä¸€ç§�é�žå¸¸æœ‰æ•ˆçš„æ–¹æ³•。能够对应用程åº�æž¶æž„ä¸æ‰€å¾—到的全部组件进行这类é…�置管ç�†ï¼Œä»Ž EJB 组件到 JMS 队列和主题。å†�到简å�•é…�ç½®å—符串或其它对象。这能够é™�低éš�时间的推移æœ�务å�˜æ›´æ‰€äº§ç”Ÿçš„维护æˆ�本,å�Œä¸€æ—¶å€™è¿˜èƒ½å¤Ÿç®€åŒ–部署,é™�低集æˆ�工作。外部资æº�â€�。
+
+总结:
+
+J2EE 规范è¦�求全部 J2EE 容器都è¦�æ��ä¾› JNDI 规范的实现。//sun 果然喜欢制定规范JNDI 在 J2EE ä¸çš„角色就是“交æ�¢æœºâ€� —— J2EE 组件在执行时间接地查找其它组件ã€�资æº�或æœ�务的通用机制。在多数情况下,æ��ä¾› JNDI 供应者的容器能够充当有é™�的数æ�®å˜å‚¨ã€‚è¿™æ ·ç®¡ç�†å‘˜å°±èƒ½å¤Ÿè®¾ç½®åº”用程åº�的执行属性,并让其它应用程åº�引用这些属性(Java 管ç�†æ‰©å±•(Java Management Extensions,JMX)也能够用作这个目的)。JNDI 在 J2EE 应用程åº�ä¸çš„主è¦�角色就是æ��ä¾›é—´æŽ¥å±‚ï¼Œè¿™æ ·ç»„ä»¶å°±èƒ½å¤Ÿå�‘现所须è¦�的资æº�,而ä¸�用了解这些间接性。
+
+在 J2EE ä¸ï¼ŒJNDI 是把 J2EE 应用程åº�å�ˆåœ¨ä¸€èµ·çš„粘å�ˆå‰‚。JNDI æ��供的间接寻å�€å�Œæ„�è·¨ä¼�业交付å�¯ä¼¸ç¼©çš„ã€�功能强大且é�žå¸¸ç�µæ´»çš„应用程åº�。
+
+这是 J2EE 的承诺,并且�过一些计划和预先考虑。这个承诺是全然能够实现的。
+
+ 从上é�¢çš„æ–‡ç« ä¸èƒ½å¤Ÿçœ‹å‡ºï¼š
+1ã€�JNDI æ��出的目的是为了解藕,是为了开å�‘æ›´åŠ easy维护,easy扩展。easy部署的应用。
+2�JNDI 是一个sun�出的一个规范(相似于jdbc),详细的实现是�个j2ee容器�供商。sun 仅仅是�求,j2ee容器必须有JNDI这�功能。
+
+3ã€�JNDI 在j2ee系统ä¸çš„角色是“交æ�¢æœºâ€�,是J2EE组件在执行时间接地查找其它组件ã€�资æº�或æœ�务的通用机制。
+4ã€�JNDI 是通过资æº�çš„å��å—æ�¥æŸ¥æ‰¾çš„,资æº�çš„å��å—在整个j2ee应用ä¸(j2ee容器ä¸)是唯一的。
+
+
+ 上文æ��到过å�Œäº²å§”派模型并ä¸�是一个强制性的约æ�Ÿæ¨¡åž‹ï¼Œè€Œæ˜¯Java设计者推è��给开å�‘è€…çš„ç±»åŠ è½½å™¨å®žçŽ°æ–¹å¼�。在Java的世界ä¸å¤§éƒ¨åˆ†çš„ç±»åŠ è½½å™¨éƒ½é�µå¾ªè¿™ä¸ªæ¨¡åž‹ï¼Œä½†ä¹Ÿæœ‰ä¾‹å¤–。
+
+ å�Œäº²å§”æ´¾æ¨¡åž‹çš„ä¸€æ¬¡â€œè¢«ç ´å��â€�是由这个模型自身的缺陷所导致的,å�Œäº²å§”派很好地解决了å�„ä¸ªç±»åŠ è½½å™¨çš„åŸºç¡€ç±»çš„ç»Ÿä¸€é—®é¢˜ï¼ˆè¶ŠåŸºç¡€çš„ç±»ç”±è¶Šä¸Šå±‚çš„åŠ è½½å™¨è¿›è¡ŒåŠ è½½ï¼‰ï¼ŒåŸºç¡€ç±»ä¹‹æ‰€ä»¥ç§°ä¸ºâ€œåŸºç¡€â€�ï¼Œæ˜¯å› ä¸ºå®ƒä»¬æ€»æ˜¯ä½œä¸ºè¢«ç”¨æˆ·ä»£ç �调用的API,但世事往往没有ç»�对的完美,如果基础类å�ˆè¦�调用回用户的代ç �,那该怎么办?
+
+这并é�žæ˜¯ä¸�å�¯èƒ½çš„事情,一个典型的例å�便是JNDIæœ�务,JNDI现在已ç»�是Javaçš„æ ‡å‡†æœ�务,它的代ç �ç”±å�¯åŠ¨ç±»åŠ è½½å™¨åŽ»åŠ è½½ï¼ˆåœ¨JDK 1.3时放进去的rt.jar),但JNDI的目的就是对资æº�进行集ä¸ç®¡ç�†å’ŒæŸ¥æ‰¾ï¼Œå®ƒéœ€è¦�调用由独立厂商实现并部署在应用程åº�çš„ClassPath下的JNDI接å�£æ��供者(SPI,Service Provider Interface)的代ç �,但å�¯åŠ¨ç±»åŠ è½½å™¨ä¸�å�¯èƒ½â€œè®¤è¯†â€�这些代ç �ï¼Œå› ä¸ºå�¯åŠ¨ç±»åŠ è½½å™¨çš„æ�œç´¢èŒƒå›´ä¸æ‰¾ä¸�到用户应用程åº�类,那该怎么办?
+
+
+为了解决这个问题,Java设计团队å�ªå¥½å¼•入了一个ä¸�å¤ªä¼˜é›…çš„è®¾è®¡ï¼šçº¿ç¨‹ä¸Šä¸‹æ–‡ç±»åŠ è½½å™¨ï¼ˆThread Context ClassLoaderï¼‰ã€‚è¿™ä¸ªç±»åŠ è½½å™¨å�¯ä»¥é€šè¿‡java.lang.Thread类的setContextClassLoader()方法进行设置,如果创建线程时还未设置,它将会从父线程ä¸ç»§æ‰¿ä¸€ä¸ªï¼Œå¦‚果在应用程åº�的全局范围内都没有设置过的è¯�ï¼Œé‚£è¿™ä¸ªç±»åŠ è½½å™¨é»˜è®¤å°±æ˜¯åº”ç”¨ç¨‹åº�ç±»åŠ è½½å™¨ï¼ˆApplication ClassLoader)。
+
+ æœ‰äº†çº¿ç¨‹ä¸Šä¸‹æ–‡ç±»åŠ è½½å™¨ï¼Œå°±å�¯ä»¥å�šä¸€äº›â€œèˆžå¼Šâ€�的事情了,JNDIæœ�åŠ¡ä½¿ç”¨è¿™ä¸ªçº¿ç¨‹ä¸Šä¸‹æ–‡ç±»åŠ è½½å™¨åŽ»åŠ è½½æ‰€éœ€è¦�çš„SPI代ç �ï¼Œä¹Ÿå°±æ˜¯çˆ¶ç±»åŠ è½½å™¨è¯·æ±‚å�ç±»åŠ è½½å™¨åŽ»å®Œæˆ�ç±»åŠ è½½çš„åŠ¨ä½œï¼Œè¿™ç§�行为实际上就是打通了å�Œäº²å§”派模型的层次结构æ�¥é€†å�‘ä½¿ç”¨ç±»åŠ è½½å™¨ï¼Œå®žé™…ä¸Šå·²ç»�è¿�背了å�Œäº²å§”æ´¾æ¨¡åž‹çš„ä¸€èˆ¬æ€§åŽŸåˆ™ï¼Œä½†è¿™ä¹Ÿæ˜¯æ— å�¯å¥ˆä½•的事情。Java䏿‰€æœ‰æ¶‰å�ŠSPIçš„åŠ è½½åŠ¨ä½œåŸºæœ¬ä¸Šéƒ½é‡‡ç”¨è¿™ç§�æ–¹å¼�,例如JNDIã€�JDBCã€�JCEã€�JAXBå’ŒJBIç‰ã€‚
+
+
+
+## OSGI
+
+
+
+ç›®å‰�,业内关于OSGI技术的å¦ä¹ 资æº�或者技术文档还是很少的。我在æŸ�å®�网æ�œç´¢äº†ä¸€ä¸‹â€œOSGIâ€�的书ç±�,结果倒是有,但是ç§�类少的å�¯æ€œï¼Œè€Œä¸”å‡ ä¹Žæ²¡æœ‰äººè´ä¹°ã€‚
+å› ä¸ºå·¥ä½œçš„åŽŸå› æˆ‘éœ€è¦�å¦ä¹ OSGI,所以我ä¸�å¾—ä¸�想尽办法æ�¥ä¸»åЍå¦ä¹ OSGI。我将用文å—记录å¦ä¹ OSGI的整个过程,通过整ç�†ä¹¦ç±�和视频教程,æ�¥è®©æˆ‘æ›´åŠ äº†è§£è¿™é—¨æŠ€æœ¯ï¼Œå�Œæ—¶ä¹Ÿè®©éœ€è¦�å¦ä¹ 这门技术的å�Œå¿—们有一个清晰的å¦ä¹ 路线。
+
+我们需è¦�è§£å†³ä¸€ä¸‹å‡ é—®é¢˜:
+
+### 1.如何æ£ç¡®çš„ç�†è§£å’Œè®¤è¯†OSGI技术?
+
+我们从外文资料上或者从翻译过æ�¥çš„资料上看到OSGi解释和定义,都是直译过æ�¥çš„,但是OSGI的真实æ„�ä¹‰æœªå¿…æ˜¯ä¸æ–‡ç›´è¯‘过æ�¥çš„æ„�æ€�。OSGI的解释就是Open Service Gateway Initiative,直译过æ�¥å°±æ˜¯â€œå¼€æ”¾çš„æœ�务入å�£(网关)çš„åˆ�始化â€�,å�¬èµ·æ�¥é�žå¸¸è´¹è§£ï¼Œä»€ä¹ˆæ˜¯æœ�务入å�£åˆ�始化?
+
+所以我们�去直译这个OSGI,我们�一�说法��述OSGI技术。
+
+我们æ�¥å›žåˆ°æˆ‘们以å‰�çš„æŸ�些开å�‘场景ä¸åŽ»ï¼Œå�‡è®¾æˆ‘们使用SSH(struts+spring+hibernate)框架æ�¥å¼€å�‘我们的Web项目,我们å�šäº§å“�设计和开å�‘的时候都是分模å�—的,我们分模å�—的目的就是实现模å�—之间的“解耦â€�,更进一æ¥çš„目的是方便对一个项目的控制和管ç�†ã€‚
+我们对一个项目进行模å�—化分解之å�Žï¼Œæˆ‘们就å�¯ä»¥æŠŠä¸�å�Œæ¨¡å�—交给ä¸�å�Œçš„å¼€å�‘人员æ�¥å®Œæˆ�å¼€å�‘,然å�Žé¡¹ç›®ç»�ç�†æŠŠå¤§å®¶å®Œæˆ�的模å�—集ä¸åœ¨ä¸€èµ·ï¼Œç„¶å�Žæ‹¼è£…æˆ�一个最终的产å“�。一般我们开å�‘éƒ½æ˜¯è¿™æ ·çš„åŸºæœ¬æƒ…å†µã€‚
+
+那么我们开å�‘çš„æ—¶å€™é¢„è®¡çš„æ˜¯ç³»ç»Ÿçš„åŠŸèƒ½ï¼Œæ ¹æ�®ç³»ç»Ÿçš„功能æ�¥è¿›è¡Œæ¨¡å�—的划分,也就是说,这个产å“�的功能或客户的需求是划分的é‡�è¦�ä¾�æ�®ã€‚
+
+但是我们在开å�‘过程ä¸ï¼Œæˆ‘们模å�—之间还è¦�å½¼æ¤ä¿�æŒ�è�”系,比如A模å�—è¦�从B模å�—拿到一些数æ�®ï¼Œè€ŒB模å�—å�¯èƒ½è¦�调用C模å�—ä¸çš„一些方法(除了公共底层的工具类之外)。所以这些模å�—å�ªæ˜¯ä¸€ç§�逻辑æ„�义上的划分。
+
+最é‡�è¦�的一点是,我们把最终的项目è¦�去部署到tomcat或者jBossçš„æœ�务器ä¸åŽ»éƒ¨ç½²ã€‚é‚£ä¹ˆæˆ‘ä»¬å�¯åЍæœ�务器的时候,能ä¸�能关é—项目的æŸ�个模å�—或功能呢?很明显是å�šä¸�到的,一旦æœ�务器å�¯åŠ¨ï¼Œæ‰€æœ‰æ¨¡å�—å°±è¦�一起å�¯åŠ¨ï¼Œéƒ½è¦�å� 用æœ�务器资æº�,所以关é—ä¸�了模å�—,å�‡è®¾èƒ½å¼ºåˆ¶æ‹¿æŽ‰ï¼Œå°±ä¼šå½±å“�其它的功能。
+
+ä»¥ä¸Šå°±æ˜¯æˆ‘ä»¬ä¼ ç»Ÿæ¨¡å�—å¼�å¼€å�‘的一些局é™�性。
+
+我们å�šè½¯ä»¶å¼€å�‘一直在追求一个境界,就是模å�—之间的真æ£â€œè§£è€¦â€�ã€�“分离â€�ï¼Œè¿™æ ·æˆ‘ä»¬åœ¨è½¯ä»¶çš„ç®¡ç�†å’Œå¼€å�‘上é�¢å°±ä¼šæ›´åŠ çš„ç�µæ´»ï¼Œç”šè‡³åŒ…括给客户部署项目的时候都å�¯ä»¥å�šåˆ°æ›´åŠ çš„ç�µæ´»å�¯æŽ§ã€‚但是我们以å‰�使用SSHæ¡†æž¶ç‰æž¶æž„模å¼�进行产å“�å¼€å�‘的时候我们是达ä¸�到这ç§�è¦�求的。
+
+所以我们“架构师�或顶尖的技术高手都在为模�化开�努力的摸索和�试,然�我们的OSGI的技术规范就应�而生。
+
+现在我们的OSGI技术就å�¯ä»¥æ»¡è¶³æˆ‘们之å‰�所说的境界:在ä¸�å�Œçš„æ¨¡å�—ä¸å�šåˆ°å½»åº•的分离,而ä¸�是逻辑æ„�义上的分离,是物ç�†ä¸Šçš„分离,也就是说在è¿�行部署之å�Žéƒ½å�¯ä»¥åœ¨ä¸�å�œæ¢æœ�务器的时候直接把æŸ�些模å�—拿下æ�¥ï¼Œå…¶ä»–模å�—的功能也ä¸�å�—å½±å“�。
+
+ç”±æ¤ï¼ŒOSGI技术将æ�¥ä¼šå�˜å¾—é�žå¸¸çš„é‡�è¦�ï¼Œå› ä¸ºå®ƒåœ¨å®žçŽ°æ¨¡å�—化解耦的路上,走得比现在大家ç»�常所用的SSH框架走的更远。这个技术在未æ�¥å¤§è§„模ã€�高访问ã€�高并å�‘çš„Java模å�—化开å�‘领域,或者是项目规范化管ç�†ä¸ï¼Œä¼šå¤§å¤§è¶…过SSHç‰æ¡†æž¶çš„地ä½�。
+
+现在主�的一些应用�务器,Oracle的weblogic�务器,IBM的WebSphere,JBoss,还有Sun公�的glassfish�务器,都对OSGI�供了强大的支�,都是在OSGI的技术基础上实现的。有那么多的大型厂商支�OSGI这门技术,我们既�以看到OSGI技术的��性。所以将�OSGI是将��常��的技术。
+
+但是OSGIä»�然脱离ä¸�了框架的支æŒ�ï¼Œå› ä¸ºOSGI本身也使用了很多springç‰æ¡†æž¶çš„基本控件(å› ä¸ºè¦�实现AOPä¾�赖注入ç‰åŠŸèƒ½),但是哪个项目å�ˆä¸�去ä¾�赖第三方jar呢?
+
+
+ å�Œäº²å§”派模型的å�¦ä¸€æ¬¡â€œè¢«ç ´å��â€�是由于用户对程åº�动æ€�性的追求而导致的,这里所说的“动æ€�性â€�指的是当å‰�一些é�žå¸¸â€œçƒé—¨â€�çš„å��è¯�:代ç �çƒæ›¿æ�¢ï¼ˆHotSwap)ã€�模å�—çƒéƒ¨ç½²ï¼ˆHotDeployment)ç‰ï¼Œè¯´ç™½äº†å°±æ˜¯å¸Œæœ›åº”用程åº�能åƒ�æˆ‘ä»¬çš„è®¡ç®—æœºå¤–è®¾é‚£æ ·ï¼ŒæŽ¥ä¸Šé¼ æ ‡ã€�U盘,ä¸�用é‡�å�¯æœºå™¨å°±èƒ½ç«‹å�³ä½¿ç”¨ï¼Œé¼ æ ‡æœ‰é—®é¢˜æˆ–è¦�å�‡çº§å°±æ�¢ä¸ªé¼ æ ‡ï¼Œä¸�用å�œæœºä¹Ÿä¸�用é‡�å�¯ã€‚
+
+ 对于个人计算机æ�¥è¯´ï¼Œé‡�å�¯ä¸€æ¬¡å…¶å®žæ²¡æœ‰ä»€ä¹ˆå¤§ä¸�了的,但对于一些生产系统æ�¥è¯´ï¼Œå…³æœºé‡�å�¯ä¸€æ¬¡å�¯èƒ½å°±è¦�被列为生产事故,这ç§�情况下çƒéƒ¨ç½²å°±å¯¹è½¯ä»¶å¼€å�‘者,尤其是ä¼�业级软件开å�‘者具有很大的å�¸å¼•力。Sunå…¬å�¸æ‰€æ��出的JSR-294ã€�JSR-277规范在与JCP组织的模å�—化规范之争ä¸è�½è´¥ç»™JSR-291(å�³OSGi R4.2),虽然Sunä¸�甘失去Java模å�—化的主导æ�ƒï¼Œç‹¬ç«‹åœ¨å�‘展Jigsaw项目,但目å‰�OSGiå·²ç»�æˆ�为了业界“事实上â€�çš„Java模å�—åŒ–æ ‡å‡†ï¼Œè€ŒOSGi实现模å�—化çƒéƒ¨ç½²çš„å…³é”®åˆ™æ˜¯å®ƒè‡ªå®šä¹‰çš„ç±»åŠ è½½å™¨æœºåˆ¶çš„å®žçŽ°ã€‚
+
+ æ¯�一个程åº�模å�—(OSGiä¸ç§°ä¸ºBundleï¼‰éƒ½æœ‰ä¸€ä¸ªè‡ªå·±çš„ç±»åŠ è½½å™¨ï¼Œå½“éœ€è¦�æ›´æ�¢ä¸€ä¸ªBundle时,就把Bundle连å�Œç±»åŠ è½½å™¨ä¸€èµ·æ�¢æŽ‰ä»¥å®žçް代ç �çš„çƒæ›¿æ�¢ã€‚
+
+ 在OSGiçŽ¯å¢ƒä¸‹ï¼Œç±»åŠ è½½å™¨ä¸�å†�是å�Œäº²å§”派模型ä¸çš„æ ‘状结构,而是进一æ¥å�‘å±•ä¸ºæ›´åŠ å¤�æ�‚çš„ç½‘çŠ¶ç»“æž„ï¼Œå½“æ”¶åˆ°ç±»åŠ è½½è¯·æ±‚æ—¶ï¼ŒOSGi将按照下é�¢çš„顺åº�进行类æ�œç´¢ï¼š
+
+ 1)将以java.*å¼€å¤´çš„ç±»å§”æ´¾ç»™çˆ¶ç±»åŠ è½½å™¨åŠ è½½ã€‚
+
+ 2)å�¦åˆ™ï¼Œå°†å§”派列表å��å�•å†…çš„ç±»å§”æ´¾ç»™çˆ¶ç±»åŠ è½½å™¨åŠ è½½ã€‚
+
+ 3)å�¦åˆ™ï¼Œå°†Import列表ä¸çš„类委派给Export这个类的Bundleçš„ç±»åŠ è½½å™¨åŠ è½½ã€‚
+
+ 4)å�¦åˆ™ï¼ŒæŸ¥æ‰¾å½“å‰�Bundleçš„ClassPathï¼Œä½¿ç”¨è‡ªå·±çš„ç±»åŠ è½½å™¨åŠ è½½ã€‚
+
+ 5)å�¦åˆ™ï¼ŒæŸ¥æ‰¾ç±»æ˜¯å�¦åœ¨è‡ªå·±çš„Fragment Bundleä¸ï¼Œå¦‚果在,则委派给Fragment Bundleçš„ç±»åŠ è½½å™¨åŠ è½½ã€‚
+
+ 6)å�¦åˆ™ï¼ŒæŸ¥æ‰¾Dynamic Import列表的Bundle,委派给对应Bundleçš„ç±»åŠ è½½å™¨åŠ è½½ã€‚
+
+ 7)�则,类查找失败。
+
+ 上é�¢çš„æŸ¥æ‰¾é¡ºåº�ä¸å�ªæœ‰å¼€å¤´ä¸¤ç‚¹ä»�然符å�ˆå�Œäº²å§”æ´¾è§„åˆ™ï¼Œå…¶ä½™çš„ç±»æŸ¥æ‰¾éƒ½æ˜¯åœ¨å¹³çº§çš„ç±»åŠ è½½å™¨ä¸è¿›è¡Œçš„。
+
+ å�ªè¦�有足够æ„�义和ç�†ç”±ï¼Œçª�ç ´å·²æœ‰çš„åŽŸåˆ™å°±å�¯è®¤ä¸ºæ˜¯ä¸€ç§�创新。æ£å¦‚OSGiä¸çš„ç±»åŠ è½½å™¨å¹¶ä¸�符å�ˆä¼ 统的å�Œäº²å§”æ´¾çš„ç±»åŠ è½½å™¨ï¼Œå¹¶ä¸”ä¸šç•Œå¯¹å…¶ä¸ºäº†å®žçŽ°çƒéƒ¨ç½²è€Œå¸¦æ�¥çš„é¢�外的高å¤�æ�‚度还å˜åœ¨ä¸�少争议,但在Java程åº�员ä¸åŸºæœ¬æœ‰ä¸€ä¸ªå…±è¯†ï¼šOSGiä¸å¯¹ç±»åŠ è½½å™¨çš„ä½¿ç”¨æ˜¯å¾ˆå€¼å¾—å¦ä¹ 的,弄懂了OSGi的实现,就å�¯ä»¥ç®—是掌æ�¡äº†ç±»åŠ è½½å™¨çš„ç²¾é«“ã€‚
+
+
+## Tomcatç±»åŠ è½½å™¨ä»¥å�Šåº”用间class隔离与共享
+
+
+
+Tomcatçš„ç”¨æˆ·ä¸€å®šéƒ½ä½¿ç”¨è¿‡å…¶åº”ç”¨éƒ¨ç½²åŠŸèƒ½ï¼Œæ— è®ºæ˜¯ç›´æŽ¥æ‹·è´�文件到webapps目录,还是修改server.xml以目录的形å¼�éƒ¨ç½²ï¼Œæˆ–è€…æ˜¯å¢žåŠ è™šæ‹Ÿä¸»æœºï¼ŒæŒ‡å®šæ–°çš„appBaseç‰ç‰ã€‚
+
+但部署应用时,ä¸�知é�“ä½ æ˜¯å�¦æ›¾æ³¨æ„�è¿‡è¿™å‡ ç‚¹ï¼š
+
+1. 如果在一个Tomcat内部署多个应用,甚至多个应用内使用了æŸ�ä¸ªç±»ä¼¼çš„å‡ ä¸ªä¸�å�Œç‰ˆæœ¬ï¼Œä½†å®ƒä»¬ä¹‹é—´å�´äº’ä¸�å½±å“�。这是如何å�šåˆ°çš„。
+
+2. 如果多个应用都用到了æŸ�类似的相å�Œç‰ˆæœ¬ï¼Œæ˜¯å�¦å�¯ä»¥ç»Ÿä¸€æ��供,ä¸�在å�„个应用内分别æ��供,å� 用内å˜å‘¢ã€‚
+
+3. 还有时候,在开å�‘Web应用时,在pom.xml䏿·»åŠ äº†servlet-apiçš„ä¾�赖,那实际应用的classåŠ è½½æ—¶ï¼Œä¼šåŠ è½½ä½ çš„servlet-api 这个jarå�—
+
+以上æ��åˆ°çš„è¿™å‡ ç‚¹ï¼Œåœ¨Tomcat以å�Šå�„类的应用æœ�务器ä¸ï¼Œéƒ½æ˜¯é€šè¿‡ç±»åŠ è½½å™¨ï¼ˆClasssLoader)æ�¥å®žçŽ°çš„ã€‚é€šè¿‡æœ¬æ–‡ï¼Œä½ å�¯ä»¥äº†è§£åˆ°Tomcat内部æ��供的å�„ç§�ç±»åŠ è½½å™¨ï¼ŒWeb应用的class和资æº�ç‰åŠ è½½çš„æ–¹å¼�,以å�Šå…¶å†…部的实现原ç�†ã€‚在é�‡åˆ°ç±»ä¼¼é—®é¢˜æ—¶ï¼Œæ›´èƒ¸æœ‰æˆ�竹。
+
+### ç±»åŠ è½½å™¨
+
+Javaè¯è¨€æœ¬èº«ï¼Œä»¥å�ŠçŽ°åœ¨å…¶å®ƒçš„ä¸€äº›åŸºäºŽJVM之上的è¯è¨€(Groovy,Jython, Scala...),都是在将代ç �编译生æˆ�class文件,以实现跨多平å�°ï¼Œwrite once, run anywhere。最终的这些class文件,在应用ä¸ï¼Œå�ˆè¢«åŠ è½½åˆ°JVM虚拟机ä¸ï¼Œå¼€å§‹å·¥ä½œã€‚而把classæ–‡ä»¶åŠ è½½åˆ°JVMçš„ç»„ä»¶ï¼Œå°±æ˜¯æˆ‘ä»¬æ‰€è¯´çš„ç±»åŠ è½½å™¨ã€‚è€Œå¯¹äºŽç±»åŠ è½½å™¨çš„æŠ½è±¡ï¼Œèƒ½é�¢å¯¹æ›´å¤šçš„classæ•°æ�®æ��供形å¼�,例如网络ã€�文件系统ç‰ã€‚
+
+Javaä¸å¸¸è§�的那个ClassNotFoundExceptionå’ŒNoClassDefFoundErrorå°±æ˜¯ç±»åŠ è½½å™¨å‘Šè¯‰æˆ‘ä»¬çš„ã€‚
+
+Servletè§„èŒƒæŒ‡å‡ºï¼Œå®¹å™¨ç”¨äºŽåŠ è½½Web应用内Servletçš„class loader, å…�è®¸åŠ è½½ä½�于Web应用内的资æº�。但ä¸�å…�许é‡�写java.*, javax.*以å�Šå®¹å™¨å®žçŽ°çš„ç±»ã€‚å�Œæ—¶
+
+æ¯�个应用内使用Thread.currentThread.getContextClassLoader()èŽ·å¾—çš„ç±»åŠ è½½å™¨ï¼Œéƒ½æ˜¯è¯¥åº”ç”¨åŒºåˆ«äºŽå…¶å®ƒåº”ç”¨çš„ç±»åŠ è½½å™¨ç‰ç‰ã€‚
+
+æ ¹æ�®Servlet规范,å�„个应用æœ�务器厂商自行实现。所以åƒ�其他的一些应用æœ�åŠ¡å™¨ä¸€æ ·ï¼Œ Tomcat也æ��供了多ç§�çš„ç±»åŠ è½½å™¨ï¼Œä»¥ä¾¿åº”ç”¨æœ�务器内的class以å�Šéƒ¨ç½²çš„Web应用类文件è¿�è¡Œåœ¨å®¹å™¨ä¸æ—¶ï¼Œå�¯ä»¥ä½¿ç”¨ä¸�å�Œçš„class repositories。
+
+在Javaä¸ï¼Œç±»åŠ è½½å™¨æ˜¯ä»¥ä¸€ç§�父å�å…³ç³»æ ‘æ�¥ç»„织的。除Bootstrap外,都会包å�«ä¸€ä¸ªparent ç±»åŠ è½½å™¨ã€‚(这里写parent ç±»åŠ è½½å™¨ï¼Œè€Œä¸�æ˜¯çˆ¶ç±»åŠ è½½å™¨ï¼Œä¸�是为了装X,是为了é�¿å…�å’ŒJava里的父类混淆)ä¸€èˆ¬ä»¥ç±»åŠ è½½å™¨éœ€è¦�åŠ è½½ä¸€ä¸ªclass或者资æº�文件的时候,他会先委托给他的parentç±»åŠ è½½å™¨ï¼Œè®©parentç±»åŠ è½½å™¨å…ˆæ�¥åŠ è½½ï¼Œå¦‚æžœæ²¡æœ‰ï¼Œæ‰�å†�åœ¨è‡ªå·±çš„è·¯å¾„ä¸ŠåŠ è½½ã€‚è¿™å°±æ˜¯äººä»¬å¸¸è¯´çš„å�Œäº²å§”托,å�³æŠŠç±»åŠ è½½çš„è¯·æ±‚å§”æ‰˜ç»™parent。
+
+但是...,这里需�注�一下
+
+> 对于Webåº”ç”¨çš„ç±»åŠ è½½ï¼Œå’Œä¸Šé�¢çš„å�Œäº²å§”托是有区别的。
+
+ 主æµ�çš„Java Webæœ�务器(也就是Web容器),如Tomcatã€�Jettyã€�WebLogicã€�WebSphere或其他笔者没有列举的æœ�åŠ¡å™¨ï¼Œéƒ½å®žçŽ°äº†è‡ªå·±å®šä¹‰çš„ç±»åŠ è½½å™¨ï¼ˆä¸€èˆ¬éƒ½ä¸�æ¢ä¸€ä¸ªï¼‰ã€‚å› ä¸ºä¸€ä¸ªåŠŸèƒ½å�¥å…¨çš„Web容器,è¦�è§£å†³å¦‚ä¸‹å‡ ä¸ªé—®é¢˜ï¼š
+
+ 1)部署在å�Œä¸€ä¸ªWeb容器上的两个Web应用程åº�所使用的Java类库å�¯ä»¥å®žçŽ°ç›¸äº’éš”ç¦»ã€‚è¿™æ˜¯æœ€åŸºæœ¬çš„éœ€æ±‚ï¼Œä¸¤ä¸ªä¸�å�Œçš„应用程åº�å�¯èƒ½ä¼šä¾�èµ–å�Œä¸€ä¸ªç¬¬ä¸‰æ–¹ç±»åº“çš„ä¸�å�Œç‰ˆæœ¬ï¼Œä¸�能è¦�求一个类库在一个æœ�务器ä¸å�ªæœ‰ä¸€ä»½ï¼Œæœ�务器应当ä¿�è¯�两个应用程åº�的类库å�¯ä»¥äº’相独立使用。
+
+ 2)部署在å�Œä¸€ä¸ªWeb容器上的两个Web应用程åº�所使用的Java类库å�¯ä»¥äº’相共享。这个需求也很常è§�,例如,用户å�¯èƒ½æœ‰10个使用[spring](https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Flink.juejin.im%2F%3Ftarget%3Dhttp%253A%252F%252Flib.csdn.net%252Fbase%252Fjavaee "Java EE知识库")组织的应用程åº�部署在å�Œä¸€å�°æœ�务器上,如果把10份Springåˆ†åˆ«å˜æ”¾åœ¨å�„个应用程åº�的隔离目录ä¸ï¼Œå°†ä¼šæ˜¯å¾ˆå¤§çš„资æº�浪费——这主è¦�倒ä¸�是浪费ç£�盘空间的问题,而是指类库在使用时都è¦�è¢«åŠ è½½åˆ°Web容器的内å˜ï¼Œå¦‚果类库ä¸�能共享,虚拟机的方法区就会很容易出现过度膨胀的风险。
+
+ 3)Web容器需è¦�å°½å�¯èƒ½åœ°ä¿�è¯�自身的安全ä¸�å�—部署的Web应用程åº�å½±å“�。目å‰�,有许多主æµ�çš„Java Web容器自身也是使用Javaè¯è¨€æ�¥å®žçŽ°çš„ã€‚å› æ¤ï¼ŒWeb容器本身也有类库ä¾�赖的问题,一般æ�¥è¯´ï¼ŒåŸºäºŽå®‰å…¨è€ƒè™‘,容器所使用的类库应该与应用程åº�的类库互相独立。
+
+ 4)支æŒ�JSP应用的Web容器,大多数都需è¦�支æŒ�HotSwap功能。我们知é�“,JSP文件最终è¦�编译æˆ�Java Classæ‰�能由虚拟机执行,但JSP文件由于其纯文本å˜å‚¨çš„特性,è¿�行时修改的概率远远大于第三方类库或程åº�自身的Class文件。而且ASPã€�[PHP](https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Flink.juejin.im%2F%3Ftarget%3Dhttp%253A%252F%252Flib.csdn.net%252Fbase%252Fphp "PHP知识库")å’ŒJSP这些网页应用也把修改å�Žæ— é¡»é‡�å�¯ä½œä¸ºä¸€ä¸ªå¾ˆå¤§çš„“优势â€�æ�¥çœ‹å¾…ï¼Œå› æ¤â€œä¸»æµ�â€�çš„Web容器都会支æŒ�JSP生æˆ�ç±»çš„çƒæ›¿æ�¢ï¼Œå½“然也有“é�žä¸»æµ�â€�的,如è¿�行在生产模å¼�(Production Mode)下的WebLogicæœ�务器默认就ä¸�会处ç�†JSP文件的å�˜åŒ–。
+
+ 由于å˜åœ¨ä¸Šè¿°é—®é¢˜ï¼Œåœ¨éƒ¨ç½²Web应用时,å�•独的一个Class Pathå°±æ— æ³•æ»¡è¶³éœ€æ±‚äº†ï¼Œæ‰€ä»¥å�„ç§�Web容都“ä¸�约而å�Œâ€�地æ��ä¾›äº†å¥½å‡ ä¸ªClass Pathè·¯å¾„ä¾›ç”¨æˆ·å˜æ”¾ç¬¬ä¸‰æ–¹ç±»åº“,这些路径一般都以“libâ€�或“classesâ€�命å��。被放置到ä¸�å�Œè·¯å¾„ä¸çš„类库,具备ä¸�å�Œçš„访问范围和æœ�务对象,通常,æ¯�ä¸€ä¸ªç›®å½•éƒ½ä¼šæœ‰ä¸€ä¸ªç›¸åº”çš„è‡ªå®šä¹‰ç±»åŠ è½½å™¨åŽ»åŠ è½½æ”¾ç½®åœ¨é‡Œé�¢çš„Java类库。现在,就以Tomcat容器为例,看一看Tomcatå…·ä½“æ˜¯å¦‚ä½•è§„åˆ’ç”¨æˆ·ç±»åº“ç»“æž„å’Œç±»åŠ è½½å™¨çš„ã€‚
+
+ 在Tomcat目录结构ä¸ï¼Œæœ‰3组目录(“/common/*â€�ã€�“/server/*â€�和“/shared/*â€�)å�¯ä»¥å˜æ”¾Java类库,å�¦å¤–还å�¯ä»¥åŠ ä¸ŠWeb应用程åº�自身的目录“/WEB-INF/*â€�,一共4组,把Java类库放置在这些目录ä¸çš„å�«ä¹‰åˆ†åˆ«å¦‚下:
+
+ ①放置在/common目录ä¸ï¼šç±»åº“å�¯è¢«Tomcat和所有的Web应用程åº�å…±å�Œä½¿ç”¨ã€‚
+
+ ②放置在/server目录ä¸ï¼šç±»åº“å�¯è¢«Tomcat使用,对所有的Web应用程åº�都ä¸�å�¯è§�。
+
+ ③放置在/shared目录ä¸ï¼šç±»åº“å�¯è¢«æ‰€æœ‰çš„Web应用程åº�å…±å�Œä½¿ç”¨ï¼Œä½†å¯¹Tomcat自己ä¸�å�¯è§�。
+
+ ④放置在/WebApp/WEB-INF目录ä¸ï¼šç±»åº“ä»…ä»…å�¯ä»¥è¢«æ¤Web应用程åº�使用,对Tomcat和其他Web应用程åº�都ä¸�å�¯è§�。
+
+ 为了支æŒ�这套目录结构,并对目录里é�¢çš„ç±»åº“è¿›è¡ŒåŠ è½½å’Œéš”ç¦»ï¼ŒTomcatè‡ªå®šä¹‰äº†å¤šä¸ªç±»åŠ è½½å™¨ï¼Œè¿™äº›ç±»åŠ è½½å™¨æŒ‰ç…§ç»�典的å�Œäº²å§”派模型æ�¥å®žçŽ°ï¼Œå…¶å…³ç³»å¦‚ä¸‹å›¾æ‰€ç¤ºã€‚
+
+
+
+
+
+
+
+
+
+
+ 上图ä¸ç�°è‰²èƒŒæ™¯çš„3ä¸ªç±»åŠ è½½å™¨æ˜¯JDK默认æ��ä¾›çš„ç±»åŠ è½½å™¨ï¼Œè¿™3ä¸ªåŠ è½½å™¨çš„ä½œç”¨å·²ç»�介ç»�过了。而CommonClassLoaderã€�CatalinaClassLoaderã€�SharedClassLoaderå’ŒWebappClassLoader则是Tomcatè‡ªå·±å®šä¹‰çš„ç±»åŠ è½½å™¨ï¼Œå®ƒä»¬åˆ†åˆ«åŠ è½½/common/*ã€�/server/*ã€�/shared/*å’Œ/WebApp/WEB-INF/*ä¸çš„Java类库。其ä¸WebAppç±»åŠ è½½å™¨å’ŒJspç±»åŠ è½½å™¨é€šå¸¸ä¼šå˜åœ¨å¤šä¸ªå®žä¾‹ï¼Œæ¯�一个Web应用程åº�对应一个WebAppç±»åŠ è½½å™¨ï¼Œæ¯�一个JSP文件对应一个Jspç±»åŠ è½½å™¨ã€‚
+
+ 从图ä¸çš„委派关系ä¸å�¯ä»¥çœ‹å‡ºï¼ŒCommonClassLoaderèƒ½åŠ è½½çš„ç±»éƒ½å�¯ä»¥è¢«CatalinaClassLoaderå’ŒSharedClassLoader使用,而CatalinaClassLoaderå’ŒSharedClassLoaderè‡ªå·±èƒ½åŠ è½½çš„ç±»åˆ™ä¸Žå¯¹æ–¹ç›¸äº’éš”ç¦»ã€‚WebAppClassLoaderå�¯ä»¥ä½¿ç”¨SharedClassLoaderåŠ è½½åˆ°çš„ç±»ï¼Œä½†å�„个WebAppClassLoader实例之间相互隔离。
+
+ 而JasperLoaderçš„åŠ è½½èŒƒå›´ä»…ä»…æ˜¯è¿™ä¸ªJSP文件所编译出æ�¥çš„那一个.Class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替æ�¢æŽ‰ç›®å‰�çš„JasperLoader的实例,并通过å†�建立一个新的Jspç±»åŠ è½½å™¨æ�¥å®žçްJSP文件的HotSwap功能。
+
+对于Tomcatçš„6.x版本,å�ªæœ‰æŒ‡å®šäº†tomcat/conf/catalina.propertiesé…�置文件的server.loaderå’Œshare.loader项å�Žæ‰�会真æ£å»ºç«‹CatalinaClassLoaderå’ŒShared ClassLoader的实例,å�¦åˆ™åœ¨ç”¨åˆ°è¿™ä¸¤ä¸ªç±»åŠ è½½å™¨çš„åœ°æ–¹éƒ½ä¼šç”¨Common ClassLoader的实例代替,而默认的é…�ç½®æ–‡ä»¶ä¸æ²¡æœ‰è®¾ç½®è¿™ä¸¤ä¸ªloader项,所以Tomcat 6.x顺ç�†æˆ�ç« åœ°æŠŠ/commonã€�/serverå’Œ/shared三个目录默认å�ˆå¹¶åˆ°ä¸€èµ·å�˜æˆ�一个/lib目录,这个目录里的类库相当于以å‰�/common目录ä¸ç±»åº“的作用。
+
+这是Tomcat设计团队为了简化大多数的部署场景所å�šçš„一项改进,如果默认设置ä¸�能满足需è¦�,用户å�¯ä»¥é€šè¿‡ä¿®æ”¹é…�置文件指定server.loaderå’Œshare.loader的方å¼�é‡�æ–°å�¯ç”¨Tomcat 5.xçš„åŠ è½½å™¨[æž¶æž„](https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Flink.juejin.im%2F%3Ftarget%3Dhttp%253A%252F%252Flib.csdn.net%252Fbase%252Farchitecture "大型网站架构知识库")。
+
+ TomcatåŠ è½½å™¨çš„å®žçŽ°æ¸…æ™°æ˜“æ‡‚ï¼Œå¹¶ä¸”é‡‡ç”¨äº†å®˜æ–¹æŽ¨è��的“æ£ç»Ÿâ€�çš„ä½¿ç”¨ç±»åŠ è½½å™¨çš„æ–¹å¼�。如果读者阅读完上é�¢çš„æ¡ˆä¾‹å�Žï¼Œèƒ½å®Œå…¨ç�†è§£Tomcatè®¾è®¡å›¢é˜Ÿè¿™æ ·å¸ƒç½®åŠ è½½å™¨æž¶æž„çš„ç”¨æ„�,那说明已ç»�大致掌æ�¡äº†ç±»åŠ è½½å™¨â€œä¸»æµ�â€�的使用方å¼�,那么笔者ä¸�妨å†�æ��一个问题让读者æ€�考一下:å‰�é�¢æ›¾ç»�æ��到过一个场景,如果有10个Web应用程åº�都是用Springæ�¥è¿›è¡Œç»„织和管ç�†çš„è¯�,å�¯ä»¥æŠŠSpring放到Common或Shared目录下让这些程åº�共享。
+
+ Springè¦�对用户程åº�的类进行管ç�†ï¼Œè‡ªç„¶è¦�能访问到用户程åº�的类,而用户的程åº�显然是放在/WebApp/WEB-INF目录ä¸çš„,那么被CommonClassLoader或SharedClassLoaderåŠ è½½çš„Spring如何访问并ä¸�åœ¨å…¶åŠ è½½èŒƒå›´å†…çš„ç”¨æˆ·ç¨‹åº�å‘¢ï¼Ÿå¦‚æžœç ”ç©¶è¿‡è™šæ‹Ÿæœºç±»åŠ è½½å™¨æœºåˆ¶ä¸çš„å�Œäº²å§”派模型,相信读者å�¯ä»¥å¾ˆå®¹æ˜“地回ç”这个问题。
+
+分æž�:如果按主æµ�çš„å�Œäº²å§”æ´¾æœºåˆ¶ï¼Œæ˜¾ç„¶æ— æ³•å�šåˆ°è®©çˆ¶ç±»åŠ è½½å™¨åŠ è½½çš„ç±»åŽ»è®¿é—®å�ç±»åŠ è½½å™¨åŠ è½½çš„ç±»ï¼Œä¸Šé�¢åœ¨ç±»åŠ è½½å™¨ä¸€èŠ‚ä¸æ��到过通过线程上下文方å¼�ä¼ æ’ç±»åŠ è½½å™¨ã€‚
+
+ ç”æ¡ˆæ˜¯ä½¿ç”¨çº¿ç¨‹ä¸Šä¸‹æ–‡ç±»åŠ è½½å™¨æ�¥å®žçŽ°çš„ï¼Œä½¿ç”¨çº¿ç¨‹ä¸Šä¸‹æ–‡åŠ è½½å™¨ï¼Œå�¯ä»¥è®©çˆ¶ç±»åŠ è½½å™¨è¯·æ±‚å�ç±»åŠ è½½å™¨åŽ»å®Œæˆ�ç±»åŠ è½½çš„åŠ¨ä½œã€‚
+
+ 看springæº�ç �å�‘现,springåŠ è½½ç±»æ‰€ç”¨çš„Classloader是通过Thread.currentThread().getContextClassLoader()æ�¥èŽ·å�–的,而当线程创建时会默认setContextClassLoader(AppClassLoader),å�³çº¿ç¨‹ä¸Šä¸‹æ–‡ç±»åŠ è½½å™¨è¢«è®¾ç½®ä¸ºAppClassLoader,springä¸å§‹ç»ˆå�¯ä»¥èŽ·å�–到这个AppClassLoader(在Tomcat里就是WebAppClassLoader)å�ç±»åŠ è½½å™¨æ�¥åŠ è½½bean,以å�Žä»»ä½•一个线程都å�¯ä»¥é€šè¿‡getContextClassLoader()获å�–到WebAppClassLoaderæ�¥getbean了。
+
+
+
+本篇�文内容��自《深入�解Java虚拟机:JVM高级特性与最佳实践》
+
+## å�‚考文ç«
+
+
+
+
+
+
+
+
+
+https://blog.csdn.net/android_hl/article/details/53228348
+
+
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\2721\357\274\232JVM\345\206\205\345\255\230\347\232\204\347\273\223\346\236\204\344\270\216\346\266\210\345\244\261\347\232\204\346\260\270\344\271\205\344\273\243.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\272\357\274\232JVM\345\206\205\345\255\230\347\232\204\347\273\223\346\236\204\344\270\216\346\266\210\345\244\261\347\232\204\346\260\270\344\271\205\344\273\243.md"
similarity index 75%
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\2721\357\274\232JVM\345\206\205\345\255\230\347\232\204\347\273\223\346\236\204\344\270\216\346\266\210\345\244\261\347\232\204\346\260\270\344\271\205\344\273\243.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\272\357\274\232JVM\345\206\205\345\255\230\347\232\204\347\273\223\346\236\204\344\270\216\346\266\210\345\244\261\347\232\204\346\260\270\344\271\205\344\273\243.md"
index d040fa5..17431e9 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2721\357\274\232JVM\345\206\205\345\255\230\347\232\204\347\273\223\346\236\204\344\270\216\346\266\210\345\244\261\347\232\204\346\260\270\344\271\205\344\273\243.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\272\357\274\232JVM\345\206\205\345\255\230\347\232\204\347\273\223\346\236\204\344\270\216\346\266\210\345\244\261\347\232\204\346\260\270\344\271\205\344\273\243.md"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [�言](#�言)
* [Javaå †ï¼ˆHeap)](#javaå †ï¼ˆheap))
* [方法区(Method Area)](#方法区(method-area))
@@ -7,25 +6,22 @@
* [JVMæ ˆï¼ˆJVM Stacks)](#jvmæ ˆï¼ˆjvm-stacks))
* [æœ¬åœ°æ–¹æ³•æ ˆï¼ˆNative Method Stacks)](#æœ¬åœ°æ–¹æ³•æ ˆï¼ˆnative-method-stacks))
* [哪儿的OutOfMemoryError](#哪儿的outofmemoryerror)
-* [[JDK8-废弃永久代(PermGen)迎�元空间(Metaspace)](https://www.cnblogs.com/yulei126/p/6777323.html)](#[jdk8-废弃永久代(permgen)迎�元空间(metaspace)]httpswwwcnblogscomyulei126p6777323html)
* [一�背景](#一�背景)
* [1.1 永久代(PermGen)在哪里?](#11-永久代(permgen)在哪里?)
* [1.2 JDK8永久代的废弃](#12-jdk8永久代的废弃)
- * [ 二�为什么废弃永久代(PermGen)](# 二�为什么废弃永久代(permgen))
- * [ 2.1 官方说明](# 21-官方说明)
+ * [二�为什么废弃永久代(PermGen)](#二�为什么废弃永久代(permgen))
+ * [2.1 官方说明](#21-官方说明)
* [Motivation](#motivation)
- * [ 2.2 çŽ°å®žä½¿ç”¨ä¸æ˜“出问题](# 22-çŽ°å®žä½¿ç”¨ä¸æ˜“出问题)
+ * [2.2 çŽ°å®žä½¿ç”¨ä¸æ˜“出问题](#22-çŽ°å®žä½¿ç”¨ä¸æ˜“出问题)
* [三�深入�解元空间(Metaspace)](#三�深入�解元空间(metaspace))
* [3.1元空间的内å˜å¤§å°�](#31元空间的内å˜å¤§å°�)
* [3.2常用�置�数](#32常用�置�数)
* [3.3测试并追踪元空间大�](#33测试并追踪元空间大�)
- * [ 3.3.1.测试å—符串常é‡�](# 331测试å—符串常é‡�)
+ * [3.3.1.测试å—符串常é‡�](#331测试å—符串常é‡�)
* [3.3.2.测试元空间溢出](#332测试元空间溢出)
- * [ 四�总结](# 四�总结)
+ * [四�总结](#四�总结)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
本文转自互è�”网,侵åˆ
@@ -54,11 +50,9 @@
å…¶å®žå¦‚æžœä½ ç»�常解决æœ�务器性能问题,那么这些问题就会å�˜çš„é�žå¸¸å¸¸è§�,了解JVM内å˜ä¹Ÿæ˜¯ä¸ºäº†æœ�务器出现性能问题的时候å�¯ä»¥å¿«é€Ÿçš„了解那å�—的内å˜åŒºåŸŸå‡ºçŽ°é—®é¢˜ï¼Œä»¥ä¾¿äºŽå¿«é€Ÿçš„è§£å†³ç”Ÿäº§æ•…éšœã€‚
-
-
å…ˆçœ‹ä¸€å¼ å›¾ï¼Œè¿™å¼ å›¾èƒ½å¾ˆæ¸…æ™°çš„è¯´æ˜ŽJVM内å˜ç»“构布局。
-
+
JVM内å˜ç»“构主è¦�有三大å�—ï¼šå †å†…å˜ã€�æ–¹æ³•åŒºå’Œæ ˆã€‚å †å†…å˜æ˜¯JVM䏿œ€å¤§çš„一å�—由年轻代和è€�年代组æˆ�,而年轻代内å˜å�ˆè¢«åˆ†æˆ�三部分,Eden空间ã€�From Survivor空间ã€�To Survivor空间,默认情况下年轻代按照8:1:1的比例æ�¥åˆ†é…�ï¼›
@@ -66,8 +60,7 @@ JVM内å˜ç»“构主è¦�有三大å�—ï¼šå †å†…å˜ã€�æ–¹æ³•åŒºå’Œæ ˆã€‚å †å†…å˜æ˜¯JV
åœ¨é€šè¿‡ä¸€å¼ å›¾æ�¥äº†è§£å¦‚何通过å�‚æ•°æ�¥æŽ§åˆ¶å�„区域的内å˜å¤§å°�
-
-
+
控制�数
* -Xmsè®¾ç½®å †çš„æœ€å°�空间大å°�。
@@ -84,7 +77,7 @@ JVM内å˜ç»“构主è¦�有三大å�—ï¼šå †å†…å˜ã€�æ–¹æ³•åŒºå’Œæ ˆã€‚å †å†…å˜æ˜¯JV
从更高的一个维度�次�看JVM和系统调用之间的关系
-
+
方法区和对是所有线程共享的内å˜åŒºåŸŸï¼›è€Œjavaæ ˆã€�æœ¬åœ°æ–¹æ³•æ ˆå’Œç¨‹åº�员计数器是è¿�行是线程ç§�有的内å˜åŒºåŸŸã€‚
@@ -112,7 +105,7 @@ Java虚拟机规范对这个区域的é™�制é�žå¸¸å®½æ�¾ï¼Œé™¤äº†å’ŒJavaå †ä¸€æ ·
方法区有时被称为�久代(PermGen)。
-
+
所有的对象在实例化å�Žçš„æ•´ä¸ªè¿�è¡Œå‘¨æœŸå†…ï¼Œéƒ½è¢«å˜æ”¾åœ¨å †å†…å˜ä¸ã€‚å †å†…å˜å�ˆè¢«åˆ’分æˆ�ä¸�å�Œçš„部分:伊甸区(Eden),幸å˜è€…区域(Survivor Sapce),è€�年代(Old Generation Space)。
@@ -121,27 +114,26 @@ Java虚拟机规范对这个区域的é™�制é�žå¸¸å®½æ�¾ï¼Œé™¤äº†å’ŒJavaå †ä¸€æ ·
-
-import java.text.SimpleDateFormat;import java.util.Date;import org.apache.log4j.Logger;
+````
+import java.text.SimpleDateFormat;import java.util.Date;import org.apache.log4j.Logger;
public class HelloWorld {
- Â Â private static Logger LOGGER = Logger.getLogger(HelloWorld.class.getName());
- Â Â public void sayHello(String message) {
- Â Â Â Â SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.YYYY");
- Â Â Â Â String today = formatter.format(new Date());
- Â Â Â Â LOGGER.info(today + ": " + message);
- Â Â }}
-
+ private static Logger LOGGER = Logger.getLogger(HelloWorld.class.getName());
+ public void sayHello(String message) {
+ SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.YYYY");
+ String today = formatter.format(new Date());
+ LOGGER.info(today + ": " + message);
+ }}
+````
这段程åº�的数æ�®åœ¨å†…å˜ä¸çš„å˜æ”¾å¦‚下:
-
-
+
通过JConsole工具å�¯ä»¥æŸ¥çœ‹è¿�行ä¸çš„Java程åº�(比如Eclipse)的一些信æ�¯ï¼šå †å†…å˜çš„分é…�,线程的数é‡�以å�ŠåŠ è½½çš„ç±»çš„ä¸ªæ•°ï¼›
-
+
## 程�计数器(Program Counter Register)
@@ -172,69 +164,38 @@ Java虚拟机规范对这个区域的é™�制é�žå¸¸å®½æ�¾ï¼Œé™¤äº†å’ŒJavaå †ä¸€æ ·
对内å˜ç»“构清晰的认识å�Œæ ·å�¯ä»¥å¸®åŠ©ç�†è§£ä¸�å�ŒOutOfMemoryErrors:
-
-
-
-Exception in thread “main�: java.lang.OutOfMemoryError: Java heap space
-
-
-
+Exception in thread “main�: java.lang.OutOfMemoryError: Java heap space
åŽŸå› ï¼šå¯¹è±¡ä¸�能被分é…�åˆ°å †å†…å˜ä¸
-
-
-
-Exception in thread “main�: java.lang.OutOfMemoryError: PermGen space
-
-
-
+Exception in thread “main�: java.lang.OutOfMemoryError: PermGen space
åŽŸå› ï¼šç±»æˆ–è€…æ–¹æ³•ä¸�èƒ½è¢«åŠ è½½åˆ°æŒ�久代。它å�¯èƒ½å‡ºçŽ°åœ¨ä¸€ä¸ªç¨‹åº�åŠ è½½å¾ˆå¤šç±»çš„æ—¶å€™ï¼Œæ¯”å¦‚å¼•ç”¨äº†å¾ˆå¤šç¬¬ä¸‰æ–¹çš„åº“ï¼›
-
-
-
-
-Exception in thread “main�: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
-
-
-
+Exception in thread “main�: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
åŽŸå› ï¼šåˆ›å»ºçš„æ•°ç»„å¤§äºŽå †å†…å˜çš„空间
-
-
-
-Exception in thread “main�: java.lang.OutOfMemoryError: request bytes for . Out of swap space?
-
-
-
+Exception in thread “main�: java.lang.OutOfMemoryError: request bytes for . Out of swap space?
åŽŸå› ï¼šåˆ†é…�本地分é…�失败。JNIã€�本地库或者Javaè™šæ‹Ÿæœºéƒ½ä¼šä»Žæœ¬åœ°å †ä¸åˆ†é…�内å˜ç©ºé—´ã€‚
-
-
-
-Exception in thread “main�: java.lang.OutOfMemoryError: (Native method)
-
-
-
+Exception in thread “main�: java.lang.OutOfMemoryError: (Native method)
åŽŸå› ï¼šå�Œæ ·æ˜¯æœ¬åœ°æ–¹æ³•内å˜åˆ†é…�失败,å�ªä¸�过是JNI或者本地方法或者Java虚拟机å�‘现
-# [JDK8-废弃永久代(PermGen)迎�元空间(Metaspace)](https://www.cnblogs.com/yulei126/p/6777323.html)
-
-
+关于永久代的废弃å�¯ä»¥å�‚考这篇文ç«
+JDK8-废弃永久代(PermGen)迎�元空间(Metaspace)
+(https://www.cnblogs.com/yulei126/p/6777323.html)
1.背景
@@ -253,8 +214,7 @@ Java虚拟机规范对这个区域的é™�制é�žå¸¸å®½æ�¾ï¼Œé™¤äº†å’ŒJavaå †ä¸€æ ·
æ ¹æ�®ï¼Œhotspot jvm结构如下(è™šæ‹Ÿæœºæ ˆå’Œæœ¬åœ°æ–¹æ³•æ ˆå�ˆä¸€èµ·äº†):
-
-
+
上图引自网络,但有个问题:方法区和heapå †éƒ½æ˜¯çº¿ç¨‹å…±äº«çš„å†…å˜åŒºåŸŸã€‚
关于方法区和永久代:
@@ -265,17 +225,16 @@ Java虚拟机规范对这个区域的é™�制é�žå¸¸å®½æ�¾ï¼Œé™¤äº†å’ŒJavaå †ä¸€æ ·
JDK8 永久代�化如下图:
-
-
+
1.新生代:Eden+From Survivor+To Survivor
2.�年代:OldGen
3.永久代(方法区的实现) : PermGen----->替æ�¢ä¸ºMetaspace(本地内å˜ä¸)
-##  二�为什么废弃永久代(PermGen)
+## 二�为什么废弃永久代(PermGen)
-###  2.1 官方说明
+### 2.1 官方说明
�照JEP122:http://openjdk.java.net/jeps/122,原文截�:
@@ -283,9 +242,9 @@ JDK8 永久代�化如下图:
This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need to configure the permanent generation (since JRockit does not have a permanent generation) and are accustomed to not configuring the permanent generation.
- å�³ï¼šç§»é™¤æ°¸ä¹…代是为èž�å�ˆHotSpot JVM与 JRockit VM而å�šå‡ºçš„åŠªåŠ›ï¼Œå› ä¸ºJRockit没有永久代,ä¸�需è¦�é…�置永久代。
+å�³ï¼šç§»é™¤æ°¸ä¹…代是为èž�å�ˆHotSpot JVM与 JRockit VM而å�šå‡ºçš„åŠªåŠ›ï¼Œå› ä¸ºJRockit没有永久代,ä¸�需è¦�é…�置永久代。
-###  2.2 çŽ°å®žä½¿ç”¨ä¸æ˜“出问题
+### 2.2 çŽ°å®žä½¿ç”¨ä¸æ˜“出问题
由于永久代内å˜ç»�常ä¸�够用或å�‘ç”Ÿå†…å˜æ³„露,爆出异常java.lang.OutOfMemoryError: PermGen
@@ -303,7 +262,7 @@ This is part of the JRockit and Hotspot convergence effort. JRockit customers do
1.MetaspaceSize
-åˆ�始化的Metaspace大å°�,控制元空间å�‘生GC的阈值。GCå�Žï¼ŒåЍæ€�å¢žåŠ æˆ–é™�低MetaspaceSize。在默认情况下,这个值大å°�æ ¹æ�®ä¸�å�Œçš„å¹³å�°åœ¨12M到20M浮动。使用[Java](http://lib.csdn.net/base/javase "Java SE知识库") -XX:+PrintFlagsInitial命令查看本机的åˆ�始化å�‚æ•°
+åˆ�始化的Metaspace大å°�,控制元空间å�‘生GC的阈值。GCå�Žï¼ŒåЍæ€�å¢žåŠ æˆ–é™�低MetaspaceSize。在默认情况下,这个值大å°�æ ¹æ�®ä¸�å�Œçš„å¹³å�°åœ¨12M到20M浮动。使用[Java](http://lib.csdn.net/base/javase "Java SE知识库")-XX:+PrintFlagsInitial命令查看本机的åˆ�始化å�‚æ•°
2.MaxMetaspaceSize
@@ -327,40 +286,32 @@ Metaspace增长时的最�幅度。在本机上该�数的默认值为340784B
### 3.3测试并追踪元空间大�
-####  3.3.1.测试å—符串常é‡�
-
-
-
-
-
-
- 1 public class StringOomMock {
- 2 static String base = "string";
- 3
- 4 public static void main(String[] args) {
- 5 List list = new ArrayList();
- 6 for (int i=0;i< Integer.MAX_VALUE;i++){
- 7 String str = base + base;
- 8 base = str;
- 9 list.add(str.intern());
-10 }
-11 }
-12 }
-
-
-
-
-
+#### 3.3.1.测试å—符串常é‡�
+
+````
+public class StringOomMock {
+ static String base = "string";
+
+ public static void main(String[] args) {
+ List list = new ArrayList();
+ for (int i=0;i< Integer.MAX_VALUE;i++){
+ String str = base + base;
+ base = str;
+ list.add(str.intern());
+ }
+ }
+}
+````
在eclipseä¸é€‰ä¸ç±»--》run configuration-->java application--》new å�‚数如下:
-
+
- 由于设定了最大内å˜20M,很快就溢出,如下图:
+由于设定了最大内å˜20M,很快就溢出,如下图:
-
+
- å�¯è§�在jdk8ä¸ï¼š
+å�¯è§�在jdk8ä¸ï¼š
1.å—符串常é‡�ç”±æ°¸ä¹…ä»£è½¬ç§»åˆ°å †ä¸ã€‚
@@ -369,86 +320,71 @@ Metaspace增长时的最�幅度。在本机上该�数的默认值为340784B
#### 3.3.2.测试元空间溢出
æ ¹æ�®å®šä¹‰ï¼Œæˆ‘ä»¬ä»¥åŠ è½½ç±»æ�¥æµ‹è¯•元空间溢出,代ç �如下:
-
-
-
-
-
-
- 1 package jdk8;
- 2
- 3 import java.io.File;
- 4 import java.lang.management.ClassLoadingMXBean;
- 5 import java.lang.management.ManagementFactory;
- 6 import java.net.URL;
- 7 import java.net.URLClassLoader;
- 8 import java.util.ArrayList;
- 9 import java.util.List;
-10
-11 /**
-12 *
-13 * @ClassName:OOMTest
-14 * @Description:æ¨¡æ‹Ÿç±»åŠ è½½æº¢å‡ºï¼ˆå…ƒç©ºé—´oom)
-15 * @author diandian.zhang
-16 * @date 2017年4月27日上�9:45:40
-17 */
-18 public class OOMTest {
-19 public static void main(String[] args) {
-20 try {
-21 //准备url
-22 URL url = new File("D:/58workplace/11study/src/main/java/jdk8").toURI().toURL();
-23 URL[] urls = {url};
-24 //获å�–æœ‰å…³ç±»åž‹åŠ è½½çš„JMX接å�£
-25 ClassLoadingMXBean loadingBean = ManagementFactory.getClassLoadingMXBean();
-26 //用于缓å˜ç±»åŠ è½½å™¨
-27 List classLoaders = new ArrayList();
-28 while (true) {
-29 //åŠ è½½ç±»åž‹å¹¶ç¼“å˜ç±»åŠ è½½å™¨å®žä¾‹
-30 ClassLoader classLoader = new URLClassLoader(urls);
-31 classLoaders.add(classLoader);
-32 classLoader.loadClass("ClassA");
-33 //显示数é‡�ä¿¡æ�¯ï¼ˆå…±åŠ è½½è¿‡çš„ç±»åž‹æ•°ç›®ï¼Œå½“å‰�还有效的类型数目,已ç»�被å�¸è½½çš„类型数目)
-34 System.out.println("total: " + loadingBean.getTotalLoadedClassCount());
-35 System.out.println("active: " + loadingBean.getLoadedClassCount());
-36 System.out.println("unloaded: " + loadingBean.getUnloadedClassCount());
-37 }
-38 } catch (Exception e) {
-39 e.printStackTrace();
-40 }
-41 }
-42 }
-
-
-
-
-
+````
+package jdk8;
+
+import java.io.File;
+import java.lang.management.ClassLoadingMXBean;
+import java.lang.management.ManagementFactory;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @ClassName:OOMTest
+ * @Description:æ¨¡æ‹Ÿç±»åŠ è½½æº¢å‡ºï¼ˆå…ƒç©ºé—´oom)
+ * @author diandian.zhang
+ * @date 2017年4月27日上�9:45:40
+ */
+public class OOMTest {
+ public static void main(String[] args) {
+ try {
+ //准备url
+ URL url = new File("D:/58workplace/11study/src/main/java/jdk8").toURI().toURL();
+ URL[] urls = {url};
+ //获å�–æœ‰å…³ç±»åž‹åŠ è½½çš„JMX接å�£
+ ClassLoadingMXBean loadingBean = ManagementFactory.getClassLoadingMXBean();
+ //用于缓å˜ç±»åŠ è½½å™¨
+ List classLoaders = new ArrayList();
+ while (true) {
+ //åŠ è½½ç±»åž‹å¹¶ç¼“å˜ç±»åŠ è½½å™¨å®žä¾‹
+ ClassLoader classLoader = new URLClassLoader(urls);
+ classLoaders.add(classLoader);
+ classLoader.loadClass("ClassA");
+ //显示数é‡�ä¿¡æ�¯ï¼ˆå…±åŠ è½½è¿‡çš„ç±»åž‹æ•°ç›®ï¼Œå½“å‰�还有效的类型数目,已ç»�被å�¸è½½çš„类型数目)
+ System.out.println("total: " + loadingBean.getTotalLoadedClassCount());
+ System.out.println("active: " + loadingBean.getLoadedClassCount());
+ System.out.println("unloaded: " + loadingBean.getUnloadedClassCount());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+````
为了快速溢出,设置�数:-XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=80m,�行结果如下:
-
+
- 上图è¯�实了,我们的JDK8ä¸ç±»åŠ è½½ï¼ˆæ–¹æ³•åŒºçš„åŠŸèƒ½ï¼‰å·²ç»�ä¸�在永久代PerGemä¸äº†ï¼Œè€Œæ˜¯Metaspaceä¸ã€‚å�¯ä»¥é…�å�ˆJVisualVMæ�¥çœ‹ï¼Œæ›´ç›´è§‚一些。
+上图è¯�实了,我们的JDK8ä¸ç±»åŠ è½½ï¼ˆæ–¹æ³•åŒºçš„åŠŸèƒ½ï¼‰å·²ç»�ä¸�在永久代PerGemä¸äº†ï¼Œè€Œæ˜¯Metaspaceä¸ã€‚å�¯ä»¥é…�å�ˆJVisualVMæ�¥çœ‹ï¼Œæ›´ç›´è§‚一些。
-##  四�总结
+## 四�总结
本文讲解了元空间(Metaspace)的由æ�¥å’Œæœ¬è´¨ï¼Œå¸¸ç”¨é…�置,以å�Šç›‘控测试。元空间的大å°�是动æ€�å�˜æ›´çš„,但ä¸�æ˜¯æ— é™�大的,最好也时常关注一下大å°�,以å…�å½±å“�æœ�务器内å˜ã€‚
-
-
-
-
-
-
## å�‚考文ç«
-
+https://segmentfault.com/a/1190000009707894
-
+https://www.cnblogs.com/hysum/p/7100874.html
-
+http://c.biancheng.net/view/939.html
-
+https://www.runoob.com
https://blog.csdn.net/android_hl/article/details/53228348
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\2722\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.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\272\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.md"
similarity index 80%
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\2722\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.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\272\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.md"
index e8a7e29..8048fb5 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2722\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.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\272\357\274\232JVM\345\236\203\345\234\276\345\233\236\346\224\266\345\237\272\346\234\254\345\216\237\347\220\206\345\222\214\347\256\227\346\263\225.md"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [JVM GC基本原�与GC算法](#jvm-gc基本原�与gc算法)
* [Java关键术è¯](#java关键术è¯)
* [Java HotSpot 虚拟机](#java-hotspot-虚拟机)
@@ -15,7 +14,7 @@
* [垃圾回收ä¸å®žä¾‹çš„终结](#垃圾回收ä¸å®žä¾‹çš„终结)
* [对象什么时候符�垃圾回收的�件?](#对象什么时候符�垃圾回收的�件?)
* [GC Scope 示例程�](#gc-scope-示例程�)
- * [[JVM GC算法](https://www.cnblogs.com/wupeixuan/p/8670341.html)](#[jvm-gc算法]httpswwwcnblogscomwupeixuanp8670341html)
+ * [JVM GC算法](#JVM GC算法)
* [JVM垃圾判定算法](#jvm垃圾判定算法)
* [引用计数算法(Reference Counting)](#引用计数算法reference-counting)
* [å�¯è¾¾æ€§åˆ†æž�ç®—æ³•ï¼ˆæ ¹æ�œç´¢ç®—法)](#å�¯è¾¾æ€§åˆ†æž�ç®—æ³•ï¼ˆæ ¹æ�œç´¢ç®—法))
@@ -26,9 +25,7 @@
* [æ ‡è®°â€”æ•´ç�†ç®—法(Mark-Compact)](#æ ‡è®°æ•´ç�†ç®—法(mark-compact))
* [分代收集算法(Generational Collection)](#分代收集算法generational-collection)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
本文转自互è�”网,侵åˆ
@@ -53,8 +50,6 @@
## JVM GC基本原�与GC算法
-
-
Java的内å˜åˆ†é…�与回收全部由JVM垃圾回收进程自动完æˆ�。与Cè¯è¨€ä¸�å�Œï¼ŒJavaå¼€å�‘者ä¸�需è¦�自己编写代ç �实现垃圾回收。这是Javaæ·±å�—大家欢迎的众多特性之一,能够帮助程åº�员更好地编写Java程åº�。
下�四篇教程是了解Java 垃圾回收(GC)的基础:
@@ -100,7 +95,7 @@ Java 垃圾回收是一项自动化的过程,用�管�程�所使用的�
虽然这个请求机制æ��供给程åº�员一个å�¯åЍ GC 过程的机会,但是å�¯åŠ¨ç”± JVM负责。JVMå�¯ä»¥æ‹’ç»�这个请求,所以并ä¸�ä¿�è¯�这些调用都将执行垃圾回收。å�¯åŠ¨æ—¶æœºçš„é€‰æ‹©ç”±JVM决定,并且å�–å†³äºŽå †å†…å˜ä¸Eden区是å�¦å�¯ç”¨ã€‚JVM将这个选择留给了Java规范的实现,ä¸�å�Œå®žçŽ°å…·ä½“ä½¿ç”¨çš„ç®—æ³•ä¸�尽相å�Œã€‚
-毋庸置疑,我们知é�“垃圾回收过程是ä¸�能被强制执行的。我刚刚å�‘现了一个调用`System.gc()`有æ„�ä¹‰çš„åœºæ™¯ã€‚é€šè¿‡è¿™ç¯‡æ–‡ç« äº†è§£ä¸€ä¸‹[适å�ˆè°ƒç”¨System.gc() ](http://javapapers.com/core-java/system-gc-invocation-a-suitable-scenario/)è¿™ç§�æž�端情况。
+毋庸置疑,我们知é�“垃圾回收过程是ä¸�能被强制执行的。我刚刚å�‘现了一个调用`System.gc()`有æ„�ä¹‰çš„åœºæ™¯ã€‚é€šè¿‡è¿™ç¯‡æ–‡ç« äº†è§£ä¸€ä¸‹[适å�ˆè°ƒç”¨System.gc()](http://javapapers.com/core-java/system-gc-invocation-a-suitable-scenario/)è¿™ç§�æž�端情况。
## ��GC的触�时机(When)
@@ -125,11 +120,11 @@ Java 垃圾回收是一项自动化的过程,用�管�程�所使用的�
除直接调用System.gc外,触�Full GC执行的情况有如下四�。
-1. 旧生代空间�足
+1.旧生代空间�足
旧生代空间�有在新生代对象转入�创建为大对象�大数组时�会出现�足的现象,当执行Full GC�空间�然�足,则抛出如下错误:
-java.lang.OutOfMemoryError: Java heap spaceÂ
+java.lang.OutOfMemoryError:Javaheapspace
为é�¿å…�以上两ç§�状况引起的Full GC,调优时应尽é‡�å�šåˆ°è®©å¯¹è±¡åœ¨Minor GC阶段被回收ã€�è®©å¯¹è±¡åœ¨æ–°ç”Ÿä»£å¤šå˜æ´»ä¸€æ®µæ—¶é—´å�Šä¸�è¦�创建过大的对象å�Šæ•°ç»„。
@@ -137,7 +132,7 @@ java.lang.OutOfMemoryError: Java heap spaceÂ
Permanet Generationä¸å˜æ”¾çš„为一些class的信æ�¯ç‰ï¼Œå½“系统ä¸è¦�åŠ è½½çš„ç±»ã€�å��射的类和调用的方法较多时,Permanet Generationå�¯èƒ½ä¼šè¢«å� 满,在未é…�置为采用CMS GC的情况下会执行Full GC。如果ç»�过Full GCä»�然回收ä¸�了,那么JVM会抛出如下错误信æ�¯ï¼š
-java.lang.OutOfMemoryError: PermGen spaceÂ
+java.lang.OutOfMemoryError:PermGenspace
为é�¿å…�Perm Genå� æ»¡é€ æˆ�Full GC现象,å�¯é‡‡ç”¨çš„æ–¹æ³•为增大Perm Gen空间或转为使用CMS GC。
@@ -149,7 +144,7 @@ promotion failed是在进行Minor GC时,survivor space放�下�对象�能
应对措施为:增大survivor spaceã€�旧生代空间或调低触å�‘å¹¶å�‘GC的比率,但在JDK 5.0+ã€�6.0+çš„ç‰ˆæœ¬ä¸æœ‰å�¯èƒ½ä¼šç”±äºŽJDKçš„bug29导致CMS在remark完毕å�Žå¾ˆä¹…æ‰�触å�‘sweeping动作。对于这ç§�状况,å�¯é€šè¿‡è®¾ç½®-XX: CMSMaxAbortablePrecleanTime=5(å�•ä½�为ms)æ�¥é�¿å…�。
-4. 统计得到的Minor GC晋�到旧生代的平�大�大于旧生代的剩余空间
+4.统计得到的Minor GC晋�到旧生代的平�大�大于旧生代的剩余空间
这是一个较为å¤�æ�‚的触å�‘情况,Hotspot为了é�¿å…�由于新生代对象晋å�‡åˆ°æ—§ç”Ÿä»£å¯¼è‡´æ—§ç”Ÿä»£ç©ºé—´ä¸�足的现象,在进行Minor GC时,å�šäº†ä¸€ä¸ªåˆ¤æ–,如果之å‰�统计所得到的Minor GC晋å�‡åˆ°æ—§ç”Ÿä»£çš„å¹³å�‡å¤§å°�大于旧生代的剩余空间,那么就直接触å�‘Full GC。
@@ -161,7 +156,7 @@ promotion failed是在进行Minor GC时,survivor space放�下�对象�能
### 总结
-** Minor GC ,Full GC 触��件**
+**Minor GC ,Full GC 触��件**
Minor GC触��件:当Eden区满时,触�Minor GC。
@@ -201,7 +196,7 @@ JVM里有一�特殊的线程��VM Threads,专门用�执行一些特殊
Eden 区:当一个实例被创建了,首先会被å˜å‚¨åœ¨å †å†…å˜å¹´è½»ä»£çš„ Eden 区ä¸ã€‚
-注æ„�ï¼šå¦‚æžœä½ ä¸�能ç�†è§£è¿™äº›è¯�æ±‡ï¼Œæˆ‘å»ºè®®ä½ é˜…è¯»è¿™ç¯‡Â [垃圾回收介ç»�](http://javapapers.com/java/java-garbage-collection-introduction/) ,这篇教程详细地介ç»�äº†å†…å˜æ¨¡åž‹ã€�JVM 架构以å�Šè¿™äº›æœ¯è¯ã€‚
+注æ„�ï¼šå¦‚æžœä½ ä¸�能ç�†è§£è¿™äº›è¯�æ±‡ï¼Œæˆ‘å»ºè®®ä½ é˜…è¯»è¿™ç¯‡[垃圾回收介ç»�](http://javapapers.com/java/java-garbage-collection-introduction/),这篇教程详细地介ç»�äº†å†…å˜æ¨¡åž‹ã€�JVM 架构以å�Šè¿™äº›æœ¯è¯ã€‚
Survivor 区(S0 å’Œ S1):作为年轻代 GC(Minor GCï¼‰å‘¨æœŸçš„ä¸€éƒ¨åˆ†ï¼Œå˜æ´»çš„对象(ä»�然被引用的)从 Eden 区被移动到 Survivor 区的 S0 ä¸ã€‚类似的,垃圾回收器会扫æ�� S0 ç„¶å�Žå°†å˜æ´»çš„实例移动到 S1 ä¸ã€‚
@@ -209,7 +204,7 @@ Survivor 区(S0 和 S1):作为年轻代 GC(Minor GC)周期的一部分
æ»äº¡çš„实例(ä¸�å†�è¢«å¼•ç”¨ï¼‰è¢«æ ‡è®°ä¸ºåžƒåœ¾å›žæ”¶ã€‚æ ¹æ�®åžƒåœ¾å›žæ”¶å™¨ï¼ˆæœ‰å››ç§�常用的垃圾回收器,将在下一教程ä¸ä»‹ç»�它们)选择的ä¸�å�Œï¼Œè¦�ä¹ˆè¢«æ ‡è®°çš„å®žä¾‹éƒ½ä¼šä¸�å�œåœ°ä»Žå†…å˜ä¸ç§»é™¤ï¼Œè¦�么回收过程会在一个å�•独的进程ä¸å®Œæˆ�。
-è€�年代: è€�年代(Old or tenured generationï¼‰æ˜¯å †å†…å˜ä¸çš„第二å�—逻辑区。当垃圾回收器执行 Minor GC 周期时,在 S1 Survivor 区ä¸çš„å˜æ´»å®žä¾‹å°†ä¼šè¢«æ™‹å�‡åˆ°è€�å¹´ä»£ï¼Œè€Œæœªè¢«å¼•ç”¨çš„å¯¹è±¡è¢«æ ‡è®°ä¸ºå›žæ”¶ã€‚
+è€�年代:è€�年代(Old or tenured generationï¼‰æ˜¯å †å†…å˜ä¸çš„第二å�—逻辑区。当垃圾回收器执行 Minor GC 周期时,在 S1 Survivor 区ä¸çš„å˜æ´»å®žä¾‹å°†ä¼šè¢«æ™‹å�‡åˆ°è€�å¹´ä»£ï¼Œè€Œæœªè¢«å¼•ç”¨çš„å¯¹è±¡è¢«æ ‡è®°ä¸ºå›žæ”¶ã€‚
è€�年代 GC(Major GC):相对于 Java 垃圾回收过程,è€�年代是实例生命周期的最å�Žé˜¶æ®µã€‚Major GC 扫æ��è€�年代的垃圾回收过程。如果实例ä¸�å†�è¢«å¼•ç”¨ï¼Œé‚£ä¹ˆå®ƒä»¬ä¼šè¢«æ ‡è®°ä¸ºå›žæ”¶ï¼Œå�¦åˆ™å®ƒä»¬ä¼šç»§ç»ç•™åœ¨è€�年代ä¸ã€‚
@@ -217,7 +212,7 @@ Survivor 区(S0 和 S1):作为年轻代 GC(Minor GC)周期的一部分
## 垃圾回收ä¸å®žä¾‹çš„终结
-在释放一个实例和回收内å˜ç©ºé—´ä¹‹å‰�,Java 垃圾回收器会调用实例å�„自的 `finalize()` 方法,从而该实例有机会释放所æŒ�有的资æº�。虽然å�¯ä»¥ä¿�è¯� `finalize()` 会在回收内å˜ç©ºé—´ä¹‹å‰�被调用,但是没有指定的顺åº�和时间。多个实例间的顺åº�æ˜¯æ— æ³•è¢«é¢„çŸ¥ï¼Œç”šè‡³å�¯èƒ½ä¼šå¹¶è¡Œå�‘生。程åº�ä¸�应该预先调整实例之间的顺åº�并使用 `finalize()` 方法回收资æº�。
+在释放一个实例和回收内å˜ç©ºé—´ä¹‹å‰�,Java 垃圾回收器会调用实例å�„自的`finalize()`方法,从而该实例有机会释放所æŒ�有的资æº�。虽然å�¯ä»¥ä¿�è¯�`finalize()`会在回收内å˜ç©ºé—´ä¹‹å‰�被调用,但是没有指定的顺åº�和时间。多个实例间的顺åº�æ˜¯æ— æ³•è¢«é¢„çŸ¥ï¼Œç”šè‡³å�¯èƒ½ä¼šå¹¶è¡Œå�‘生。程åº�ä¸�应该预先调整实例之间的顺åº�并使用`finalize()`方法回收资æº�。
* 任何在 finalizeè¿‡ç¨‹ä¸æœªè¢«æ�•获的异常会自动被忽略,然å�Žè¯¥å®žä¾‹çš„ finalize 过程被å�–消。
* JVM 规范ä¸å¹¶æ²¡æœ‰è®¨è®ºå…³äºŽå¼±å¼•用的垃圾回收机制,也没有很明确的è¦�求。具体的实现都由实现方决定。
@@ -237,8 +232,8 @@ Survivor 区(S0 和 S1):作为年轻代 GC(Minor GC)周期的一部分
| 弱引用(Weak Reference) | 符�垃圾收集 |
| 虚引用(Phantom Reference) | 符�垃圾收集 |
-在编译过程ä¸ä½œä¸ºä¸€ç§�优化技术,Java 编译器能选择给实例赋 `null`Â å€¼ï¼Œä»Žè€Œæ ‡è®°å®žä¾‹ä¸ºå�¯å›žæ”¶ã€‚
-
+在编译过程ä¸ä½œä¸ºä¸€ç§�优化技术,Java 编译器能选择给实例赋`null`å€¼ï¼Œä»Žè€Œæ ‡è®°å®žä¾‹ä¸ºå�¯å›žæ”¶ã€‚
+````
class Animal {
public static void main(String[] args) {
@@ -258,140 +253,143 @@ Survivor 区(S0 和 S1):作为年轻代 GC(Minor GC)周期的一部分
}
}
-
-在上é�¢çš„ç±»ä¸ï¼Œ`lion` 对象在实例化行å�Žä»Žæœªè¢«ä½¿ç”¨è¿‡ã€‚å› æ¤ Java 编译器作为一ç§�优化措施å�¯ä»¥ç›´æŽ¥åœ¨å®žä¾‹åŒ–行å�Žèµ‹å€¼`lion = null`ã€‚å› æ¤ï¼Œå�³ä½¿åœ¨ SOP 输出之å‰�, finalize 函数也能够打å�°å‡ºÂ `'Rest in Peace!'`。我们ä¸�能è¯�明这确定会å�‘ç”Ÿï¼Œå› ä¸ºå®ƒä¾�èµ–JVM的实现方å¼�å’Œè¿�行时使用的内å˜ã€‚然而,我们还能å¦ä¹ 到一点:如果编译器看到该实例在未æ�¥å†�也ä¸�会被引用,能够选择并æ��早释放实例空间。
+````
+在上é�¢çš„ç±»ä¸ï¼Œ`lion`对象在实例化行å�Žä»Žæœªè¢«ä½¿ç”¨è¿‡ã€‚å› æ¤ Java 编译器作为一ç§�优化措施å�¯ä»¥ç›´æŽ¥åœ¨å®žä¾‹åŒ–行å�Žèµ‹å€¼`lion = null`ã€‚å› æ¤ï¼Œå�³ä½¿åœ¨ SOP 输出之å‰�, finalize 函数也能够打å�°å‡º`'Rest in Peace!'`。我们ä¸�能è¯�明这确定会å�‘ç”Ÿï¼Œå› ä¸ºå®ƒä¾�èµ–JVM的实现方å¼�å’Œè¿�行时使用的内å˜ã€‚然而,我们还能å¦ä¹ 到一点:如果编译器看到该实例在未æ�¥å†�也ä¸�会被引用,能够选择并æ��早释放实例空间。
* 关于对象什么时候符å�ˆåžƒåœ¾å›žæ”¶æœ‰ä¸€ä¸ªæ›´å¥½çš„例å�。实例的所有属性能被å˜å‚¨åœ¨å¯„å˜å™¨ä¸ï¼Œéš�å�Žå¯„å˜å™¨å°†è¢«è®¿é—®å¹¶è¯»å�–å†…å®¹ã€‚æ— ä¸€ä¾‹å¤–ï¼Œè¿™äº›å€¼å°†è¢«å†™å›žåˆ°å®žä¾‹ä¸ã€‚虽然这些值在将æ�¥èƒ½è¢«ä½¿ç”¨ï¼Œè¿™ä¸ªå®žä¾‹ä»�ç„¶èƒ½è¢«æ ‡è®°ä¸ºç¬¦å�ˆåžƒåœ¾å›žæ”¶ã€‚这是一个很ç»�典的例å�,ä¸�是å�—?
* 当被赋值为null时,这是很简å�•的一个符å�ˆåžƒåœ¾å›žæ”¶çš„示例。当然,å¤�æ�‚的情况å�¯ä»¥åƒ�上é�¢çš„å‡ ç‚¹ã€‚è¿™æ˜¯ç”± JVM 实现者所å�šçš„选择。目的是留下尽å�¯èƒ½å°�的内å˜å� ç”¨ï¼ŒåŠ å¿«å“�应速度,æ��高å�žå��é‡�ã€‚ä¸ºäº†å®žçŽ°è¿™ä¸€ç›®æ ‡ï¼Œ JVM 的实现者å�¯ä»¥é€‰æ‹©ä¸€ä¸ªæ›´å¥½çš„æ–¹æ¡ˆæˆ–算法在垃圾回收过程ä¸å›žæ”¶å†…å˜ç©ºé—´ã€‚
-* 当 `finalize()` 方法被调用时,JVM 会释放该线程上的所有å�Œæ¥é”�。
+* 当`finalize()`方法被调用时,JVM 会释放该线程上的所有å�Œæ¥é”�。
### GC Scope 示例程�
- Class GCScope {
-
- GCScope t;
-
- static int i = 1;
-
-
-
- public static void main(String args[]) {
-
- GCScope t1 = new GCScope();
-
- GCScope t2 = new GCScope();
-
- GCScope t3 = new GCScope();
-
-
-
- // No Object Is Eligible for GC
-
-
-
- t1.t = t2; // No Object Is Eligible for GC
-
- t2.t = t3; // No Object Is Eligible for GC
-
- t3.t = t1; // No Object Is Eligible for GC
-
-
-
- t1 = null;
-
- // No Object Is Eligible for GC (t3.t still has a reference to t1)
-
-
-
- t2 = null;
-
- // No Object Is Eligible for GC (t3.t.t still has a reference to t2)
-
-
-
- t3 = null;
-
- // All the 3 Object Is Eligible for GC (None of them have a reference.
-
- // only the variable t of the objects are referring each other in a
-
- // rounded fashion forming the Island of objects with out any external
-
- // reference)
-
- }
-
-
-
- protected void finalize() {
-
- System.out.println("Garbage collected from object" + i);
-
- i++;
-
- }
-
-
-
- class GCScope {
-
- GCScope t;
-
- static int i = 1;
-
-
-
- public static void main(String args[]) {
-
- GCScope t1 = new GCScope();
-
- GCScope t2 = new GCScope();
-
- GCScope t3 = new GCScope();
-
-
-
- // 没有对象符�GC
-
- t1.t = t2; // 没有对象符�GC
-
- t2.t = t3; // 没有对象符�GC
-
- t3.t = t1; // 没有对象符�GC
-
-
-
- t1 = null;
-
- // 没有对象符�GC (t3.t �然有一个到 t1 的引用)
-
-
-
- t2 = null;
-
- // 没有对象符�GC (t3.t.t �然有一个到 t2 的引用)
-
-
-
- t3 = null;
-
- // 所有三个对象都符å�ˆGC (å®ƒä»¬ä¸æ²¡æœ‰ä¸€ä¸ªæ‹¥æœ‰å¼•用。
-
- // å�ªæœ‰å�„对象的å�˜é‡� t 还指å�‘了彼æ¤ï¼Œ
-
- // 形�了一个由对象组�的环形的岛,而没有任何外部的引用。)
-
- }
-
-
-
- protected void finalize() {
-
- System.out.println("Garbage collected from object" + i);
-
- i++;
-
- }
-## [JVM GC算法](https://www.cnblogs.com/wupeixuan/p/8670341.html)
+````
+Class GCScope {
+
+ GCScope t;
+
+ static int i = 1;
+
+
+
+ public static void main(String args[]) {
+
+ GCScope t1 = new GCScope();
+
+ GCScope t2 = new GCScope();
+
+ GCScope t3 = new GCScope();
+
+
+
+ // No Object Is Eligible for GC
+
+
+
+ t1.t = t2; // No Object Is Eligible for GC
+
+ t2.t = t3; // No Object Is Eligible for GC
+
+ t3.t = t1; // No Object Is Eligible for GC
+
+
+
+ t1 = null;
+
+ // No Object Is Eligible for GC (t3.t still has a reference to t1)
+
+
+
+ t2 = null;
+
+ // No Object Is Eligible for GC (t3.t.t still has a reference to t2)
+
+
+
+ t3 = null;
+
+ // All the 3 Object Is Eligible for GC (None of them have a reference.
+
+ // only the variable t of the objects are referring each other in a
+
+ // rounded fashion forming the Island of objects with out any external
+
+ // reference)
+
+ }
+
+
+
+ protected void finalize() {
+
+ System.out.println("Garbage collected from object" + i);
+
+ i++;
+
+ }
+
+
+
+class GCScope {
+
+ GCScope t;
+
+ static int i = 1;
+
+
+
+ public static void main(String args[]) {
+
+ GCScope t1 = new GCScope();
+
+ GCScope t2 = new GCScope();
+
+ GCScope t3 = new GCScope();
+
+
+
+ // 没有对象符�GC
+
+ t1.t = t2; // 没有对象符�GC
+
+ t2.t = t3; // 没有对象符�GC
+
+ t3.t = t1; // 没有对象符�GC
+
+
+
+ t1 = null;
+
+ // 没有对象符�GC (t3.t �然有一个到 t1 的引用)
+
+
+
+ t2 = null;
+
+ // 没有对象符�GC (t3.t.t �然有一个到 t2 的引用)
+
+
+
+ t3 = null;
+
+ // 所有三个对象都符å�ˆGC (å®ƒä»¬ä¸æ²¡æœ‰ä¸€ä¸ªæ‹¥æœ‰å¼•用。
+
+ // å�ªæœ‰å�„对象的å�˜é‡� t 还指å�‘了彼æ¤ï¼Œ
+
+ // 形�了一个由对象组�的环形的岛,而没有任何外部的引用。)
+
+ }
+
+
+
+ protected void finalize() {
+
+ System.out.println("Garbage collected from object" + i);
+
+ i++;
+
+ }
+}
+````
+## JVM GC算法
在判æ–哪些内å˜éœ€è¦�回收和什么时候回收用到GC 算法,本文主è¦�对GC 算法进行讲解。
@@ -433,7 +431,6 @@ public class ReferenceCountingGC {
�行结果
```
-
[GC (System.gc()) [PSYoungGen: 3329K->744K(38400K)] 3329K->752K(125952K), 0.0341414 secs] [Times: user=0.00 sys=0.00, real=0.06 secs]
[Full GC (System.gc()) [PSYoungGen: 744K->0K(38400K)] [ParOldGen: 8K->628K(87552K)] 752K->628K(125952K), [Metaspace: 3450K->3450K(1056768K)], 0.0060728 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]
Heap
@@ -457,7 +454,7 @@ Process finished with exit code 0
从GC Roots(æ¯�ç§�具体实现对GC Roots有ä¸�å�Œçš„定义)作为起点,å�‘下æ�œç´¢å®ƒä»¬å¼•用的对象,å�¯ä»¥ç”Ÿæˆ�ä¸€æ£µå¼•ç”¨æ ‘ï¼Œæ ‘çš„èŠ‚ç‚¹è§†ä¸ºå�¯è¾¾å¯¹è±¡ï¼Œå��之视为ä¸�å�¯è¾¾ã€‚
-
+
在Javaè¯è¨€ä¸ï¼Œå�¯ä»¥ä½œä¸ºGC Roots的对象包括下é�¢å‡ ç§�:
@@ -524,8 +521,7 @@ Stop-the-worldæ„�味ç�€ JVM由于è¦�执行GC而å�œæ¢äº†åº”用程åº�的执行,
* æ ‡è®°å’Œæ¸…é™¤è¿‡ç¨‹æ•ˆçŽ‡éƒ½ä¸�高
* 会产生大é‡�碎片,内å˜ç¢Žç‰‡è¿‡å¤šå�¯èƒ½å¯¼è‡´æ— 法给大对象分é…�内å˜ã€‚
-
-
+
## �制算法(Copying)
将内å˜åˆ’分为大å°�相ç‰çš„两å�—,æ¯�次å�ªä½¿ç”¨å…¶ä¸ä¸€å�—,当这一å�—内å˜ç”¨å®Œäº†å°±å°†è¿˜å˜æ´»çš„对象å¤�制到å�¦ä¸€å�—上é�¢ï¼Œç„¶å�Žå†�把使用过的内å˜ç©ºé—´è¿›è¡Œä¸€æ¬¡æ¸…ç�†ã€‚
@@ -537,7 +533,7 @@ Stop-the-worldæ„�味ç�€ JVM由于è¦�执行GC而å�œæ¢äº†åº”用程åº�的执行,
* 将内å˜ç¼©å°�为原æ�¥çš„一å�Šï¼Œæµªè´¹äº†ä¸€å�Šçš„内å˜ç©ºé—´ï¼Œä»£ä»·å¤ªé«˜ï¼›å¦‚æžœä¸�想浪费一å�Šçš„空间,就需è¦�有é¢�外的空间进行分é…�æ‹…ä¿�,以应对被使用的内å˜ä¸æ‰€æœ‰å¯¹è±¡éƒ½100%å˜æ´»çš„æž�端情况,所以在è€�年代一般ä¸�能直接选用这ç§�算法。
* å¤�åˆ¶æ”¶é›†ç®—æ³•åœ¨å¯¹è±¡å˜æ´»çŽ‡è¾ƒé«˜æ—¶å°±è¦�进行较多的å¤�制æ“�作,效率将会å�˜ä½Žã€‚
-
+
## æ ‡è®°â€”æ•´ç�†ç®—法(Mark-Compact)
@@ -547,7 +543,7 @@ Stop-the-worldæ„�味ç�€ JVM由于è¦�执行GC而å�œæ¢äº†åº”用程åº�的执行,
效率ä¸�高,ä¸�ä»…è¦�æ ‡è®°å˜æ´»å¯¹è±¡ï¼Œè¿˜è¦�æ•´ç�†æ‰€æœ‰å˜æ´»å¯¹è±¡çš„引用地å�€ï¼Œåœ¨æ•ˆçŽ‡ä¸Šä¸�如å¤�制算法。
-
+
## 分代收集算法(Generational Collection)
@@ -569,20 +565,4 @@ Stop-the-worldæ„�味ç�€ JVM由于è¦�执行GC而å�œæ¢äº†åº”用程åº�的执行,
https://blog.csdn.net/android_hl/article/details/53228348
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
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\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\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\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
new file mode 100644
index 0000000..caac027
--- /dev/null
+++ "b/docs/Java/JVM/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\272\357\274\232JVM\345\270\270\347\224\250\345\217\202\346\225\260\344\273\245\345\217\212\350\260\203\344\274\230\345\256\236\350\267\265.md"
@@ -0,0 +1,659 @@
+# 目录
+
+ * [JVM优化的必�性](#jvm优化的必�性)
+ * [JVM调优原则](#jvm调优原则)
+ * [JVM�行�数设置](#jvm�行�数设置)
+ * [JVM性能调优工具](#jvm性能调优工具)
+ * [常用调优ç–ç•¥](#常用调优ç–ç•¥)
+ * [å…ã€�JVM调优实例](#å…ã€�jvm调优实例)
+ * [七�一个具体的实战案例分�](#七�一个具体的实战案例分�)
+ * [�考资料](#�考资料)
+ * [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
+
+
+
+
+
+
+## JVM优化的必�性
+
+**1.1: 项目上线å�Žï¼Œä»€ä¹ˆåŽŸå› ä½¿å¾—æˆ‘ä»¬éœ€è¦�进行jvm调优**
+
+1)ã€�垃圾太多(java线程,对象å� 满内å˜ï¼‰ï¼Œå†…å˜å� 满了,程åº�è·‘ä¸�动了ï¼�ï¼�
+2)ã€�垃圾回收线程太多,频ç¹�地回收垃圾(垃圾回收线程本身也会å� 用资æº�: å� 用内å˜ï¼Œcpu资æº�),导致程åº�性能下é™�
+3)�回收垃圾频�导致STW
+
+å› æ¤åŸºäºŽä»¥ä¸Šçš„åŽŸå› ï¼Œç¨‹åº�上线å�Žï¼Œå¿…须进行调优,å�¦åˆ™ç¨‹åº�æ€§èƒ½å°±æ— æ³•æ��å�‡ï¼›ä¹Ÿå°±æ˜¯ç¨‹åº�上线å�Žï¼Œå¿…须设置å�ˆç�†çš„垃圾回收ç–略;
+
+**1.2: jvm调优的本质是什么??**
+
+ç”æ¡ˆï¼š 回收垃圾,å�Šæ—¶å›žæ”¶æ²¡æœ‰ç”¨åžƒåœ¾å¯¹è±¡ï¼Œå�Šæ—¶é‡Šæ”¾æŽ‰å†…å˜ç©ºé—´
+
+**1.3: 基于æœ�务器环境,jvmå †å†…å˜åˆ°åº•应用设置多少内å˜ï¼Ÿ**
+
+1�32�的�作系统 --- 寻�能力 2^32 = 4GB ,最大的能支�4gb; jvm�以分� 2g+
+
+2�64�的�作系统 --- 寻�能力 2^64 = 16384PB , 高性能计算机(IBM Z unix 128G 200+)
+
+
+
+Jvmå †å†…å˜ä¸�能设置太大,å�¦åˆ™ä¼šå¯¼è‡´å¯»å�€åžƒåœ¾çš„æ—¶é—´è¿‡é•¿ï¼Œä¹Ÿå°±æ˜¯å¯¼è‡´æ•´ä¸ªç¨‹åº�STW, 也ä¸�能设置太å°�,å�¦åˆ™ä¼šå¯¼è‡´å›žæ”¶åžƒåœ¾è¿‡äºŽé¢‘ç¹�ï¼›
+
+**1.4:总结**
+
+å¦‚æžœä½ é�‡åˆ°ä»¥ä¸‹æƒ…况,就需è¦�考虑进行JVM调优了:
+
+* Heap内å˜ï¼ˆè€�年代)æŒ�ç»ä¸Šæ¶¨è¾¾åˆ°è®¾ç½®çš„æœ€å¤§å†…å˜å€¼ï¼›
+
+* Full GC 次数频�;
+
+* GC �顿时间过长(超过1秒);
+
+* 应用出现OutOfMemory ç‰å†…å˜å¼‚常;
+
+* åº”ç”¨ä¸æœ‰ä½¿ç”¨æœ¬åœ°ç¼“å˜ä¸”å� 用大é‡�内å˜ç©ºé—´ï¼›
+
+* 系统���与�应性能�高或下�。
+
+## JVM调优原则
+
+
+
+JVM调优是一个手段,但并ä¸�一定所有问题都å�¯ä»¥é€šè¿‡JVMè¿›è¡Œè°ƒä¼˜è§£å†³ï¼Œå› æ¤ï¼Œåœ¨è¿›è¡ŒJVM调优时,我们è¦�é�µå¾ªä¸€äº›åŽŸåˆ™ï¼š
+
+* 大多数的Java应用�需�进行JVM优化;
+
+* 大多数导致GCé—®é¢˜çš„åŽŸå› æ˜¯ä»£ç �层é�¢çš„问题导致的(代ç �层é�¢ï¼‰ï¼›
+
+* 上线之�,应先考虑将机器的JVM�数设置到最优;
+
+* å‡�少创建对象的数é‡�(代ç �层é�¢ï¼‰ï¼›
+
+* å‡�少使用全局å�˜é‡�和大对象(代ç �层é�¢ï¼‰ï¼›
+
+* 优先架构调优和代ç �调优,JVM优化是ä¸�得已的手段(代ç �ã€�架构层é�¢ï¼‰ï¼›
+
+* 分æž�GC情况优化代ç �比优化JVMå�‚数更好(代ç �层é�¢ï¼‰ï¼›
+
+通过以上原则,我们å�‘现,其实最有效的优化手段是架构和代ç �层é�¢çš„优化,而JVM优化则是最å�Žä¸�得已的手段,也å�¯ä»¥è¯´æ˜¯å¯¹æœ�务器é…�置的最å�Žä¸€æ¬¡â€œåŽ‹æ¦¨â€�。
+
+**2.1 JVMè°ƒä¼˜ç›®æ ‡**
+
+调优的最终目的都是为了令应用程åº�使用最å°�的硬件消耗æ�¥æ‰¿è½½æ›´å¤§çš„å�žå��。jvm调优主è¦�是针对垃圾收集器的收集性能优化,令è¿�行在虚拟机上的应用能够使用更少的内å˜ä»¥å�Šå»¶è¿ŸèŽ·å�–更大的å�žå��é‡�。
+
+* 延迟:GC低�顿和GC低频率;
+
+* 低内å˜å� 用;
+
+* 高���;
+
+å…¶ä¸ï¼Œä»»ä½•一个属性性能的æ��é«˜ï¼Œå‡ ä¹Žéƒ½æ˜¯ä»¥ç‰ºç‰²å…¶ä»–å±žæ€§æ€§èƒ½çš„æ�Ÿä¸ºä»£ä»·çš„,ä¸�å�¯å…¼å¾—ã€‚å…·ä½“æ ¹æ�®åœ¨ä¸šåŠ¡ä¸çš„é‡�è¦�性确定。
+
+**2.2 JVM调优é‡�åŒ–ç›®æ ‡**
+
+下é�¢å±•示了一些JVM调优的é‡�åŒ–ç›®æ ‡å�‚考实例:
+
+* Heap 内å˜ä½¿ç”¨çއ <= 70%;
+
+* Old generation内å˜ä½¿ç”¨çއ<= 70%;
+
+* avgpause <= 1ç§’;
+
+* Full gc 次数0 或 avg pause interval >= 24�时 ;
+
+注æ„�:ä¸�å�Œåº”用的JVM调优é‡�åŒ–ç›®æ ‡æ˜¯ä¸�ä¸€æ ·çš„ã€‚
+
+**2.3 JVM调优的æ¥éª¤**
+
+一般情况下,JVM调优å�¯é€šè¿‡ä»¥ä¸‹æ¥éª¤è¿›è¡Œï¼š
+
+* 分æž�GC日志å�Šdumpæ–‡ä»¶ï¼Œåˆ¤æ–æ˜¯å�¦éœ€è¦�优化,确定瓶颈问题点;
+
+* 确定JVM调优é‡�åŒ–ç›®æ ‡ï¼›
+
+* 确定JVM调优å�‚æ•°ï¼ˆæ ¹æ�®åކå�²JVMå�‚æ•°æ�¥è°ƒæ•´ï¼‰ï¼›
+
+* ä¾�次调优内å˜ã€�延迟ã€�å�žå��é‡�ç‰æŒ‡æ ‡ï¼›
+
+* 对比观察调优��的差异;
+
+* ä¸�æ–的分æž�和调整,直到找到å�ˆé€‚çš„JVMå�‚æ•°é…�置;
+
+* 找到最å�ˆé€‚çš„å�‚数,将这些å�‚数应用到所有æœ�务器,并进行å�Žç»è·Ÿè¸ªã€‚
+
+以上æ“�作æ¥éª¤ä¸ï¼ŒæŸ�些æ¥éª¤æ˜¯éœ€è¦�多次ä¸�æ–è¿ä»£å®Œæˆ�的。一般是从满足程åº�的内å˜ä½¿ç”¨éœ€æ±‚开始的,之å�Žæ˜¯æ—¶é—´å»¶è¿Ÿçš„è¦�求,最å�Žæ‰�是å�žå��é‡�çš„è¦�求,è¦�基于这个æ¥éª¤æ�¥ä¸�æ–优化,æ¯�一个æ¥éª¤éƒ½æ˜¯è¿›è¡Œä¸‹ä¸€æ¥çš„基础,ä¸�å�¯é€†è¡Œä¹‹ã€‚
+
+
+
+**调优原则总结**
+
+JVM的自动内å˜ç®¡ç�†æœ¬æ�¥å°±æ˜¯ä¸ºäº†å°†å¼€å�‘人员从内å˜ç®¡ç�†çš„æ³¥æ½é‡Œæ‹‰å‡ºæ�¥ã€‚JVM调优ä¸�是常规手段,性能问题一般第一选择是优化程åº�,最å�Žçš„选择æ‰�是进行JVM调优。
+
+�使�得�进行JVM调优,也�对�能�脑门就去调整�数,一定�全�监控,详细分�性能数�。
+
+**附录:系统性能优化指导**
+
+
+
+### JVM�行�数设置
+
+**3.1ã€�å †å�‚数设置**
+
+**-XX:+PrintGC**使用这个�数,虚拟机�动�,���到GC就会打�日志
+
+**-XX:+UseSerialGC**�置串行回收器
+
+**-XX:+PrintGCDetails**�以查看详细信�,包括�个区的情况
+
+**-Xms**设置Java程åº�å�¯åŠ¨æ—¶åˆ�å§‹åŒ–å †å¤§å°�
+
+**-Xmx**设置Java程åº�èƒ½èŽ·å¾—æœ€å¤§çš„å †å¤§å°�
+
+**-Xmx20m -Xms5m -XX:+PrintCommandLineFlags**å�¯ä»¥å°†éš�å¼�æˆ–è€…æ˜¾ç¤ºä¼ ç»™è™šæ‹Ÿæœºçš„å�‚数输出
+
+**3.2�新生代�数�置**
+
+**-Xmn**å�¯ä»¥è®¾ç½®æ–°ç”Ÿä»£çš„大å°�,设置一个比较大的新生代会å‡�å°‘è€�年代的大å°�,这个å�‚数对系统性能以å�ŠGC行为有很大的影å“�,新生代大å°�ä¸€èˆ¬ä¼šè®¾ç½®æ•´ä¸ªå †ç©ºé—´çš„1/3到1/4å·¦å�³
+
+**-XX:SurvivorRatio**用æ�¥è®¾ç½®æ–°ç”Ÿä»£ä¸eden空间和from/to空间的比例。å�«ä¹‰ï¼š-XX:SurvivorRatio=eden/from**/**eden/to
+
+ä¸�å�Œçš„å †åˆ†å¸ƒæƒ…å†µï¼Œå¯¹ç³»ç»Ÿæ‰§è¡Œä¼šäº§ç”Ÿä¸€å®šçš„å½±å“�,在实际工作ä¸ï¼Œåº”è¯¥æ ¹æ�®ç³»ç»Ÿçš„特点å�šå‡ºå�ˆç�†çš„é…�置,基本ç–略:尽å�¯èƒ½å°†å¯¹è±¡é¢„留在新生代,å‡�å°‘è€�年代的GC次数
+
+除了�以设置新生代的�对大�(-Xmn),还�以使用(-XX:NewRatio)设置新生代和�年代的比例:-XX:NewRatio=�年代/新生代
+
+**�置�行时�数:**
+
+-Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC
+
+**3.3ã€�å †æº¢å‡ºå�‚æ•°é…�ç½®**
+
+在Java程åº�在è¿�行过程ä¸ï¼Œå¦‚果对空间ä¸�è¶³ï¼Œåˆ™ä¼šæŠ›å‡ºå†…å˜æº¢å‡ºçš„错误(Out Of Memory)OOM,一旦这类问题å�‘生在生产环境,则å�¯èƒ½å¼•起严é‡�çš„ä¸šåŠ¡ä¸æ–,Java虚拟机æ��供了**-XX:+
+HeapDumpOnOutOfMemoryError**,使用该å�‚æ•°å�¯ä»¥åœ¨å†…å˜æº¢å‡ºæ—¶å¯¼å‡ºæ•´ä¸ªå †ä¿¡æ�¯ï¼Œä¸Žä¹‹é…�å�ˆä½¿ç”¨çš„还有å�‚æ•°**-XX:HeapDumpPath**,å�¯ä»¥è®¾ç½®å¯¼å‡ºå †çš„å˜æ”¾è·¯å¾„
+
+内å˜åˆ†æž�工具:Memory Analyzer
+
+**�置�行时�数**-Xms1m -Xmx1m -XX:+
+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/Demo3.dump
+
+**3.4ã€�æ ˆå�‚æ•°é…�ç½®**
+
+Java虚拟机æ��供了å�‚æ•°**-Xss**æ�¥æŒ‡å®šçº¿ç¨‹çš„æœ€å¤§æ ˆç©ºé—´ï¼Œæ•´ä¸ªå�‚数也直接决定了函数å�¯è°ƒç”¨çš„æœ€å¤§æ·±åº¦ã€‚
+
+**�置�行时�数:**-Xss1m
+
+3.5�方法区�数�置
+
+å’ŒJavaå †ä¸€æ ·ï¼Œæ–¹æ³•åŒºæ˜¯ä¸€å�—所有线程共享的内å˜åŒºåŸŸï¼Œå®ƒç”¨äºŽä¿�å˜ç³»ç»Ÿçš„类信æ�¯ï¼Œæ–¹æ³•区(永久区)å�¯ä»¥ä¿�å˜å¤šå°‘ä¿¡æ�¯å�¯ä»¥å¯¹å…¶è¿›è¡Œé…�置,在默认情况下,**-XX:MaxPermSize**为64M,如果系统è¿�行时生产大é‡�的类,就需è¦�设置一个相对å�ˆé€‚的方法区,以å…�å‡ºçŽ°æ°¸ä¹…åŒºå†…å˜æº¢å‡ºçš„问题
+
+-XX:PermSize=64M -XX:MaxPermSize=64M
+
+**3.6ã€�直接内å˜å�‚æ•°é…�ç½®**
+
+直接内å˜ä¹Ÿæ˜¯Java程åº�ä¸é�žå¸¸é‡�è¦�的组æˆ�部分,特别是广泛用在NIOä¸ï¼Œç›´æŽ¥å†…å˜è·³è¿‡äº†Javaå †ï¼Œä½¿ç”¨Java程åº�å�¯ä»¥ç›´æŽ¥è®¿é—®åŽŸç”Ÿå †ç©ºé—´ï¼Œå› æ¤åœ¨ä¸€å®šç¨‹åº¦ä¸ŠåŠ å¿«äº†å†…å˜ç©ºé—´çš„访问速度
+
+但是说直接内å˜ä¸€å®šå°±å�¯ä»¥æ��高内å˜è®¿é—®é€Ÿåº¦ä¹Ÿä¸�è§�得,具体情况具体分æž�
+
+**相关é…�ç½®å�‚数:-XX:MaxDirectMemorySize**,如果ä¸�è®¾ç½®ï¼Œé»˜è®¤å€¼ä¸ºæœ€å¤§å †ç©ºé—´ï¼Œå�³-Xmx。直接内å˜ä½¿ç”¨è¾¾åˆ°ä¸Šé™�时,就会触å�‘垃圾回收,如果ä¸�能有效的释放空间,就会引起系统的OOM
+
+**3.7�对象进入�年代的�数�置**
+
+一般而言,对象首次创建会被放置在新生代的eden区,如果没有GC介入,则对象�会离开eden区,那么eden区的对象如何进入�年代呢?
+
+通常情况下,å�ªè¦�对象的年龄达到一定的大å°�,就会自动离开年轻代进入è€�年代,对象年龄是由对象ç»�历数次GC决定的,在新生代æ¯�次GC之å�Žå¦‚æžœå¯¹è±¡æ²¡æœ‰è¢«å›žæ”¶ï¼Œåˆ™å¹´é¾„åŠ 1
+
+虚拟机�供了一个�数�控制新生代对象的最大年龄,当超过这个年龄范围就会晋��年代
+
+**-XX:MaxTenuringThreshold**,默认情况下为15
+
+**�置�行时�数:**-Xmx64M -Xms64M -XX:+PrintGCDetails
+
+**结论**:对象首次创建会被放置在新生代的edenåŒºï¼Œå› æ¤è¾“出结果ä¸fromå’Œto区都为0%
+
+æ ¹æ�®è®¾ç½®MaxTenuringThresholdå�‚数,å�¯ä»¥æŒ‡å®šæ–°ç”Ÿä»£å¯¹è±¡ç»�过多少次回收å�Žè¿›å…¥è€�年代。å�¦å¤–,大对象新生代edenåŒºæ— æ³•è£…å…¥æ—¶ï¼Œä¹Ÿä¼šç›´æŽ¥è¿›å…¥è€�年代。
+
+JVM里有个�数�以设置对象的大�超过在指定的大�之�,直接晋��年代 **-XX:PretenureSizeThreshold=15**
+
+�数:-Xmx1024M -Xms1024M -XX:+UseSerialGC -XX:MaxTenuringThreshold=15 -XX:+PrintGCDetails
+
+使用PretenureSizeThresholdå�¯ä»¥è¿›è¡ŒæŒ‡å®šè¿›å…¥è€�年代的对象大å°�,但是è¦�注æ„�TLAB区域优先分é…�空间。虚拟机对于体积ä¸�大的对象 会优先把数æ�®åˆ†é…�到TLAB区域ä¸ï¼Œå› æ¤å°±å¤±åŽ»äº†åœ¨è€�年代分é…�的机会
+
+�数:-Xmx30M -Xms30M -XX:+UseSerialGC -XX:+PrintGCDetails
+-XX:PretenureSizeThreshold=1000 -XX:-UseTLAB
+
+**3.8�TLAB�数�置**
+
+TLAB全称是Thread Local Allocation Buffer,å�³çº¿ç¨‹æœ¬åœ°åˆ†é…�缓å˜ï¼Œä»Žå��å—上看是一个线程专用的内å˜åˆ†é…�åŒºåŸŸï¼Œæ˜¯ä¸ºäº†åŠ é€Ÿå¯¹è±¡åˆ†é…�对象而生的。æ¯�一个线程都会产生一个TLAB,该线程独享的工作区域,Java虚拟机使用这ç§�TLAB区æ�¥é�¿å…�多线程冲çª�问题,æ��高了对象分é…�的效率
+
+TLAB空间一般ä¸�ä¼šå¤ªå¤§ï¼Œå½“å¤§å¯¹è±¡æ— æ³•åœ¨TLAB分é…�时,则会直接分é…�åˆ°å †ä¸Š
+
+**-XX:+UseTLAB**使用TLAB
+
+**-XX:+TLABSize**设置TLAB大�
+
+**-XX:TLABRefillWasteFraction**设置维护进入TLAB空间的å�•个对象大å°�,它是一个比例值,默认为64,å�³å¦‚果对象大于整个空间的1/64ï¼Œåˆ™åœ¨å †åˆ›å»ºå¯¹è±¡
+
+**-XX:+PrintTLAB**查看TLAB信�
+
+**-XX:ResizeTLAB**自调整TLABRefillWasteFraction阈值
+
+�数:-XX:+UseTLAB -XX:+PrintTLAB -XX:+PrintGC -XX:TLABSize=102400 -XX:-ResizeTLAB
+-XX:TLABRefillWasteFraction=100 -XX:-DoEscapeAnalysis -server
+
+内å˜å�‚æ•°
+
+
+
+
+
+
+
+
+
+
+
+## JVM性能调优工具
+
+这个篇幅在这里就�过多介�了,�以�照:
+
+深入ç�†è§£JVM虚拟机——Java虚拟机的监控å�Šè¯Šæ–工具大全
+
+## 常用调优ç–ç•¥
+
+这里还是��一下,�时确定�进行JVM调优,也��陷入“知�障�,进行分�之�,�现�以通过优化程���性能,�然首选优化程�。
+
+**5.1�选择�适的垃圾回收器**
+
+CPUå�•æ ¸ï¼Œé‚£ä¹ˆæ¯«æ— ç–‘é—®Serial åžƒåœ¾æ”¶é›†å™¨æ˜¯ä½ å”¯ä¸€çš„é€‰æ‹©ã€‚
+
+CPUå¤šæ ¸ï¼Œå…³æ³¨å�žå��é‡� ,那么选择PS+PO组å�ˆã€‚
+
+CPUå¤šæ ¸ï¼Œå…³æ³¨ç”¨æˆ·å�œé¡¿æ—¶é—´ï¼ŒJDK版本1.6或者1.7,那么选择CMS。
+
+CPUå¤šæ ¸ï¼Œå…³æ³¨ç”¨æˆ·å�œé¡¿æ—¶é—´ï¼ŒJDK1.8å�Šä»¥ä¸Šï¼ŒJVMå�¯ç”¨å†…å˜6G以上,那么选择G1。
+
+�数�置:
+
+> //设置Serial垃圾收集器(新生代)
+>
+> 开�:-XX:+UseSerialGC
+>
+> //设置PS+PO,新生代使用功能Parallel Scavenge �年代将会使用Parallel Old收集器
+>
+> 开� -XX:+UseParallelOldGC
+>
+> //CMS垃圾收集器(�年代)
+>
+> 开� -XX:+UseConcMarkSweepGC
+>
+> //设置G1垃圾收集器
+>
+> 开� -XX:+UseG1GC
+
+**5.2ã€�调整内å˜å¤§å°�**
+
+现象:垃圾收集频率�常频�。
+
+åŽŸå› ï¼šå¦‚æžœå†…å˜å¤ªå°�,就会导致频ç¹�的需è¦�进行垃圾收集æ‰�能释放出足够的空间æ�¥åˆ›å»ºæ–°çš„å¯¹è±¡ï¼Œæ‰€ä»¥å¢žåŠ å †å†…å˜å¤§å°�的效果是é�žå¸¸æ˜¾è€Œæ˜“è§�的。
+
+注æ„�:如果垃圾收集次数é�žå¸¸é¢‘ç¹�,但是æ¯�次能回收的对象é�žå¸¸å°‘,那么这个时候并é�žå†…å˜å¤ªå°�,而å�¯èƒ½æ˜¯å†…å˜æ³„éœ²å¯¼è‡´å¯¹è±¡æ— æ³•å›žæ”¶ï¼Œä»Žè€Œé€ æˆ�频ç¹�GC。
+
+�数�置:
+
+> //è®¾ç½®å †åˆ�始值
+>
+> 指令1:-Xms2g
+>
+> 指令2:-XX:InitialHeapSize=2048m
+>
+> //è®¾ç½®å †åŒºæœ€å¤§å€¼
+>
+> 指令1:`-Xmx2g`
+>
+> 指令2: -XX:MaxHeapSize=2048m
+>
+> //新生代内å˜é…�ç½®
+>
+> 指令1:-Xmn512m
+>
+> 指令2:-XX:MaxNewSize=512m
+
+**5.3�设置符�预期的�顿时间**
+
+**现象**:程�间接性的�顿
+
+**åŽŸå› **:如果没有确切的å�œé¡¿æ—¶é—´è®¾å®šï¼Œåžƒåœ¾æ”¶é›†å™¨ä»¥å�žå��é‡�为主,那么垃圾收集时间就会ä¸�稳定。
+
+**注æ„�**:ä¸�è¦�设置ä¸�切实际的å�œé¡¿æ—¶é—´ï¼Œå�•次时间越çŸä¹Ÿæ„�味ç�€éœ€è¦�更多的GC次数æ‰�能回收完原有数é‡�的垃圾.
+
+**�数�置**:
+
+> //GC�顿时间,垃圾收集器会�试用��手段达到这个时间
+>
+> -XX:MaxGCPauseMillis
+
+**5.4ã€�调整内å˜åŒºåŸŸå¤§å°�比率**
+
+现象:æŸ�一个区域的GC频ç¹�,其他都æ£å¸¸ã€‚
+
+åŽŸå› ï¼šå¦‚æžœå¯¹åº”åŒºåŸŸç©ºé—´ä¸�足,导致需è¦�频ç¹�GCæ�¥é‡Šæ”¾ç©ºé—´ï¼Œåœ¨JVMå †å†…å˜æ— æ³•å¢žåŠ çš„æƒ…å†µä¸‹ï¼Œå�¯ä»¥è°ƒæ•´å¯¹åº”区域的大å°�比率。
+
+注æ„�:也许并é�žç©ºé—´ä¸�è¶³ï¼Œè€Œæ˜¯å› ä¸ºå†…å˜æ³„é€ æˆ�å†…å˜æ— 法回收。从而导致GC频ç¹�。
+
+�数�置:
+
+> //survivor区和Eden区大�比率
+>
+> 指令:-XX:SurvivorRatio=6 //S区和Eden区å� 新生代比率为1:6,两个S区2:6
+>
+> //新生代和è€�年代的å� 比
+>
+> -XX:NewRatio=4 //表示新生代:è€�年代 = 1:4 å�³è€�年代å� æ•´ä¸ªå †çš„4/5;默认值=2
+
+**5.5�调整对象��年代的年龄**
+
+**现象**:�年代频�GC,�次回收的对象很多。
+
+**åŽŸå› **:如果å�‡ä»£å¹´é¾„å°�,新生代的对象很快就进入è€�年代了,导致è€�年代对象å�˜å¤šï¼Œè€Œè¿™äº›å¯¹è±¡å…¶å®žåœ¨éš�å�Žçš„å¾ˆçŸæ—¶é—´å†…å°±å�¯ä»¥å›žæ”¶ï¼Œè¿™æ—¶å€™å�¯ä»¥è°ƒæ•´å¯¹è±¡çš„å�‡çº§ä»£å¹´é¾„,让对象ä¸�那么容易进入è€�年代解决è€�年代空间ä¸�足频ç¹�GC问题。
+
+**注æ„�**ï¼šå¢žåŠ äº†å¹´é¾„ä¹‹å�Žï¼Œè¿™äº›å¯¹è±¡åœ¨æ–°ç”Ÿä»£çš„æ—¶é—´ä¼šå�˜é•¿å�¯èƒ½å¯¼è‡´æ–°ç”Ÿä»£çš„GCé¢‘çŽ‡å¢žåŠ ï¼Œå¹¶ä¸”é¢‘ç¹�å¤�制这些对象新生的GC时间也å�¯èƒ½å�˜é•¿ã€‚
+
+�置�数:
+
+> //进入�年代最�的GC年龄,年轻代对象转�为�年代对象最�年龄值,默认值7
+>
+> -XX:InitialTenuringThreshol=7
+
+**5.6ã€�è°ƒæ•´å¤§å¯¹è±¡çš„æ ‡å‡†**
+
+**现象**:�年代频�GC,�次回收的对象很多,而且�个对象的体积都比较大。
+
+**åŽŸå› **:如果大é‡�的大对象直接分é…�到è€�年代,导致è€�å¹´ä»£å®¹æ˜“è¢«å¡«æ»¡è€Œé€ æˆ�频ç¹�GC,å�¯è®¾ç½®å¯¹è±¡ç›´æŽ¥è¿›å…¥è€�å¹´ä»£çš„æ ‡å‡†ã€‚
+
+**注æ„�**:这些大对象进入新生代å�Žå�¯èƒ½ä¼šä½¿æ–°ç”Ÿä»£çš„GCé¢‘çŽ‡å’Œæ—¶é—´å¢žåŠ ã€‚
+
+�置�数:
+
+> //新生代�容纳的最大对象,大于则直接会分�到�年代,0代表没有�制。
+>
+> -XX:PretenureSizeThreshold=1000000
+
+**5.7�调整GC的触�时机**
+
+**现象**:CMS,G1 �常 Full GC,程��顿严�。
+
+**åŽŸå› **:G1å’ŒCMS 部分GC阶段是并å�‘进行的,业务线程和垃圾收集线程一起工作,也就说明垃圾收集的过程ä¸ä¸šåŠ¡çº¿ç¨‹ä¼šç”Ÿæˆ�新的对象,所以在GC的时候需è¦�预留一部分内å˜ç©ºé—´æ�¥å®¹çº³æ–°äº§ç”Ÿçš„对象,如果这个时候内å˜ç©ºé—´ä¸�足以容纳新产生的对象,那么JVM就会å�œæ¢å¹¶å�‘收集暂å�œæ‰€æœ‰ä¸šåŠ¡çº¿ç¨‹ï¼ˆSTW)æ�¥ä¿�è¯�垃圾收集的æ£å¸¸è¿�行。这个时候å�¯ä»¥è°ƒæ•´GC触å�‘的时机(比如在è€�年代å� 用60%就触å�‘GCï¼‰ï¼Œè¿™æ ·å°±å�¯ä»¥é¢„留足够的空间æ�¥è®©ä¸šåŠ¡çº¿ç¨‹åˆ›å»ºçš„å¯¹è±¡æœ‰è¶³å¤Ÿçš„ç©ºé—´åˆ†é…�。
+
+**注æ„�**:æ��早触å�‘GCä¼šå¢žåŠ è€�年代GC的频率。
+
+�置�数:
+
+> //使用多少比例的�年代�开始CMS收集,默认是68%,如果频��生SerialOld�顿,应该调�
+>
+> -XX:CMSInitiatingOccupancyFraction
+>
+> //G1æ··å�ˆåžƒåœ¾å›žæ”¶å‘¨æœŸä¸è¦�包括的旧区域设置å� 用率阈值。默认å� 用率为 65%
+>
+> -XX:G1MixedGCLiveThresholdPercent=65
+
+5.8ã€�调整 JVM本地内å˜å¤§å°�
+
+**现象**:GC的次数ã€�时间和回收的对象都æ£å¸¸ï¼Œå †å†…å˜ç©ºé—´å……足,但是报OOM
+
+**åŽŸå› **: JVMé™¤äº†å †å†…å˜ä¹‹å¤–还有一å�—å †å¤–å†…å˜ï¼Œè¿™ç‰‡å†…å˜ä¹Ÿå�«æœ¬åœ°å†…å˜ï¼Œå�¯æ˜¯è¿™å�—内å˜åŒºåŸŸä¸�足了并ä¸�会主动触å�‘GC,å�ªæœ‰åœ¨å †å†…å˜åŒºåŸŸè§¦å�‘的时候顺带会把本地内å˜å›žæ”¶äº†ï¼Œè€Œä¸€æ—¦æœ¬åœ°å†…å˜åˆ†é…�ä¸�足就会直接报OOM异常。
+
+**注æ„�**: 本地内å˜å¼‚常的时候除了上é�¢çš„现象之外,异常信æ�¯å�¯èƒ½æ˜¯OutOfMemoryError:Direct buffer memory。 解决方å¼�除了调整本地内å˜å¤§å°�之外,也å�¯ä»¥åœ¨å‡ºçްæ¤å¼‚常时进行æ�•获,手动触å�‘GC(System.gc())。
+
+�置�数:
+
+> XX:MaxDirectMemorySize
+
+## å…ã€�JVM调优实例
+
+整�的一些JVM调优实例:
+
+**6.1�网站���览�暴增�,网站�应页��很慢**
+
+> 1ã€�问题推测:在测试环境测速度比较快,但是一到生产就å�˜æ…¢ï¼Œæ‰€ä»¥æŽ¨æµ‹å�¯èƒ½æ˜¯å› 为垃圾收集导致的业务线程å�œé¡¿ã€‚
+>
+> 2ã€�定ä½�:为了确认推测的æ£ç¡®æ€§ï¼Œåœ¨çº¿ä¸Šé€šè¿‡jstat -gc 指令 看到JVM进行GC 次数频率é�žå¸¸é«˜ï¼ŒGC所å� 用的时间é�žå¸¸é•¿ï¼Œæ‰€ä»¥åŸºæœ¬æŽ¨æ–å°±æ˜¯å› ä¸ºGC频率é�žå¸¸é«˜ï¼Œæ‰€ä»¥å¯¼è‡´ä¸šåŠ¡çº¿ç¨‹ç»�常å�œé¡¿ï¼Œä»Žè€Œé€ æˆ�网页å��应很慢。
+>
+> 3ã€�è§£å†³æ–¹æ¡ˆï¼šå› ä¸ºç½‘é¡µè®¿é—®é‡�很高,所以对象创建速度é�žå¸¸å¿«ï¼Œå¯¼è‡´å †å†…å˜å®¹æ˜“填满从而频ç¹�GC,所以这里问题在于新生代内å˜å¤ªå°�,所以这里å�¯ä»¥å¢žåŠ JVM内å˜å°±è¡Œäº†ï¼Œæ‰€ä»¥åˆ�æ¥ä»ŽåŽŸæ�¥çš„2G内å˜å¢žåŠ åˆ°16G内å˜ã€‚
+>
+> 4ã€�ç¬¬äºŒä¸ªé—®é¢˜ï¼šå¢žåŠ å†…å˜å�Žçš„确平常的请求比较快了,但是å�ˆå‡ºçŽ°äº†å�¦å¤–一个问题,就是ä¸�å®šæœŸçš„ä¼šé—´æ–æ€§çš„å�¡é¡¿ï¼Œè€Œä¸”å�•次å�¡é¡¿çš„æ—¶é—´è¦�比之å‰�è¦�长很多。
+>
+> 5ã€�é—®é¢˜æŽ¨æµ‹ï¼šç»ƒä¹ åˆ°æ˜¯ä¹‹å‰�çš„ä¼˜åŒ–åŠ å¤§äº†å†…å˜ï¼Œæ‰€ä»¥æŽ¨æµ‹å�¯èƒ½æ˜¯å› 为内å˜åŠ å¤§äº†ï¼Œä»Žè€Œå¯¼è‡´å�•次GC的时间å�˜é•¿ä»Žè€Œå¯¼è‡´é—´æŽ¥æ€§çš„å�¡é¡¿ã€‚
+>
+> 6ã€�定ä½�:还是通过jstat -gc 指令 查看到 的确FGC次数并ä¸�是很高,但是花费在FGC上的时间是é�žå¸¸é«˜çš„,æ ¹æ�®GC日志 查看到å�•次FGCçš„æ—¶é—´æœ‰è¾¾åˆ°å‡ å��秒的。
+>
+> 7ã€�解决方案: å› ä¸ºJVM默认使用的是PS+PO的组å�ˆï¼ŒPS+POåžƒåœ¾æ ‡è®°å’Œæ”¶é›†é˜¶æ®µéƒ½æ˜¯STW,所以内å˜åŠ å¤§äº†ä¹‹å�Žï¼Œéœ€è¦�进行垃圾回收的时间就å�˜é•¿äº†ï¼Œæ‰€ä»¥è¿™é‡Œè¦�想é�¿å…�å�•次GC时间过长,所以需è¦�æ›´æ�¢å¹¶å�‘ç±»çš„æ”¶é›†å™¨ï¼Œå› ä¸ºå½“å‰�çš„JDK版本为1.7,所以最å�Žé€‰æ‹©CMSåžƒåœ¾æ”¶é›†å™¨ï¼Œæ ¹æ�®ä¹‹å‰�垃圾收集情况设置了一个预期的å�œé¡¿çš„æ—¶é—´ï¼Œä¸Šçº¿å�Žç½‘ç«™å†�也没有了å�¡é¡¿é—®é¢˜ã€‚
+
+**6.2���导出数�引�的OOM**
+
+**问题æ��述:**å…¬å�¸çš„å�Žå�°ç³»ç»Ÿï¼Œå�¶å�‘性的引å�‘OOMå¼‚å¸¸ï¼Œå †å†…å˜æº¢å‡ºã€‚
+
+> 1ã€�å› ä¸ºæ˜¯å�¶å�‘性的,所以第一次简å�•çš„è®¤ä¸ºå°±æ˜¯å †å†…å˜ä¸�足导致,所以å�•æ–¹é�¢çš„åŠ å¤§äº†å †å†…å˜ä»Ž4G调整到8G。
+>
+> 2ã€�但是问题ä¾�然没有解决,å�ªèƒ½ä»Žå †å†…å˜ä¿¡æ�¯ä¸‹æ‰‹ï¼Œé€šè¿‡å¼€å�¯äº†-XX:+
+> HeapDumpOnOutOfMemoryErrorå�‚æ•° èŽ·å¾—å †å†…å˜çš„dump文件。
+>
+> 3ã€�VisualVM 对 å †dump文件进行分æž�,通过VisualVM查看到å� ç”¨å†…å˜æœ€å¤§çš„对象是String对象,本æ�¥æƒ³è·Ÿè¸ªç�€String对象找到其引用的地方,但dump文件太大,跟踪进去的时候总是å�¡æ»ï¼Œè€ŒString对象å� 用比较多也比较æ£å¸¸ï¼Œæœ€å¼€å§‹ä¹Ÿæ²¡æœ‰è®¤å®šå°±æ˜¯è¿™é‡Œçš„问题,于是就从线程信æ�¯é‡Œé�¢æ‰¾çª�ç ´ç‚¹ã€‚
+>
+> 4ã€�通过线程进行分æž�ï¼Œå…ˆæ‰¾åˆ°äº†å‡ ä¸ªæ£åœ¨è¿�行的业务线程,然å�Žé€�一跟进业务线程看了下代ç �,å�‘现有个引起我注æ„�的方法,导出订å�•ä¿¡æ�¯ã€‚
+>
+> 5ã€�å› ä¸ºè®¢å�•ä¿¡æ�¯å¯¼å‡ºè¿™ä¸ªæ–¹æ³•å�¯èƒ½ä¼šæœ‰å‡ 万的数æ�®é‡�,首先è¦�从数æ�®åº“里é�¢æŸ¥è¯¢å‡ºæ�¥è®¢å�•ä¿¡æ�¯ï¼Œç„¶å�ŽæŠŠè®¢å�•ä¿¡æ�¯ç”Ÿæˆ�excel,这个过程会产生大é‡�çš„String对象。
+>
+> 6ã€�为了验è¯�自己的猜想,于是准备登录å�Žå�°åŽ»æµ‹è¯•ä¸‹ï¼Œç»“æžœåœ¨æµ‹è¯•çš„è¿‡ç¨‹ä¸å�‘现到处订å�•的按钮å‰�端居然没有å�šç‚¹å‡»å�ŽæŒ‰é’®ç½®ç�°äº¤äº’事件,结果按钮å�¯ä»¥ä¸€ç›´ç‚¹ï¼Œå› 为导出订å�•æ•°æ�®æœ¬æ�¥å°±é�žå¸¸æ…¢ï¼Œä½¿ç”¨çš„人员å�¯èƒ½å�‘现点击å�Žå¾ˆä¹…å�Žé¡µé�¢éƒ½æ²¡å��应,结果就一直点,结果就大é‡�的请求进入到å�Žå�°ï¼Œå †å†…å˜äº§ç”Ÿäº†å¤§é‡�的订å�•对象和EXCEL对象,而且方法执行é�žå¸¸æ…¢ï¼Œå¯¼è‡´è¿™ä¸€æ®µæ—¶é—´å†…è¿™äº›å¯¹è±¡éƒ½æ— æ³•è¢«å›žæ”¶ï¼Œæ‰€ä»¥æœ€ç»ˆå¯¼è‡´å†…å˜æº¢å‡ºã€‚
+>
+> 7ã€�知é�“了问题就容易解决了,最终没有调整任何JVMå�‚数,å�ªæ˜¯åœ¨å‰�端的导出订å�•æŒ‰é’®ä¸ŠåŠ ä¸Šäº†ç½®ç�°çжæ€�,ç‰å�Žç«¯å“�应之å�ŽæŒ‰é’®æ‰�å�¯ä»¥è¿›è¡Œç‚¹å‡»ï¼Œç„¶å�Žå‡�少了查询订å�•ä¿¡æ�¯çš„é�žå¿…è¦�å—æ®µæ�¥å‡�少生æˆ�对象的体积,然å�Žé—®é¢˜å°±è§£å†³äº†ã€‚
+
+**6.3ã€�å�•ä¸ªç¼“å˜æ•°æ�®è¿‡å¤§å¯¼è‡´çš„系统CPU飚高**
+
+> 1ã€�系统å�‘布å�Žå�‘现CPU一直飚高到600%,å�‘现这个问题å�Žé¦–å…ˆè¦�å�šçš„æ˜¯å®šä½�到是哪个应用å� 用CPU高,通过top 找到了对应的一个java应用å� 用CPU资æº�600%。
+>
+> 2ã€�如果是应用的CPU飚高,那么基本上å�¯ä»¥å®šä½�å�¯èƒ½æ˜¯é”�资æº�竞争,或者是频ç¹�GCé€ æˆ�的。
+>
+> 3ã€�所以准备首先从GC的情况排查,如果GCæ£å¸¸çš„è¯�å†�从线程的角度排查,首先使用jstat -gc PID 指令打å�°å‡ºGC的信æ�¯ï¼Œç»“果得到得到的GC 统计信æ�¯æœ‰æ˜Žæ˜¾çš„异常,应用在è¿�行了æ‰�å‡ åˆ†é’Ÿçš„æƒ…å†µä¸‹GC的时间就å� 用了482秒,那么问这很明显就是频ç¹�GC导致的CPU飚高。
+>
+> 4ã€�定ä½�到了是GC的问题,那么下一æ¥å°±æ˜¯æ‰¾åˆ°é¢‘ç¹�GCçš„åŽŸå› äº†ï¼Œæ‰€ä»¥å�¯ä»¥ä»Žä¸¤æ–¹é�¢å®šä½�了,å�¯èƒ½æ˜¯å“ªä¸ªåœ°æ–¹é¢‘ç¹�åˆ›å»ºå¯¹è±¡ï¼Œæˆ–è€…å°±æ˜¯æœ‰å†…å˜æ³„露导致内å˜å›žæ”¶ä¸�掉。
+>
+> 5ã€�æ ¹æ�®è¿™ä¸ªæ€�è·¯å†³å®šæŠŠå †å†…å˜ä¿¡æ�¯dump下æ�¥çœ‹ä¸€ä¸‹ï¼Œä½¿ç”¨jmap -dump æŒ‡ä»¤æŠŠå †å†…å˜ä¿¡æ�¯dump下æ�¥ï¼ˆå †å†…å˜ç©ºé—´å¤§çš„æ…Žç”¨è¿™ä¸ªæŒ‡ä»¤å�¦åˆ™å®¹æ˜“导致会影å“�åº”ç”¨ï¼Œå› ä¸ºæˆ‘ä»¬çš„å †å†…å˜ç©ºé—´æ‰�2G所以也就没考虑这个问题了)。
+>
+> 6ã€�æŠŠå †å†…å˜ä¿¡æ�¯dump下æ�¥å�Žï¼Œå°±ä½¿ç”¨visualVM进行离线分æž�了,首先从å� ç”¨å†…å˜æœ€å¤šçš„å¯¹è±¡ä¸æŸ¥æ‰¾ï¼Œç»“果排å��第三看到一个业务VOå� ç”¨å †å†…å˜çº¦10%的空间,很明显这个对象是有问题的。
+>
+> 7ã€�通过业务对象找到了对应的业务代ç �,通过代ç �的分æž�找到了一个å�¯ç–‘之处,这个业务对象是查看新闻资讯信æ�¯ç”Ÿæˆ�的对象,由于想æ��å�‡æŸ¥è¯¢çš„æ•ˆçŽ‡ï¼Œæ‰€ä»¥æŠŠæ–°é—»èµ„è®¯ä¿�å˜åˆ°äº†redis缓å˜é‡Œé�¢ï¼Œæ¯�次调用资讯接å�£éƒ½æ˜¯ä»Žç¼“å˜é‡Œé�¢èŽ·å�–。
+>
+> 8ã€�把新闻ä¿�å˜åˆ°redis缓å˜é‡Œé�¢è¿™ä¸ªæ–¹å¼�是没有问题的,有问题的是新闻的50000多æ�¡æ•°æ�®éƒ½æ˜¯ä¿�å˜åœ¨ä¸€ä¸ªkey里é�¢ï¼Œè¿™æ ·å°±å¯¼è‡´æ¯�次调用查询新闻接å�£éƒ½ä¼šä»Žredis里é�¢æŠŠ50000多æ�¡æ•°æ�®éƒ½æ‹¿å‡ºæ�¥ï¼Œå†�å�šç›é€‰åˆ†é¡µæ‹¿å‡º10æ�¡è¿”回给å‰�端。50000多æ�¡æ•°æ�®ä¹Ÿå°±æ„�味ç�€ä¼šäº§ç”Ÿ50000多个对象,æ¯�个对象280个å—节左å�³ï¼Œ50000个对象就有13.3M,这就æ„�味ç�€å�ªè¦�查看一次新闻信æ�¯å°±ä¼šäº§ç”Ÿè‡³å°‘13.3M的对象,那么并å�‘请求é‡�å�ªè¦�到10,那么æ¯�秒钟都会产生133M的对象,而这ç§�大对象会被直接分é…�到è€�å¹´ä»£ï¼Œè¿™æ ·çš„è¯�一个2G大å°�çš„è€�年代内å˜ï¼Œå�ªéœ€è¦�å‡ ç§’å°±ä¼šå¡žæ»¡ï¼Œä»Žè€Œè§¦å�‘GC。
+>
+> 9ã€�知é�“了问题所在å�Žé‚£ä¹ˆå°±å®¹æ˜“è§£å†³äº†ï¼Œé—®é¢˜æ˜¯å› ä¸ºå�•个缓å˜è¿‡å¤§é€ æˆ�的,那么å�ªéœ€è¦�把缓å˜å‡�å°�就行了,这里å�ªéœ€è¦�把缓å˜ä»¥é¡µçš„粒度进行缓å˜å°±è¡Œäº†ï¼Œæ¯�个key缓å˜10æ�¡ä½œä¸ºè¿”回给å‰�端1页的数æ�®ï¼Œè¿™æ ·çš„è¯�æ¯�次查询新闻信æ�¯å�ªä¼šä»Žç¼“å˜æ‹¿å‡º10æ�¡æ•°æ�®ï¼Œå°±é�¿å…�了æ¤é—®é¢˜çš„ 产生。
+
+**6.4�CPU�常100% 问题定�**
+
+问题分æž�:CPU高一定是æŸ�个程åº�长期å� 用了CPU资æº�。
+
+1ã€�所以先需è¦�找出那个进行å� 用CPU高。
+
+> top 列出系统å�„个进程的资æº�å� 用情况。
+
+2ã€�ç„¶å�Žæ ¹æ�®æ‰¾åˆ°å¯¹åº”进行里哪个线程å� 用CPU高。
+
+> top -Hp 进程ID 列出对应进程里é�¢çš„线程å� 用资æº�情况
+
+3ã€�找到对应线程IDå�Žï¼Œå†�打å�°å‡ºå¯¹åº”çº¿ç¨‹çš„å †æ ˆä¿¡æ�¯
+
+> printf "%x\n" PID 把线程ID转�为16进制。
+>
+> jstack PID 打å�°å‡ºè¿›ç¨‹çš„æ‰€æœ‰çº¿ç¨‹ä¿¡æ�¯ï¼Œä»Žæ‰“å�°å‡ºæ�¥çš„线程信æ�¯ä¸æ‰¾åˆ°ä¸Šä¸€æ¥è½¬æ�¢ä¸º16进制的线程ID对应的线程信æ�¯ã€‚
+
+4ã€�最å�Žæ ¹æ�®çº¿ç¨‹çš„å †æ ˆä¿¡æ�¯å®šä½�到具体业务方法,从代ç �é€»è¾‘ä¸æ‰¾åˆ°é—®é¢˜æ‰€åœ¨ã€‚
+
+> 查看是�有线程长时间的watting 或blocked
+>
+> 如果线程长期处于watting状æ€�下, 关注watting on xxxxxx,说明线程在ç‰å¾…这把é”�,然å�Žæ ¹æ�®é”�的地å�€æ‰¾åˆ°æŒ�有é”�的线程。
+
+**6.5ã€�内å˜é£šé«˜é—®é¢˜å®šä½�**
+
+分æž�: 内å˜é£šé«˜å¦‚果是å�‘生在javaè¿›ç¨‹ä¸Šï¼Œä¸€èˆ¬æ˜¯å› ä¸ºåˆ›å»ºäº†å¤§é‡�对象所导致,æŒ�ç»é£šé«˜è¯´æ˜Žåžƒåœ¾å›žæ”¶è·Ÿä¸�ä¸Šå¯¹è±¡åˆ›å»ºçš„é€Ÿåº¦ï¼Œæˆ–è€…å†…å˜æ³„éœ²å¯¼è‡´å¯¹è±¡æ— æ³•å›žæ”¶ã€‚
+
+1�先观察垃圾回收的情况
+
+> jstat -gcPID 1000查看GC次数,时间ç‰ä¿¡æ�¯ï¼Œæ¯�隔一秒打å�°ä¸€æ¬¡ã€‚
+>
+> jmap -histo PID | head -20 æŸ¥çœ‹å †å†…å˜å� 用空间最大的å‰�20个对象类型,å�¯åˆ�æ¥æŸ¥çœ‹æ˜¯å“ªä¸ªå¯¹è±¡å� 用了内å˜ã€‚
+
+如果æ¯�次GC次数频ç¹�,而且æ¯�次回收的内å˜ç©ºé—´ä¹Ÿæ£å¸¸ï¼Œé‚£è¯´æ˜Žæ˜¯å› 为对象创建速度快导致内å˜ä¸€ç›´å� 用很高;如果æ¯�次回收的内å˜é�žå¸¸å°‘,那么很å�¯èƒ½æ˜¯å› ä¸ºå†…å˜æ³„露导致内å˜ä¸€ç›´æ— 法被回收。
+
+2ã€�å¯¼å‡ºå †å†…å˜æ–‡ä»¶å¿«ç…§
+
+> jmap -dump:live,format=b,file=/home/myheapdump.hprof PID dumpå †å†…å˜ä¿¡æ�¯åˆ°æ–‡ä»¶ã€‚
+
+3ã€�使用visualVM对dump文件进行离线分æž�,找到å� 用内å˜é«˜çš„对象,å†�找到创建该对象的业务代ç �ä½�置,从代ç �和业务场景ä¸å®šä½�具体问题。
+
+**6.6�数�分�平�系统频� Full GC**
+
+å¹³å�°ä¸»è¦�对用户在 App ä¸è¡Œä¸ºè¿›è¡Œå®šæ—¶åˆ†æž�统计,并支æŒ�报表导出,使用 CMS GC 算法。
+
+æ•°æ�®åˆ†æž�师在使用ä¸å�‘现系统页é�¢æ‰“å¼€ç»�常å�¡é¡¿ï¼Œé€šè¿‡ jstat 命令å�‘现系统æ¯�次 Young GC å�Žå¤§çº¦æœ‰ 10% çš„å˜æ´»å¯¹è±¡è¿›å…¥è€�年代。
+
+原æ�¥æ˜¯å› 为 Survivor 区空间设置过å°�,æ¯�次 Young GC å�Žå˜æ´»å¯¹è±¡åœ¨ Survivor 区域放ä¸�下,æ��å‰�进入è€�年代。
+
+通过调大 Survivor 区,使得 Survivor 区å�¯ä»¥å®¹çº³ Young GC å�Žå˜æ´»å¯¹è±¡ï¼Œå¯¹è±¡åœ¨ Survivor 区ç»�历多次 Young GC 达到年龄阈值æ‰�进入è€�年代。
+
+调整之å�Žæ¯�次 Young GC å�Žè¿›å…¥è€�å¹´ä»£çš„å˜æ´»å¯¹è±¡ç¨³å®šè¿�è¡Œæ—¶ä»…å‡ ç™¾ Kb,Full GC 频率大大é™�低。
+
+**6.7�业务对接网关 OOM**
+
+网关主è¦�消费 Kafka æ•°æ�®ï¼Œè¿›è¡Œæ•°æ�®å¤„ç�†è®¡ç®—ç„¶å�Žè½¬å�‘到å�¦å¤–çš„ Kafka 队列,系统è¿�è¡Œå‡ ä¸ªå°�时候出现 OOM,é‡�å�¯ç³»ç»Ÿå‡ 个å°�时之å�Žå�ˆ OOM。
+
+通过 jmap å¯¼å‡ºå †å†…å˜ï¼Œåœ¨ eclipse MAT 工具分æž�æ‰�æ‰¾å‡ºåŽŸå› ï¼šä»£ç �ä¸å°†æŸ�个业务 Kafka çš„ topic æ•°æ�®è¿›è¡Œæ—¥å¿—å¼‚æ¥æ‰“å�°ï¼Œè¯¥ä¸šåŠ¡æ•°æ�®é‡�较大,大é‡�å¯¹è±¡å †ç§¯åœ¨å†…å˜ä¸ç‰å¾…被打å�°ï¼Œå¯¼è‡´ OOM。
+
+**6.8�鉴�系统频�长时间 Full GC**
+
+系统对外æ��ä¾›å�„ç§�è´¦å�·é‰´æ�ƒæœ�务,使用时å�‘现系统ç»�常æœ�务ä¸�å�¯ç”¨ï¼Œé€šè¿‡ Zabbix 的监控平å�°ç›‘控å�‘现系统频ç¹�å�‘生长时间 Full GC,且触å�‘æ—¶è€�å¹´ä»£çš„å †å†…å˜é€šå¸¸å¹¶æ²¡æœ‰å� 满,å�‘现原æ�¥æ˜¯ä¸šåС代ç �ä¸è°ƒç”¨äº†
+
+## 七�一个具体的实战案例分�
+
+**7.1 典型调优�数设置**
+
+> æœ�务器é…�置: 4cpu,8GBå†…å˜ ---- jvm调优实际上是设置一个å�ˆç�†å¤§å°�çš„jvmå †å†…å˜ï¼ˆæ—¢ä¸�能太大,也ä¸�能太å°�)
+
+> -Xmx3550m 设置jvmå †å†…å˜æœ€å¤§å€¼ (ç»�验值设置: æ ¹æ�®åŽ‹åŠ›æµ‹è¯•ï¼Œæ ¹æ�®çº¿ä¸Šç¨‹åº�è¿�行效果情况)
+>
+> -Xms3550m 设置jvmå †å†…å˜åˆ�始化大å°�,一般情况下必须设置æ¤å€¼å’Œæœ€å¤§çš„æœ€å¤§çš„å †å†…å˜ç©ºé—´ä¿�æŒ�一致,防æ¢å†…å˜æŠ–åŠ¨ï¼Œæ¶ˆè€—æ€§èƒ½
+>
+> -Xmn2g 设置年轻代å� 用的空间大å°�
+>
+> -Xss256k è®¾ç½®çº¿ç¨‹å †æ ˆçš„å¤§å°�ï¼›jdk5.0以å�Žé»˜è®¤çº¿ç¨‹å †æ ˆå¤§å°�为1MB; 在相å�Œçš„å†…å˜æƒ…况下,å‡�å°�å †æ ˆå¤§å°�,å�¯ä»¥ä½¿å¾—æ“�作系统创建更多的业务线程;
+
+jvmå †å†…å˜è®¾ç½®:
+
+> nohup java -Xmx3550m -Xms3550m -Xmn2g -Xss256k -jar jshop-web-1.0-SNAPSHOT.jar --spring.addition-location=application.yaml > jshop.log 2>&1 ><
+
+TPS性能曲线:
+
+
+
+**7.2 分�gc日志**
+
+如果需è¦�分æž�gc日志,就必须使得æœ�务gc输入gc详情到log日志文件ä¸ï¼Œç„¶å�Žä½¿ç”¨ç›¸åº”gc日志分æž�工具æ�¥å¯¹æ—¥å¿—进行分æž�å�³å�¯ï¼›
+
+把gc详情输出到一个gc.log日志文件ä¸ï¼Œä¾¿äºŽgc分æž�
+
+> -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log
+
+Throughput: 业务线程执行时间 / (gc时间+业务线程时间)
+
+
+
+分�gc日志,�现,一开始就�生了3次fullgc,很明显jvm优化�数的设置是有问题的;
+
+
+
+查看fullgcå�‘ç”Ÿé—®é¢˜åŽŸå› ï¼š jstat -gcutil pid
+
+
+
+MetaspaceæŒ�久代: åˆ�始化分é…�大å°�20m , 当metaspace被å� 满å�Žï¼Œå¿…须对æŒ�久代进行扩容,如果metaspaceæ¯�进行一次扩容,fullgc就需è¦�执行一次;(fullgcå›žæ”¶æ•´ä¸ªå †ç©ºé—´ï¼Œé�žå¸¸å� 用时间)
+
+调整gc�置: 修改永久代空间�始化大�:
+
+> nohup java -Xmx3550m -Xms3550m -Xmn2g -Xss256k -XX:MetaspaceSize=256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop-web-1.0-SNAPSHOT.jar --spring.addition-location=application.yaml > jshop.log 2>&1 ><
+
+�过调优�,fullgc现象已�消失了:
+
+
+
+**7.3 Young&Old比例**
+
+年轻代和è€�年代比例:1:2 å�‚数:-XX:NewRetio = 4 , 表示年轻代(eden,s0,s1)和è€�年代所å� 比值为1:4
+
+1) -XX:NewRetio = 4
+
+
+
+年轻代分é…�的内å˜å¤§å°�å�˜å°�äº†ï¼Œè¿™æ ·YGC次数å�˜å¤šäº†ï¼Œè™½ç„¶fullgcä¸�å�‘生了,但是YGC花费的时间更多了ï¼�
+
+2) -XX:NewRetio = 2 YGCå�‘生的次数必然会å‡�å°‘ï¼›å› ä¸ºeden区域的大å°�å�˜å¤§äº†ï¼Œå› æ¤YGC就会å�˜å°‘ï¼›
+
+
+
+7.4 Eden&S0S1
+
+为了进一æ¥å‡�å°‘YGC, å�¯ä»¥è®¾ç½® enden ,s 区域的比值大å°�ï¼› 设置方å¼�: -XX:SurvivorRatio=8
+
+1) 设置比值:8:1:1
+
+
+
+2) Xmn2g 8:1:1
+
+nohup java -Xmx3550m -Xms3550m -Xmn2g -XX:SurvivorRatio=8 -Xss256k -XX:MetaspaceSize=256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop-web-1.0-SNAPSHOT.jar --spring.addition-location=application.yaml > jshop.log 2>&1 ><
+
+æ ¹æ�®gc调优,垃圾回收次数,时间,å�žå��é‡�都是一个比较优的一个é…�置;
+
+
+
+**7.5 ���优先**
+
+使用并行的垃圾回收器,å�¯ä»¥å……åˆ†åˆ©ç”¨å¤šæ ¸å¿ƒcpuæ�¥å¸®åŠ©è¿›è¡Œåžƒåœ¾å›žæ”¶ï¼›è¿™æ ·çš„gcæ–¹å¼�,就å�«å�šå�žå��é‡�优先的调优方å¼�
+
+垃圾回收器组å�ˆï¼š ps(parallel scavenge) + po (parallel old) æ¤åžƒåœ¾å›žæ”¶å™¨æ˜¯Jdk1.8 默认的垃圾回收器组å�ˆï¼›
+
+> nohup java -Xmx3550m -Xms3550m -Xmn2g -XX:SurvivorRatio=8 -Xss256k -XX:+UseParallelGC -XX:UseParallelOldGC -XX:MetaspaceSize=256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop-web-1.0-SNAPSHOT.jar --spring.addition-location=application.yaml > jshop.log 2>&1 ><
+
+**7.6 �应时间优先**
+
+使用cms垃圾回收器,就是一个å“�应时间优先的组å�ˆï¼› cms垃圾回收器(垃圾回收和业务线程交å�‰æ‰§è¡Œï¼Œä¸�会让业务线程进行å�œé¡¿stw)尽å�¯èƒ½çš„å‡�å°‘stwçš„æ—¶é—´ï¼Œå› æ¤ä½¿ç”¨cms垃圾回收器组å�ˆï¼Œæ˜¯å“�应时间优先组å�ˆ
+
+> nohup java -Xmx3550m -Xms3550m -Xmn2g -XX:SurvivorRatio=8 -Xss256k -XX:+UseParNewGC -XX:UseConcMarkSweepGC -XX:MetaspaceSize=256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop-web-1.0-SNAPSHOT.jar --spring.addition-location=application.yaml > jshop.log 2>&1 ><
+
+�以�现,cms垃圾回收器时间�长;
+
+**7.7 g1**
+
+�置方�如下所示:
+
+> nohup java -Xmx3550m -Xms3550m -Xmn2g -XX:SurvivorRatio=8 -Xss256k -XX:+UseG1GC -XX:MetaspaceSize=256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop-web-1.0-SNAPSHOT.jar --spring.addition-location=application.yaml > jshop.log 2>&1 ><
+
+
+
+
+## �考资料
+
+* [Java HotSpotâ„¢ Virtual Machine Performance Enhancements](http://docs.oracle.com/javase/8/docs/technotes/guides/vm/performance-enhancements-7.html)
+* [Java HotSpot Virtual Machine Garbage Collection Tuning Guide](http://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/index.html)
+* [[HotSpot VM] JVM调优的â€�æ ‡å‡†å�‚æ•°â€�çš„å�„ç§�陷阱](http://hllvm.group.iteye.com/group/topic/27945)
+
+
+## å�‚考文ç«
+
+
+
+
+
+
+
+
+
+https://blog.csdn.net/android_hl/article/details/53228348
+
+
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\27212\357\274\232JVM\346\200\247\350\203\275\347\256\241\347\220\206\347\245\236\345\231\250VisualVM\344\273\213\347\273\215\344\270\216\345\256\236\346\210\230.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\272\357\274\232JVM\346\200\247\350\203\275\347\256\241\347\220\206\347\245\236\345\231\250VisualVM\344\273\213\347\273\215\344\270\216\345\256\236\346\210\230.md"
similarity index 90%
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\27212\357\274\232JVM\346\200\247\350\203\275\347\256\241\347\220\206\347\245\236\345\231\250VisualVM\344\273\213\347\273\215\344\270\216\345\256\236\346\210\230.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\272\357\274\232JVM\346\200\247\350\203\275\347\256\241\347\220\206\347\245\236\345\231\250VisualVM\344\273\213\347\273\215\344\270\216\345\256\236\346\210\230.md"
index 9df9174..e2547b3 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\27212\357\274\232JVM\346\200\247\350\203\275\347\256\241\347\220\206\347\245\236\345\231\250VisualVM\344\273\213\347\273\215\344\270\216\345\256\236\346\210\230.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\272\357\274\232JVM\346\200\247\350\203\275\347\256\241\347\220\206\347\245\236\345\231\250VisualVM\344\273\213\347\273\215\344\270\216\345\256\236\346\210\230.md"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [一�VisualVM是什么?](#一�visualvm是什么?)
* [二�如何获�VisualVM?](#二�如何获�visualvm?)
* [三�获�那个版本?](#三�获�那个版本?)
@@ -9,9 +8,6 @@
* [查找JAVA应用程�耗时的方法函数](#查找java应用程�耗时的方法函数)
* [排查JAVA应用程�线程�](#排查java应用程�线程�)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
本文转自互è�”网,侵åˆ
@@ -36,9 +32,6 @@
## 一�VisualVM是什么?
VisualVM是一款�费的JAVA虚拟机图形化监控分�工具。
-
-
-
1. 拥有图形化的监控界�。
2. �供本地�远程的JVM监控分�功能。
3. 是一款�费的JAVA工具。
@@ -49,13 +42,7 @@
VisualVM�版本下载页�: http://visualvm.java.net/releases.html
下载VisualVM时也应该注æ„�,ä¸�å�Œçš„JDK版本对应ä¸�å�Œç‰ˆæœ¬çš„VisualVMï¼Œå…·ä½“æ ¹æ�®å®‰è£…çš„JDK版本æ�¥ä¸‹è½½ç¬¬ä¸€çš„VisualVM。
-
-
-
-
-
## 三�获�那个版本?
-
下载版本�考:Java虚拟机性能管�神器 - VisualVM(4) - JDK版本与VisualVM版本对应关系
@@ -257,20 +244,4 @@
https://blog.csdn.net/android_hl/article/details/53228348
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
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\2729\357\274\232JVM\347\233\221\346\216\247\345\267\245\345\205\267\344\270\216\350\257\212\346\226\255\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\272\357\274\232JVM\347\233\221\346\216\247\345\267\245\345\205\267\344\270\216\350\257\212\346\226\255\345\256\236\350\267\265.md"
similarity index 89%
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\2729\357\274\232JVM\347\233\221\346\216\247\345\267\245\345\205\267\344\270\216\350\257\212\346\226\255\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\272\357\274\232JVM\347\233\221\346\216\247\345\267\245\345\205\267\344\270\216\350\257\212\346\226\255\345\256\236\350\267\265.md"
index ab03095..1d57b95 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2729\357\274\232JVM\347\233\221\346\216\247\345\267\245\345\205\267\344\270\216\350\257\212\346\226\255\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\272\357\274\232JVM\347\233\221\346\216\247\345\267\245\345\205\267\344\270\216\350\257\212\346\226\255\345\256\236\350\267\265.md"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [一�jvm常�监控工具&指令](#一�jvm常�监控工具指令)
* [1� jps:jvm进程状况工具](#1�-jpsjvm进程状况工具)
* [2�jstat: jvm统计信�监控工具](#2�jstat-jvm统计信�监控工具)
@@ -14,9 +13,7 @@
* [2.查看java进程的线程快照信�](#2查看java进程的线程快照信�)
* [3ã€�OOMå†…å˜æ³„露](#3ã€�oomå†…å˜æ³„露)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
本文转自:https://juejin.im/post/59e6c1f26fb9a0451c397a8c
@@ -57,10 +54,10 @@
```
-jps [options] [hostid]å¤�制代ç �
+jps [options] [hostid]
```
-
+
如果�指定hostid就默认为当�主机或�务器。
@@ -95,6 +92,7 @@ generalOption - �个的常用的命令行选项,如-help, -options, 或 -ver
outputOptions -一个或多个输出选项,由å�•个的statOption选项组æˆ�,å�¯ä»¥å’Œ-t, -h, and -Jç‰é€‰é¡¹é…�å�ˆä½¿ç”¨ã€‚å¤�制代ç �
```
+
�数选项:
@@ -117,7 +115,6 @@ outputOptions -一个或多个输出选项,由�个的statOption选项组�
查看gc 情况执行:jstat-gcutil 27777
-
### 3�jinfo: java�置信�
@@ -129,11 +126,10 @@ outputOptions -一个或多个输出选项,由�个的statOption选项组�
jinfo[option] pidå¤�制代ç �
```
-
+
比如:获�一些当�进程的jvm�行和�动信�。
-
### 4ã€�jmap: java å†…å˜æ˜ 射工具
@@ -150,7 +146,7 @@ jmap [ option ] executable core
jmap [ option ] [server-id@]remote-hostname-or-IPå¤�制代ç �
```
-
+
�数选项:
@@ -175,10 +171,12 @@ jmap [ option ] [server-id@]remote-hostname-or-IPå¤�制代ç �
-J ä¼ é€’å�‚æ•°ç»™jmapå�¯åŠ¨çš„jvm. å¤�制代ç �
```
+
### 5ã€�jhat:jvmå †å¿«ç…§åˆ†æž�工具
jhat 命令与jampæ�é…�使用,用æ�¥åˆ†æž�mapç”Ÿäº§çš„å †å¿«å˜å‚¨å¿«ç…§ã€‚jhat内置了一个微型http/Htmlæœ�务器,å�¯ä»¥åœ¨æµ�览器找那个查看。ä¸�过建议尽é‡�ä¸�用,既然有dumpt文件,å�¯ä»¥ä»Žç”Ÿäº§çŽ¯å¢ƒæ‹‰å�–下æ�¥ï¼Œç„¶å�Žé€šè¿‡æœ¬åœ°å�¯è§†åŒ–工具æ�¥åˆ†æž�ï¼Œè¿™æ ·æ—¢å‡�轻了线上æœ�务器压力,有å�¯ä»¥åˆ†æž�的足够详尽(比如 MAT/jprofile/visualVm)ç‰ã€‚
+
### 6ã€�jstack:javaå †æ ˆè·Ÿè¸ªå·¥å…·
jstack用于生æˆ�java虚拟机当å‰�时刻的线程快照。线程快照是当å‰�java虚拟机内æ¯�一æ�¡çº¿ç¨‹æ£åœ¨æ‰§è¡Œçš„æ–¹æ³•å †æ ˆçš„é›†å�ˆï¼Œç”Ÿæˆ�线程快照的主è¦�目的是定ä½�线程出现长时间å�œé¡¿çš„åŽŸå› ï¼Œå¦‚çº¿ç¨‹é—´æ»é”�ã€�æ»å¾ªçޝã€�请求外部资æº�导致的长时间ç‰å¾…ç‰ã€‚
@@ -391,20 +389,4 @@ jmap -dump:format=b,file=/tmp/dump.dat 11869
https://blog.csdn.net/android_hl/article/details/53228348
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
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\27211\357\274\232Java\345\206\205\345\255\230\345\274\202\345\270\270\345\216\237\347\220\206\344\270\216\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\272\357\274\232Java\345\206\205\345\255\230\345\274\202\345\270\270\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md"
similarity index 87%
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\27211\357\274\232Java\345\206\205\345\255\230\345\274\202\345\270\270\345\216\237\347\220\206\344\270\216\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\272\357\274\232Java\345\206\205\345\255\230\345\274\202\345\270\270\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md"
index 0805113..a999de2 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\27211\357\274\232Java\345\206\205\345\255\230\345\274\202\345\270\270\345\216\237\347\220\206\344\270\216\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\272\357\274\232Java\345\206\205\345\255\230\345\274\202\345\270\270\345\216\237\347\220\206\344\270\216\345\256\236\350\267\265.md"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [å®žæˆ˜å†…å˜æº¢å‡ºå¼‚常](#å®žæˆ˜å†…å˜æº¢å‡ºå¼‚常)
* [1 . 对象的创建过程](#1--对象的创建过程)
* [2 . 对象的内å˜å¸ƒå±€](#2--对象的内å˜å¸ƒå±€)
@@ -22,9 +21,7 @@
* [6��例模�](#6��例模�)
* [å¦‚ä½•æ£€æµ‹å†…å˜æ³„æ¼�](#å¦‚ä½•æ£€æµ‹å†…å˜æ³„æ¼�)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
本文转自互è�”网,侵åˆ
@@ -77,16 +74,16 @@ Student stu =new Student("å¼ ä¸‰","18");
* 实例数�
* 对�填充
-**对象头:** 对象头ä¸åŒ…å�«äº†å¯¹è±¡è¿�行时一些必è¦�的信æ�¯ï¼Œå¦‚GC分代信æ�¯ï¼Œé”�ä¿¡æ�¯ï¼Œå“ˆå¸Œç �,指å�‘Class类元信æ�¯çš„æŒ‡é’ˆç‰ï¼Œå…¶ä¸å¯¹Javaer比较有用的是**é”�ä¿¡æ�¯ä¸ŽæŒ‡å�‘Class对象的指针**,关于é”�ä¿¡æ�¯ï¼Œå�ŽæœŸæœ‰æœºä¼šè®²è§£å¹¶å�‘编程JUCæ—¶å†�扩展,关于指å�‘Class对象的指针其实很好ç�†è§£ã€‚比如上é�¢é‚£ä¸ªStudent的例å�,当我们拿到stu对象时,调用Class stuClass=stu.getClass();çš„æ—¶å€™ï¼Œå…¶å®žå°±æ˜¯æ ¹æ�®è¿™ä¸ªæŒ‡é’ˆåŽ»æ‹¿åˆ°äº†stu对象所属的Studentç±»åœ¨æ–¹æ³•åŒºå˜æ”¾çš„Class类对象。虽然说的有点拗å�£ï¼Œä½†è¿™å�¥è¯�我å��å¤�ç�¢ç£¨äº†å¥½å‡ é��,应该是说清楚了。
+**对象头:**对象头ä¸åŒ…å�«äº†å¯¹è±¡è¿�行时一些必è¦�的信æ�¯ï¼Œå¦‚GC分代信æ�¯ï¼Œé”�ä¿¡æ�¯ï¼Œå“ˆå¸Œç �,指å�‘Class类元信æ�¯çš„æŒ‡é’ˆç‰ï¼Œå…¶ä¸å¯¹Javaer比较有用的是**é”�ä¿¡æ�¯ä¸ŽæŒ‡å�‘Class对象的指针**,关于é”�ä¿¡æ�¯ï¼Œå�ŽæœŸæœ‰æœºä¼šè®²è§£å¹¶å�‘编程JUCæ—¶å†�扩展,关于指å�‘Class对象的指针其实很好ç�†è§£ã€‚比如上é�¢é‚£ä¸ªStudent的例å�,当我们拿到stu对象时,调用Class stuClass=stu.getClass();çš„æ—¶å€™ï¼Œå…¶å®žå°±æ˜¯æ ¹æ�®è¿™ä¸ªæŒ‡é’ˆåŽ»æ‹¿åˆ°äº†stu对象所属的Studentç±»åœ¨æ–¹æ³•åŒºå˜æ”¾çš„Class类对象。虽然说的有点拗å�£ï¼Œä½†è¿™å�¥è¯�我å��å¤�ç�¢ç£¨äº†å¥½å‡ é��,应该是说清楚了。
-**实例数æ�®:** 实例数æ�®éƒ¨åˆ†æ˜¯å¯¹è±¡çœŸæ£å˜å‚¨çš„æœ‰æ•ˆä¿¡æ�¯ï¼Œå°±æ˜¯ç¨‹åº�代ç �䏿‰€å®šä¹‰çš„å�„ç§�ç±»åž‹çš„å—æ®µå†…容。
+**实例数æ�®:**实例数æ�®éƒ¨åˆ†æ˜¯å¯¹è±¡çœŸæ£å˜å‚¨çš„æœ‰æ•ˆä¿¡æ�¯ï¼Œå°±æ˜¯ç¨‹åº�代ç �䏿‰€å®šä¹‰çš„å�„ç§�ç±»åž‹çš„å—æ®µå†…容。
-**对é½�å¡«å……:** 虚拟机规范è¦�求对象大å°�必须是8å—节的整数å€�。对é½�填充其实就是æ�¥è¡¥å…¨å¯¹è±¡å¤§å°�的。
+**对é½�å¡«å……:**虚拟机规范è¦�求对象大å°�必须是8å—节的整数å€�。对é½�填充其实就是æ�¥è¡¥å…¨å¯¹è±¡å¤§å°�的。
## 3 . 对象的访问定�
谈到对象的访问,还拿上é�¢å¦ç”Ÿçš„例å�æ�¥è¯´ï¼Œå½“我们拿到stu对象时,直接调用stu.getName();时,其实就完æˆ�了对对象的访问。但这里è¦�累赘说一下的是,stu虽然通常被认为是一个对象,其实准确æ�¥è¯´æ˜¯ä¸�准确的,stuå�ªæ˜¯ä¸€ä¸ªå�˜é‡�,å�˜é‡�里å˜å‚¨çš„æ˜¯æŒ‡å�‘对象的指针,(如果干过C或者C++çš„å°�伙伴应该比较清楚指针这个概念),当我们调用stu.getName()æ—¶ï¼Œè™šæ‹Ÿæœºä¼šæ ¹æ�®æŒ‡é’ˆæ‰¾åˆ°å †é‡Œé�¢çš„对象然å�Žæ‹¿åˆ°å®žä¾‹æ•°æ�®name.需è¦�注æ„�的是,当我们调用stu.getClass()æ—¶ï¼Œè™šæ‹Ÿæœºä¼šé¦–å…ˆæ ¹æ�®stu指针定ä½�åˆ°å †é‡Œé�¢çš„对象,然å�Žæ ¹æ�®å¯¹è±¡å¤´é‡Œé�¢å˜å‚¨çš„æŒ‡å�‘Class类元信æ�¯çš„æŒ‡é’ˆå†�次到方法区拿到Class对象,进行了两次指针寻找。具体讲解图如下:
-
+
## 4 .实战内å˜å¼‚常
@@ -140,8 +137,10 @@ Dumping heap to /Users/zdy/Desktop/dump/java_pid1099.hprof …
å�¯ä»¥çœ‹åˆ°ç”Ÿæˆ�了dump文件到指定目录。并且爆出了OutOfMemoryErrorï¼Œè¿˜å‘Šè¯‰äº†ä½ æ˜¯å“ªä¸€ç‰‡åŒºåŸŸå‡ºçš„é—®é¢˜:heap space
打开VisualVM工具导入对应的heapDump文件(如何使用请读者自行查阅相关资料),相应的说明�图:
-
-
+
+
+
+
分æž�dump文件å�Žï¼Œæˆ‘们å�¯ä»¥çŸ¥é�“,OOMObject这个类创建了810326个实例。所以它能ä¸�溢出å�—?接下æ�¥å°±åœ¨ä»£ç �里找这个类在哪new的。排查问题。(æˆ‘ä»¬çš„æ ·ä¾‹ä»£ç �å°±ä¸�用排查了,While循环太凶猛了)分æž�dump文件å�Žï¼Œæˆ‘们å�¯ä»¥çŸ¥é�“,OOMObject这个类创建了810326个实例。所以它能ä¸�溢出å�—?接下æ�¥å°±åœ¨ä»£ç �里找这个类在哪new的。排查问题。(æˆ‘ä»¬çš„æ ·ä¾‹ä»£ç �å°±ä¸�用排查了,While循环太凶猛了)
### Javaæ ˆå†…å˜å¼‚常
@@ -182,7 +181,7 @@ public class JavaVMStackSOF {
å�¯ä»¥çœ‹åˆ°ï¼Œé€’归调用了751æ¬¡ï¼Œæ ˆå®¹é‡�ä¸�够用了。
é»˜è®¤çš„æ ˆå®¹é‡�在æ£å¸¸çš„æ–¹æ³•è°ƒç”¨æ—¶ï¼Œæ ˆæ·±åº¦å�¯ä»¥è¾¾åˆ°1000-2000深度,所以,一般的递归是å�¯ä»¥æ‰¿å�—çš„ä½�çš„ã€‚å¦‚æžœä½ çš„ä»£ç �出现了StackOverflowError,首先检查代ç �,而ä¸�是改å�‚数。
-这里顺带æ��一下,很多人在å�šå¤šçº¿ç¨‹å¼€å�‘时,当创建很多线程时,**容易出现OOM(OutOfMemoryError),** 这时å�¯ä»¥é€šè¿‡å…·ä½“情况,å‡�å°‘æœ€å¤§å †å®¹é‡�ï¼Œæˆ–è€…æ ˆå®¹é‡�æ�¥è§£å†³é—®é¢˜ï¼Œè¿™æ˜¯ä¸ºä»€ä¹ˆå‘¢ã€‚请看下é�¢çš„å…¬å¼�:
+这里顺带æ��一下,很多人在å�šå¤šçº¿ç¨‹å¼€å�‘时,当创建很多线程时,**容易出现OOM(OutOfMemoryError),**这时å�¯ä»¥é€šè¿‡å…·ä½“情况,å‡�å°‘æœ€å¤§å †å®¹é‡�ï¼Œæˆ–è€…æ ˆå®¹é‡�æ�¥è§£å†³é—®é¢˜ï¼Œè¿™æ˜¯ä¸ºä»€ä¹ˆå‘¢ã€‚请看下é�¢çš„å…¬å¼�:
线程数*(æœ€å¤§æ ˆå®¹é‡�)+æœ€å¤§å †å€¼+其他内å˜(忽略ä¸�计或者一般ä¸�改动)=机器最大内å˜
@@ -190,10 +189,10 @@ public class JavaVMStackSOF {
### 方法区内å˜å¼‚常
-写到这里时,作者本æ�¥æƒ³å†™ä¸€ä¸ªæ— é™�创建动æ€�代ç�†å¯¹è±¡çš„例å�æ�¥æ¼”示方法区溢出,é�¿å¼€è°ˆè®ºJDK7与JDK8的内å˜åŒºåŸŸå�˜æ›´çš„过渡,但细想一想,还是把这一å�—ä»Žå§‹è‡´ç»ˆçš„è¯´æ¸…æ¥šã€‚åœ¨ä¸Šä¸€ç¯‡æ–‡ç« ä¸JVM系列之Java内å˜ç»“构详解讲到方法区时æ��到,JDK7环境下方法区包括了(è¿�行时常é‡�æ± ),其实这么说是ä¸�å‡†ç¡®çš„ã€‚å› ä¸ºä»ŽJDK7开始,HotSpot团队就想到开始去"永久代",大家首先明确一个概念,**方法区和"永久代"(PermGen space)是两个概念,方法区是JVM虚拟机规范,任何虚拟机实现(J9ç‰)都ä¸�能少这个区间,而"永久代"å�ªæ˜¯HotSpot对方法区的一个实现。** 为了把知识点列清楚,我还是æ‰�用列表的形å¼�:
+写到这里时,作者本æ�¥æƒ³å†™ä¸€ä¸ªæ— é™�创建动æ€�代ç�†å¯¹è±¡çš„例å�æ�¥æ¼”示方法区溢出,é�¿å¼€è°ˆè®ºJDK7与JDK8的内å˜åŒºåŸŸå�˜æ›´çš„过渡,但细想一想,还是把这一å�—ä»Žå§‹è‡´ç»ˆçš„è¯´æ¸…æ¥šã€‚åœ¨ä¸Šä¸€ç¯‡æ–‡ç« ä¸JVM系列之Java内å˜ç»“构详解讲到方法区时æ��到,JDK7环境下方法区包括了(è¿�行时常é‡�æ± ),其实这么说是ä¸�å‡†ç¡®çš„ã€‚å› ä¸ºä»ŽJDK7开始,HotSpot团队就想到开始去"永久代",大家首先明确一个概念,**方法区和"永久代"(PermGen space)是两个概念,方法区是JVM虚拟机规范,任何虚拟机实现(J9ç‰)都ä¸�能少这个区间,而"永久代"å�ªæ˜¯HotSpot对方法区的一个实现。**为了把知识点列清楚,我还是æ‰�用列表的形å¼�:
-* [ ]  JDK7之å‰�(包括JDK7)拥有"永久代"(PermGen space),用æ�¥å®žçŽ°æ–¹æ³•åŒºã€‚ä½†åœ¨JDK7ä¸å·²ç»�é€�æ¸�åœ¨å®žçŽ°ä¸æŠŠæ°¸ä¹…ä»£ä¸æŠŠå¾ˆå¤šä¸œè¥¿ç§»äº†å‡ºæ�¥ï¼Œæ¯”如:符å�·å¼•用(Symbols)转移到了native heap,è¿�行时常é‡�æ± (interned strings)转移到了java heap;类的é�™æ€�å�˜é‡�(class statics)转移到了java heap.
-* [ ] Â æ‰€ä»¥è¿™å°±æ˜¯ä¸ºä»€ä¹ˆæˆ‘è¯´ä¸Šä¸€ç¯‡æ–‡ç« ä¸è¯´æ–¹æ³•区ä¸åŒ…å�«è¿�行时常é‡�æ± æ˜¯ä¸�æ£ç¡®çš„ï¼Œå› ä¸ºå·²ç»�移动到了java heap;
+* [ ] JDK7之å‰�(包括JDK7)拥有"永久代"(PermGen space),用æ�¥å®žçŽ°æ–¹æ³•åŒºã€‚ä½†åœ¨JDK7ä¸å·²ç»�é€�æ¸�åœ¨å®žçŽ°ä¸æŠŠæ°¸ä¹…ä»£ä¸æŠŠå¾ˆå¤šä¸œè¥¿ç§»äº†å‡ºæ�¥ï¼Œæ¯”如:符å�·å¼•用(Symbols)转移到了native heap,è¿�行时常é‡�æ± (interned strings)转移到了java heap;类的é�™æ€�å�˜é‡�(class statics)转移到了java heap.
+* [ ] æ‰€ä»¥è¿™å°±æ˜¯ä¸ºä»€ä¹ˆæˆ‘è¯´ä¸Šä¸€ç¯‡æ–‡ç« ä¸è¯´æ–¹æ³•区ä¸åŒ…å�«è¿�行时常é‡�æ± æ˜¯ä¸�æ£ç¡®çš„ï¼Œå› ä¸ºå·²ç»�移动到了java heap;
**在JDK7之�(包括7)�以通过-XX:PermSize -XX:MaxPermSize�控制永久代的大�.
JDK8æ£å¼�去除"永久代",æ�¢æˆ�Metaspace(元空间)作为JVMè™šæ‹Ÿæœºè§„èŒƒä¸æ–¹æ³•区的实现。**
元空间与永久代之间最大的区别在于:元空间并ä¸�在虚拟机ä¸ï¼Œè€Œæ˜¯ä½¿ç”¨æœ¬åœ°å†…å˜ã€‚å› æ¤ï¼Œé»˜è®¤æƒ…况下,元空间的大å°�ä»…å�—本地内å˜é™�制,但ä»�å�¯ä»¥é€šè¿‡å�‚数控制:-XX:MetaspaceSize与-XX:MaxMetaspaceSizeæ�¥æŽ§åˆ¶å¤§å°�。
@@ -316,7 +315,8 @@ Java的一个��优点就是通过垃圾收集器(Garbage Collection,GC)自
为了更好ç�†è§£GC的工作原ç�†ï¼Œæˆ‘们å�¯ä»¥å°†å¯¹è±¡è€ƒè™‘为有å�‘图的顶点,将引用关系考虑为图的有å�‘边,有å�‘边从引用者指å�‘被引对象。å�¦å¤–,æ¯�个线程对象å�¯ä»¥ä½œä¸ºä¸€ä¸ªå›¾çš„起始顶点,例如大多程åº�从main进程开始执行,那么该图就是以mainè¿›ç¨‹é¡¶ç‚¹å¼€å§‹çš„ä¸€æ£µæ ¹æ ‘ã€‚åœ¨è¿™ä¸ªæœ‰å�‘图ä¸ï¼Œæ ¹é¡¶ç‚¹å�¯è¾¾çš„对象都是有效对象,GCå°†ä¸�回收这些对象。如果æŸ�个对象 (连通å�图)ä¸Žè¿™ä¸ªæ ¹é¡¶ç‚¹ä¸�å�¯è¾¾(注æ„�,该图为有å�‘图),那么我们认为这个(这些)对象ä¸�å†�被引用,å�¯ä»¥è¢«GC回收。
以下,我们举一个例å�说明如何用有å�‘图表示内å˜ç®¡ç�†ã€‚对于程åº�çš„æ¯�一个时刻,我们都有一个有å�‘图表示JVM的内å˜åˆ†é…�情况。以下å�³å›¾ï¼Œå°±æ˜¯å·¦è¾¹ç¨‹åº�è¿�行到第6行的示æ„�图。
-
+
+
Java使用有å�‘图的方å¼�进行内å˜ç®¡ç�†ï¼Œå�¯ä»¥æ¶ˆé™¤å¼•用循环的问题,例如有三个对象,相互引用,å�ªè¦�å®ƒä»¬å’Œæ ¹è¿›ç¨‹ä¸�å�¯è¾¾çš„,那么GC也是å�¯ä»¥å›žæ”¶å®ƒä»¬çš„。这ç§�æ–¹å¼�的优点是管ç�†å†…å˜çš„精度很高,但是效率较低。å�¦å¤–一ç§�常用的内å˜ç®¡ç�†æŠ€æœ¯æ˜¯ä½¿ç”¨è®¡æ•°å™¨ï¼Œä¾‹å¦‚COM模型采用计数器方å¼�管ç�†æž„件,它与有å�‘图相比,精度行低(很难处ç�†å¾ªçŽ¯å¼•ç”¨çš„é—®é¢˜),但执行效率很高。
## 什么是Javaä¸çš„å†…å˜æ³„露?
@@ -326,7 +326,8 @@ Java使用有å�‘图的方å¼�进行内å˜ç®¡ç�†ï¼Œå�¯ä»¥æ¶ˆé™¤å¼•用循环的问
在C++ä¸ï¼Œå†…å˜æ³„æ¼�的范围更大一些。有些对象被分é…�了内å˜ç©ºé—´ï¼Œç„¶å�Žå�´ä¸�å�¯è¾¾ï¼Œç”±äºŽC++䏿²¡æœ‰GC,这些内å˜å°†æ°¸è¿œæ”¶ä¸�回æ�¥ã€‚在Javaä¸ï¼Œè¿™äº›ä¸�å�¯è¾¾çš„对象都由GCè´Ÿè´£å›žæ”¶ï¼Œå› æ¤ç¨‹åº�员ä¸�需è¦�è€ƒè™‘è¿™éƒ¨åˆ†çš„å†…å˜æ³„露。
通过分�,我们得知,对于C++,程�员需�自己管�边和顶点,而对于Java程�员�需�管�边就�以了(�需�管�顶点的释放)。通过这�方�,Java�高了编程的效率。
-
+
+
å› æ¤ï¼Œé€šè¿‡ä»¥ä¸Šåˆ†æž�,我们知é�“在Javaä¸ä¹Ÿæœ‰å†…å˜æ³„æ¼�,但范围比C++è¦�å°�ä¸€äº›ã€‚å› ä¸ºJava从è¯è¨€ä¸Šä¿�è¯�,任何对象都是å�¯è¾¾çš„,所有的ä¸�å�¯è¾¾å¯¹è±¡éƒ½ç”±GC管ç�†ã€‚
对于程åº�员æ�¥è¯´ï¼ŒGC基本是é€�明的,ä¸�å�¯è§�的。虽然,我们å�ªæœ‰å‡ 个函数å�¯ä»¥è®¿é—®GC,例如è¿�行GC的函数System.gc()ï¼Œä½†æ˜¯æ ¹æ�®Javaè¯è¨€è§„范定义, 该函数ä¸�ä¿�è¯�JVMçš„åžƒåœ¾æ”¶é›†å™¨ä¸€å®šä¼šæ‰§è¡Œã€‚å› ä¸ºï¼Œä¸�å�Œçš„JVM实现者å�¯èƒ½ä½¿ç”¨ä¸�å�Œçš„算法管ç�†GC。通常,GC的线程的优先级别较低。JVM调用GCçš„ç–略也有很多ç§�,有的是内å˜ä½¿ç”¨åˆ°è¾¾ä¸€å®šç¨‹åº¦æ—¶ï¼ŒGCæ‰�开始工作,也有定时执行的,有的是平缓执行GCï¼Œæœ‰çš„æ˜¯ä¸æ–å¼�执行GC。但通常æ�¥è¯´ï¼Œæˆ‘们ä¸�需è¦�关心这些。除é�žåœ¨ä¸€äº›ç‰¹å®šçš„场å�ˆï¼ŒGC的执行影å“�应用程åº�的性能,例如对于基于Web的实时系统,如网络游æˆ�ç‰ï¼Œç”¨æˆ·ä¸�希望GCçª�ç„¶ä¸æ–应用程åº�执行而进行垃圾回收,那么我们需è¦�调整GCçš„å�‚数,让GC能够通过平缓的方å¼�释放内å˜ï¼Œä¾‹å¦‚将垃圾回收分解为一系列的å°�æ¥éª¤æ‰§è¡Œï¼ŒSunæ��供的HotSpot JVM就支æŒ�这一特性。
@@ -443,12 +444,6 @@ Optimizeit Profiler版本4.11支�Application,Applet,Servlet和Romote Appli
当设置好所有的å�‚数了,我们就å�¯ä»¥åœ¨OptimizeIt环境下è¿�行被测程åº�,在程åº�è¿�行过程ä¸ï¼ŒOptimizeitå�¯ä»¥ç›‘视内å˜çš„使用曲线(如下图),包括JVMç”³è¯·çš„å †(heap)的大å°�,和实际使用的内å˜å¤§å°�。å�¦å¤–,在è¿�行过程ä¸ï¼Œæˆ‘们å�¯ä»¥éš�æ—¶æš‚å�œç¨‹åº�çš„è¿�行,甚至强行调用GC,让GC进行内å˜å›žæ”¶ã€‚通过内å˜ä½¿ç”¨æ›²çº¿ï¼Œæˆ‘们å�¯ä»¥æ•´ä½“了解程åº�使用内å˜çš„æƒ…况。这ç§�监测对于长期è¿�行的应用程åº�é�žå¸¸æœ‰å¿…è¦�,也很容易å�‘çŽ°å†…å˜æ³„露。
-
-
-
-
-
-
## å�‚考文ç«
@@ -461,20 +456,4 @@ Optimizeit Profiler版本4.11支�Application,Applet,Servlet和Romote Appli
https://blog.csdn.net/android_hl/article/details/53228348
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
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\272\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 97%
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\272\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"
index 2371f8f..cf18680 100644
--- "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\272\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"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [�言](#�言)
* [Class文件](#class文件)
* [什么是Class文件?](#什么是class文件?)
@@ -50,8 +49,7 @@ java之所以能够实现跨平å�°ï¼Œä¾¿åœ¨äºŽå…¶ç¼–译阶段ä¸�是将代ç �ç›´
éš�便找到一个class文件,用Sublime Textæ‰“å¼€æ˜¯è¿™æ ·çš„ï¼š
-
-
+
是ä¸�是一脸懵逼,ä¸�过java虚拟机规范ä¸ç»™å‡ºäº†classæ–‡ä»¶çš„åŸºæœ¬æ ¼å¼�,å�ªè¦�æŒ‰ç…§è¿™ä¸ªæ ¼å¼�去解æž�å°±å�¯ä»¥äº†ï¼š
@@ -337,11 +335,7 @@ for (int j = 0; j < methodInfo.attributesCount; j++) {
整个项目终于写完了,接下�就�看看效果如何,�便找一个class文件解��行:
-
-
-
-
-
+
哈哈,是�是很赞�
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\272\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 85%
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\272\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"
index 2db99f7..58b8166 100644
--- "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\272\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"
@@ -1,6 +1,5 @@
-# Table of Contents
-
- * [[java编译期优化](https://www.cnblogs.com/LeonNew/p/6187411.html)](#[java编译期优化]httpswwwcnblogscomleonnewp6187411html)
+# 目录
+ * [java编译期优化](#[java编译期优化])
* [早期(编译期)优化](#早期(编译期)优化)
* [泛型与类型擦除](#泛型与类型擦除)
* [自动装箱�拆箱与�历循环](#自动装箱�拆箱与�历循环)
@@ -12,9 +11,7 @@
* [编译优化技术](#编译优化技术)
* [java与C/C++编译器对比](#java与cc编译器对比)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
本文转自互è�”网,侵åˆ
@@ -37,24 +34,14 @@
-
-
-
-
-
-
-## [java编译期优化](https://www.cnblogs.com/LeonNew/p/6187411.html)
-
-
-
-
+## java编译期优化
javaè¯è¨€çš„编译期其实是一段ä¸�确定的æ“�ä½œè¿‡ç¨‹ï¼Œå› ä¸ºå®ƒå�¯ä»¥åˆ†ä¸ºä¸‰ç±»ç¼–译过程:
1.�端编译:把_.java文件转�为_.class文件
2.å�Žç«¯ç¼–译:把å—节ç �转å�˜ä¸ºæœºå™¨ç �
3.é�™æ€�æ��å‰�编译:直接把*.java文件编译æˆ�本地机器代ç �
从JDK1.3开始,虚拟机设计团队就把对性能的优化集ä¸åˆ°äº†å�Žç«¯çš„å�³æ—¶ç¼–译ä¸ï¼Œè¿™æ ·å�¯ä»¥è®©é‚£äº›ä¸�是由Javac产生的Class文件(如JRubyã€�Groovyç‰è¯è¨€çš„Class文件)也能享å�—到编译期优化所带æ�¥çš„好处
-**Javaä¸å�³æ—¶ç¼–译在è¿�行期的优化过程对于程åº�è¿�行æ�¥è¯´æ›´é‡�è¦�,而å‰�端编译期在编译期的优化过程对于程åº�ç¼–ç �æ�¥è¯´å…³ç³»æ›´åŠ å¯†åˆ‡Â Â Â Â **
+**Javaä¸å�³æ—¶ç¼–译在è¿�行期的优化过程对于程åº�è¿�行æ�¥è¯´æ›´é‡�è¦�,而å‰�端编译期在编译期的优化过程对于程åº�ç¼–ç �æ�¥è¯´å…³ç³»æ›´åŠ å¯†åˆ‡**
### 早期(编译期)优化
@@ -115,11 +102,10 @@ public static void main(String[] args) {
##### 解释器与编译器
-Java程åº�最åˆ�是通过解释器进行解释执行的,当程åº�需è¦�迅速å�¯åŠ¨å’Œæ‰§è¡Œæ—¶ï¼Œè§£é‡Šå™¨å�¯ä»¥é¦–å…ˆå�‘挥作用,çœ�去编译时间,立å�³æ‰§è¡Œï¼›å½“程åº�è¿�行å�Žï¼Œéš�ç�€æ—¶é—´çš„æŽ¨ç§»ï¼Œç¼–译期é€�æ¸�å�‘挥作用,把越æ�¥è¶Šå¤šçš„代ç �编译æˆ�本地代ç �,获得更高的执行效率。**解释执行节约内å˜ï¼Œç¼–译执行æ��å�‡æ•ˆçŽ‡ã€‚** å�Œæ—¶ï¼Œè§£é‡Šå™¨å�¯ä»¥ä½œä¸ºç¼–译器激进优化时的一个“逃生门â€�ï¼Œè®©ç¼–è¯‘å™¨æ ¹æ�®æ¦‚率选择一些大多数时候都能æ��å�‡è¿�行速度的优化手段,当激进优化的å�‡è®¾ä¸�æˆ�立,则通过逆优化退回到解释状æ€�ç»§ç»æ‰§è¡Œã€‚
+Java程åº�最åˆ�是通过解释器进行解释执行的,当程åº�需è¦�迅速å�¯åŠ¨å’Œæ‰§è¡Œæ—¶ï¼Œè§£é‡Šå™¨å�¯ä»¥é¦–å…ˆå�‘挥作用,çœ�去编译时间,立å�³æ‰§è¡Œï¼›å½“程åº�è¿�行å�Žï¼Œéš�ç�€æ—¶é—´çš„æŽ¨ç§»ï¼Œç¼–译期é€�æ¸�å�‘挥作用,把越æ�¥è¶Šå¤šçš„代ç �编译æˆ�本地代ç �,获得更高的执行效率。**解释执行节约内å˜ï¼Œç¼–译执行æ��å�‡æ•ˆçŽ‡ã€‚**å�Œæ—¶ï¼Œè§£é‡Šå™¨å�¯ä»¥ä½œä¸ºç¼–译器激进优化时的一个“逃生门â€�ï¼Œè®©ç¼–è¯‘å™¨æ ¹æ�®æ¦‚率选择一些大多数时候都能æ��å�‡è¿�行速度的优化手段,当激进优化的å�‡è®¾ä¸�æˆ�立,则通过逆优化退回到解释状æ€�ç»§ç»æ‰§è¡Œã€‚
HotSpot虚拟机ä¸å†…置了两个å�³æ—¶ç¼–译器,分别称为Client Compiler(C1编译器)å’ŒServer Compiler(C2编译器),默认采用解释器与其ä¸ä¸€ä¸ªç¼–译器直接é…�å�ˆçš„æ–¹å¼�工作,使用哪个编译器å�–决于虚拟机è¿�行的模å¼�,也å�¯ä»¥è‡ªå·±åŽ»æŒ‡å®šã€‚è‹¥å¼ºåˆ¶è™šæ‹Ÿæœºè¿�行与“解释模å¼�â€�,编译器完全ä¸�介入工作,若强制虚拟机è¿�行于“编译模å¼�â€�,则优先采用编译方å¼�执行程åº�,解释器ä»�ç„¶è¦�åœ¨ç¼–è¯‘æ— æ³•è¿›è¡Œçš„æƒ…å†µä¸‹ä»‹å…¥æ‰§è¡Œè¿‡ç¨‹ã€‚
-
-
+
##### 分层编译ç–ç•¥
```
@@ -143,13 +129,11 @@ HotSpot虚拟机ä¸å†…置了两个å�³æ—¶ç¼–译器,分别称为Client Compiler(
```
HotSpot虚拟机使用的是第二�,它为�个方法准备了两类计数器:方法调用计数器和回边计数器,下图表示方法调用计数器触��时编译:
-
-
+
如果ä¸�å�šä»»ä½•设置,执行引擎会继ç»è¿›å…¥è§£é‡Šå™¨æŒ‰ç…§è§£é‡Šæ–¹å¼�执行å—节ç �,直到æ��交的请求被编译器编译完æˆ�,下次调用æ‰�会使用已编译的版本。å�¦å¤–,方法调用计数器的值也ä¸�是一个ç»�对次数,而是一段时间之内被调用的次数,超过这个时间,次数就å‡�å�Šï¼Œè¿™ç§°ä¸ºè®¡æ•°å™¨çƒåº¦çš„è¡°å‡�。
下图表示回边计数器触��时编译:
-
-
+
回边计数器没有计数器çƒåº¦è¡°å‡�çš„è¿‡ç¨‹ï¼Œå› æ¤ç»Ÿè®¡çš„就是ç»�对次数,并且当计数器溢出时,它还会把方法计数器的值也调整到溢出状æ€�ï¼Œè¿™æ ·ä¸‹æ¬¡è¿›å…¥è¯¥æ–¹æ³•çš„æ—¶å€™å°±ä¼šæ‰§è¡Œæ ‡å‡†ç¼–è¯‘è¿‡ç¨‹ã€‚
##### 编译优化技术
@@ -235,20 +219,4 @@ Java虚拟机的�时编译器与C/C++的��编译器相比,�能会由
https://blog.csdn.net/android_hl/article/details/53228348
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
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\27213\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\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\272\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\345\256\236\350\267\265.md"
similarity index 81%
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\27213\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\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\272\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\345\256\236\350\267\265.md"
index 3167cfa..cca62d4 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\27213\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\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\272\357\274\232\345\206\215\350\260\210\345\233\233\347\247\215\345\274\225\347\224\250\345\217\212GC\345\256\236\350\267\265.md"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [一�背景](#一�背景)
* [二�简介](#二�简介)
* [1.强引用 StrongReference](#1强引用-strongreference)
@@ -8,9 +7,7 @@
* [4.虚引用 PhantomReference](#4虚引用-phantomreference)
* [三��结](#三��结)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
本文转自互è�”网,侵åˆ
@@ -35,15 +32,15 @@
## 一�背景
-Java的内å˜å›žæ”¶ä¸�需è¦�程åº�员负责,JVM会在必è¦�æ—¶å�¯åЍJava GC完æˆ�垃圾回收。Java以便我们控制对象的生å˜å‘¨æœŸï¼Œæ��供给了我们四ç§�引用方å¼�,引用强度从强到弱分别为:强引用ã€�软引用ã€�弱引用ã€�虚引用。Â
+Java的内å˜å›žæ”¶ä¸�需è¦�程åº�员负责,JVM会在必è¦�æ—¶å�¯åЍJava GC完æˆ�垃圾回收。Java以便我们控制对象的生å˜å‘¨æœŸï¼Œæ��供给了我们四ç§�引用方å¼�,引用强度从强到弱分别为:强引用ã€�软引用ã€�弱引用ã€�虚引用。
## 二�简介
### 1.强引用 StrongReference
StrongReference是Java的默认引用形å¼�,使用时ä¸�需è¦�显示定义。任何通过强引用所使用的对象ä¸�管系统资æº�æœ‰å¤šç´§å¼ ï¼ŒJava GC都ä¸�会主动回收具有强引用的对象。
-
-public class StrongReferenceTest {
+````
+public class StrongReferenceTest {
public static int M = 1024*1024;
@@ -76,17 +73,16 @@ StrongReference是Java的默认引用形�,使用时�需�显示定义。
System.out.println("strongReference : "+strongReference);
}
}
-
+````
�行结果:
-
-
+
### 2.弱引用 WeakReference
如果一个对象å�ªå…·æœ‰å¼±å¼•ç”¨ï¼Œæ— è®ºå†…å˜å……足与å�¦ï¼ŒJava GCå�Žå¯¹è±¡å¦‚æžœå�ªæœ‰å¼±å¼•用将会被自动回收。
-
-public class WeakReferenceTest {
+````
+public class WeakReferenceTest {
public static int M = 1024*1024;
@@ -110,17 +106,16 @@ StrongReference是Java的默认引用形�,使用时�需�显示定义。
System.out.println("weakRerference.get() : "+weakRerference.get());
}
}
-
+````
�行结果:
-
-
+
### 3.软引用 SoftReference
软引用和弱引用的特性基本一致, 主è¦�的区别在于软引用在内å˜ä¸�足时æ‰�会被回收。如果一个对象å�ªå…·æœ‰è½¯å¼•用,Java GC在内å˜å……足的时候ä¸�会回收它,内å˜ä¸�足时æ‰�会被回收。
-
-public class SoftReferenceTest {
+````
+public class SoftReferenceTest {
public static int M = 1024*1024;
@@ -151,17 +146,16 @@ StrongReference是Java的默认引用形�,使用时�需�显示定义。
System.out.println("softRerference2.get() : "+softRerference2.get());
}
}
-
+````
�行结果:
-
-
+
### 4.虚引用 PhantomReference
从PhantomReference类的æº�代ç �å�¯ä»¥çŸ¥é�“,它的get()æ–¹æ³•æ— è®ºä½•æ—¶è¿”å›žçš„éƒ½å�ªä¼šæ˜¯null。所以å�•独使用虚引用时,没有什么æ„�义,需è¦�和引用队列ReferenceQueueç±»è�”å�ˆä½¿ç”¨ã€‚当执行Java GC时如果一个对象å�ªæœ‰è™šå¼•ç”¨ï¼Œå°±ä¼šæŠŠè¿™ä¸ªå¯¹è±¡åŠ å…¥åˆ°ä¸Žä¹‹å…³è�”çš„ReferenceQueueä¸ã€‚
-
-public class PhantomReferenceTest {
+````
+public class PhantomReferenceTest {
public static int M = 1024*1024;
@@ -205,12 +199,11 @@ StrongReference是Java的默认引用形�,使用时�需�显示定义。
System.out.println("referenceQueue.poll() : "+referenceQueue.poll());
}
}
-
+````
�行结果:
-
-
+
## 三��结
强引用是 Java 的默认引用形å¼�,使用时ä¸�需è¦�显示定义,是我们平时最常使用到的引用方å¼�。ä¸�管系统资æº�æœ‰å¤šç´§å¼ ï¼ŒJava GC都ä¸�会主动回收具有强引用的对象。 弱引用和软引用一般在引用对象为é�žå¿…需对象的时候使用。它们的区别是被弱引用关è�”的对象在垃圾回收时总是会被回收,被软引用关è�”的对象å�ªæœ‰åœ¨å†…å˜ä¸�足时æ‰�会被回收。 虚引用的get()方法获å�–的永远是nullï¼Œæ— æ³•èŽ·å�–对象实例。Java GC会把虚引用的对象放到引用队列里é�¢ã€‚å�¯ç”¨æ�¥åœ¨å¯¹è±¡è¢«å›žæ”¶æ—¶å�šé¢�外的一些资æº�清ç�†æˆ–事物回滚ç‰å¤„ç�†ã€‚ ç”±äºŽæ— æ³•ä»Žè™šå¼•èŽ·å�–到引用对象的实例。它的使用情况比较特别,所以这里ä¸�æŠŠè™šå¼•ç”¨æ”¾å…¥è¡¨æ ¼è¿›è¡Œå¯¹æ¯”ã€‚è¿™é‡Œå¯¹å¼ºå¼•ç”¨ã€�弱引用ã€�软引用进行对比:
@@ -229,20 +222,4 @@ StrongReference是Java的默认引用形�,使用时�需�显示定义。
https://blog.csdn.net/android_hl/article/details/53228348
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
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\2723\357\274\232\345\236\203\345\234\276\345\233\236\346\224\266\345\231\250\350\257\246\350\247\243.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\272\357\274\232\345\236\203\345\234\276\345\233\236\346\224\266\345\231\250\350\257\246\350\247\243.md"
similarity index 77%
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\2723\357\274\232\345\236\203\345\234\276\345\233\236\346\224\266\345\231\250\350\257\246\350\247\243.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\272\357\274\232\345\236\203\345\234\276\345\233\236\346\224\266\345\231\250\350\257\246\350\247\243.md"
index 741c437..7e89241 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2723\357\274\232\345\236\203\345\234\276\345\233\236\346\224\266\345\231\250\350\257\246\350\247\243.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\272\357\274\232\345\236\203\345\234\276\345\233\236\346\224\266\345\231\250\350\257\246\350\247\243.md"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [1 概述](#1-概述)
* [2 对象已ç»�æ»äº¡ï¼Ÿ](#2-对象已ç»�æ»äº¡ï¼Ÿ)
* [2.1引用计数法](#21引用计数法)
@@ -85,8 +84,7 @@ Minor Gc和Full GC 有什么��呢?
### 2.2�达性分�算法
-这个算法的基本æ€�想就是通过一系列的称为 **“GC Rootsâ€�** 的对象作为起点,从这些节点开始å�‘下æ�œç´¢ï¼ŒèŠ‚ç‚¹æ‰€èµ°è¿‡çš„è·¯å¾„ç§°ä¸ºå¼•ç”¨é“¾ï¼Œå½“ä¸€ä¸ªå¯¹è±¡åˆ°GC Roots没有任何引用链相连的è¯�,则è¯�明æ¤å¯¹è±¡æ˜¯ä¸�å�¯ç”¨çš„。
-
+这个算法的基本æ€�想就是通过一系列的称为**“GC Rootsâ€�**的对象作为起点,从这些节点开始å�‘下æ�œç´¢ï¼ŒèŠ‚ç‚¹æ‰€èµ°è¿‡çš„è·¯å¾„ç§°ä¸ºå¼•ç”¨é“¾ï¼Œå½“ä¸€ä¸ªå¯¹è±¡åˆ°GC Roots没有任何引用链相连的è¯�,则è¯�明æ¤å¯¹è±¡æ˜¯ä¸�å�¯ç”¨çš„。
### 2.3 �谈引用
@@ -114,7 +112,7 @@ JDK1.2以�,Java对引用的感念进行了扩充,将引用分为强引用
**虚引用主�用�跟踪对象被垃圾回收的活动**。
-**虚引用与软引用和弱引用的一个区别在于:** 虚引用必须和引用队列(ReferenceQueue)è�”å�ˆä½¿ç”¨ã€‚当垃 圾回收器准备回收一个对象时,如果å�‘现它还有虚引用,就会在回收对象的内å˜ä¹‹å‰�ï¼ŒæŠŠè¿™ä¸ªè™šå¼•ç”¨åŠ å…¥åˆ°ä¸Žä¹‹å…³è�”的引用队列ä¸ã€‚程åº�å�¯ä»¥é€šè¿‡åˆ¤æ–å¼•ç”¨é˜Ÿåˆ—ä¸æ˜¯ å�¦å·²ç»�åŠ å…¥äº†è™šå¼•ç”¨ï¼Œæ�¥äº†è§£è¢«å¼•用的对象是å�¦å°†è¦�被垃圾回收。程åº�如果å�‘现æŸ�个虚引用已ç»�è¢«åŠ å…¥åˆ°å¼•ç”¨é˜Ÿåˆ—ï¼Œé‚£ä¹ˆå°±å�¯ä»¥åœ¨æ‰€å¼•用的对象的内å˜è¢«å›žæ”¶ä¹‹å‰�采å�–å¿…è¦�的行动。
+**虚引用与软引用和弱引用的一个区别在于:**虚引用必须和引用队列(ReferenceQueue)è�”å�ˆä½¿ç”¨ã€‚当垃 圾回收器准备回收一个对象时,如果å�‘现它还有虚引用,就会在回收对象的内å˜ä¹‹å‰�ï¼ŒæŠŠè¿™ä¸ªè™šå¼•ç”¨åŠ å…¥åˆ°ä¸Žä¹‹å…³è�”的引用队列ä¸ã€‚程åº�å�¯ä»¥é€šè¿‡åˆ¤æ–å¼•ç”¨é˜Ÿåˆ—ä¸æ˜¯ å�¦å·²ç»�åŠ å…¥äº†è™šå¼•ç”¨ï¼Œæ�¥äº†è§£è¢«å¼•用的对象是å�¦å°†è¦�被垃圾回收。程åº�如果å�‘现æŸ�个虚引用已ç»�è¢«åŠ å…¥åˆ°å¼•ç”¨é˜Ÿåˆ—ï¼Œé‚£ä¹ˆå°±å�¯ä»¥åœ¨æ‰€å¼•用的对象的内å˜è¢«å›žæ”¶ä¹‹å‰�采å�–å¿…è¦�的行动。
特别注æ„�,在程åº�设计ä¸ä¸€èˆ¬å¾ˆå°‘ä½¿ç”¨å¼±å¼•ç”¨ä¸Žè™šå¼•ç”¨ï¼Œä½¿ç”¨è½¯å¼•ç”¨çš„æƒ…å†µè¾ƒå¤šï¼Œè¿™æ˜¯å› ä¸º**软引用å�¯ä»¥åŠ é€ŸJVM对垃圾内å˜çš„回收速度,å�¯ä»¥ç»´æŠ¤ç³»ç»Ÿçš„è¿�行安全,防æ¢å†…å˜æº¢å‡ºï¼ˆOutOfMemory)ç‰é—®é¢˜çš„产生**。
@@ -126,7 +124,7 @@ JDK1.2以�,Java对引用的感念进行了扩充,将引用分为强引用
方法区(或Hotspot虚拟ä¸çš„æ°¸ä¹…代)的垃圾收集主è¦�回收两部分内容:**废弃常é‡�å’Œæ— ç”¨çš„ç±»ã€‚**
-判定一个常é‡�是å�¦æ˜¯â€œåºŸå¼ƒå¸¸é‡�â€�比较简å�•,而è¦�判定一个类是å�¦æ˜¯â€œæ— 用的类â€�çš„æ�¡ä»¶åˆ™ç›¸å¯¹è‹›åˆ»è®¸å¤šã€‚类需è¦�å�Œæ—¶æ»¡è¶³ä¸‹é�¢3个æ�¡ä»¶æ‰�能算是 **â€œæ— ç”¨çš„ç±»â€�** :
+判定一个常é‡�是å�¦æ˜¯â€œåºŸå¼ƒå¸¸é‡�â€�比较简å�•,而è¦�判定一个类是å�¦æ˜¯â€œæ— 用的类â€�çš„æ�¡ä»¶åˆ™ç›¸å¯¹è‹›åˆ»è®¸å¤šã€‚类需è¦�å�Œæ—¶æ»¡è¶³ä¸‹é�¢3个æ�¡ä»¶æ‰�能算是**â€œæ— ç”¨çš„ç±»â€�**:
- 该类所有的实例都已ç»�被回收,也就是Javaå †ä¸ä¸�å˜åœ¨è¯¥ç±»çš„任何实例。
- åŠ è½½è¯¥ç±»çš„ClassLoaderå·²ç»�被回收。
- 该类对应的java.lang.Classå¯¹è±¡æ²¡æœ‰åœ¨ä»»ä½•åœ°æ–¹è¢«å¼•ç”¨ï¼Œæ— æ³•åœ¨ä»»ä½•åœ°æ–¹é€šè¿‡å��射访问该类的方法。
@@ -136,19 +134,16 @@ JDK1.2以�,Java对引用的感念进行了扩充,将引用分为强引用
### 3.1 æ ‡è®°-清除算法
ç®—æ³•åˆ†ä¸ºâ€œæ ‡è®°â€�和“清除â€�é˜¶æ®µï¼šé¦–å…ˆæ ‡è®°å‡ºæ‰€æœ‰éœ€è¦�å›žæ”¶çš„å¯¹è±¡ï¼Œåœ¨æ ‡è®°å®Œæˆ�å�Žç»Ÿä¸€å›žæ”¶æ‰€æœ‰è¢«æ ‡è®°çš„对象。它是最基础的收集算法,会带æ�¥ä¸¤ä¸ªæ˜Žæ˜¾çš„问题;1:效率问题和2ï¼šç©ºé—´é—®é¢˜ï¼ˆæ ‡è®°æ¸…é™¤å�Žä¼šäº§ç”Ÿå¤§é‡�ä¸�连ç»çš„碎片)
-
### 3.2 �制算法
为了解决效率问题,“å¤�制â€�收集算法出现了。它å�¯ä»¥å°†å†…å˜åˆ†ä¸ºå¤§å°�相å�Œçš„两å�—,æ¯�次使用其ä¸çš„一å�—。当这一å�—的内å˜ä½¿ç”¨å®Œå�Žï¼Œå°±å°†è¿˜å˜æ´»çš„对象å¤�制到å�¦ä¸€å�—去,然å�Žå†�把使用的空间一次清ç�†æŽ‰ã€‚è¿™æ ·å°±ä½¿æ¯�次的内å˜å›žæ”¶éƒ½æ˜¯å¯¹å†…å˜åŒºé—´çš„一å�Šè¿›è¡Œå›žæ”¶ã€‚
-
### 3.3 æ ‡è®°-æ•´ç�†ç®—法
æ ¹æ�®è€�年代的特点特出的一ç§�æ ‡è®°ç®—æ³•ï¼Œæ ‡è®°è¿‡ç¨‹ä»�ç„¶ä¸Žâ€œæ ‡è®°-清除â€�ç®—æ³•ä¸€æ ·ï¼Œä½†å�Žç»æ¥éª¤ä¸�是直接对å�¯å›žæ”¶å¯¹è±¡å›žæ”¶ï¼Œè€Œæ˜¯è®©æ‰€æœ‰å˜æ´»çš„对象å�‘一段移动,然å�Žç›´æŽ¥æ¸…ç�†æŽ‰ç«¯è¾¹ç•Œä»¥å¤–的内å˜ã€‚
-
### 3.4分代收集算法
@@ -156,7 +151,7 @@ JDK1.2以�,Java对引用的感念进行了扩充,将引用分为强引用
比如在新生代ä¸ï¼Œæ¯�次收集都会有大é‡�对象æ»åŽ»ï¼Œæ‰€ä»¥å�¯ä»¥é€‰æ‹©å¤�制算法,å�ªéœ€è¦�付出少é‡�对象的å¤�制æˆ�本就å�¯ä»¥å®Œæˆ�æ¯�次垃圾收集。而è€�å¹´ä»£çš„å¯¹è±¡å˜æ´»å‡ 率是比较高的所以我们å�¯ä»¥é€‰æ‹©â€œæ ‡è®°-清ç�†â€�æˆ–â€œæ ‡è®°-æ•´ç�†â€�算法进行垃圾收集。
-**延伸�试问题:** HotSpot为什么�分为新生代和�年代?
+**延伸�试问题:**HotSpot为什么�分为新生代和�年代?
æ ¹æ�®ä¸Šé�¢çš„对分代收集算法的介ç»�回ç”。
@@ -167,8 +162,7 @@ JDK1.2以�,Java对引用的感念进行了扩充,将引用分为强引用
### 4.1 Serial收集器
-Serial(串行)收集器收集器是最基本ã€�历å�²æœ€æ‚ 久的垃圾收集器了。大家看å��å—就知é�“这个收集器是一个å�•线程收集器了。它的 **“å�•线程â€�** 的æ„�义ä¸�ä»…ä»…æ„�味ç�€å®ƒå�ªä¼šä½¿ç”¨ä¸€æ�¡åžƒåœ¾æ”¶é›†çº¿ç¨‹åŽ»å®Œæˆ�垃圾收集工作,更é‡�è¦�的是它在进行垃圾收集工作的时候必须暂å�œå…¶ä»–所有的工作线程( **“Stop The Worldâ€�** 了解一下),直到它收集结æ�Ÿã€‚
-
+Serial(串行)收集器收集器是最基本ã€�历å�²æœ€æ‚ 久的垃圾收集器了。大家看å��å—就知é�“这个收集器是一个å�•线程收集器了。它的**“å�•线程â€�**çš„æ„�义ä¸�ä»…ä»…æ„�味ç�€å®ƒå�ªä¼šä½¿ç”¨ä¸€æ�¡åžƒåœ¾æ”¶é›†çº¿ç¨‹åŽ»å®Œæˆ�垃圾收集工作,更é‡�è¦�的是它在进行垃圾收集工作的时候必须暂å�œå…¶ä»–所有的工作线程(**“Stop The Worldâ€�**了解一下),直到它收集结æ�Ÿã€‚
虚拟机的设计者们当然知é�“Stop The World带æ�¥çš„ä¸�良用户体验,所以在å�Žç»çš„垃圾收集器设计ä¸å�œé¡¿æ—¶é—´åœ¨ä¸�æ–缩çŸï¼ˆä»�然还有å�œé¡¿ï¼Œå¯»æ‰¾æœ€ä¼˜ç§€çš„垃圾收集器的过程ä»�然在继ç»ï¼‰ã€‚
@@ -178,12 +172,11 @@ Serial(串行)收集器收集器是最基本ã€�历å�²æœ€æ‚ 久的垃圾收
**ParNew收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制å�‚æ•°ã€�收集算法ã€�回收ç–ç•¥ç‰ç‰ï¼‰å’ŒSerialæ”¶é›†å™¨å®Œå…¨ä¸€æ ·ã€‚**
-
它是许多è¿�行在Server模å¼�下的虚拟机的首è¦�选择,除了Serial收集器外,å�ªæœ‰å®ƒèƒ½ä¸ŽCMSæ”¶é›†å™¨ï¼ˆçœŸæ£æ„�义上的并å�‘收集器,å�Žé�¢ä¼šä»‹ç»�到)é…�å�ˆå·¥ä½œã€‚
**并行和并�概念补充:**
-* **并行(Parallel)** :指多æ�¡åžƒåœ¾æ”¶é›†çº¿ç¨‹å¹¶è¡Œå·¥ä½œï¼Œä½†æ¤æ—¶ç”¨æˆ·çº¿ç¨‹ä»�然处于ç‰å¾…状æ€�。
+* **并行(Parallel)**:指多æ�¡åžƒåœ¾æ”¶é›†çº¿ç¨‹å¹¶è¡Œå·¥ä½œï¼Œä½†æ¤æ—¶ç”¨æˆ·çº¿ç¨‹ä»�然处于ç‰å¾…状æ€�。
* **å¹¶å�‘(Concurrent)**:指用户线程与垃圾收集线程å�Œæ—¶æ‰§è¡Œï¼ˆä½†ä¸�一定是并行,å�¯èƒ½ä¼šäº¤æ›¿æ‰§è¡Œï¼‰ï¼Œç”¨æˆ·ç¨‹åº�在继ç»è¿�行,而垃圾收集器è¿�行在å�¦ä¸€ä¸ªCPU上。
@@ -191,7 +184,7 @@ Serial(串行)收集器收集器是最基本ã€�历å�²æœ€æ‚ 久的垃圾收
Parallel Scavenge收集器是一个新生代收集器,它也是使用�制算法的收集器,�是并行的的多线程收集器。。。那么它有什么特别之处呢?
-**Parallel Scavenge收集器关注点是å�žå��é‡�(高效率的利用CPU)。CMSç‰åžƒåœ¾æ”¶é›†å™¨çš„关注点更多的是用户线程的å�œé¡¿æ—¶é—´ï¼ˆæ��高用户体验)。所谓å�žå��é‡�就是CPUä¸ç”¨äºŽè¿�行用户代ç �的时间与CPU总消耗时间的比值。** Parallel Scavenge收集器æ��供了很多å�‚数供用户找到最å�ˆé€‚çš„å�œé¡¿æ—¶é—´æˆ–最大å�žå��é‡�,如果对于收集器è¿�作ä¸�太了解的è¯�,手工优化å˜åœ¨çš„è¯�å�¯ä»¥é€‰æ‹©æŠŠå†…å˜ç®¡ç�†ä¼˜åŒ–交给虚拟机去完æˆ�也是一个ä¸�错的选择。
+**Parallel Scavenge收集器关注点是å�žå��é‡�(高效率的利用CPU)。CMSç‰åžƒåœ¾æ”¶é›†å™¨çš„关注点更多的是用户线程的å�œé¡¿æ—¶é—´ï¼ˆæ��高用户体验)。所谓å�žå��é‡�就是CPUä¸ç”¨äºŽè¿�行用户代ç �的时间与CPU总消耗时间的比值。**Parallel Scavenge收集器æ��供了很多å�‚数供用户找到最å�ˆé€‚çš„å�œé¡¿æ—¶é—´æˆ–最大å�žå��é‡�,如果对于收集器è¿�作ä¸�太了解的è¯�,手工优化å˜åœ¨çš„è¯�å�¯ä»¥é€‰æ‹©æŠŠå†…å˜ç®¡ç�†ä¼˜åŒ–交给虚拟机去完æˆ�也是一个ä¸�错的选择。
### 4.4.Serial Old收集器
@@ -205,45 +198,41 @@ Parallel Scavenge收集器是一个新生代收集器,它也是使用�制算
**CMS(Concurrent Mark Sweep)收集器是一ç§�以获å�–最çŸå›žæ”¶å�œé¡¿æ—¶é—´ä¸ºç›®æ ‡çš„æ”¶é›†å™¨ã€‚它而é�žå¸¸ç¬¦å�ˆåœ¨æ³¨é‡�用户体验的应用上使用。**
-从å��å—ä¸çš„**Mark Sweep**这两个è¯�å�¯ä»¥çœ‹å‡ºï¼ŒCMS收集器是一ç§� **â€œæ ‡è®°-清除â€�算法**实现的,它的è¿�作过程相比于å‰�é�¢å‡ ç§�垃圾收集器æ�¥è¯´æ›´åŠ å¤�æ�‚一些。整个过程分为四个æ¥éª¤ï¼š
-
-* **åˆ�å§‹æ ‡è®°ï¼š** 暂å�œæ‰€æœ‰çš„其他线程,并记录下直接与root相连的对象,速度很快 ï¼›
-* **å¹¶å�‘æ ‡è®°ï¼š** å�Œæ—¶å¼€å�¯GC和用户线程,用一个é—包结构去记录å�¯è¾¾å¯¹è±¡ã€‚但在这个阶段结æ�Ÿï¼Œè¿™ä¸ªé—包结构并ä¸�能ä¿�è¯�包å�«å½“å‰�所有的å�¯è¾¾å¯¹è±¡ã€‚å› ä¸ºç”¨æˆ·çº¿ç¨‹å�¯èƒ½ä¼šä¸�æ–的更新引用域,所以GCçº¿ç¨‹æ— æ³•ä¿�è¯�å�¯è¾¾æ€§åˆ†æž�的实时性。所以这个算法里会跟踪记录这些å�‘生引用更新的地方。
-* **é‡�æ–°æ ‡è®°ï¼š** é‡�æ–°æ ‡è®°é˜¶æ®µå°±æ˜¯ä¸ºäº†ä¿®æ£å¹¶å�‘æ ‡è®°æœŸé—´å› ä¸ºç”¨æˆ·ç¨‹åº�ç»§ç»è¿�è¡Œè€Œå¯¼è‡´æ ‡è®°äº§ç”Ÿå�˜åŠ¨çš„é‚£ä¸€éƒ¨åˆ†å¯¹è±¡çš„æ ‡è®°è®°å½•ï¼Œè¿™ä¸ªé˜¶æ®µçš„å�œé¡¿æ—¶é—´ä¸€èˆ¬ä¼šæ¯”åˆ�å§‹æ ‡è®°é˜¶æ®µçš„æ—¶é—´ç¨�长,远远比并å�‘æ ‡è®°é˜¶æ®µæ—¶é—´çŸ
-* **å¹¶å�‘清除:** 开å�¯ç”¨æˆ·çº¿ç¨‹ï¼Œå�Œæ—¶GCçº¿ç¨‹å¼€å§‹å¯¹ä¸ºæ ‡è®°çš„åŒºåŸŸå�šæ¸…æ‰«ã€‚
+从å��å—ä¸çš„**Mark Sweep**这两个è¯�å�¯ä»¥çœ‹å‡ºï¼ŒCMS收集器是一ç§�**â€œæ ‡è®°-清除â€�算法**实现的,它的è¿�作过程相比于å‰�é�¢å‡ ç§�垃圾收集器æ�¥è¯´æ›´åŠ å¤�æ�‚一些。整个过程分为四个æ¥éª¤ï¼š
-
+* **åˆ�å§‹æ ‡è®°ï¼š**æš‚å�œæ‰€æœ‰çš„其他线程,并记录下直接与root相连的对象,速度很快 ï¼›
+* **å¹¶å�‘æ ‡è®°ï¼š**å�Œæ—¶å¼€å�¯GC和用户线程,用一个é—包结构去记录å�¯è¾¾å¯¹è±¡ã€‚但在这个阶段结æ�Ÿï¼Œè¿™ä¸ªé—包结构并ä¸�能ä¿�è¯�包å�«å½“å‰�所有的å�¯è¾¾å¯¹è±¡ã€‚å› ä¸ºç”¨æˆ·çº¿ç¨‹å�¯èƒ½ä¼šä¸�æ–的更新引用域,所以GCçº¿ç¨‹æ— æ³•ä¿�è¯�å�¯è¾¾æ€§åˆ†æž�的实时性。所以这个算法里会跟踪记录这些å�‘生引用更新的地方。
+* **é‡�æ–°æ ‡è®°ï¼š**é‡�æ–°æ ‡è®°é˜¶æ®µå°±æ˜¯ä¸ºäº†ä¿®æ£å¹¶å�‘æ ‡è®°æœŸé—´å› ä¸ºç”¨æˆ·ç¨‹åº�ç»§ç»è¿�è¡Œè€Œå¯¼è‡´æ ‡è®°äº§ç”Ÿå�˜åŠ¨çš„é‚£ä¸€éƒ¨åˆ†å¯¹è±¡çš„æ ‡è®°è®°å½•ï¼Œè¿™ä¸ªé˜¶æ®µçš„å�œé¡¿æ—¶é—´ä¸€èˆ¬ä¼šæ¯”åˆ�å§‹æ ‡è®°é˜¶æ®µçš„æ—¶é—´ç¨�长,远远比并å�‘æ ‡è®°é˜¶æ®µæ—¶é—´çŸ
+* **å¹¶å�‘清除:**å¼€å�¯ç”¨æˆ·çº¿ç¨‹ï¼Œå�Œæ—¶GCçº¿ç¨‹å¼€å§‹å¯¹ä¸ºæ ‡è®°çš„åŒºåŸŸå�šæ¸…æ‰«ã€‚
从它的å��å—å°±å�¯ä»¥çœ‹å‡ºå®ƒæ˜¯ä¸€æ¬¾ä¼˜ç§€çš„垃圾收集器,主è¦�优点:**å¹¶å�‘收集ã€�低å�œé¡¿**。但是它有下é�¢ä¸‰ä¸ªæ˜Žæ˜¾çš„缺点:
-- **对CPU资��感;**
-- **æ— æ³•å¤„ç�†æµ®åŠ¨åžƒåœ¾ï¼›**
-- **它使用的回收算法-â€œæ ‡è®°-清除â€�算法会导致收集结æ�Ÿæ—¶ä¼šæœ‰å¤§é‡�空间碎片产生。**
+-**对CPU资��感;**
+-**æ— æ³•å¤„ç�†æµ®åŠ¨åžƒåœ¾ï¼›**
+-**它使用的回收算法-â€œæ ‡è®°-清除â€�算法会导致收集结æ�Ÿæ—¶ä¼šæœ‰å¤§é‡�空间碎片产生。**
### 4.7 G1收集器
上一代的垃圾收集器(串行serial, 并行parallel, 以å�ŠCMS)éƒ½æŠŠå †å†…å˜åˆ’分为固定大å°�的三个部分: 年轻代(young generation), å¹´è€�代(old generation), 以å�ŠæŒ�久代(permanent generation).
-
**G1 (Garbage-First)是一款é�¢å�‘æœ�务器的垃圾收集器,主è¦�针对é…�备多颗处ç�†å™¨å�Šå¤§å®¹é‡�内å˜çš„æœºå™¨. 以æž�高概率满足GCå�œé¡¿æ—¶é—´è¦�求的å�Œæ—¶,还具备高å�žå��é‡�性能特å¾�.**
被视为JDK1.7ä¸HotSpot虚拟机的一个é‡�è¦�进化特å¾�。它具备一下特点:
-- **并行与并å�‘**:G1能充分利用CPUã€�å¤šæ ¸çŽ¯å¢ƒä¸‹çš„ç¡¬ä»¶ä¼˜åŠ¿ï¼Œä½¿ç”¨å¤šä¸ªCPU(CPU或者CPUæ ¸å¿ƒï¼‰æ�¥ç¼©çŸstop-The-Worldå�œé¡¿æ—¶é—´ã€‚部分其他收集器原本需è¦�å�œé¡¿Java线程执行的GC动作,G1收集器ä»�ç„¶å�¯ä»¥é€šè¿‡å¹¶å�‘的方å¼�让java程åº�ç»§ç»æ‰§è¡Œã€‚
-- **分代收集**:虽然G1å�¯ä»¥ä¸�需è¦�其他收集器é…�å�ˆå°±èƒ½ç‹¬ç«‹ç®¡ç�†æ•´ä¸ªGCå †ï¼Œä½†æ˜¯è¿˜æ˜¯ä¿�留了分代的概念。
-- **空间整å�ˆ**:与CMSçš„â€œæ ‡è®°â€“æ¸…ç�†â€�算法ä¸�å�Œï¼ŒG1从整体æ�¥çœ‹æ˜¯åŸºäºŽâ€œæ ‡è®°æ•´ç�†â€�算法实现的收集器;从局部上æ�¥çœ‹æ˜¯åŸºäºŽâ€œå¤�制â€�算法实现的。
-- **å�¯é¢„测的å�œé¡¿**:这是G1相对于CMSçš„å�¦ä¸€ä¸ªå¤§ä¼˜åŠ¿ï¼Œé™�低å�œé¡¿æ—¶é—´æ˜¯G1和Cï¼ï¼³å…±å�Œçš„关注点,但G1除了追求低å�œé¡¿å¤–,还能建立å�¯é¢„测的å�œé¡¿æ—¶é—´æ¨¡åž‹ï¼Œèƒ½è®©ä½¿ç”¨è€…明确指定在一个长度为M毫秒的时间片段内。
+-**并行与并å�‘**:G1能充分利用CPUã€�å¤šæ ¸çŽ¯å¢ƒä¸‹çš„ç¡¬ä»¶ä¼˜åŠ¿ï¼Œä½¿ç”¨å¤šä¸ªCPU(CPU或者CPUæ ¸å¿ƒï¼‰æ�¥ç¼©çŸstop-The-Worldå�œé¡¿æ—¶é—´ã€‚部分其他收集器原本需è¦�å�œé¡¿Java线程执行的GC动作,G1收集器ä»�ç„¶å�¯ä»¥é€šè¿‡å¹¶å�‘的方å¼�让java程åº�ç»§ç»æ‰§è¡Œã€‚
+-**分代收集**:虽然G1å�¯ä»¥ä¸�需è¦�其他收集器é…�å�ˆå°±èƒ½ç‹¬ç«‹ç®¡ç�†æ•´ä¸ªGCå †ï¼Œä½†æ˜¯è¿˜æ˜¯ä¿�留了分代的概念。
+-**空间整å�ˆ**:与CMSçš„â€œæ ‡è®°â€“æ¸…ç�†â€�算法ä¸�å�Œï¼ŒG1从整体æ�¥çœ‹æ˜¯åŸºäºŽâ€œæ ‡è®°æ•´ç�†â€�算法实现的收集器;从局部上æ�¥çœ‹æ˜¯åŸºäºŽâ€œå¤�制â€�算法实现的。
+-**å�¯é¢„测的å�œé¡¿**:这是G1相对于CMSçš„å�¦ä¸€ä¸ªå¤§ä¼˜åŠ¿ï¼Œé™�低å�œé¡¿æ—¶é—´æ˜¯G1和Cï¼ï¼³å…±å�Œçš„关注点,但G1除了追求低å�œé¡¿å¤–,还能建立å�¯é¢„测的å�œé¡¿æ—¶é—´æ¨¡åž‹ï¼Œèƒ½è®©ä½¿ç”¨è€…明确指定在一个长度为M毫秒的时间片段内。
**G1收集器在å�Žå�°ç»´æŠ¤äº†ä¸€ä¸ªä¼˜å…ˆåˆ—表,æ¯�æ¬¡æ ¹æ�®å…�许的收集时间,优先选择回收价值最大的Region(这也就是它的å��å—Garbage-First的由æ�¥)**。这ç§�使用Region划分内å˜ç©ºé—´ä»¥å�Šæœ‰ä¼˜å…ˆçº§çš„区域回收方å¼�,ä¿�è¯�了GF收集器在有é™�时间内å�¯ä»¥å°½å�¯èƒ½é«˜çš„æ”¶é›†æ•ˆçŽ‡ï¼ˆæŠŠå†…å˜åŒ–整为零)。
G1收集器的è¿�ä½œå¤§è‡´åˆ†ä¸ºä»¥ä¸‹å‡ ä¸ªæ¥éª¤ï¼š
-- **åˆ�å§‹æ ‡è®°**
-- **å¹¶å�‘æ ‡è®°**
-- **æœ€ç»ˆæ ‡è®°**
-- **ç›é€‰å›žæ”¶**
+-**åˆ�å§‹æ ‡è®°**
+-**å¹¶å�‘æ ‡è®°**
+-**æœ€ç»ˆæ ‡è®°**
+-**ç›é€‰å›žæ”¶**
上é�¢å‡ 个æ¥éª¤çš„è¿�作过程和CMS有很多相似之处。åˆ�å§‹æ ‡è®°é˜¶æ®µä»…ä»…å�ªæ˜¯æ ‡è®°ä¸€ä¸‹GC Roots能直接关è�”到的对象,并且修改TAMS的值,让下一个阶段用户程åº�å¹¶å�‘è¿�行时,能在æ£ç¡®å�¯ç”¨çš„Regionä¸åˆ›å»ºæ–°å¯¹è±¡ï¼Œè¿™ä¸€é˜¶æ®µéœ€è¦�å�œé¡¿çº¿ç¨‹ï¼Œä½†æ˜¯è€—时很çŸï¼Œå¹¶å�‘æ ‡è®°é˜¶æ®µæ˜¯ä»ŽGC Rootå¼€å§‹å¯¹å †ä¸å¯¹è±¡è¿›è¡Œå�¯è¾¾æ€§åˆ†æž�ï¼Œæ‰¾å‡ºå˜æ´»çš„对象,这阶段时耗时较长,但å�¯ä¸Žç”¨æˆ·ç¨‹åº�å¹¶å�‘æ‰§è¡Œã€‚è€Œæœ€ç»ˆæ ‡è®°é˜¶æ®µåˆ™æ˜¯ä¸ºäº†ä¿®æ£åœ¨å¹¶å�‘æ ‡è®°æœŸé—´å› ç”¨æˆ·ç¨‹åº�ç»§ç»è¿�ä½œè€Œå¯¼è‡´æ ‡è®°äº§ç”Ÿå�˜åŠ¨çš„é‚£ä¸€éƒ¨åˆ†æ ‡è®°è®°å½•ï¼Œè™šæ‹Ÿæœºå°†è¿™æ®µæ—¶é—´å¯¹è±¡å�˜åŒ–记录在线程Remenbered Set Logs里é�¢ï¼Œæœ€ç»ˆæ ‡è®°é˜¶æ®µéœ€è¦�把Remembered Set Logs的数æ�®å�ˆå¹¶åˆ°Remembered Set Logs里é�¢ï¼Œæœ€ç»ˆæ ‡è®°é˜¶æ®µéœ€è¦�把Remembered Set Logs的数æ�®å�ˆå¹¶åˆ°Remembered Setä¸ï¼Œè¿™ä¸€é˜¶æ®µéœ€è¦�å�œé¡¿çº¿ç¨‹ï¼Œä½†æ˜¯å�¯å¹¶è¡Œæ‰§è¡Œã€‚最å�Žåœ¨ç›é€‰å›žæ”¶é˜¶æ®µé¦–先对å�„个Region的回收价值和æˆ�本进行排åº�ï¼Œæ ¹æ�®ç”¨æˆ·æ‰€æœŸæœ›çš„GCå�œé¡¿æ—¶é—´æ�¥åˆ¶å®šå›žæ”¶è®¡åˆ’。
-
## 5 内å˜åˆ†é…�与回收ç–ç•¥
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\2726\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243JVM\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.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\272\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243JVM\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md"
similarity index 82%
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\2726\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243JVM\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.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\272\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243JVM\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md"
index 60ad7b7..198ce72 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2726\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243JVM\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.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\272\357\274\232\346\267\261\345\205\245\347\220\206\350\247\243JVM\347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [一.ç›®æ ‡ï¼š](#ä¸€ç›®æ ‡ï¼š)
* [二.原ç�† ï¼ˆç±»çš„åŠ è½½è¿‡ç¨‹å�Šå…¶æœ€ç»ˆäº§å“�):](#二原ç�†-ï¼ˆç±»çš„åŠ è½½è¿‡ç¨‹å�Šå…¶æœ€ç»ˆäº§å“�))
* [三.过程(类的生命周期):](#三过程(类的生命周期):)
@@ -11,9 +10,6 @@
* [å››.ç±»åŠ è½½å™¨ï¼š](#å››ç±»åŠ è½½å™¨ï¼š)
* [五.�亲委派机制:](#五�亲委派机制:)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
本文转自互è�”网,侵åˆ
@@ -36,7 +32,6 @@
-
## 一.ç›®æ ‡ï¼š
1.ä»€ä¹ˆæ˜¯ç±»çš„åŠ è½½ï¼Ÿ
@@ -56,14 +51,7 @@ JVMå°†class文件å—节ç �æ–‡ä»¶åŠ è½½åˆ°å†…å˜ä¸ï¼Œ 并将这些é�™æ€�æ•°æ�®
JVMç±»åŠ è½½æœºåˆ¶åˆ†ä¸ºäº”ä¸ªéƒ¨åˆ†ï¼šåŠ è½½ï¼ŒéªŒè¯�,准备,解æž�,åˆ�始化,下é�¢æˆ‘们就分别æ�¥çœ‹ä¸€ä¸‹è¿™äº”个过程。其ä¸åŠ è½½ã€�检验ã€�准备ã€�åˆ�始化和å�¸è½½è¿™ä¸ªäº”个阶段的顺åº�是固定的,而解æž�则未必。为了支æŒ�动æ€�绑定,解æž�这个过程å�¯ä»¥å�‘生在åˆ�始化阶段之å�Žã€‚
-
-
-
-
-
-
-
-
+
### åŠ è½½ï¼š
@@ -139,13 +127,7 @@ javaä¸ï¼Œå¯¹äºŽåˆ�始化阶段,有且å�ªæœ‰ä»¥ä¸‹äº”ç§�情况æ‰�会对è¦�求
## 五.�亲委派机制:
-
-
-
-
-
-
-
+
�亲委派机制工作过程:
@@ -169,20 +151,4 @@ javaä¸ï¼Œå¯¹äºŽåˆ�始化阶段,有且å�ªæœ‰ä»¥ä¸‹äº”ç§�情况æ‰�会对è¦�求
https://blog.csdn.net/android_hl/article/details/53228348
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
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\2725\357\274\232\350\231\232\346\213\237\346\234\272\345\255\227\350\212\202\347\240\201\346\211\247\350\241\214\345\274\225\346\223\216.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\272\357\274\232\350\231\232\346\213\237\346\234\272\345\255\227\350\212\202\347\240\201\346\211\247\350\241\214\345\274\225\346\223\216.md"
similarity index 85%
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\2725\357\274\232\350\231\232\346\213\237\346\234\272\345\255\227\350\212\202\347\240\201\346\211\247\350\241\214\345\274\225\346\223\216.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\272\357\274\232\350\231\232\346\213\237\346\234\272\345\255\227\350\212\202\347\240\201\346\211\247\350\241\214\345\274\225\346\223\216.md"
index faebc2d..aabb34c 100644
--- "a/docs/java/jvm/\346\267\261\345\205\245\347\220\206\350\247\243JVM\350\231\232\346\213\237\346\234\2725\357\274\232\350\231\232\346\213\237\346\234\272\345\255\227\350\212\202\347\240\201\346\211\247\350\241\214\345\274\225\346\223\216.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\272\357\274\232\350\231\232\346\213\237\346\234\272\345\255\227\350\212\202\347\240\201\346\211\247\350\241\214\345\274\225\346\223\216.md"
@@ -1,5 +1,4 @@
-# Table of Contents
-
+# 目录
* [1 概述](#1-概述)
* [2 è¿�è¡Œæ—¶æ ˆå¸§ç»“æž„](#2-è¿�è¡Œæ—¶æ ˆå¸§ç»“æž„)
* [2.1 局部��表](#21-局部��表)
@@ -45,14 +44,13 @@
## 2 è¿�è¡Œæ—¶æ ˆå¸§ç»“æž„
-**æ ˆå¸§ï¼ˆStack Frame)** 是用于支æŒ�虚拟机方法调用和方法执行的数æ�®ç»“构,它是虚拟机è¿�行时数æ�®åŒºä¸**è™šæ‹Ÿæœºæ ˆï¼ˆVirtual Machine Stackï¼‰çš„æ ˆå…ƒç´ **。
+**æ ˆå¸§ï¼ˆStack Frame)**是用于支æŒ�虚拟机方法调用和方法执行的数æ�®ç»“构,它是虚拟机è¿�行时数æ�®åŒºä¸**è™šæ‹Ÿæœºæ ˆï¼ˆVirtual Machine Stackï¼‰çš„æ ˆå…ƒç´ **。
æ ˆå¸§å˜å‚¨äº†æ–¹æ³•的局部å�˜é‡�表ã€�æ“�ä½œæ•°æ ˆã€�动æ€�连接和方法返回地å�€ç‰ä¿¡æ�¯ã€‚æ¯�一个方法从调用开始至执行完æˆ�的过程,都对应ç�€ä¸€ä¸ªæ ˆå¸§åœ¨è™šæ‹Ÿæœºæ ˆé‡Œé�¢ä»Žå…¥æ ˆåˆ°å‡ºæ ˆçš„过程。
**æ ˆå¸§æ¦‚å¿µç»“æž„å¦‚ä¸‹å›¾æ‰€ç¤ºï¼š**
-
-
+
### 2.1 局部��表
**局部å�˜é‡�表是一组å�˜é‡�值å˜å‚¨ç©ºé—´ï¼Œç”¨äºŽå˜æ”¾æ–¹æ³•å�‚数和方法内定义的局部å�˜é‡�。
@@ -66,17 +64,16 @@
### 2.2 æ“�ä½œæ•°æ ˆ
-**æ“�ä½œæ•°æ ˆï¼ˆOperand Stack)** 也常称为æ“�ä½œæ ˆï¼Œå®ƒæ˜¯ä¸€ä¸ª**å�Žå…¥å…ˆå‡ºæ ˆ**。当一个方法执行开始时,这个方法的æ“�ä½œæ•°æ ˆæ˜¯ç©ºçš„ï¼Œåœ¨æ–¹æ³•æ‰§è¡Œè¿‡ç¨‹ä¸ï¼Œä¼šæœ‰å�„ç§�å—节ç �指令往æ“�ä½œæ•°æ ˆä¸å†™å…¥å’Œæ��å�–内容,也就是 **å‡ºæ ˆ/å…¥æ ˆ**æ“�作。
-
-
+**æ“�ä½œæ•°æ ˆï¼ˆOperand Stack)**也常称为æ“�ä½œæ ˆï¼Œå®ƒæ˜¯ä¸€ä¸ª**å�Žå…¥å…ˆå‡ºæ ˆ**。当一个方法执行开始时,这个方法的æ“�ä½œæ•°æ ˆæ˜¯ç©ºçš„ï¼Œåœ¨æ–¹æ³•æ‰§è¡Œè¿‡ç¨‹ä¸ï¼Œä¼šæœ‰å�„ç§�å—节ç �指令往æ“�ä½œæ•°æ ˆä¸å†™å…¥å’Œæ��å�–内容,也就是**å‡ºæ ˆ/å…¥æ ˆ**æ“�作。
+
在概念模型ä¸ï¼Œä¸€ä¸ªæ´»åŠ¨çº¿ç¨‹ä¸ä¸¤ä¸ªæ ˆå¸§æ˜¯ç›¸äº’独立的。但大多数虚拟机实现都会å�šä¸€äº›ä¼˜åŒ–处ç�†ï¼šè®©ä¸‹ä¸€ä¸ªæ ˆå¸§çš„部分æ“�ä½œæ•°æ ˆä¸Žä¸Šä¸€ä¸ªæ ˆå¸§çš„éƒ¨åˆ†å±€éƒ¨å�˜é‡�表é‡�å� åœ¨ä¸€èµ·ï¼Œè¿™æ ·çš„å¥½å¤„æ˜¯æ–¹æ³•è°ƒç”¨æ—¶å�¯ä»¥å…±äº«ä¸€éƒ¨åˆ†æ•°æ�®ï¼Œè€Œæ— 须进行é¢�外的å�‚æ•°å¤�åˆ¶ä¼ é€’ã€‚
### 2.3 动�连接
æ¯�ä¸ªæ ˆå¸§éƒ½åŒ…å�«ä¸€ä¸ªæŒ‡å�‘è¿�行时常é‡�æ± ä¸è¯¥æ ˆå¸§æ‰€å±žæ–¹æ³•的引用,æŒ�有这个引用是为了支æŒ�方法调用过程ä¸çš„**动æ€�连接**ï¼›
-å—节ç �䏿–¹æ³•调用指令是以常é‡�æ± ä¸çš„æŒ‡å�‘方法的符å�·å¼•用为å�‚数的,有一部分符å�·å¼•ç”¨ä¼šåœ¨ç±»åŠ è½½é˜¶æ®µæˆ–ç¬¬ä¸€æ¬¡ä½¿ç”¨çš„æ—¶å€™è½¬åŒ–ä¸ºç›´æŽ¥å¼•ç”¨ï¼Œè¿™ç§�转化称为 **é�™æ€�è§£æž�**,å�¦å¤–一部分在æ¯�次的è¿�行期间转化为直接引用,这部分称为**动æ€�连接**。
+å—节ç �䏿–¹æ³•调用指令是以常é‡�æ± ä¸çš„æŒ‡å�‘方法的符å�·å¼•用为å�‚数的,有一部分符å�·å¼•ç”¨ä¼šåœ¨ç±»åŠ è½½é˜¶æ®µæˆ–ç¬¬ä¸€æ¬¡ä½¿ç”¨çš„æ—¶å€™è½¬åŒ–ä¸ºç›´æŽ¥å¼•ç”¨ï¼Œè¿™ç§�转化称为**é�™æ€�è§£æž�**,å�¦å¤–一部分在æ¯�次的è¿�行期间转化为直接引用,这部分称为**动æ€�连接**。
### 2.4 方法返回地�
@@ -106,11 +103,11 @@
“编译期å�¯çŸ¥ï¼Œè¿�行期ä¸�å�¯å�˜â€�的方法(é�™æ€�方法和ç§�æœ‰æ–¹æ³•ï¼‰ï¼Œåœ¨ç±»åŠ è½½çš„è§£æž�阶段,会将其符å�·å¼•用转化为直接引用(入å�£åœ°å�€ï¼‰ã€‚这类方法的调用称为“**è§£æž�(Resolution)**â€�。
在Javaè™šæ‹Ÿæœºä¸æ��供了5æ�¡æ–¹æ³•调用å—节ç �指令:
-- **invokestatic** : 调用��方法
-- **invokespecial**:è°ƒç”¨å®žä¾‹æž„é€ å™¨æ–¹æ³•ã€�ç§�有方法ã€�父类方法
-- **invokevirtual**:调用所有的虚方法
-- **invokeinterface**:调用接å�£æ–¹æ³•,会在è¿�è¡Œæ—¶åœ¨ç¡®å®šä¸€ä¸ªå®žçŽ°æ¤æŽ¥å�£çš„对象
-- **invokedynamic**:先在è¿�行时动æ€�è§£æž�出点é™�定符所引用的方法,然å�Žå†�执行该方法,在æ¤ä¹‹å‰�çš„4æ�¡è°ƒç”¨å‘½ä»¤çš„分派逻辑是固化在Java虚拟机内部的,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的。
+-**invokestatic**: 调用��方法
+-**invokespecial**:è°ƒç”¨å®žä¾‹æž„é€ å™¨æ–¹æ³•ã€�ç§�有方法ã€�父类方法
+-**invokevirtual**:调用所有的虚方法
+-**invokeinterface**:调用接å�£æ–¹æ³•,会在è¿�è¡Œæ—¶åœ¨ç¡®å®šä¸€ä¸ªå®žçŽ°æ¤æŽ¥å�£çš„对象
+-**invokedynamic**:先在è¿�行时动æ€�è§£æž�出点é™�定符所引用的方法,然å�Žå†�执行该方法,在æ¤ä¹‹å‰�çš„4æ�¡è°ƒç”¨å‘½ä»¤çš„分派逻辑是固化在Java虚拟机内部的,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的。
### 3.2 分派
@@ -252,14 +249,14 @@ JDKæ–°å¢žåŠ äº†invokedynamic指令æ�¥æ˜¯å®žçŽ°â€œåŠ¨æ€�类型è¯è¨€â€�。
**é�™æ€�è¯è¨€å’ŒåЍæ€�è¯è¨€çš„区别:**
* **é�™æ€�è¯è¨€ï¼ˆå¼ºç±»åž‹è¯è¨€ï¼‰**:
- é�™æ€�è¯è¨€æ˜¯åœ¨ç¼–译时å�˜é‡�的数æ�®ç±»åž‹å�³å�¯ç¡®å®šçš„è¯è¨€ï¼Œå¤šæ•°é�™æ€�类型è¯è¨€è¦�求在使用å�˜é‡�之å‰�必须声明数æ�®ç±»åž‹ã€‚Â
+ é�™æ€�è¯è¨€æ˜¯åœ¨ç¼–译时å�˜é‡�的数æ�®ç±»åž‹å�³å�¯ç¡®å®šçš„è¯è¨€ï¼Œå¤šæ•°é�™æ€�类型è¯è¨€è¦�求在使用å�˜é‡�之å‰�必须声明数æ�®ç±»åž‹ã€‚
例如:C++ã€�Javaã€�Delphiã€�C#ç‰ã€‚
-* **动æ€�è¯è¨€ï¼ˆå¼±ç±»åž‹è¯è¨€ï¼‰** :
- 动æ€�è¯è¨€æ˜¯åœ¨è¿�行时确定数æ�®ç±»åž‹çš„è¯è¨€ã€‚å�˜é‡�使用之å‰�ä¸�需è¦�类型声明,通常å�˜é‡�的类型是被赋值的那个值的类型。Â
+* **动æ€�è¯è¨€ï¼ˆå¼±ç±»åž‹è¯è¨€ï¼‰**:
+ 动æ€�è¯è¨€æ˜¯åœ¨è¿�行时确定数æ�®ç±»åž‹çš„è¯è¨€ã€‚å�˜é‡�使用之å‰�ä¸�需è¦�类型声明,通常å�˜é‡�的类型是被赋值的那个值的类型。
例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shellç‰ç‰ã€‚
-* **强类型定义è¯è¨€** :
+* **强类型定义è¯è¨€**:
强制数æ�®ç±»åž‹å®šä¹‰çš„è¯è¨€ã€‚也就是说,一旦一个å�˜é‡�被指定了æŸ�个数æ�®ç±»åž‹ï¼Œå¦‚æžœä¸�ç»�过强制转æ�¢ï¼Œé‚£ä¹ˆå®ƒå°±æ°¸è¿œæ˜¯è¿™ä¸ªæ•°æ�®ç±»åž‹äº†ã€‚举个例å�ï¼šå¦‚æžœä½ å®šä¹‰äº†ä¸€ä¸ªæ•´åž‹å�˜é‡�a,那么程åº�æ ¹æœ¬ä¸�å�¯èƒ½å°†a当作å—符串类型处ç�†ã€‚强类型定义è¯è¨€æ˜¯ç±»åž‹å®‰å…¨çš„è¯è¨€ã€‚
-* **弱类型定义è¯è¨€** :
+* **弱类型定义è¯è¨€**:
æ•°æ�®ç±»åž‹å�¯ä»¥è¢«å¿½ç•¥çš„è¯è¨€ã€‚它与强类型定义è¯è¨€ç›¸å��, 一个å�˜é‡�å�¯ä»¥èµ‹ä¸�å�Œæ•°æ�®ç±»åž‹çš„值。强类型定义è¯è¨€åœ¨é€Ÿåº¦ä¸Šå�¯èƒ½ç•¥é€Šè‰²äºŽå¼±ç±»åž‹å®šä¹‰è¯è¨€ï¼Œä½†æ˜¯å¼ºç±»åž‹å®šä¹‰è¯è¨€å¸¦æ�¥çš„严谨性能够有效的é�¿å…�许多错误。
## 4 åŸºäºŽæ ˆçš„å—节ç �解释执行引擎
@@ -268,15 +265,13 @@ JDKæ–°å¢žåŠ äº†invokedynamic指令æ�¥æ˜¯å®žçŽ°â€œåŠ¨æ€�类型è¯è¨€â€�。
### 4.1 解释执行
-Javaè¯è¨€ç»�常被人们定ä½�为 **“解释执行â€�è¯è¨€**,在Javaåˆ�生的JDK1.0时代,这ç§�定义还比较准确的,但当主æµ�的虚拟机ä¸éƒ½åŒ…å�«äº†å�³æ—¶ç¼–译å�Žï¼ŒClass文件ä¸çš„代ç �到底会被解释执行还是编译执行,就æˆ�了å�ªæœ‰è™šæ‹Ÿæœºè‡ªå·±æ‰�能准确判æ–的事情。å†�å�Žæ�¥ï¼ŒJava也å�‘展出æ�¥äº†ç›´æŽ¥ç”Ÿæˆ�本地代ç �的编译器[如何GCJ(GNU Compiler for the Java)],而C/C++也出现了通过解释器执行的版本(如CINT),这时候å†�笼统的说“解释执行â€�,对于整个Javaè¯è¨€æ�¥è¯´å°±æˆ�äº†å‡ ä¹Žæ²¡æœ‰ä»»ä½•æ„�义的概念,**å�ªæœ‰ç¡®å®šäº†è°ˆè®ºå¯¹è±¡æ˜¯æŸ�ç§�具体的Java实现版本和执行引擎è¿�行模å¼�时,谈解释执行还是编译执行æ‰�会比较确切**。
-
-
+Javaè¯è¨€ç»�常被人们定ä½�为**“解释执行â€�è¯è¨€**,在Javaåˆ�生的JDK1.0时代,这ç§�定义还比较准确的,但当主æµ�的虚拟机ä¸éƒ½åŒ…å�«äº†å�³æ—¶ç¼–译å�Žï¼ŒClass文件ä¸çš„代ç �到底会被解释执行还是编译执行,就æˆ�了å�ªæœ‰è™šæ‹Ÿæœºè‡ªå·±æ‰�能准确判æ–的事情。å†�å�Žæ�¥ï¼ŒJava也å�‘展出æ�¥äº†ç›´æŽ¥ç”Ÿæˆ�本地代ç �的编译器[如何GCJ(GNU Compiler for the Java)],而C/C++也出现了通过解释器执行的版本(如CINT),这时候å†�笼统的说“解释执行â€�,对于整个Javaè¯è¨€æ�¥è¯´å°±æˆ�äº†å‡ ä¹Žæ²¡æœ‰ä»»ä½•æ„�义的概念,**å�ªæœ‰ç¡®å®šäº†è°ˆè®ºå¯¹è±¡æ˜¯æŸ�ç§�具体的Java实现版本和执行引擎è¿�行模å¼�时,谈解释执行还是编译执行æ‰�会比较确切**。
Javaè¯è¨€ä¸ï¼Œjavac编译器完æˆ�了程åº�代ç �ç»�过è¯�法分æž�ã€�è¯æ³•分æž�åˆ°æŠ½è±¡è¯æ³•æ ‘ï¼Œå†�é��åŽ†è¯æ³•æ ‘ç”Ÿæˆ�线性的å—节ç �指令æµ�çš„è¿‡ç¨‹ï¼Œå› ä¸ºè¿™ä¸€éƒ¨åˆ†åŠ¨ä½œæ˜¯åœ¨Java虚拟机之外进行的,而解释器在虚拟机内部,所以Java程åº�的编译就是å�Šç‹¬ç«‹å®žçŽ°çš„ï¼Œ
### 4.2 åŸºäºŽæ ˆçš„æŒ‡ä»¤é›†å’ŒåŸºäºŽå¯„å˜å™¨çš„æŒ‡ä»¤é›†
-Java编译器输出的指令æµ�,基本上是一ç§�**åŸºäºŽæ ˆçš„æŒ‡ä»¤é›†æž¶æž„ï¼ˆInstruction Set Architecture,ISA)**,**ä¾�èµ–æ“�ä½œæ•°æ ˆè¿›è¡Œå·¥ä½œ**。与之相对应的å�¦ä¸€å¥—常用的指令集架构是**基于寄å˜å™¨çš„æŒ‡ä»¤é›†**, **ä¾�赖寄å˜å™¨è¿›è¡Œå·¥ä½œ**。
+Java编译器输出的指令æµ�,基本上是一ç§�**åŸºäºŽæ ˆçš„æŒ‡ä»¤é›†æž¶æž„ï¼ˆInstruction Set Architecture,ISA)**,**ä¾�èµ–æ“�ä½œæ•°æ ˆè¿›è¡Œå·¥ä½œ**。与之相对应的å�¦ä¸€å¥—常用的指令集架构是**基于寄å˜å™¨çš„æŒ‡ä»¤é›†**,**ä¾�赖寄å˜å™¨è¿›è¡Œå·¥ä½œ**。
那么,**åŸºäºŽæ ˆçš„æŒ‡ä»¤é›†å’ŒåŸºäºŽå¯„å˜å™¨çš„æŒ‡ä»¤é›†è¿™ä¸¤è€…有什么ä¸�å�Œå‘¢ï¼Ÿ**
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/Java8\346\226\260\347\211\271\346\200\247\347\273\210\346\236\201\346\214\207\345\215\227.md"
similarity index 81%
rename from "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"
rename to "docs/Java/basic/Java8\346\226\260\347\211\271\346\200\247\347\273\210\346\236\201\346\214\207\345\215\227.md"
index 14b4137..fa70648 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/Java8\346\226\260\347\211\271\346\200\247\347\273\210\346\236\201\346\214\207\345\215\227.md"
@@ -16,18 +16,7 @@
* [Java虚拟机(JVM)的新特性](#java虚拟机(jvm)的新特性)
* [总结](#总结)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [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 +37,7 @@ tags:
这是一个Java8新增特性的总结图。接下�让我们一次实践一下这些新特性�
-
-
+
## Javaè¯è¨€æ–°ç‰¹æ€§
### Lambda表达�
@@ -100,13 +88,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 +103,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 +190,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 +228,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 +280,7 @@ Lambda表达�和方法引用
有了函数å¼�接å�£ä¹‹å�Žï¼Œå°±å�¯ä»¥ä½¿ç”¨Lambda表达å¼�和方法引用了。其实函数å¼�接å�£çš„表ä¸çš„函数æ��述符就是Lambda表达å¼�,在函数å¼�接å�£ä¸Lambda表达å¼�相当于匿å��内部类的效果。 举个简å�•的例å�:
-
+````
public class TestLambda {
public static void execute(Runnable runnable) {
@@ -310,7 +300,7 @@ public class TestLambda {
execute(() -> System.out.println("run"));
}
}
-
+````
å�¯ä»¥çœ‹åˆ°ï¼Œç›¸æ¯”于使用匿å��内部类的方å¼�,Lambda表达å¼�å�¯ä»¥ä½¿ç”¨æ›´å°‘的代ç �但是有更清晰的表述。注æ„�,Lambda表达å¼�也ä¸�是完全ç‰ä»·äºŽåŒ¿å��内部类的, 两者的ä¸�å�Œç‚¹åœ¨äºŽthis的指å�‘和本地å�˜é‡�çš„å±�蔽上。
方法引用�以看作Lambda表达�的更简�的一�表达形�,使用::�作符,方法引用主�有三类:
@@ -351,31 +341,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 +375,7 @@ Java 8 使我们能够使用default 关键å—给接å�£å¢žåŠ é�žæŠ½è±¡çš„æ–¹æ³•
å¦‚æžœæ— æ³•ä¾�æ�®ç¬¬ä¸€æ�¡è§„则进行判æ–,那么å�接å�£çš„优先级更高:函数ç¾å��相å�Œæ—¶ï¼Œä¼˜å…ˆé€‰æ‹©æ‹¥æœ‰æœ€å…·ä½“实现的默认方法的接å�£ã€‚å�³å¦‚æžœB继承了A,那么B就比A更具体。
最å�Žï¼Œå¦‚æžœè¿˜æ˜¯æ— æ³•åˆ¤æ–,继承了多个接å�£çš„类必须通过显å¼�覆盖和调用期望的方法,显å¼�地选择使用哪一个默认方法的实现。那么如何显å¼�地指定呢:
-
+````
public class C implements B, A {
public void hello() {
@@ -393,43 +383,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 +430,7 @@ Java 8带�的�一个有趣的特性是接��以声明(并且�以�
defaulable = DefaulableFactory.create( OverridableImpl::new );
System.out.println( defaulable.notRequired() );
}
+````
这个程�的控制�输出如下:
Default implementation
@@ -450,58 +444,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 +508,7 @@ public class ParameterNames {
}
}
}
+````
如果�使用–parameters�数�编译这个类,然��行这个类,会得到下�的输出:
Parameter: arg0
@@ -531,7 +525,7 @@ Java 8 é€šè¿‡å¢žåŠ å¤§é‡�新类,扩展已有类的功能的方å¼�æ�¥æ”¹å–„对
Optional实际上是个容器:它å�¯ä»¥ä¿�å˜ç±»åž‹T的值,或者仅仅ä¿�å˜null。Optionalæ��ä¾›å¾ˆå¤šæœ‰ç”¨çš„æ–¹æ³•ï¼Œè¿™æ ·æˆ‘ä»¬å°±ä¸�用显å¼�进行空值检测。更多详情请å�‚考官方文档。
我们下é�¢ç”¨ä¸¤ä¸ªå°�例å�æ�¥æ¼”示如何使用Optional类:一个å…�许为空值,一个ä¸�å…�许为空值。
-
+````
public class 空指针Optional {
public static void main(String[] args) {
@@ -554,7 +548,7 @@ Optional实际上是个容器:它å�¯ä»¥ä¿�å˜ç±»åž‹T的值,或者仅仅ä¿�
//输出Optional.empty。
}
}
-
+````
如果Optional类的实例为é�žç©ºå€¼çš„è¯�,isPresent()返回true,å�¦ä»Žè¿”回false。为了防æ¢Optional为空值,orElseGet()方法通过回调函数æ�¥äº§ç”Ÿä¸€ä¸ªé»˜è®¤å€¼ã€‚map()函数对当å‰�Optional的值进行转化,然å�Žè¿”回一个新的Optional实例。orElse()方法和orElseGet()方法类似,但是orElse接å�—一个默认值而ä¸�是一个回调函数。下é�¢æ˜¯è¿™ä¸ªç¨‹åº�的输出:
Full Name is set? false
@@ -581,14 +575,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 +592,10 @@ Task类有一个分数的概念(或者说是伪��度),其次是还有
.sum();
System.out.println( "Total points: " + totalPointsOfOpenTasks );
+````
程�在控制�上的输出如下:
-Total points: 18
+ Total points: 18
è¿™é‡Œæœ‰å‡ ä¸ªæ³¨æ„�事项。
@@ -617,7 +613,7 @@ Total points: 18
streamå�¦ä¸€ä¸ªæœ‰ä»·å€¼çš„地方是能够原生支æŒ�并行处ç�†ã€‚让我们æ�¥çœ‹çœ‹è¿™ä¸ªç®—task分数和的例å�。
streamå�¦ä¸€ä¸ªæœ‰ä»·å€¼çš„地方是能够原生支æŒ�并行处ç�†ã€‚让我们æ�¥çœ‹çœ‹è¿™ä¸ªç®—task分数和的例å�。
-
+````
// Calculate total points of all tasks
final double totalPoints = tasks
.stream()
@@ -626,23 +622,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 +656,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 +679,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 +705,7 @@ Java 8通过å�‘布新的Date-Time API (JSR 310)æ�¥è¿›ä¸€æ¥åŠ å¼ºå¯¹æ—¥æœŸä¸Žæ—¶
System.out.println( time );
System.out.println( timeFromClock );
-
+````
下�是程�在控制�上的输出:
2014-04-12
@@ -715,7 +720,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 +728,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 +738,7 @@ Duration in hours: 8783
### 并行(parallel)数组
Java 8å¢žåŠ äº†å¤§é‡�的新方法æ�¥å¯¹æ•°ç»„进行并行处ç�†ã€‚å�¯ä»¥è¯´ï¼Œæœ€é‡�è¦�的是parallelSort()æ–¹æ³•ï¼Œå› ä¸ºå®ƒå�¯ä»¥åœ¨å¤šæ ¸æœºå™¨ä¸Šæž�大æ��高数组排åº�的速度。下é�¢çš„例å�展示了新方法(parallelXxx)的使用。
-
+````
package com.javacodegeeks.java8.parallel.arrays;
import java.util.Arrays;
@@ -755,7 +760,7 @@ Java 8å¢žåŠ äº†å¤§é‡�的新方法æ�¥å¯¹æ•°ç»„进行并行处ç�†ã€‚å�¯ä»¥è¯´ï¼Œ
System.out.println();
}
}
-
+````
上é�¢çš„代ç �片段使用了parallelSetAll()方法æ�¥å¯¹ä¸€ä¸ªæœ‰20000ä¸ªå…ƒç´ çš„æ•°ç»„è¿›è¡Œéš�机赋值。然å�Žï¼Œè°ƒç”¨parallelSort方法。这个程åº�首先打å�°å‡ºå‰�10ä¸ªå…ƒç´ çš„å€¼ï¼Œä¹‹å�Žå¯¹æ•´ä¸ªæ•°ç»„排åº�。这个程åº�在控制å�°ä¸Šçš„输出如下(请注æ„�æ•°ç»„å…ƒç´ æ˜¯éš�机生产的):
Unsorted: 591217 891976 443951 424479 766825 351964 242997 642839 119108 552378
@@ -766,7 +771,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 +780,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 +797,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所代替。
@@ -824,20 +832,3 @@ https://www.jianshu.com/p/4df02599aeb2
https://www.cnblogs.com/yangzhilong/p/10973006.html
https://www.cnblogs.com/JackpotHan/p/9701147.html
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
diff --git "a/docs/java/basic/16\343\200\201JavaIO\346\265\201.md" "b/docs/Java/basic/JavaIO\346\265\201.md"
similarity index 88%
rename from "docs/java/basic/16\343\200\201JavaIO\346\265\201.md"
rename to "docs/Java/basic/JavaIO\346\265\201.md"
index a405b7f..9d1ecd1 100644
--- "a/docs/java/basic/16\343\200\201JavaIO\346\265\201.md"
+++ "b/docs/Java/basic/JavaIO\346\265\201.md"
@@ -21,18 +21,7 @@
* [说说File类](#说说file类)
* [说说RandomAccessFile?](#说说randomaccessfile)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [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 +49,6 @@ tags:
> 在这一å°�节,我会试ç�€ç»™å‡ºJava IO(java.io)åŒ…ä¸‹æ‰€æœ‰ç±»çš„æ¦‚è¿°ã€‚æ›´å…·ä½“åœ°è¯´ï¼Œæˆ‘ä¼šæ ¹æ�®ç±»çš„ç”¨é€”å¯¹ç±»è¿›è¡Œåˆ†ç»„ã€‚è¿™ä¸ªåˆ†ç»„å°†ä¼šä½¿ä½ åœ¨æœªæ�¥çš„工作ä¸ï¼Œè¿›è¡Œç±»çš„用途判定时,或者是为æŸ�个特定用途选择类时å�˜å¾—æ›´åŠ å®¹æ˜“ã€‚
-​
**输入和输出**
术è¯â€œè¾“å…¥â€�和“输出â€�有时候会有一点让人疑惑。一个应用程åº�的输入往往是å�¦å¤–一个应用程åº�的输出
@@ -174,7 +162,7 @@ java.io.InputStream类是所有Java IO输入æµ�çš„åŸºç±»ã€‚å¦‚æžœä½ æ£åœ¨å¼€å�‘
这使得RandomAccessFileå�¯ä»¥è¦†ç›–一个文件的æŸ�些部分ã€�æˆ–è€…è¿½åŠ å†…å®¹åˆ°å®ƒçš„æœ«å°¾ã€�æˆ–è€…åˆ é™¤å®ƒçš„æŸ�些内容,当然它也å�¯ä»¥ä»Žæ–‡ä»¶çš„任何ä½�置开始读å�–文件。
下é�¢æ˜¯å…·ä½“例å�:
-
+````
@Test
//文件æµ�范例,打开一个文件的输入æµ�,读å�–到å—节数组,å†�写入å�¦ä¸€ä¸ªæ–‡ä»¶çš„输出æµ�
public void test1() {
@@ -193,6 +181,7 @@ java.io.InputStream类是所有Java IO输入æµ�çš„åŸºç±»ã€‚å¦‚æžœä½ æ£åœ¨å¼€å�‘
e.printStackTrace();
}
}
+````
### å—符æµ�å’Œå—节æµ�
Java IOçš„Readerå’ŒWriter除了基于å—符之外,其他方é�¢éƒ½ä¸ŽInputStreamå’ŒOutputStreamé�žå¸¸ç±»ä¼¼ã€‚他们被用于读写文本。InputStreamå’ŒOutputStream是基于å—节的,还记得å�—?
@@ -204,46 +193,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 +248,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 +295,7 @@ Javaä¸ç½‘络的内容或多或少的超出了Java IO的范畴。关于Java网
当两个进程之间建立了网络连接之å�Žï¼Œä»–们通信的方å¼�如å�Œæ“�ä½œæ–‡ä»¶ä¸€æ ·ï¼šåˆ©ç”¨InputStream读å�–æ•°æ�®ï¼Œåˆ©ç”¨OutputStream写入数æ�®ã€‚æ�¢å�¥è¯�æ�¥è¯´ï¼ŒJava网络API用æ�¥åœ¨ä¸�å�Œè¿›ç¨‹ä¹‹é—´å»ºç«‹ç½‘络连接,而Java IO则用æ�¥åœ¨å»ºç«‹äº†è¿žæŽ¥ä¹‹å�Žçš„进程之间交æ�¢æ•°æ�®ã€‚
基本上æ„�味ç�€å¦‚æžœä½ æœ‰ä¸€ä»½èƒ½å¤Ÿå¯¹æ–‡ä»¶è¿›è¡Œå†™å…¥æŸ�些数æ�®çš„代ç �,那么这些数æ�®ä¹Ÿå�¯ä»¥å¾ˆå®¹æ˜“地写入到网络连接ä¸åŽ»ã€‚ä½ æ‰€éœ€è¦�å�šçš„ä»…ä»…å�ªæ˜¯åœ¨ä»£ç �ä¸åˆ©ç”¨OutputStream替代FileOutputStream进行数æ�®çš„å†™å…¥ã€‚å› ä¸ºFileOutputStream是OuputStreamçš„å�类,所以这么å�šå¹¶æ²¡æœ‰ä»€ä¹ˆé—®é¢˜ã€‚
-
+````
//从网络ä¸è¯»å�–å—节æµ�也å�¯ä»¥ç›´æŽ¥ä½¿ç”¨OutputStream
public void test3() {
//读�网络进程的输出�
@@ -318,7 +309,7 @@ Javaä¸ç½‘络的内容或多或少的超出了Java IO的范畴。关于Java网
//处�网络信�
//do something with the OutputStream
}
-
+````
### å—节和å—符数组
@@ -330,7 +321,7 @@ Javaä¸ç½‘络的内容或多或少的超出了Java IO的范畴。关于Java网
å‰�é�¢çš„例å�ä¸ï¼Œå—符数组或å—节数组是用æ�¥ç¼“å˜æ•°æ�®çš„临时å˜å‚¨ç©ºé—´ï¼Œä¸�过它们å�Œæ—¶ä¹Ÿå�¯ä»¥ä½œä¸ºæ•°æ�®æ�¥æº�或者写入目的地。
举个例å�:
-
+````
//å—符数组和å—节数组在io过程ä¸çš„作用
public void test4() {
//arr和brr分别作为数��
@@ -339,7 +330,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 +349,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 +361,7 @@ System.outå’ŒSystem.err的简å�•例å�:
// 10
// out
}
-
+````
### å—符æµ�çš„Bufferedå’ŒFilter
@@ -437,8 +428,6 @@ Filter Stream是一ç§�IOæµ�主è¦�作用是用æ�¥å¯¹å˜åœ¨çš„æµ�å¢žåŠ ä¸€äº›é¢�
在java.io包ä¸ä¸»è¦�ç”±4个å�¯ç”¨çš„filter Stream。两个å—节filter stream,两个å—符filter stream. 分别是FilterInputStream, FilterOutputStream, FilterReader and FilterWriter.这些类是抽象类,ä¸�能被实例化的。
-
-
### 在文件拷�的时候,那一���用��更多的性能?
在å—节æµ�的时候,使用BufferedInputStreamå’ŒBufferedOutputStream。
在å—符æµ�的时候,使用BufferedReader å’Œ BufferedWriter
@@ -459,20 +448,3 @@ https://www.cnblogs.com/UncleWang001/articles/10454685.html
https://www.cnblogs.com/Jixiangwei/p/Java.html
https://blog.csdn.net/baidu_37107022/article/details/76890019
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
diff --git "a/docs/java/basic/9\343\200\201Java\344\270\255\347\232\204Class\347\261\273\345\222\214Object\347\261\273.md" "b/docs/Java/basic/Java\344\270\255\347\232\204Class\347\261\273\345\222\214Object\347\261\273.md"
similarity index 91%
rename from "docs/java/basic/9\343\200\201Java\344\270\255\347\232\204Class\347\261\273\345\222\214Object\347\261\273.md"
rename to "docs/Java/basic/Java\344\270\255\347\232\204Class\347\261\273\345\222\214Object\347\261\273.md"
index 4caf35a..7ff3baa 100644
--- "a/docs/java/basic/9\343\200\201Java\344\270\255\347\232\204Class\347\261\273\345\222\214Object\347\261\273.md"
+++ "b/docs/Java/basic/Java\344\270\255\347\232\204Class\347\261\273\345\222\214Object\347\261\273.md"
@@ -1,4 +1,4 @@
-# Table of Contents
+# 目录
* [Javaä¸Classç±»å�Šç”¨æ³•](#javaä¸classç±»å�Šç”¨æ³•)
* [Class类原�](#class类原�)
@@ -16,9 +16,7 @@
* [finalize()方法](#finalize方法)
* [CLass类和Object类的关系](#class类和object类的关系)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
> https://github.com/h2pl/Java-Tutorial
@@ -48,25 +46,25 @@ Java程�在�行时,Java�行时系统一直对所有的对象进行所谓
> Classç±»çš„å¯¹è±¡å†…å®¹æ˜¯ä½ åˆ›å»ºçš„ç±»çš„ç±»åž‹ä¿¡æ�¯ï¼Œæ¯”å¦‚ä½ åˆ›å»ºä¸€ä¸ªshapes类,那么,Java会生æˆ�一个内容是shapesçš„Class类的对象
> Class类的对象ä¸�能åƒ�æ™®é€šç±»ä¸€æ ·ï¼Œä»¥ new shapes() 的方å¼�创建,它的对象å�ªèƒ½ç”±JVMåˆ›å»ºï¼Œå› ä¸ºè¿™ä¸ªç±»æ²¡æœ‰publicæž„é€ å‡½æ•°
-
- /*
- * Private constructor. Only the Java Virtual Machine creates Class objects.
- * This constructor is not used and prevents the default constructor being
- * generated.
- */
- //ç§�æœ‰æž„é€ æ–¹æ³•ï¼Œå�ªèƒ½ç”±jvm进行实例化
- private Class(ClassLoader loader) {
- // Initialize final field for classLoader. The initialization value of non-null
- // prevents future JIT optimizations from assuming this final field is null.
- classLoader = loader;
- }
-
+````
+/*
+ * Private constructor. Only the Java Virtual Machine creates Class objects.
+ * This constructor is not used and prevents the default constructor being
+ * generated.
+ */
+ //ç§�æœ‰æž„é€ æ–¹æ³•ï¼Œå�ªèƒ½ç”±jvm进行实例化
+private Class(ClassLoader loader) {
+ // Initialize final field for classLoader. The initialization value of non-null
+ // prevents future JIT optimizations from assuming this final field is null.
+ classLoader = loader;
+}
+````
> Class类的作用是è¿�行时æ��供或获得æŸ�个对象的类型信æ�¯ï¼Œå’ŒC++ä¸çš„typeid()函数类似。这些信æ�¯ä¹Ÿå�¯ç”¨äºŽå��射。
### Class类原�
看一下Class类的部分æº�ç �
-
+````
//Classç±»ä¸å°�装了类型的å�„ç§�ä¿¡æ�¯ã€‚在jvmä¸å°±æ˜¯é€šè¿‡Class类的实例æ�¥èŽ·å�–æ¯�个Java类的所有信æ�¯çš„。
public class Classç±» {
@@ -161,6 +159,7 @@ Java程�在�行时,Java�行时系统一直对所有的对象进行所谓
// }
// }
}
+````
> 我们都知é�“所有的java类都是继承了object这个类,在objectè¿™ä¸ªç±»ä¸æœ‰ä¸€ä¸ªæ–¹æ³•:getclass().这个方法是用æ�¥å�–得该类已ç»�被实例化了的对象的该类的引用,这个引用指å�‘的是Class类的对象。
>
@@ -172,11 +171,7 @@ Java程�在�行时,Java�行时系统一直对所有的对象进行所谓
{
return defineClass(name, b, off, len, null);
}
->
-> 我们生æˆ�çš„å¯¹è±¡éƒ½ä¼šæœ‰ä¸ªå—æ®µè®°å½•该对象所属类在CLass类的对象的所在ä½�置。如下图所示:
-
-[外链图片转å˜å¤±è´¥(img-ZfMJTzO4-1569074134147)(http://dl.iteye.com/upload/picture/pic/101542/0047a6e9-6608-3c3c-a67c-d8ee95e7fcb8.jpg)]
-
+>
### 如何获得一个Class类对象
@@ -204,7 +199,7 @@ Java程�在�行时,Java�行时系统一直对所有的对象进行所谓
> 生��精确的object实例
>
-==获å�–一个Class类的对象å�Žï¼Œå�¯ä»¥ç”¨ newInstance() 函数æ�¥ç”Ÿæˆ�ç›®æ ‡ç±»çš„ä¸€ä¸ªå®žä¾‹ã€‚ç„¶è€Œï¼Œè¯¥å‡½æ•°å¹¶ä¸�能直接生æˆ�ç›®æ ‡ç±»çš„å®žä¾‹ï¼Œå�ªèƒ½ç”Ÿæˆ�object类的实例==
+获å�–一个Class类的对象å�Žï¼Œå�¯ä»¥ç”¨ newInstance() 函数æ�¥ç”Ÿæˆ�ç›®æ ‡ç±»çš„ä¸€ä¸ªå®žä¾‹ã€‚ç„¶è€Œï¼Œè¯¥å‡½æ•°å¹¶ä¸�能直接生æˆ�ç›®æ ‡ç±»çš„å®žä¾‹ï¼Œå�ªèƒ½ç”Ÿæˆ�object类的实例
> Class obj=Class.forName("shapes");
> Object ShapesInstance=obj.newInstance();
@@ -214,7 +209,7 @@ Java程�在�行时,Java�行时系统一直对所有的对象进行所谓
> Class obj=shapes.class;
> shapes newShape=obj.newInstance();
> å› ä¸ºæœ‰äº†ç±»åž‹é™�制,所以使用泛化Classè¯æ³•的对象引用ä¸�能指å�‘别的类。
-
+
Class obj1=int.class;
Class obj2=int.class;
obj1=double.class;
@@ -236,11 +231,12 @@ Java程�在�行时,Java�行时系统一直对所有的对象进行所谓
Class rclass=round.class;
Class super round> sclass= rclass.getSuperClass();
//Class sclass=rclass.getSuperClass();
+
我们明知é�“,round的基类就是shapes,但是å�´ä¸�能直接声明 Class < shapes >ï¼Œå¿…é¡»ä½¿ç”¨ç‰¹æ®Šè¯æ³•
Class < ? super round >
-
-这个记�就�以啦。
+
+ 这个记�就�以啦。
## Objectç±»
@@ -288,7 +284,9 @@ Objectç±»ä½�于java.lang包ä¸ï¼Œjava.lang包包å�«ç�€Javaæœ€åŸºç¡€å’Œæ ¸å¿ƒçš„
### registerNatives()方法;
+````
private static native void registerNatives();
+````
> registerNatives函数å‰�é�¢æœ‰native关键å—修饰,Javaä¸ï¼Œç”¨native关键å—修饰的函数表明该方法的实现并ä¸�是在Javaä¸åŽ»å®Œæˆ�,而是由C/C++去完æˆ�,并被编译æˆ�了.dll,由Java去调用。
>
@@ -298,19 +296,16 @@ private static native void registerNatives();
>
> 既然如æ¤ï¼Œå�¯èƒ½æœ‰äººä¼šé—®ï¼ŒregisterNatives()修饰符为private,且并没有执行,作用何以达到?其实,在Javaæº�ç �ä¸ï¼Œæ¤æ–¹æ³•的声明å�Žæœ‰ç´§æŽ¥ç�€ä¸€æ®µé�™æ€�代ç �å�—:
-
- private static native void registerNatives();
- static {
- registerNatives();
- }
-
+````
+private static native void registerNatives();
+static {
+ registerNatives();
+}
+````
### Clone()方法实现浅拷�
-
- protected native Object clone() throwsCloneNotSupportedException;
-
-
-
-
+````
+protected native Object clone() throwsCloneNotSupportedException;
+````
> 看,clode()方法å�ˆæ˜¯ä¸€ä¸ªè¢«å£°æ˜Žä¸ºnativeçš„æ–¹æ³•ï¼Œå› æ¤ï¼Œæˆ‘们知é�“了clone()方法并ä¸�是Java的原生方法,具体的实现是有C/C++完æˆ�的。clone英文翻译为"克隆",其目的是创建并返回æ¤å¯¹è±¡çš„一个副本。
> 形象点ç�†è§£ï¼Œè¿™æœ‰ä¸€è¾†ç§‘é²�å…¹ï¼Œä½ çœ‹ç�€ä¸�错,想è¦�ä¸ªä¸€æ¨¡ä¸€æ ·çš„ã€‚ä½ è°ƒç”¨æ¤æ–¹æ³•å�³å�¯åƒ�å�˜é”æœ¯ä¸€æ ·å�˜å‡ºä¸€è¾†ä¸€æ¨¡ä¸€æ ·çš„ç§‘é²�兹出æ�¥ã€‚é…�ç½®ä¸€æ ·ï¼Œé•¿ç›¸ä¸€æ ·ã€‚ä½†ä»Žæ¤åˆ»èµ·ï¼ŒåŽŸæ�¥çš„那辆科é²�å…¹å¦‚æžœè¿›è¡Œäº†æ–°çš„è£…é¥°ï¼Œä¸Žä½ å…‹éš†å‡ºæ�¥çš„这辆科é²�兹没有任何关系了。
@@ -321,7 +316,7 @@ private static native void registerNatives();
首先看一下下é�¢çš„这个例å�:
-
+````
package com.corn.objectsummary;
import com.corn.Person;
@@ -336,9 +331,7 @@ private static native void registerNatives();
}
}
-
-
-
+````
> 例å�很简å�•,在main()方法ä¸ï¼Œnew一个Oject对象å�Žï¼Œæƒ³ç›´æŽ¥è°ƒç”¨æ¤å¯¹è±¡çš„clone方法克隆一个对象,但是出现错误æ��示:"The method clone() from the type Object is not visible"
>
@@ -350,25 +343,23 @@ private static native void registerNatives();
于是,上例改æˆ�如下形å¼�,我们å�‘现,å�¯ä»¥æ£å¸¸ç¼–译:
-
- public class clone方法 {
- public static void main(String[] args) {
+````
+public class clone方法 {
+ public static void main(String[] args) {
- }
- public void test1() {
+ }
+ public void test1() {
- User user = new User();
- // User copy = user.clone();
- }
- public void test2() {
- User user = new User();
- // User copy = (User)user.clone();
- }
+ User user = new User();
+ //User copy = user.clone();
}
+ public void test2() {
+ User user = new User();
+ //User copy = (User)user.clone();
+ }
+}
-
-
-
+````
æ˜¯çš„ï¼Œå› ä¸ºæ¤æ—¶çš„主调已ç»�是å�类的引用了。
> 上述代ç �在è¿�行过程ä¸ä¼šæŠ›å‡º"java.lang.CloneNotSupportedException",表明clone()方法并未æ£ç¡®æ‰§è¡Œå®Œæ¯•ï¼Œé—®é¢˜çš„åŽŸå› åœ¨ä¸ŽJavaä¸çš„è¯æ³•规定:
@@ -378,9 +369,8 @@ private static native void registerNatives();
> Cloneable接å�£ä»…是一个表示接å�£ï¼ŒæŽ¥å�£æœ¬èº«ä¸�包å�«ä»»ä½•方法,用æ�¥æŒ‡ç¤ºObject.clone()å�¯ä»¥å�ˆæ³•的被å�类引用所调用。
>
> 于是,上述代ç �改æˆ�如下形å¼�,å�³å�¯æ£ç¡®æŒ‡å®šclone()方法以实现克隆。
-
-
- public class User implements Cloneable{
+````
+public class User implements Cloneable{
public int id;
public String name;
public UserInfo userInfo;
@@ -407,11 +397,12 @@ private static native void registerNatives();
// com.javase.Class和Object.Object方法.用到的类.User@6ff3c5b5
// com.javase.Class和Object.Object方法.用到的类.UserInfo@d716361
}
+````
总结:
clone方法实现的是浅拷è´�,å�ªæ‹·è´�当å‰�å¯¹è±¡ï¼Œå¹¶ä¸”åœ¨å †ä¸åˆ†é…�新的空间,放这个å¤�制的对象。但是对象如果里é�¢æœ‰å…¶ä»–类的å�对象,那么就ä¸�会拷è´�到新的对象ä¸ã€‚
-==深拷�和浅拷�的区别==
+深拷�和浅拷�的区别
> æµ…æ‹·è´�
> æµ…æ‹·è´�是按ä½�æ‹·è´�对象,它会创建一个新对象,这个对象有ç�€åŽŸå§‹å¯¹è±¡å±žæ€§å€¼çš„ä¸€ä»½ç²¾ç¡®æ‹·è´�。如果属性是基本类型,拷è´�的就是基本类型的值;如果属性是内å˜åœ°å�€ï¼ˆå¼•用类型),拷è´�的就是内å˜åœ°å�€ ï¼Œå› æ¤å¦‚果其ä¸ä¸€ä¸ªå¯¹è±¡æ”¹å�˜äº†è¿™ä¸ªåœ°å�€ï¼Œå°±ä¼šå½±å“�到å�¦ä¸€ä¸ªå¯¹è±¡ã€‚
@@ -430,12 +421,13 @@ clone方法实现的是浅拷è´�,å�ªæ‹·è´�当å‰�å¯¹è±¡ï¼Œå¹¶ä¸”åœ¨å †ä¸åˆ†é…�
>
> 填充完æˆ�之å�Žï¼Œclone方法返回,一个新的相å�Œçš„对象被创建,å�Œæ ·å�¯ä»¥æŠŠè¿™ä¸ªæ–°å¯¹è±¡çš„引用å�‘布到外部。
-==也就是说,一个对象在浅拷è´�以å�Žï¼Œå�ªæ˜¯æŠŠå¯¹è±¡å¤�åˆ¶äº†ä¸€ä»½æ”¾åœ¨å †ç©ºé—´çš„å�¦ä¸€ä¸ªåœ°æ–¹ï¼Œä½†æ˜¯æˆ�员å�˜é‡�如果有引用指å�‘其他对象,这个引用指å�‘的对象和被拷è´�的对象ä¸å¼•用指å�‘çš„å¯¹è±¡æ˜¯ä¸€æ ·çš„ã€‚å½“ç„¶ï¼ŒåŸºæœ¬æ•°æ�®ç±»åž‹è¿˜æ˜¯ä¼šé‡�æ–°æ‹·è´�一份的。==
-
+也就是说,一个对象在浅拷è´�以å�Žï¼Œå�ªæ˜¯æŠŠå¯¹è±¡å¤�åˆ¶äº†ä¸€ä»½æ”¾åœ¨å †ç©ºé—´çš„å�¦ä¸€ä¸ªåœ°æ–¹ï¼Œä½†æ˜¯æˆ�员å�˜é‡�如果有引用指å�‘其他对象,这个引用指å�‘的对象和被拷è´�的对象ä¸å¼•用指å�‘çš„å¯¹è±¡æ˜¯ä¸€æ ·çš„ã€‚å½“ç„¶ï¼ŒåŸºæœ¬æ•°æ�®ç±»åž‹è¿˜æ˜¯ä¼šé‡�æ–°æ‹·è´�一份的。
### getClass()方法
+````
+public final native Class> getClass();
-4.public final native Class> getClass();
+````
> getClass()也是一个native方法,返回的是æ¤Object对象的类对象/è¿�行时类对象Class>。效果与Object.class相å�Œã€‚
>
@@ -443,8 +435,8 @@ clone方法实现的是浅拷è´�,å�ªæ‹·è´�当å‰�å¯¹è±¡ï¼Œå¹¶ä¸”åœ¨å †ä¸åˆ†é…�
>
> 作为概念层次的类,其本身也具有æŸ�些共å�Œçš„特性,如都具有类å��ç§°ã€�ç”±ç±»åŠ è½½å™¨åŽ»åŠ è½½ï¼Œéƒ½å…·æœ‰åŒ…ï¼Œå…·æœ‰çˆ¶ç±»ï¼Œå±žæ€§å’Œæ–¹æ³•ç‰ã€‚
>
-> 于是,Java䏿œ‰ä¸“门定义了一个类,Class,去æ��è¿°å…¶ä»–ç±»æ‰€å…·æœ‰çš„è¿™äº›ç‰¹æ€§ï¼Œå› æ¤ï¼Œä»Žæ¤è§’度去看,类本身也都是属于Class类的对象。为与ç»�常æ„�义上的对象相区分,在æ¤ç§°ä¹‹ä¸º"类对象"。
-
+> 于是,Javaä¸å®šä¹‰äº†ä¸€ä¸ªç±»ï¼ŒClass,去æ��è¿°å…¶ä»–ç±»æ‰€å…·æœ‰çš„è¿™äº›ç‰¹æ€§ï¼Œå› æ¤ï¼Œä»Žæ¤è§’度去看,类本身也都是属于Class类的对象。为与ç»�常æ„�义上的对象相区分,在æ¤ç§°ä¹‹ä¸º"类对象"。
+````
public class getClass方法 {
public static void main(String[] args) {
User user = new User();
@@ -470,6 +462,7 @@ clone方法实现的是浅拷è´�,å�ªæ‹·è´�当å‰�å¯¹è±¡ï¼Œå¹¶ä¸”åœ¨å †ä¸åˆ†é…�
}
}
}
+````
æ¤å¤„主è¦�大é‡�涉å�Šåˆ°Javaä¸çš„å��射知识
@@ -490,9 +483,6 @@ clone方法实现的是浅拷è´�,å�ªæ‹·è´�当å‰�å¯¹è±¡ï¼Œå¹¶ä¸”åœ¨å †ä¸åˆ†é…�
return (this == obj);
}
-
-
-
> ç”±æ¤å�¯è§�,Object原生的equals()æ–¹æ³•å†…éƒ¨è°ƒç”¨çš„æ£æ˜¯==,与==具有相å�Œçš„å�«ä¹‰ã€‚既然如æ¤ï¼Œä¸ºä»€ä¹ˆè¿˜è¦�定义æ¤equals()方法?
>
> equals()方法的æ£ç¡®ç�†è§£åº”该是:判æ–两个对象是å�¦ç›¸ç‰ã€‚那么判æ–对象相ç‰çš„æ ‡å°ºå�ˆæ˜¯ä»€ä¹ˆï¼Ÿ
@@ -506,10 +496,10 @@ ObjectTest䏿‰“å�°å‡ºtrueï¼Œå› ä¸ºUser类定义ä¸é‡�写了equals()方法,这
> 如上é‡�写equals方法表é�¢ä¸Šçœ‹ä¸ŠåŽ»æ˜¯å�¯ä»¥äº†ï¼Œå®žåˆ™ä¸�ç„¶ã€‚å› ä¸ºå®ƒç ´å��了Javaä¸çš„约定:é‡�写equals()方法必须é‡�写hasCode()方法。
-
### hashCode()方法;
-
-6. public native int hashCode()
+````
+public native int hashCode()
+````
hashCode()方法返回一个整形数值,表示该对象的哈希ç �值。
@@ -549,16 +539,16 @@ hashCode()具有如下约定:
### toString()方法
-7.public String toString();
+````
+public String toString();
toString()方法返回该对象的å—符串表示。先看一下Objectä¸çš„具体方法体:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
-
-
-
+
+````
> toString()方法相信大家都�常用到,�使没有显�调用,但当我们使用System.out.println(obj)时,其内部也是通过toString()�实现的。
>
@@ -570,7 +560,7 @@ hashCode()具有如下约定:
### wait() notify() notifAll()
-8/9/10/11/12. wait(...) / notify() / notifyAll()
+
>
> 一说到wait(...) / notify() | notifyAll()å‡ ä¸ªæ–¹æ³•ï¼Œé¦–å…ˆæƒ³åˆ°çš„æ˜¯çº¿ç¨‹ã€‚ç¡®å®žï¼Œè¿™å‡ ä¸ªæ–¹æ³•ä¸»è¦�用于java多线程之间的å��ä½œã€‚å…ˆå…·ä½“çœ‹ä¸‹è¿™å‡ ä¸ªæ–¹æ³•çš„ä¸»è¦�å�«ä¹‰ï¼š
>
@@ -583,8 +573,7 @@ hashCode()具有如下约定:
> wait(...) / notify() | notifyAll()一般情况下都是é…�套使用。下é�¢æ�¥çœ‹ä¸€ä¸ªç®€å�•的例å�:
这是一个生产者消费者的模型,å�ªä¸�过这里å�ªç”¨flagæ�¥æ ‡è¯†å“ªä¸ªçº¿ç¨‹éœ€è¦�工作
-
-
+````
public class waitå’Œnotify {
//volatile��线程��性
volatile static int flag = 1;
@@ -652,6 +641,7 @@ hashCode()具有如下约定:
// notify t2
//ä¸�æ–循环
}
+````
> 从上述例å�的输出结果ä¸å�¯ä»¥å¾—出如下结论:
>
@@ -661,13 +651,11 @@ hashCode()具有如下约定:
在Javaæº�ç �ä¸ï¼Œå�¯ä»¥çœ‹åˆ°wait()具体定义如下:
-
- public final void wait() throws InterruptedException {
- wait(0);
- }
-
-
-
+````
+public final void wait() throws InterruptedException {
+ wait(0);
+}
+````
> 且wait(long timeout, int nanos)方法定义内部实质上也是通过调用wait(long timeout)完æˆ�。而wait(long timeout)是一个nativeæ–¹æ³•ã€‚å› æ¤ï¼Œwait(...)方法本质上都是nativeæ–¹å¼�实现。
@@ -676,15 +664,11 @@ notify()/notifyAll()方法也都是native方法。
Javaä¸çº¿ç¨‹å…·æœ‰è¾ƒå¤šçš„知识点,是一å�—比较大且é‡�è¦�的知识点。å�ŽæœŸä¼šæœ‰å�šæ–‡ä¸“é—¨é’ˆå¯¹Java多线程作出详细总结。æ¤å¤„ä¸�å†�细述。
### finalize()方法
-13. protected void finalize();
-
finalize方法主è¦�与Java垃圾回收机制有关。首先我们看一下finalized方法在Objectä¸çš„具体定义:
-
- protected void finalize() throws Throwable { }
-
-
-
+````
+protected void finalize() throws Throwable { }
+````
> 我们å�‘现Objectç±»ä¸finalize方法被定义æˆ�一个空方法,为什么è¦�如æ¤å®šä¹‰å‘¢ï¼Ÿfinalizeæ–¹æ³•çš„è°ƒç”¨æ—¶æœºæ˜¯æ€Žä¹ˆæ ·çš„å‘¢ï¼Ÿ
>
@@ -727,21 +711,11 @@ https://blog.csdn.net/dufufd/article/details/80537638
https://blog.csdn.net/farsight1/article/details/80664104
https://blog.csdn.net/xiaomingdetianxia/article/details/77429180
-## 微信公众�
-
### Java技术江湖
如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
+
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/Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md"
similarity index 84%
rename from "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"
rename to "docs/Java/basic/Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md"
index 655b4c2..b871b14 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/Java\345\237\272\346\234\254\346\225\260\346\215\256\347\261\273\345\236\213.md"
@@ -15,9 +15,7 @@
* [å˜åœ¨æ ˆä¸](#å˜åœ¨æ ˆä¸)
* [å˜åœ¨å †é‡Œ](#å˜åœ¨å †é‡Œ)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
@@ -34,9 +32,6 @@
å¦‚æžœå¯¹æœ¬ç³»åˆ—æ–‡ç« æœ‰ä»€ä¹ˆå»ºè®®ï¼Œæˆ–è€…æ˜¯æœ‰ä»€ä¹ˆç–‘é—®çš„è¯�,也å�¯ä»¥å…³æ³¨å…¬ä¼—å�·ã€�Java技术江湖】è�”ç³»ä½œè€…ï¼Œæ¬¢è¿Žä½ å�‚与本系列å�šæ–‡çš„åˆ›ä½œå’Œä¿®è®¢ã€‚
-
-
-
# Java 基本数�类型
@@ -53,7 +48,6 @@
- 内置数�类型
- 引用数�类型
-- - *
### 内置数�类型
@@ -128,50 +122,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 +152,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 +181,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 +226,7 @@ Java 5å¢žåŠ äº†è‡ªåŠ¨è£…ç®±ä¸Žè‡ªåŠ¨æ‹†ç®±æœºåˆ¶ï¼Œæ–¹ä¾¿åŸºæœ¬ç±»åž‹ä¸ŽåŒ…è£…
Integeræº�ç �
-```
+````
public final class Integer extends Number implements Comparable {
private final int value;
@@ -343,7 +293,7 @@ public final class Integer extends Number implements Comparable {
private IntegerCache() {}
}
-```
+````
以上是Oracle(Sun)å…¬å�¸JDK 1.7ä¸Integeræº�ç �的一部分,通过分æž�上é�¢çš„代ç �,得到:
@@ -363,21 +313,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 +345,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 +361,6 @@ public static void main(String[] args) {
System.out.println(d1 == d2);
System.out.println(d3 == d4);
-
`结果`
`false`
@@ -423,8 +372,6 @@ public static void main(String[] args) {
`false`
`true`
-
-
Integer i = 10;
Byte b = 10;
//比较Byteå’ŒInteger.ä¸¤ä¸ªå¯¹è±¡æ— æ³•ç›´æŽ¥æ¯”è¾ƒï¼ŒæŠ¥é”™
@@ -460,8 +407,6 @@ public static void main(String[] args) {
需è¦�注æ„�的是:“==â€�在没é�‡åˆ°ç®—术è¿�算时,ä¸�会自动拆箱;基本类型å�ªä¼šè‡ªåŠ¨è£…ç®±ä¸ºå¯¹åº”çš„åŒ…è£…ç±»åž‹ï¼Œä»£ç �䏿œ€å�Žä¸€æ�¡è¯´æ˜Žçš„内容。
-
-
在JDK 1.5䏿��供了自动装箱与自动拆箱,这其实是Java ç¼–è¯‘å™¨çš„è¯æ³•糖,编译器通过调用包装类型的valueOf()方法实现自动装箱,调用xxxValue()方法自动拆箱。自动装箱和拆箱会有一些陷阱,那就是包装类型å¤�用了æŸ�些对象。
(1)Integer默认å¤�用了[-128,127]这些对象,其ä¸é«˜ä½�ç½®å�¯ä»¥ä¿®æ”¹ï¼›
@@ -574,10 +519,6 @@ System.out.println(s3 == s4);
JDK1.6以�以下:false false
JDK1.7以�以上:false true
```
-
-
-
-
JDK1.6查找到常é‡�æ± å˜åœ¨ç›¸å�Œå€¼çš„对象时会直接返回该对象的地å�€ã€‚
JDK 1.7å�Žï¼Œintern方法还是会先去查询常é‡�æ± ä¸æ˜¯å�¦æœ‰å·²ç»�å˜åœ¨ï¼Œå¦‚æžœå˜åœ¨ï¼Œåˆ™è¿”回常é‡�æ± ä¸çš„引用,这一点与之å‰�没有区别,区别在于,如果在常é‡�æ± æ‰¾ä¸�到对应的å—符串,则ä¸�会å†�å°†å—符串拷è´�到常é‡�æ± ï¼Œè€Œå�ªæ˜¯åœ¨å¸¸é‡�æ± ä¸ç”Ÿæˆ�一个对原å—符串的引用。
@@ -602,20 +543,4 @@ https://blog.csdn.net/a724888/article/details/80033043
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
diff --git "a/docs/java/basic/10\343\200\201Java\345\274\202\345\270\270.md" "b/docs/Java/basic/Java\345\274\202\345\270\270.md"
similarity index 64%
rename from "docs/java/basic/10\343\200\201Java\345\274\202\345\270\270.md"
rename to "docs/Java/basic/Java\345\274\202\345\270\270.md"
index c937417..4f77437 100644
--- "a/docs/java/basic/10\343\200\201Java\345\274\202\345\270\270.md"
+++ "b/docs/Java/basic/Java\345\274\202\345\270\270.md"
@@ -15,14 +15,7 @@
* [当finally�上return](#当finally�上return)
* [JAVA异常常��试题](#java异常常��试题)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
----
-
- - Java异常
----
æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
> https://github.com/h2pl/Java-Tutorial
@@ -51,7 +44,7 @@
> 3� 由调用函数�分�异常,这�求程�员对库函数有很深的了解。
>
- 在OO䏿��供的异常处ç�†æœºåˆ¶æ˜¯æ��供代ç �å�¥å£®çš„强有力的方å¼�。使用异常机制它能够é™�低错误处ç�†ä»£ç �çš„å¤�æ�‚度,如果ä¸�使用异常,那么就必须检查特定的错误,并在程åº�ä¸çš„许多地方去处ç�†å®ƒã€‚
+在OO䏿��供的异常处ç�†æœºåˆ¶æ˜¯æ��供代ç �å�¥å£®çš„强有力的方å¼�。使用异常机制它能够é™�低错误处ç�†ä»£ç �çš„å¤�æ�‚度,如果ä¸�使用异常,那么就必须检查特定的错误,并在程åº�ä¸çš„许多地方去处ç�†å®ƒã€‚
而如果使用异常,那就ä¸�å¿…åœ¨æ–¹æ³•è°ƒç”¨å¤„è¿›è¡Œæ£€æŸ¥ï¼Œå› ä¸ºå¼‚å¸¸æœºåˆ¶å°†ä¿�è¯�能够æ�•获这个错误,并且,å�ªéœ€åœ¨ä¸€ä¸ªåœ°æ–¹å¤„ç�†é”™è¯¯ï¼Œå�³æ‰€è°“的异常处ç�†ç¨‹åº�ä¸ã€‚
@@ -61,21 +54,20 @@
## 异常基本定义
-> 在《Think in javaã€‹ä¸æ˜¯è¿™æ ·å®šä¹‰å¼‚常的:异常情形是指阻æ¢å½“å‰�æ–¹æ³•æˆ–è€…ä½œç”¨åŸŸç»§ç»æ‰§è¡Œçš„问题。在这里一定è¦�明确一点:异常代ç �æŸ�ç§�程度的错误,尽管Java有异常处ç�†æœºåˆ¶ï¼Œä½†æ˜¯æˆ‘们ä¸�能以“æ£å¸¸â€�的眼光æ�¥çœ‹å¾…异常,异常处ç�†æœºåˆ¶çš„åŽŸå› å°±æ˜¯å‘Šè¯‰ä½ ï¼šè¿™é‡Œå�¯èƒ½ä¼šæˆ–者已ç»�产生了错误,您的程åº�出现了ä¸�æ£å¸¸çš„æƒ…况,å�¯èƒ½ä¼šå¯¼è‡´ç¨‹åº�失败ï¼�
+> 在《Think in javaã€‹ä¸æ˜¯è¿™æ ·å®šä¹‰å¼‚常的:异常情形是指阻æ¢å½“å‰�æ–¹æ³•æˆ–è€…ä½œç”¨åŸŸç»§ç»æ‰§è¡Œçš„问题。在这里一定è¦�明确一点:异常代ç �æŸ�ç§�程度的错误,尽管Java有异常处ç�†æœºåˆ¶ï¼Œä½†æ˜¯æˆ‘们ä¸�能以“æ£å¸¸â€�的眼光æ�¥çœ‹å¾…异常,异常处ç�†æœºåˆ¶çš„åŽŸå› å°±æ˜¯å‘Šè¯‰ä½ ï¼šè¿™é‡Œå�¯èƒ½ä¼šæˆ–者已ç»�产生了错误,您的程åº�出现了ä¸�æ£å¸¸çš„æƒ…况,å�¯èƒ½ä¼šå¯¼è‡´ç¨‹åº�失败ï¼�
-> 那么什么时候æ‰�会出现异常呢?å�ªæœ‰åœ¨ä½ 当å‰�的环境下程åº�æ— æ³•æ£å¸¸è¿�行下去,也就是说程åº�å·²ç»�æ— æ³•æ�¥æ£ç¡®è§£å†³é—®é¢˜äº†ï¼Œè¿™æ—¶å®ƒæ‰€å°±ä¼šä»Žå½“å‰�环境ä¸è·³å‡ºï¼Œå¹¶æŠ›å‡ºå¼‚常。抛出异常å�Žï¼Œå®ƒé¦–先会å�šå‡ 件事。
+> 那么什么时候æ‰�会出现异常呢?å�ªæœ‰åœ¨ä½ 当å‰�的环境下程åº�æ— æ³•æ£å¸¸è¿�行下去,也就是说程åº�å·²ç»�æ— æ³•æ�¥æ£ç¡®è§£å†³é—®é¢˜äº†ï¼Œè¿™æ—¶å®ƒæ‰€å°±ä¼šä»Žå½“å‰�环境ä¸è·³å‡ºï¼Œå¹¶æŠ›å‡ºå¼‚常。抛出异常å�Žï¼Œå®ƒé¦–先会å�šå‡ 件事。
> 首先,它会使用new创建一个异常对象,然å�Žåœ¨äº§ç”Ÿå¼‚常的ä½�置终æ¢ç¨‹åº�,并且从当å‰�环境ä¸å¼¹å‡ºå¯¹å¼‚常对象的引用,这时。异常处ç�†æœºåˆ¶å°±ä¼šæŽ¥ç®¡ç¨‹åº�,并开始寻找一个æ�°å½“的地方æ�¥ç»§ç»æ‰§è¡Œç¨‹åº�,这个æ�°å½“的地方就是异常处ç�†ç¨‹åº�。
-> 总的æ�¥è¯´å¼‚常处ç�†æœºåˆ¶å°±æ˜¯å½“程åº�å�‘生异常时,它强制终æ¢ç¨‹åº�è¿�行,记录异常信æ�¯å¹¶å°†è¿™äº›ä¿¡æ�¯å��馈给我们,由我们æ�¥ç¡®å®šæ˜¯å�¦å¤„ç�†å¼‚常。
+> 总的æ�¥è¯´å¼‚常处ç�†æœºåˆ¶å°±æ˜¯å½“程åº�å�‘生异常时,它强制终æ¢ç¨‹åº�è¿�行,记录异常信æ�¯å¹¶å°†è¿™äº›ä¿¡æ�¯å��馈给我们,由我们æ�¥ç¡®å®šæ˜¯å�¦å¤„ç�†å¼‚常。
## 异常体系
-[外链图片转å˜å¤±è´¥(img-KNxcBTK0-1569073569353)(https://images0.cnblogs.com/blog/381060/201311/22185952-834d92bc2bfe498f9a33414cc7a2c8a4.png)]
+
从上é�¢è¿™å¹…图å�¯ä»¥çœ‹å‡ºï¼ŒThrowable是javaè¯è¨€ä¸æ‰€æœ‰é”™è¯¯å’Œå¼‚常的超类(万物å�³å�¯æŠ›ï¼‰ã€‚它有两个å�类:Errorã€�Exception。
-
Javaæ ‡å‡†åº“å†…å»ºäº†ä¸€äº›é€šç”¨çš„å¼‚å¸¸ï¼Œè¿™äº›ç±»ä»¥Throwable为顶层父类。
Throwable�派生出Error类和Exception类。
@@ -103,7 +95,7 @@ Throwable�派生出Error类和Exception类。
异常是在执行æŸ�个函数时引å�‘的,而函数å�ˆæ˜¯å±‚级调用,形æˆ�è°ƒç”¨æ ˆçš„ï¼Œå› ä¸ºï¼Œå�ªè¦�一个函数å�‘生了异常,那么他的所有的caller都会被异常影å“�。当这些被影å“�的函数以异常信æ�¯è¾“出时,就形æˆ�çš„äº†å¼‚å¸¸è¿½è¸ªæ ˆã€‚
异常最先�生的地方,��异常抛出点。
-
+````
public class 异常 {
public static void main (String [] args )
{
@@ -130,9 +122,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 +133,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 +146,7 @@ Throwable�派生出Error类和Exception类。
## 异常和错误
下é�¢çœ‹ä¸€ä¸ªä¾‹å�
-
+````
//错误å�³error一般指jvmæ— æ³•å¤„ç�†çš„错误
//异常是Java定义的用于简化错误处��程和定�错误的一�工具。
public class 错误和错误 {
@@ -198,7 +187,7 @@ Throwable�派生出Error类和Exception类。
// at com.javase.异常.错误.main(错误.java:11)
}
-
+````
## 异常的处�方�
在编写代ç �处ç�†å¼‚常时,对于检查异常,有2ç§�ä¸�å�Œçš„处ç�†æ–¹å¼�:
@@ -213,7 +202,7 @@ Throwable�派生出Error类和Exception类。
上é�¢çš„例å�是è¿�行时异常,ä¸�需è¦�显示æ�•获。
下é�¢è¿™ä¸ªä¾‹å�是å�¯æ£€æŸ¥å¼‚常需,è¦�显示æ�•获或者抛出。
-
+````
@Test
public void testException() throws IOException
{
@@ -309,6 +298,7 @@ Throwable�派生出Error类和Exception类。
// at com.javase.异常.异常处�方�.test(异常处�方�.java:62)
throw new StringIndexOutOfBoundsException();
}
+````
其实有的è¯è¨€åœ¨é�‡åˆ°å¼‚常å�Žä»�ç„¶å�¯ä»¥ç»§ç»è¿�行
@@ -321,11 +311,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 +332,7 @@ finally��管异常是��生,��对应的try执行了,则它一定
3ã€�在å�Œä¸€try…catch…finallyå�—ä¸ ï¼Œtryå�‘生异常,且匹é…�çš„catchå�—ä¸å¤„ç�†å¼‚常时也抛出异常,那么å�Žé�¢çš„finally也会执行:首先执行finallyå�—,然å�ŽåŽ»å¤–å›´è°ƒç”¨è€…ä¸å¯»æ‰¾å�ˆé€‚çš„catchå�—。
+````
public class finally使用 {
public static void main(String[] args) {
try {
@@ -357,6 +349,7 @@ finally��管异常是��生,��对应的try执行了,则它一定
}
}
}
+````
## throw : JRE也使用的关键å—
@@ -365,15 +358,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 +381,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 +472,7 @@ throw è¯å�¥å¿…须写在函数ä¸ï¼Œæ‰§è¡Œthrow è¯å�¥çš„地方就是一个异
一个带有Stringå�‚æ•°å’ŒThrowableå�‚æ•°ï¼Œå¹¶éƒ½ä¼ é€’ç»™çˆ¶ç±»æž„é€ å‡½æ•°
一个带有Throwable å�‚æ•°çš„æž„é€ å‡½æ•°ï¼Œå¹¶ä¼ é€’ç»™çˆ¶ç±»çš„æž„é€ å‡½æ•°ã€‚
下é�¢æ˜¯IOException类的完整æº�代ç �,å�¯ä»¥å€Ÿé‰´ã€‚
-
+````
public class IOException extends Exception
{
static final long serialVersionUID = 7818375828146090155L;
@@ -507,7 +497,7 @@ throw è¯å�¥å¿…须写在函数ä¸ï¼Œæ‰§è¡Œthrow è¯å�¥çš„地方就是一个异
super(cause);
}
}
-
+````
## 异常的注�事项
异常的注�事项
@@ -517,47 +507,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 +555,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 +600,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 +769,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 +798,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çš„ä¸ªæ•°ï¼Œå› æ¤ï¼Œåœ¨è‡ªå®šä¹‰å¼‚常和通用异常之间维æŒ�一个平衡是æˆ�功的关键。
@@ -862,21 +839,4 @@ http://c.biancheng.net/view/1038.html
https://blog.csdn.net/Lisiluan/article/details/88745820
https://blog.csdn.net/michaelgo/article/details/82790253
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
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/Java\346\263\250\350\247\243\345\222\214\346\234\200\344\275\263\345\256\236\350\267\265.md"
similarity index 85%
rename from "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"
rename to "docs/Java/basic/Java\346\263\250\350\247\243\345\222\214\346\234\200\344\275\263\345\256\236\350\267\265.md"
index ab4a401..435e587 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/Java\346\263\250\350\247\243\345\222\214\346\234\200\344\275\263\345\256\236\350\267\265.md"
@@ -22,21 +22,7 @@
* [什么是元注解?](#什么是元注解?)
* [下é�¢çš„代ç �会编译å�—?](#下é�¢çš„代ç �会编译å�—?)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [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 +59,7 @@ Annotation 䏿–‡è¯‘过æ�¥å°±æ˜¯æ³¨è§£ã€�æ ‡é‡Šçš„æ„�æ€�,在 Java 䏿³¨è§£æ˜¯
å¹¶ä¸”ï¼Œå¾€æŠ½è±¡åœ°è¯´ï¼Œæ ‡ç¾å¹¶ä¸�ä¸€å®šæ˜¯ä¸€å¼ çº¸ï¼Œå®ƒå�¯ä»¥æ˜¯å¯¹äººå’Œäº‹ç‰©çš„å±žæ€§è¯„ä»·ã€‚ä¹Ÿå°±æ˜¯è¯´ï¼Œæ ‡ç¾å…·å¤‡å¯¹äºŽæŠ½è±¡äº‹ç‰©çš„解释。
-
-
-
+
所以,基于如æ¤ï¼Œæˆ‘完æˆ�了自我的知识认知å�‡çº§ï¼Œæˆ‘å†³å®šç”¨æ ‡ç¾æ�¥è§£é‡Šæ³¨è§£ã€‚
@@ -166,8 +150,8 @@ java.lang.annotation�供了四�元注解,专门注解其他的注解(在
JDK 内置注解
å…ˆæ�¥çœ‹å‡ 个 Java 内置的注解,让大家çƒçƒèº«ã€‚
- @Override 演示
-
+@Override 演示
+````
class Parent {
public void run() {
}
@@ -182,7 +166,9 @@ JDK 内置注解
public void run() {
}
}
+````
@Deprecated 演示
+````
class Parent {
/**
@@ -201,7 +187,9 @@ class Parent {
parent.run(); // åœ¨ç¼–è¯‘å™¨ä¸æ¤æ–¹æ³•ä¼šæ˜¾ç¤ºè¿‡æ—¶æ ‡å¿—
}
}
+````
@SuppressWarnings 演示
+````
class Parent {
// å› ä¸ºå®šä¹‰çš„ name 没有使用,那么编译器就会有è¦å‘Šï¼Œè¿™æ—¶å€™ä½¿ç”¨æ¤æ³¨è§£å�¯ä»¥å±�蔽掉è¦å‘Š
@@ -209,8 +197,10 @@ class Parent {
@SuppressWarnings("all")
private String name;
}
-
+````
@FunctionalInterface 演示
+
+````
/**
* æ¤æ³¨è§£æ˜¯ Java8 æ��出的函数å¼�接å�£ï¼ŒæŽ¥å�£ä¸å�ªå…�许有一个抽象方法
* åŠ ä¸Šè¿™ä¸ªæ³¨è§£ä¹‹å�Žï¼Œç±»ä¸å¤šä¸€ä¸ªæŠ½è±¡æ–¹æ³•或者少一个抽象方法都会报错
@@ -219,7 +209,7 @@ class Parent {
interface Func {
void run();
}
-
+````
## 注解处�器实战
@@ -230,27 +220,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 +253,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 +288,7 @@ interface Func {
ä½ å�¯ä»¥åœ¨è¿�行期访问类,方法或者å�˜é‡�的注解信æ�¯ï¼Œä¸‹æ˜¯ä¸€ä¸ªè®¿é—®ç±»æ³¨è§£çš„例å�:
```
- Class aClass = TheClass.class;
+Class aClass = TheClass.class;
Annotation[] annotations = aClass.getAnnotations();
for(Annotation annotation : annotations){
@@ -410,8 +403,8 @@ public class TheClass {
ä½ å�¯ä»¥åƒ�è¿™æ ·æ�¥è®¿é—®å�˜é‡�的注解:
```
-Field field = ... //获�方法对象
-Annotation[] annotations = field.getDeclaredAnnotations();
+Field field = ... //获�方法对象目录
+Annotation[] annotations = field.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
@@ -425,8 +418,8 @@ for(Annotation annotation : annotations){
ä½ å�¯ä»¥åƒ�è¿™æ ·è®¿é—®æŒ‡å®šçš„å�˜é‡�注解:
```
-Field field = ...//获�方法对象
-
+Field field = ...//获�方法对象目录
+
Annotation annotation = field.getAnnotation(MyAnnotation.class);
if(annotation instanceof MyAnnotation){
@@ -668,20 +661,5 @@ https://blog.51cto.com/4247649/2109129
https://www.jianshu.com/p/2f2460e6f8e7
https://blog.csdn.net/yuzongtao/article/details/83306182
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
diff --git "a/docs/java/basic/5\343\200\201Java\347\261\273\345\222\214\345\214\205.md" "b/docs/Java/basic/Java\347\261\273\345\222\214\345\214\205.md"
similarity index 67%
rename from "docs/java/basic/5\343\200\201Java\347\261\273\345\222\214\345\214\205.md"
rename to "docs/Java/basic/Java\347\261\273\345\222\214\345\214\205.md"
index 4084792..43d7244 100644
--- "a/docs/java/basic/5\343\200\201Java\347\261\273\345\222\214\345\214\205.md"
+++ "b/docs/Java/basic/Java\347\261\273\345\222\214\345\214\205.md"
@@ -1,27 +1,21 @@
# 目录
- * [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é�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
@@ -74,11 +68,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 +81,6 @@ Java 使用包(package)这ç§�机制是为了防æ¢å‘½å��冲çª�,访问控
由于包创建了新的命å��空间(namespace),所以ä¸�会跟其他包ä¸çš„任何å��å—产生命å��冲çª�。使用包这ç§�机制,更容易实现访问控制,并且让定ä½�ç›¸å…³ç±»æ›´åŠ ç®€å�•。
-
-
### package 的目录结构
类放在包ä¸ä¼šæœ‰ä¸¤ç§�主è¦�的结果:
@@ -104,28 +92,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 +112,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\Runoob.class
+ .\com\runoob\test\Google.class
+````
-ä½ å�¯ä»¥åƒ�下é�¢è¿™æ ·æ�¥å¯¼å…¥æ‰€æœ‰** \com\runoob\test\ **ä¸å®šä¹‰çš„ç±»ã€�接å�£ç‰ï¼š
-
-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 +198,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 +266,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。
-
+䏿–‡ç¿»è¯‘过æ�¥å°±æ˜¯ï¼š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文件。
-
-
- rt.jar 默认就在Root Classloaderçš„åŠ è½½è·¯å¾„é‡Œé�¢çš„,而在Claspathé…�置该å�˜é‡�是ä¸�需è¦�的;å�Œæ—¶jre/lib目录下的其他jar:jce.jarã€�jsse.jarã€�charsets.jarã€�resources.jar都在Root Classloaderä¸ã€‚
+
-## *.java文件的奥秘
+rt.jar 默认就在Root Classloaderçš„åŠ è½½è·¯å¾„é‡Œé�¢çš„,而在Claspathé…�置该å�˜é‡�是ä¸�需è¦�的;å�Œæ—¶jre/lib目录下的其他jar:jce.jarã€�jsse.jarã€�charsets.jarã€�resources.jar都在Root Classloaderä¸ã€‚
-### *.Java文件简介
+## java文件的奥秘
+### Java文件简介
.javaæ–‡ä»¶ä½ å�¯ä»¥è®¤ä¸ºå�ªæ˜¯ä¸€ä¸ªæ–‡æœ¬æ–‡ä»¶ï¼Œ 这个文件å�³æ˜¯ç”¨javaè¯è¨€å†™æˆ�的程åº�,或者说任务的代ç �å�—。
@@ -335,43 +304,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 +367,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包的命�规则
@@ -444,20 +409,3 @@ https://www.runoob.com/java/java-package.html
https://www.breakyizhan.com/java/4260.html
https://blog.csdn.net/qq_36626914/article/details/80627454
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
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/Java\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"
similarity index 63%
rename from "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"
rename to "docs/Java/basic/Java\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..4d2dfac 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/Java\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"
@@ -14,14 +14,8 @@
* [å˜åœ¨æ ˆä¸ï¼š](#å˜åœ¨æ ˆä¸ï¼š)
* [å˜åœ¨å †é‡Œ](#å˜åœ¨å †é‡Œ)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
- - Java基本数�类型
----
-
æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
> https://github.com/h2pl/Java-Tutorial
@@ -148,14 +142,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 +162,9 @@ boolean bf = Boolean.FALSE;
`1.4E-45`
`1.7976931348623157E308`
`4.9E-324`
-`ï¿¿`
-
`true`
`false`
+```
### 引用类型
@@ -203,23 +196,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 +224,7 @@ Integer value = Integer.valueOf(10);
实例方法xxxValue():将具体的包装类型对象转��基本类型;
下é�¢æˆ‘们以intå’ŒInteger为例,说明Javaä¸è‡ªåŠ¨è£…ç®±ä¸Žè‡ªåŠ¨æ‹†ç®±çš„å®žçŽ°æœºåˆ¶ã€‚çœ‹å¦‚ä¸‹ä»£ç �:
+````
class Auto //code1
{
public static void main(String[] args)
@@ -246,7 +240,10 @@ class Auto //code1
}
}
+````
+
上é�¢çš„代ç �先将int型转为Integer对象,å†�讲Integer对象转æ�¢ä¸ºintåž‹ï¼Œæ¯«æ— ç–‘é—®ï¼Œè¿™æ˜¯å�¯ä»¥æ£ç¡®è¿�行的。å�¯æ˜¯ï¼Œè¿™ç§�转æ�¢æ˜¯æ€Žä¹ˆè¿›è¡Œçš„呢?使用å��编译工具,将生æˆ�çš„Class文件在å��编译为Java文件,让我们看看å�‘生了什么:
+````
class Auto//code2
{
public static void main(String[] paramArrayOfString)
@@ -254,17 +251,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 +265,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 +404,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 +436,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 +463,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 +482,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 +537,6 @@ JDK1.7å�Žï¼Œå¸¸é‡�æ± è¢«æ”¾å…¥åˆ°å †ç©ºé—´ä¸ï¼Œè¿™å¯¼è‡´intern()函数的功能
```
-[java] view plain copy
String s = new String("1");
s.intern();
String s2 = "1";
@@ -554,9 +553,6 @@ JDK1.6以�以下:false false
JDK1.7以�以上:false true
```
-
-
-
JDK1.6查找到常é‡�æ± å˜åœ¨ç›¸å�Œå€¼çš„对象时会直接返回该对象的地å�€ã€‚
JDK 1.7å�Žï¼Œintern方法还是会先去查询常é‡�æ± ä¸æ˜¯å�¦æœ‰å·²ç»�å˜åœ¨ï¼Œå¦‚æžœå˜åœ¨ï¼Œåˆ™è¿”回常é‡�æ± ä¸çš„引用,这一点与之å‰�没有区别,区别在于,如果在常é‡�æ± æ‰¾ä¸�到对应的å—符串,则ä¸�会å†�å°†å—符串拷è´�到常é‡�æ± ï¼Œè€Œå�ªæ˜¯åœ¨å¸¸é‡�æ± ä¸ç”Ÿæˆ�一个对原å—符串的引用。
@@ -581,23 +577,6 @@ https://blog.csdn.net/a724888/article/details/80033043
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
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/Java\351\233\206\345\220\210\346\241\206\346\236\266\346\242\263\347\220\206.md"
similarity index 67%
rename from "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"
rename to "docs/Java/basic/Java\351\233\206\345\220\210\346\241\206\346\236\266\346\242\263\347\220\206.md"
index 8ad5827..16fe721 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/Java\351\233\206\345\220\210\346\241\206\346\236\266\346\242\263\347\220\206.md"
@@ -26,9 +26,7 @@
* [线程安全的阻塞队列](#线程安全的阻塞队列)
* [å�Œæ¥é˜Ÿåˆ—](#å�Œæ¥é˜Ÿåˆ—)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
---
title: 夯实Java基础系列19:一文�懂Java集�类框架,以�常��试题
date: 2019-9-19 15:56:26 # æ–‡ç« ç”Ÿæˆ�时间,一般ä¸�改
@@ -61,8 +59,7 @@ tags:
在编写java程åº�ä¸ï¼Œæˆ‘们最常用的除了八ç§�基本数æ�®ç±»åž‹ï¼ŒString对象外还有一个集å�ˆç±»ï¼Œåœ¨æˆ‘们的的程åº�ä¸åˆ°å¤„å……æ–¥ç�€é›†å�ˆç±»çš„身影ï¼�
-
-
+
javaä¸é›†å�ˆå¤§å®¶æ—�çš„æˆ�员实在是太丰富了,有常用的ArrayListã€�HashMapã€�HashSet,也有ä¸�常用的Stackã€�Queue,有线程安全的Vectorã€�HashTable,也有线程ä¸�安全的LinkedListã€�TreeMapç‰ç‰ï¼�

@@ -90,63 +87,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 +170,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 +258,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 +345,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;
+ }
- 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 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;
+ }
+ }
+}
+````
## 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
@@ -712,20 +710,3 @@ https://www.cnblogs.com/uodut/p/7067162.html
https://www.jb51.net/article/135672.htm
https://www.cnblogs.com/suiyue-/p/6052456.html
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
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/final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md"
similarity index 91%
rename from "docs/java/basic/4\343\200\201final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md"
rename to "docs/Java/basic/final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md"
index ff1118c..6b28474 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/final\345\205\263\351\224\256\345\255\227\347\211\271\346\200\247.md"
@@ -18,9 +18,7 @@
* [读 final 域的�排�规则](#读-final-域的�排�规则)
* [如果 final 域是引用类型](#如果-final-域是引用类型)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
> https://github.com/h2pl/Java-Tutorial
@@ -184,7 +182,7 @@ final方法的好处:
2. finalå�˜é‡�在多线程ä¸å¹¶å�‘å®‰å…¨ï¼Œæ— éœ€é¢�外的å�Œæ¥å¼€é”€
3. final方法是��编译的,�高了调用速度
4. **final类创建的对象是��读的,在多线程�以安全共享**
-5.
+
## final关键å—的最佳实践
### final的用法
@@ -198,7 +196,7 @@ final修饰的��有三�:�����实例��和局部��,分
 å�¦å¤–,finalå�˜é‡�定义的时候,å�¯ä»¥å…ˆå£°æ˜Žï¼Œè€Œä¸�ç»™åˆ�值,这ä¸å�˜é‡�也称为finalç©ºç™½ï¼Œæ— è®ºä»€ä¹ˆæƒ…å†µï¼Œç¼–è¯‘å™¨éƒ½ç¡®ä¿�空白final在使用之å‰�必须被åˆ�始化。
 
但是,final空白在final关键å—final的使用上æ��供了更大的ç�µæ´»æ€§ï¼Œä¸ºæ¤ï¼Œä¸€ä¸ªç±»ä¸çš„finalæ•°æ�®æˆ�员就å�¯ä»¥å®žçްä¾�对象而有所ä¸�å�Œï¼Œå�´æœ‰ä¿�æŒ�å…¶æ�’定ä¸�å�˜çš„特å¾�。
-
+````
public class FinalTest {
final int p;
final int q=3;
@@ -210,19 +208,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 +229,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
for(int j=0;j<1000;j++)
{System.out.println("g");}
}}
-
+````
看出æ�¥åŒºåˆ«äº†å�§ï¼Ÿç¼–译器直接将funcçš„å‡½æ•°ä½“å†…åµŒåˆ°äº†è°ƒç”¨å‡½æ•°çš„åœ°æ–¹ï¼Œè¿™æ ·çš„ç»“æžœæ˜¯èŠ‚çœ�了1000次函数调用,当然编译器处ç�†æˆ�å—节ç �,å�ªæ˜¯æˆ‘们å�¯ä»¥æƒ³è±¡æˆ�è¿™æ ·ï¼Œçœ‹ä¸ªæ˜Žç™½ã€‚
ä¸�过,当函数体太长的è¯�,用finalå�¯èƒ½é€‚å¾—å…¶å��ï¼Œå› ä¸ºç»�过编译器内嵌之å�Žä»£ç �é•¿åº¦å¤§å¤§å¢žåŠ ï¼ŒäºŽæ˜¯å°±å¢žåŠ äº†jvm解释å—节ç �的时间。
@@ -243,7 +242,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
è§�下é�¢çš„æµ‹è¯•代ç �,我会执行五次:
-
+````
public class Test
{
public static void getJava()
@@ -283,6 +282,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
}
}
+````
结果为:
第一次:
@@ -308,13 +308,13 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
由以上è¿�行结果ä¸�难看出,执行最快的是“æ£å¸¸çš„æ‰§è¡Œâ€�å�³ä»£ç �直接编写,而使用final修饰的方法,ä¸�åƒ�æœ‰äº›ä¹¦ä¸Šæˆ–è€…æ–‡ç« ä¸Šæ‰€è¯´çš„é‚£æ ·ï¼Œé€Ÿåº¦ä¸Žæ•ˆçŽ‡ä¸Žâ€œæ£å¸¸çš„æ‰§è¡Œâ€�æ— å¼‚ï¼Œè€Œæ˜¯ä½�于第二ä½�,最差的是调用ä¸�åŠ final修饰的方法。
-è§‚ç‚¹ï¼šåŠ äº†æ¯”ä¸�åŠ å¥½ä¸€ç‚¹ã€‚
+ è§‚ç‚¹ï¼šåŠ äº†æ¯”ä¸�åŠ å¥½ä¸€ç‚¹ã€‚
### 使用final修饰��会让��的值�能被改��;
è§�代ç �:
-
+````
public class Final
{
public static void main(String[] args)
@@ -335,18 +335,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 +384,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
}
-
+````
è¿™æ ·å°±OK了,既ä¿�è¯�了代ç �安全,å�ˆèƒ½è®©æ•°ç»„ä¸çš„å…ƒç´ è¢«è®¿é—®äº†ã€‚
@@ -397,7 +397,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
规则3:父类ä¸private final方法,å�ç±»å�¯ä»¥é‡�新定义,这ç§�情况ä¸�是é‡�写。
代ç �示例
-
+````
规则1代ç �
public class FinalMethodTest
@@ -429,7 +429,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
// 下�方法定义将�会出现问题
public void test(){}
}
-
+````
## final 和 jvm的关系
@@ -439,8 +439,8 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
2. �次读一个包� final 域的对象的引用,与���次读这个 final 域,这两个�作之间�能�排�。
下é�¢ï¼Œæˆ‘们通过一些示例性的代ç �æ�¥åˆ†åˆ«è¯´æ˜Žè¿™ä¸¤ä¸ªè§„则:
-
-public class FinalExample {
+````
+public class FinalExample {
int i; // 普通��
final int j; //final ��
static FinalExample obj;
@@ -460,7 +460,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
int b = object.j; // 读 final 域
}
}
-
+````
这里�设一个线程 A 执行 writer () 方法,���一个线程 B 执行 reader () 方法。下�我们通过这两个线程的交互�说明这两个规则。
@@ -478,7 +478,7 @@ final修饰的函数会被编译器优化,优化的结果是�少了函数调
�设线程 B 读对象引用与读对象的�员域之间没有�排�(马上会说明为什么需�这个�设),下图是一��能的执行时�:
-
+
在上图ä¸ï¼Œå†™æ™®é€šåŸŸçš„æ“�作被编译器é‡�排åº�åˆ°äº†æž„é€ å‡½æ•°ä¹‹å¤–ï¼Œè¯»çº¿ç¨‹ B 错误的读å�–了普通å�˜é‡� i åˆ�始化之å‰�的值。而写 final 域的æ“�作,被写 final 域的é‡�排åº�规则“é™�定â€�åœ¨äº†æž„é€ å‡½æ•°ä¹‹å†…ï¼Œè¯»çº¿ç¨‹ B æ£ç¡®çš„读å�–了 final å�˜é‡�åˆ�始化之å�Žçš„值。
@@ -511,8 +511,8 @@ reader() 方法包�三个�作:
上�我们看到的 final 域是基础数�类型,下�让我们看看如果 final 域是引用类型,将会有什么效果?
请看下列示例代ç �:
-
-public class FinalReferenceExample {
+````
+public class FinalReferenceExample {
final int[] intArray; //final 是引用类型
static FinalReferenceExample obj;
@@ -535,7 +535,7 @@ public static void reader () { // 读线程 C 执行
}
}
}
-
+````
这里 final 域为一个引用类型,它引用一个 int 型的数组对象。对于引用类型,写 final 域的é‡�排åº�规则对编译器和处ç�†å™¨å¢žåŠ äº†å¦‚ä¸‹çº¦æ�Ÿï¼š
@@ -543,14 +543,14 @@ public static void reader () { // 读线程 C 执行
对上�的示例程�,我们�设首先线程 A 执行 writerOne() 方法,执行完�线程 B 执行 writerTwo() 方法,执行完�线程 C 执行 reader () 方法。下�是一��能的线程执行时�:
-
-
+
在上图ä¸ï¼Œ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
@@ -561,20 +561,4 @@ https://www.iteye.com/blog/cakin24-2334965
https://blog.csdn.net/chengqiuming/article/details/70139503
https://blog.csdn.net/hupuxiang/article/details/7362267
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
diff --git "a/docs/java/basic/20\343\200\201javac\345\222\214javap.md" "b/docs/Java/basic/javac\345\222\214javap.md"
similarity index 74%
rename from "docs/java/basic/20\343\200\201javac\345\222\214javap.md"
rename to "docs/Java/basic/javac\345\222\214javap.md"
index dde513d..f797af7 100644
--- "a/docs/java/basic/20\343\200\201javac\345\222\214javap.md"
+++ "b/docs/Java/basic/javac\345\222\214javap.md"
@@ -18,28 +18,10 @@
* [-encoding](#-encoding)
* [-verbose](#-verbose)
* [其他命令](#其他命令)
- * [使用javac构建项目](#使用javac构建项目)
- * [](#)
-* [java文件列表目录](#java文件列表目录)
- * [放入列表文件ä¸](#放入列表文件ä¸)
- * [生�bin目录](#生�bin目录)
- * [列表](#列表)
- * [通过-cp指定所有的引用jar包,将src下的所有java文件进行编译](#通过-cp指定所有的引用jar包,将src下的所有java文件进行编译)
- * [通过-cp指定所有的引用jar包,指定入�函数�行](#通过-cp指定所有的引用jar包,指定入�函数�行)
+ * [使用javac构建项目](#使用javac构建项目)
* [javap 的使用](#javap-的使用)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [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 +63,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 +298,7 @@ javac:如果当å‰�ä½ è¦�编译的java文件ä¸å¼•用了其它的类(比如说
> 这里展示一个web项目的.classpath
Xml代ç �
-
+````
@@ -328,7 +310,7 @@ Xml代ç �
……
-
+````
> XML文档包å�«ä¸€ä¸ªæ ¹å…ƒç´ ,就是classpath,类路径,那么这里é�¢åŒ…å�«äº†ä»€ä¹ˆä¿¡æ�¯å‘¢ï¼Ÿå�å…ƒç´ æ˜¯classpathentry,kind属性区别了ç§� 类信æ�¯ï¼Œsrcæº�ç �,conä½ çœ‹çœ‹å�Žé�¢çš„path就知é�“是JRE容器的信æ�¯ã€‚lib是项目ä¾�赖的第三方类库,output是src编译å�Žçš„ä½�置。
> 既然是web项目,那么就是WEB-INF/classes目录,å�¯èƒ½ç”¨MyEclipseçš„å�Œå¦ä¼šè¯´ä»–们那里是WebRoot或者是WebContext而ä¸�是webapp,有区别么?回ç”:完全没有ï¼�
@@ -393,27 +375,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 +433,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 +454,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 A
+{
+ public static void main(String[] args) {
+ B b = new B();
}
-
- public class B
- {
- }
-
- 如果使用:
+}
+
+public class B
+{
+}
+````
+如果使用:
-​
-​ javac -implicit:none A.java
+
+javac -implicit:none A.java
则�会生� B.class。
@@ -578,18 +560,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 +579,14 @@ java文件�常简�
System.out.println("helloWorld");
}
}
+````
+
编译:
javac src/com/yp/test/HelloWorld.java -d build
-d 表示编译到 build文件夹下
-```
+````
查看build文件夹
├─build
│ └─com
@@ -615,10 +599,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 +662,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 +696,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 +714,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 +743,7 @@ ok 一个简�的java 工程就�行完了
但是 貌似有些��, 需�手动键入 java文件 以�相应的jar包 很是麻烦,
so �以用 shell �脚本�简化相关�作
shell 文件整�如下:
-
+````
#!/bin/bash
echo "build start"
@@ -788,6 +774,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 +792,7 @@ shell 文件整�如下:
1.需è¦�å�§ 编译时设置的bin目录和 所有jaråŒ…åŠ å…¥åˆ° classpath ä¸åŽ»
-​
+
## javap 的使用
> javap是jdk自带的一个工具,å�¯ä»¥å¯¹ä»£ç �å��编译,也å�¯ä»¥æŸ¥çœ‹java编译器生æˆ�çš„å—节ç �。
@@ -815,37 +802,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 +863,7 @@ Compiled from "DocFooter.java"
29: return
}
+````
上é�¢è¾“出的内容就是å—节ç �。
用法摘�
@@ -903,20 +891,3 @@ https://www.jianshu.com/p/6a8997560b05
https://blog.csdn.net/w372426096/article/details/81664431
https://blog.csdn.net/qincidong/article/details/82492140
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
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/string\345\222\214\345\214\205\350\243\205\347\261\273.md"
similarity index 50%
rename from "docs/java/basic/3\343\200\201string\345\222\214\345\214\205\350\243\205\347\261\273.md"
rename to "docs/Java/basic/string\345\222\214\345\214\205\350\243\205\347\261\273.md"
index 13dfe0a..9adf53e 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/string\345\222\214\345\214\205\350\243\205\347\261\273.md"
@@ -27,9 +27,7 @@
* [���有什么好处?](#���有什么好处?)
* [String常用工具类](#string常用工具类)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
@@ -46,11 +44,8 @@
å¦‚æžœå¯¹æœ¬ç³»åˆ—æ–‡ç« æœ‰ä»€ä¹ˆå»ºè®®ï¼Œæˆ–è€…æ˜¯æœ‰ä»€ä¹ˆç–‘é—®çš„è¯�,也å�¯ä»¥å…³æ³¨å…¬ä¼—å�·ã€�Java技术江湖】è�”ç³»ä½œè€…ï¼Œæ¬¢è¿Žä½ å�‚与本系列å�šæ–‡çš„åˆ›ä½œå’Œä¿®è®¢ã€‚
-
-
-
## string基础
### Java String ç±»
@@ -70,9 +65,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 +87,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ä¸å¸¸ç”¨çš„æ–¹æ³•,用法如图所示,具体问度娘

### 三个方法的使用: 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 +125,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之间的区别:
-引用指�的内容和引用指�的地�
+引用指�的内容和引用指�的地�
-
-
-
-
-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 +167,9 @@ runoob
System.out.println(str1.equals(str3)); //true 内容相�
System.out.println(str1==str2); //true 地�相�
System.out.println(str1==str3); //false 地���
- }
-}
-
+ }
+}
+````
### å—符串的ä¸�å�¯å�˜æ€§
@@ -170,7 +177,7 @@ String的对象一旦被创建,则�能修改,是���的
所谓的修改其实是创建了新的对象,所指å�‘的内å˜ç©ºé—´ä¸�å�˜
-
+
上图ä¸ï¼Œs1ä¸�å†�指å�‘imooc所在的内å˜ç©ºé—´ï¼Œè€Œæ˜¯æŒ‡å�‘了hello,imooc
### String的连接
@@ -218,85 +225,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 +320,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 +342,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 +391,26 @@ ensureCapacityInternal(count + len);
## String和JVM的关系
-
-
-
下é�¢æˆ‘们了解下Javaæ ˆã€�Javaå †ã€�方法区和常é‡�æ± ï¼š
-
-
Javaæ ˆï¼ˆçº¿ç¨‹ç§�有数æ�®åŒºï¼‰ï¼š
```
æ¯�个Java虚拟机线程都有自己的Javaè™šæ‹Ÿæœºæ ˆï¼ŒJavaè™šæ‹Ÿæœºæ ˆç”¨æ�¥å˜æ”¾æ ˆå¸§ï¼Œæ¯�个方法被执行的时候都会å�Œæ—¶åˆ›å»ºä¸€ä¸ªæ ˆå¸§ï¼ˆStack Frame)用于å˜å‚¨å±€éƒ¨å�˜é‡�表ã€�æ“�ä½œæ ˆã€�动æ€�链接ã€�方法出å�£ç‰ä¿¡æ�¯ã€‚æ¯�一个方法被调用直至执行完æˆ�的过程,就对应ç�€ä¸€ä¸ªæ ˆå¸§åœ¨è™šæ‹Ÿæœºæ ˆä¸ä»Žå…¥æ ˆåˆ°å‡ºæ ˆçš„过程。
```
-
-
Javaå †ï¼ˆçº¿ç¨‹å…±äº«æ•°æ�®åŒºï¼‰ï¼š
```
在虚拟机å�¯åŠ¨æ—¶åˆ›å»ºï¼Œæ¤å†…å˜åŒºåŸŸçš„å”¯ä¸€ç›®çš„å°±æ˜¯å˜æ”¾å¯¹è±¡å®žä¾‹ï¼Œå‡ 乎所有的对象实例都在这里分é…�。
```
-
-
方法区(线程共享数�区):
```
方法区在虚拟机å�¯åŠ¨çš„æ—¶å€™è¢«åˆ›å»ºï¼Œå®ƒå˜å‚¨äº†æ¯�一个类的结构信æ�¯ï¼Œä¾‹å¦‚è¿�行时常é‡�æ± ã€�å—æ®µå’Œæ–¹æ³•æ•°æ�®ã€�æž„é€ å‡½æ•°å’Œæ™®é€šæ–¹æ³•çš„å—节ç �内容ã€�还包括在类ã€�实例ã€�接å�£åˆ�始化时用到的特殊方法。在JDK8之å‰�永久代是方法区的一ç§�实现,而JDK8元空间替代了永久代,永久代被移除,也å�¯ä»¥ç�†è§£ä¸ºå…ƒç©ºé—´æ˜¯æ–¹æ³•区的一ç§�实现。
```
-
-
常é‡�æ± ï¼ˆçº¿ç¨‹å…±äº«æ•°æ�®åŒºï¼‰ï¼š
```
@@ -437,23 +431,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 +452,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 +474,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 +504,7 @@ System.out.println(f);
System.out.println(ff);
}
-```
+````
这里的对f.a的修改å�¯ä»¥ç�†è§£ä¸ºchar[0] = 'a'è¿™æ ·çš„æ“�作。å�ªæ”¹å�˜æ•°æ�®å€¼ï¼Œä¸�改å�˜å†…å˜å€¼ã€‚
@@ -523,301 +512,288 @@ 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();
- }
-
- 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();
- }
+ s = s.toLowerCase(locale);
+ StringBuilder sb = new StringBuilder();
+ for (char c : s.toCharArray()) {
+ sb.append(c == split ? Character.toUpperCase(c) : c);
}
-## å�‚考文ç«
-https://blog.csdn.net/qq_34490018/article/details/82110578
-https://www.runoob.com/java/java-string.html
-https://www.cnblogs.com/zhangyinhua/p/7689974.html
-https://blog.csdn.net/sinat_21925975/article/details/86493248
-https://www.cnblogs.com/niew/p/9597379.html
+ return sb.toString();
+}
-## 微信公众�
+public static String toCamelCase(String s) {
+ return toCamelCase(s, Locale.getDefault(), SEPARATOR);
+}
-### Java技术江湖
+public static String toCamelCase(String s, Locale locale) {
+ return toCamelCase(s, locale, SEPARATOR);
+}
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
+public static String toCamelCase(String s, char split) {
+ return toCamelCase(s, Locale.getDefault(), split);
+}
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
+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();
+}
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
+public static String toUnderScoreCase(String s) {
+ return toUnderScoreCase(s, SEPARATOR);
+}
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
+/**
+ * 把å—符串转æ�¢ä¸º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
+https://www.runoob.com/java/java-string.html
+https://www.cnblogs.com/zhangyinhua/p/7689974.html
+https://blog.csdn.net/sinat_21925975/article/details/86493248
+https://www.cnblogs.com/niew/p/9597379.html
-
diff --git "a/docs/java/basic/7\343\200\201\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md" "b/docs/Java/basic/\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md"
similarity index 89%
rename from "docs/java/basic/7\343\200\201\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md"
rename to "docs/Java/basic/\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md"
index 09dc5b5..7ebb784 100644
--- "a/docs/java/basic/7\343\200\201\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md"
+++ "b/docs/Java/basic/\344\273\243\347\240\201\345\235\227\345\222\214\344\273\243\347\240\201\346\211\247\350\241\214\351\241\272\345\272\217.md"
@@ -17,9 +17,7 @@
* [é�™æ€�代ç �å�—](#é�™æ€�代ç �å�—)
* [Java代ç �å�—ã€�æž„é€ æ–¹æ³•ï¼ˆåŒ…å�«ç»§æ‰¿å…³ç³»ï¼‰çš„æ‰§è¡Œé¡ºåº�](#java代ç �å�—ã€�æž„é€ æ–¹æ³•ï¼ˆåŒ…å�«ç»§æ‰¿å…³ç³»ï¼‰çš„æ‰§è¡Œé¡ºåº�)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
> https://github.com/h2pl/Java-Tutorial
@@ -40,20 +38,20 @@
## Javaä¸çš„æž„é€ æ–¹æ³•
### æž„é€ æ–¹æ³•ç®€ä»‹
-æž„é€ æ–¹æ³•æ˜¯ç±»çš„ä¸€ç§�特殊方法,用æ�¥åˆ�始化类的一个新的对象。[Java](http://c.biancheng.net/java/) ä¸çš„æ¯�ä¸ªç±»éƒ½æœ‰ä¸€ä¸ªé»˜è®¤çš„æž„é€ æ–¹æ³•ï¼Œå®ƒå¿…é¡»å…·æœ‰å’Œç±»å��相å�Œçš„å��ç§°ï¼Œè€Œä¸”æ²¡æœ‰è¿”å›žç±»åž‹ã€‚æž„é€ æ–¹æ³•çš„é»˜è®¤è¿”å›žç±»åž‹å°±æ˜¯å¯¹è±¡ç±»åž‹æœ¬èº«ï¼Œå¹¶ä¸”æž„é€ æ–¹æ³•ä¸�能被 staticã€�finalã€�synchronizedã€�abstract å’Œ native 修饰。
+æž„é€ æ–¹æ³•æ˜¯ç±»çš„ä¸€ç§�特殊方法,用æ�¥åˆ�始化类的一个新的对象。[Java](http://c.biancheng.net/java/)ä¸çš„æ¯�ä¸ªç±»éƒ½æœ‰ä¸€ä¸ªé»˜è®¤çš„æž„é€ æ–¹æ³•ï¼Œå®ƒå¿…é¡»å…·æœ‰å’Œç±»å��相å�Œçš„å��ç§°ï¼Œè€Œä¸”æ²¡æœ‰è¿”å›žç±»åž‹ã€‚æž„é€ æ–¹æ³•çš„é»˜è®¤è¿”å›žç±»åž‹å°±æ˜¯å¯¹è±¡ç±»åž‹æœ¬èº«ï¼Œå¹¶ä¸”æž„é€ æ–¹æ³•ä¸�能被 staticã€�finalã€�synchronizedã€�abstract å’Œ native 修饰。
æ��ç¤ºï¼šæž„é€ æ–¹æ³•ç”¨äºŽåˆ�始化一个新对象,所以用 static 修饰没有æ„�ä¹‰ï¼›æž„é€ æ–¹æ³•ä¸�能被å�类继承,所以用 final å’Œ abstract 修饰没有æ„�义;多个线程ä¸�会å�Œæ—¶åˆ›å»ºå†…å˜åœ°å�€ç›¸å�Œçš„å�Œä¸€ä¸ªå¯¹è±¡ï¼Œæ‰€ä»¥ç”¨ synchronized 修饰没有必è¦�。
æž„é€ æ–¹æ³•çš„è¯æ³•æ ¼å¼�如下:
-
-class class_name
+````
+class class_name
{
public class_name(){} //é»˜è®¤æ— å�‚æž„é€ æ–¹æ³•
public ciass_name([paramList]){} //å®šä¹‰æž„é€ æ–¹æ³•
…
//类主体
-}
-
+}
+````
在一个类ä¸ï¼Œä¸Žç±»å��相å�Œçš„æ–¹æ³•å°±æ˜¯æž„é€ æ–¹æ³•ã€‚æ¯�个类å�¯ä»¥å…·æœ‰å¤šä¸ªæž„é€ æ–¹æ³•ï¼Œä½†è¦�求它们å�„自包å�«ä¸�å�Œçš„æ–¹æ³•å�‚数。
### æž„é€ æ–¹æ³•å®žä¾‹
@@ -61,8 +59,8 @@
#### 例 1
æž„é€ æ–¹æ³•ä¸»è¦�æœ‰æ— å�‚æž„é€ æ–¹æ³•å’Œæœ‰å�‚æž„é€ æ–¹æ³•ä¸¤ç§�,示例如下:
-
-public class MyClass
+````
+public class MyClass
{
private int m; //定义�有��
MyClass()
@@ -75,8 +73,8 @@
//定义有å�‚çš„æž„é€ æ–¹æ³•
this.m=m;
}
-}
-
+}
+````
è¯¥ç¤ºä¾‹å®šä¹‰äº†ä¸¤ä¸ªæž„é€ æ–¹æ³•ï¼Œåˆ†åˆ«æ˜¯æ— å�‚æž„é€ æ–¹æ³•å’Œæœ‰å�‚æž„é€ æ–¹æ³•ã€‚åœ¨ä¸€ä¸ªç±»ä¸å®šä¹‰å¤šä¸ªå…·æœ‰ä¸�å�Œå�‚æ•°çš„å�Œå��方法,这就是方法的é‡�è½½ã€‚è¿™ä¸¤ä¸ªæž„é€ æ–¹æ³•çš„å��称都与类å��相å�Œï¼Œå�‡ä¸º MyClass。在实例化该类时å�¯ä»¥è°ƒç”¨ä¸�å�Œçš„æž„é€ æ–¹æ³•è¿›è¡Œåˆ�始化。
注æ„�ï¼šç±»çš„æž„é€ æ–¹æ³•ä¸�是è¦�æ±‚å¿…é¡»å®šä¹‰çš„ã€‚å¦‚æžœåœ¨ç±»ä¸æ²¡æœ‰å®šä¹‰ä»»ä½•ä¸€ä¸ªæž„é€ æ–¹æ³•ï¼Œåˆ™ Java 会自动为该类生æˆ�ä¸€ä¸ªé»˜è®¤çš„æž„é€ æ–¹æ³•ã€‚é»˜è®¤çš„æž„é€ æ–¹æ³•ä¸�包å�«ä»»ä½•å�‚æ•°ï¼Œå¹¶ä¸”æ–¹æ³•ä½“ä¸ºç©ºã€‚å¦‚æžœç±»ä¸æ˜¾å¼�åœ°å®šä¹‰äº†ä¸€ä¸ªæˆ–å¤šä¸ªæž„é€ æ–¹æ³•ï¼Œåˆ™ Java ä¸�å†�æ��ä¾›é»˜è®¤æž„é€ æ–¹æ³•ã€‚
@@ -86,8 +84,8 @@
è¦�在ä¸�å�Œçš„æ�¡ä»¶ä¸‹ä½¿ç”¨ä¸�å�Œçš„åˆ�始化行为创建类的对象,这时候就需è¦�在一个类ä¸åˆ›å»ºå¤šä¸ªæž„é€ æ–¹æ³•ã€‚ä¸‹é�¢é€šè¿‡ä¸€ä¸ªç¤ºä¾‹æ�¥æ¼”ç¤ºæž„é€ æ–¹æ³•çš„ä½¿ç”¨ã€‚
(1) 首先在员工类 Worker ä¸å®šä¹‰ä¸¤ä¸ªæž„é€ æ–¹æ³•ï¼Œä»£ç �如下:
-
-public class Worker
+````
+public class Worker
{
public String name; //姓�
private int age; //年龄
@@ -106,15 +104,15 @@
{
return"大家好�我是新�的员工,我�"+name+",今年"+age+"�。";
}
-}
-
+}
+````
在 Worker ç±»ä¸å®šä¹‰äº†ä¸¤ä¸ªå±žæ€§ï¼Œå…¶ä¸ name 属性ä¸�å�¯æ”¹å�˜ã€‚分别定义了带有一个å�‚数和带有两个å�‚æ•°çš„æž„é€ æ–¹æ³•ï¼Œå¹¶å¯¹å…¶å±žæ€§è¿›è¡Œåˆ�始化。最å�Žå®šä¹‰äº†è¯¥ç±»çš„ toString() 方法,返回一æ�¡æ–°è¿›å‘˜å·¥çš„介ç»�è¯å�¥ã€‚
æ��示:Object 类具有一个 toString() 方法,该方法是个特殊的方法,创建的æ¯�个类都会继承该方法,它返回一个 String 类型的å—符串。如果一个类ä¸å®šä¹‰äº†è¯¥æ–¹æ³•,则在调用该类对象时,将会自动调用该类对象的 toString() 方法返回一个å—符串,然å�Žä½¿ç”¨â€œSystem.out.println(对象å��)â€�å°±å�¯ä»¥å°†è¿”回的å—符串内容打å�°å‡ºæ�¥ã€‚
(2) 在 TestWorker ç±»ä¸åˆ›å»º main() 方法作为程åº�的入å�£å¤„,在 main() 方法ä¸è°ƒç”¨ä¸�å�Œçš„æž„é€ æ–¹æ³•å®žä¾‹åŒ– Worker 对象,并对该对象ä¸çš„属性进行åˆ�始化,代ç �如下:
-
-public class TestWorker
+````
+public class TestWorker
{
public static void main(String[] args)
{
@@ -127,16 +125,16 @@
Worker worker2=new Worker("�丽",25);
System.out.println(worker2);
}
-}
-
+}
+````
在上述代ç �ä¸ï¼Œåˆ›å»ºäº†ä¸¤ä¸ªä¸�å�Œçš„ Worker 对象:一个是姓å��ä¸ºå¼ å¼ºçš„å‘˜å·¥å¯¹è±¡ï¼Œä¸€ä¸ªæ˜¯å§“å��为æ�Žä¸½ã€�年龄为 25 的员工对象。对于第一个 Worker 对象 Worker1,并未指定 age å±žæ€§å€¼ï¼Œå› æ¤ç¨‹åº�会将其值采用默认值 0。对于第二个 Worker 对象 Worker2,分别对其指定了 name 属性值和 age å±žæ€§å€¼ï¼Œå› æ¤ç¨‹åº�ä¼šå°†ä¼ é€’çš„å�‚数值é‡�新赋值给 Worker ç±»ä¸çš„属性值。
�行 TestWorker 类,输出的结果如下:
------------带有一个å�‚æ•°çš„æž„é€ æ–¹æ³•-----------
-大家好ï¼�我是新æ�¥çš„员工,我å�«å¼ 强,今年0å²�。
------------带有两个å�‚æ•°çš„æž„é€ æ–¹æ³•------------
-大家好�我是新�的员工,我��丽,今年25�。
+ -----------带有一个å�‚æ•°çš„æž„é€ æ–¹æ³•-----------
+ 大家好ï¼�我是新æ�¥çš„员工,我å�«å¼ 强,今年0å²�。
+ -----------带有两个å�‚æ•°çš„æž„é€ æ–¹æ³•------------
+ 大家好�我是新�的员工,我��丽,今年25�。
通过调用带å�‚æ•°çš„æž„é€ æ–¹æ³•ï¼Œåœ¨åˆ›å»ºå¯¹è±¡æ—¶ï¼Œä¸€å¹¶å®Œæˆ�了对象æˆ�员的åˆ�始化工作,简化了对象åˆ�始化的代ç �。
@@ -152,7 +150,7 @@
ä¸�能被staticã€�finalã€�abstract修饰(有finalå’Œstatic修饰的是ä¸�能被å�类继承的,abstract修饰的是抽象类,抽象类是ä¸�能实例化的,也就是ä¸�能new)
�以被private修饰,�以在本类里�实例化,但是外部�能实例化对象(注����)
-
+````
public class A{
int i=0;
public A(){
@@ -162,25 +160,26 @@
this.i=i;
}
}
-
+````
### é»˜è®¤æž„é€ æ–¹æ³•
å¦‚æžœæ²¡æœ‰ä»»ä½•çš„æž„é€ æ–¹æ³•ï¼Œç¼–è¯‘æ—¶ç³»ç»Ÿä¼šè‡ªåŠ¨æ·»åŠ ä¸€ä¸ªé»˜è®¤æ— å�‚æž„é€ æ–¹æ³•
éš�å�«çš„é»˜è®¤æž„é€ æ–¹æ³•
-
+````
public A(){}
-
+````
æ˜¾ç¤ºçš„é»˜è®¤æž„é€ æ–¹æ³•
-
+````
public A(){
System.out.print("æ˜¾ç¤ºçš„é»˜è®¤æž„é€ æ–¹æ³•")
}
+````
### é‡�è½½æž„é€ æ–¹æ³•
æ¯”å¦‚åŽŸæœ¬çš„ç±»é‡Œçš„æž„é€ æ–¹æ³•æ˜¯ä¸€ä¸ªå�‚数的,现在新建的对象是有三个å�‚æ•°ï¼Œæ¤æ—¶å°±è¦�é‡�è½½æž„é€ æ–¹æ³•
å½“ä¸€ä¸ªç±»ä¸æœ‰å¤šä¸ªæž„é€ æ–¹æ³•ï¼Œæœ‰å�¯èƒ½ä¼šå‡ºçްé‡�å¤�性æ“�作,这时å�¯ä»¥ç”¨thisè¯å�¥è°ƒç”¨å…¶ä»–çš„æž„é€ æ–¹æ³•ã€‚
-
+````
public class A{
private int age;
private String name;
@@ -209,6 +208,7 @@
System.out.println(name);
System.out.println(name1);
System.out.println(age);
+````
### javaå�ç±»æž„é€ æ–¹æ³•è°ƒç”¨çˆ¶ç±»æž„é€ æ–¹æ³•
@@ -265,9 +265,9 @@
> 调用:调用其所在的方法时执行
-​
-
- public class 局部代ç �å�— {
+
+````
+public class 局部代ç �å�— {
@Test
public void test (){
B b = new B();
@@ -294,7 +294,7 @@
System.out.println("hello");
}
}
-
+````
### æž„é€ ä»£ç �å�—
>ä½�置:类æˆ�员的ä½�ç½®ï¼Œå°±æ˜¯ç±»ä¸æ–¹æ³•之外的ä½�ç½®
@@ -302,7 +302,7 @@
>ä½œç”¨ï¼šæŠŠå¤šä¸ªæž„é€ æ–¹æ³•å…±å�Œçš„部分æ��å�–出æ�¥ï¼Œå…±ç”¨æž„é€ ä»£ç �å�—
>调用:æ¯�æ¬¡è°ƒç”¨æž„é€ æ–¹æ³•æ—¶ï¼Œéƒ½ä¼šä¼˜å…ˆäºŽæž„é€ æ–¹æ³•æ‰§è¡Œï¼Œä¹Ÿå°±æ˜¯æ¯�次new一个对象时自动调用,对 对象的åˆ�始化
-
+````
class A{
int i = 1;
int initValue;//æˆ�员å�˜é‡�çš„åˆ�始化交给代ç �å�—æ�¥å®Œæˆ�
@@ -340,7 +340,7 @@
A a = new A();
}
}
-
+````
### é�™æ€�代ç �å�—
ä½�置:类æˆ�员ä½�置,用static修饰的代ç �å�—
@@ -348,7 +348,8 @@
作用:对类进行一些åˆ�始化 å�ªåŠ è½½ä¸€æ¬¡ï¼Œå½“new多个对象时,å�ªæœ‰ç¬¬ä¸€æ¬¡ä¼šè°ƒç”¨é�™æ€�代ç �å�—ï¼Œå› ä¸ºï¼Œé�™æ€�代ç �å�— 是属于类的,所有对象共享一份
调用: new 一个对象时自动调用
-
+
+ ````
public class é�™æ€�代ç �å�— {
@Test
@@ -376,7 +377,7 @@
System.out.println("é�™æ€�代ç �å�—调用");
}
}
-
+````
## Java代ç �å�—ã€�æž„é€ æ–¹æ³•ï¼ˆåŒ…å�«ç»§æ‰¿å…³ç³»ï¼‰çš„æ‰§è¡Œé¡ºåº�
这是一é�“常è§�çš„é�¢è¯•题,è¦�回ç”这个问题,先看看这个实例å�§ã€‚
@@ -385,7 +386,7 @@
å…¶ä¸A是B的父类,Cæ— ç»§æ‰¿ä»…ä½œä¸ºè¾“å‡º
A类:
-
+````
public class A {
static {
@@ -408,8 +409,9 @@ A类:
}
}
+````
B类:
-
+````
public class B extends A {
private static C c1 = new C("B���员");
@@ -434,14 +436,16 @@ B类:
}
}
+````
C类:
-
+````
public class C {
public C(String str) {
Log.i("HIDETAG", str + "æž„é€ æ–¹æ³•");
}
}
+````
执行è¯å�¥ï¼šnew B();
输出结果如下:
@@ -473,7 +477,7 @@ C类:
**看完上é�¢è¿™ä¸ªdemo,å†�æ�¥çœ‹çœ‹ä¸‹é�¢è¿™é�“é¢˜ï¼Œçœ‹çœ‹ä½ æ�žå¾—定å�—?**
看下é�¢ä¸€æ®µä»£ç �,求执行顺åº�:
-
+````
class A {
public A() {
System.out.println("1Aç±»çš„æž„é€ æ–¹æ³•");
@@ -485,7 +489,7 @@ C类:
System.out.println("3A类的���");
}
}
-
+
public class B extends A {
public B() {
System.out.println("4Bç±»çš„æž„é€ æ–¹æ³•");
@@ -503,6 +507,7 @@ C类:
System.out.println("8");
}
}
+````
执行顺�结果为:367215421548
@@ -535,20 +540,3 @@ http://c.biancheng.net/view/976.html
https://blog.csdn.net/evilcry2012/article/details/79499786
https://www.jb51.net/article/129990.htm
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
diff --git "a/docs/java/basic/12\343\200\201\345\217\215\345\260\204.md" "b/docs/Java/basic/\345\217\215\345\260\204.md"
similarity index 51%
rename from "docs/java/basic/12\343\200\201\345\217\215\345\260\204.md"
rename to "docs/Java/basic/\345\217\215\345\260\204.md"
index 0513f67..14629eb 100644
--- "a/docs/java/basic/12\343\200\201\345\217\215\345\260\204.md"
+++ "b/docs/Java/basic/\345\217\215\345\260\204.md"
@@ -22,18 +22,6 @@
* [Java�射机制的作用](#java�射机制的作用)
* [如何使用Java的�射?](#如何使用java的�射)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
----
-title: 夯实Java基础系列12:深入ç�†è§£Javaä¸çš„å��射机制
-date: 2019-9-12 15:56:26 # æ–‡ç« ç”Ÿæˆ�时间,一般ä¸�改
-categories:
- - Java技术江湖
- - Java基础
-tags:
- - Java�射
----
æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
@@ -61,11 +49,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 +70,15 @@ Java�射框架主��供以下功能:
## �射的主�用途
->  很多人都认为å��射在实际的Javaå¼€å�‘应用ä¸å¹¶ä¸�广泛,其实ä¸�然。
+> 很多人都认为å��射在实际的Javaå¼€å�‘应用ä¸å¹¶ä¸�广泛,其实ä¸�然。
->  当我们在使用IDE(如Eclipse,IDEA)时,当我们输入一个对象或类并想调用它的属性或方法时,一按点�,编译器就会自动列出它的属性或方法,这里就会用到�射。
+> 当我们在使用IDE(如Eclipse,IDEA)时,当我们输入一个对象或类并想调用它的属性或方法时,一按点�,编译器就会自动列出它的属性或方法,这里就会用到�射。
->  �射最��的用途就是开���通用框架。
+> �射最��的用途就是开���通用框架。
->  很多框架(比如Spring)都是é…�置化的(比如通过XML文件é…�ç½®JavaBean,Action之类的),为了ä¿�è¯�框架的通用性,它们å�¯èƒ½éœ€è¦�æ ¹æ�®é…�ç½®æ–‡ä»¶åŠ è½½ä¸�å�Œçš„对象或类,调用ä¸�å�Œçš„æ–¹æ³•,这个时候就必须用到å��射——è¿�行时动æ€�åŠ è½½éœ€è¦�åŠ è½½çš„å¯¹è±¡ã€‚
+> 很多框架(比如Spring)都是é…�置化的(比如通过XML文件é…�ç½®JavaBean,Action之类的),为了ä¿�è¯�框架的通用性,它们å�¯èƒ½éœ€è¦�æ ¹æ�®é…�ç½®æ–‡ä»¶åŠ è½½ä¸�å�Œçš„对象或类,调用ä¸�å�Œçš„æ–¹æ³•,这个时候就必须用到å��射——è¿�行时动æ€�åŠ è½½éœ€è¦�åŠ è½½çš„å¯¹è±¡ã€‚
->  举一个例å�,在è¿�用Struts 2框架的开å�‘䏿ˆ‘们一般会在struts.xml里去é…�ç½®Action,比如:
-
-
- /shop/shop-index.jsp
- login.jsp
-
-é…�置文件与Action建立了一ç§�æ˜ å°„å…³ç³»ï¼Œå½“View层å�‘出请求时,请求会被StrutsPrepareAndExecuteFilter拦截,然å�ŽStrutsPrepareAndExecuteFilter会去动æ€�地创建Action实例。
-
-——比如我们请求login.action,那么StrutsPrepareAndExecuteFilter就会去解æž�struts.xml文件,检索actionä¸name为loginçš„Actionï¼Œå¹¶æ ¹æ�®class属性创建SimpleLoginAction实例,并用invoke方法æ�¥è°ƒç”¨execute方法,这个过程离ä¸�å¼€å��射。
-
-> 对与框架开å�‘人员æ�¥è¯´ï¼Œå��射虽å°�但作用é�žå¸¸å¤§ï¼Œå®ƒæ˜¯å�„ç§�å®¹å™¨å®žçŽ°çš„æ ¸å¿ƒã€‚è€Œå¯¹äºŽä¸€èˆ¬çš„å¼€å�‘者æ�¥è¯´ï¼Œä¸�深入框架开å�‘则用å��射用的就会少一点,ä¸�过了解一下框架的底层机制有助于丰富自己的编程æ€�想,也是很有益的。
+> 对于框架开å�‘人员æ�¥è¯´ï¼Œå��射虽å°�但作用é�žå¸¸å¤§ï¼Œå®ƒæ˜¯å�„ç§�å®¹å™¨å®žçŽ°çš„æ ¸å¿ƒã€‚è€Œå¯¹äºŽä¸€èˆ¬çš„å¼€å�‘者æ�¥è¯´ï¼Œä¸�深入框架开å�‘则用å��射用的就会少一点,ä¸�过了解一下框架的底层机制有助于丰富自己的编程æ€�想,也是很有益的。
## �射的基础:关于Class类
@@ -117,25 +93,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 +123,7 @@ JAVAå��射机制是在è¿�行状æ€�ä¸ï¼Œå¯¹äºŽä»»æ„�一个类,都能够知é�“
如图是类的æ£å¸¸åŠ è½½è¿‡ç¨‹ï¼šå��射的原ç�†åœ¨ä¸Žclass对象。
ç†Ÿæ‚‰ä¸€ä¸‹åŠ è½½çš„æ—¶å€™ï¼šClass对象的由æ�¥æ˜¯å°†class文件读入内å˜ï¼Œå¹¶ä¸ºä¹‹åˆ›å»ºä¸€ä¸ªClass对象。
-
-
+
## Java为什么需��射?�射�解决什么问题?
Javaä¸ç¼–译类型有两ç§�:
@@ -176,29 +152,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 +184,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 +205,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 +246,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 +295,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 +396,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�射常��试题
@@ -637,20 +612,3 @@ https://blog.csdn.net/grandgrandpa/article/details/84832343
http://blog.csdn.net/lylwo317/article/details/52163304
https://blog.csdn.net/qq_37875585/article/details/89340495
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
diff --git "a/docs/java/basic/17\343\200\201\345\244\232\347\272\277\347\250\213.md" "b/docs/Java/basic/\345\244\232\347\272\277\347\250\213.md"
similarity index 94%
rename from "docs/java/basic/17\343\200\201\345\244\232\347\272\277\347\250\213.md"
rename to "docs/Java/basic/\345\244\232\347\272\277\347\250\213.md"
index e2cc758..35e3ada 100644
--- "a/docs/java/basic/17\343\200\201\345\244\232\347\272\277\347\250\213.md"
+++ "b/docs/Java/basic/\345\244\232\347\272\277\347\250\213.md"
@@ -16,18 +16,7 @@
* [Java多线程优先级](#java多线程优先级)
* [Java多线程�试题](#java多线程�试题)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [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
@@ -91,7 +80,7 @@ Java 给多线程编程�供了内置的支�。 一�线程指的是进程
* **新建状�:**
- 使用 **new** 关键å—和 **Thread** 类或其å�类建立一个线程对象å�Žï¼Œè¯¥çº¿ç¨‹å¯¹è±¡å°±å¤„于新建状æ€�。它ä¿�æŒ�这个状æ€�直到程åº� **start()** 这个线程。
+ 使用**new**关键å—å’Œ**Thread**类或其å�类建立一个线程对象å�Žï¼Œè¯¥çº¿ç¨‹å¯¹è±¡å°±å¤„于新建状æ€�。它ä¿�æŒ�这个状æ€�直到程åº�**start()**这个线程。
* **就绪状�:**
@@ -99,7 +88,7 @@ Java 给多线程编程�供了内置的支�。 一�线程指的是进程
* **�行状�:**
- 如果就绪状æ€�的线程获å�– CPU 资æº�,就å�¯ä»¥æ‰§è¡ŒÂ **run()**ï¼Œæ¤æ—¶çº¿ç¨‹ä¾¿å¤„于è¿�行状æ€�。处于è¿�行状æ€�的线程最为å¤�æ�‚,它å�¯ä»¥å�˜ä¸ºé˜»å¡žçжæ€�ã€�就绪状æ€�å’Œæ»äº¡çжæ€�。
+ 如果就绪状æ€�的线程获å�– CPU 资æº�,就å�¯ä»¥æ‰§è¡Œ**run()**ï¼Œæ¤æ—¶çº¿ç¨‹ä¾¿å¤„于è¿�行状æ€�。处于è¿�行状æ€�的线程最为å¤�æ�‚,它å�¯ä»¥å�˜ä¸ºé˜»å¡žçжæ€�ã€�就绪状æ€�å’Œæ»äº¡çжæ€�。
* **阻塞状�:**
@@ -642,21 +631,4 @@ https://blog.csdn.net/qq_38038480/article/details/80584715
https://blog.csdn.net/tongxuexie/article/details/80145663
https://www.cnblogs.com/snow-flower/p/6114765.html
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
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/\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"
similarity index 57%
rename from "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"
rename to "docs/Java/basic/\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..c6d33a7 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/\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"
@@ -9,18 +9,7 @@
* [为什么�实现Serializable](#为什么�实现serializable)
* [�列化知识点总结](#�列化知识点总结)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [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 +26,6 @@ tags:
-
本文�考 http://www.importnew.com/17964.html和
https://www.ibm.com/developerworks/cn/java/j-lo-serial/
@@ -86,96 +74,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 +169,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() {
+
+ }
+ //实现下é�¢ä¸¤ä¸ªæ–¹æ³•å�¯ä»¥é€‰æ‹©åº�列化ä¸éœ€è¦�被å¤�制的æˆ�员。
+ //并且,写入顺�和读�顺��一致,�则报错。
+ //�以写入多个�类型��,顺���一致��。
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeInt(i);
+ out.writeInt(j);
+ out.writeObject(s);
}
-
- @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 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 +228,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 +323,7 @@ ArrayList的�列化
带ç�€è¿™ä¸ªé—®é¢˜ï¼Œæˆ‘们æ�¥çœ‹java.util.ArrayListçš„æº�ç �
+````
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
{
@@ -341,26 +331,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 +367,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 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 writeObject0 --->writeOrdinaryObject--->writeSerialData--->invokeWriteObject
这里看一下invokeWriteObject:
-
- void invokeWriteObject(Object obj, ObjectOutputStream out)
- throws IOException, UnsupportedOperationException
- {
- if (writeObjectMethod != null) {
- try {
- writeObjectMethod.invoke(obj, new Object[]{ out });
- } catch (InvocationTargetException ex) {
- Throwable th = ex.getTargetException();
- if (th instanceof IOException) {
- throw (IOException) th;
- } else {
- throwMiscException(th);
- }
- } catch (IllegalAccessException ex) {
- // should not occur, as access checks have been suppressed
- throw new InternalError(ex);
+````
+void invokeWriteObject(Object obj, ObjectOutputStream out)
+ throws IOException, UnsupportedOperationException
+ {
+ if (writeObjectMethod != null) {
+ try {
+ writeObjectMethod.invoke(obj, new Object[]{ out });
+ } catch (InvocationTargetException ex) {
+ Throwable th = ex.getTargetException();
+ if (th instanceof IOException) {
+ throw (IOException) th;
+ } else {
+ throwMiscException(th);
}
- } else {
- throw new UnsupportedOperationException();
+ } catch (IllegalAccessException ex) {
+ // should not occur, as access checks have been suppressed
+ throw new InternalError(ex);
}
+ } else {
+ throw new UnsupportedOperationException();
}
+ }
+````
å…¶ä¸writeObjectMethod.invoke(obj, new Object[]{ out });是关键,通过å��射的方å¼�调用writeObjectMethod方法。官方是这么解释这个writeObjectMethod的:
class-defined writeObject method, or null if none
@@ -489,45 +479,45 @@ class-defined writeObject method, or null if none
如果一个类ä¸åŒ…å�«writeObject å’Œ readObject 方法,那么这两个方法是怎么被调用的?
ç”:在使用ObjectOutputStreamçš„writeObject方法和ObjectInputStreamçš„readObject方法时,会通过å��射的方å¼�调用。
-
-
-​
+
## 为什么�实现Serializable
至æ¤ï¼Œæˆ‘们已ç»�介ç»�完了ArrayListçš„åº�列化方å¼�。那么,ä¸�知é�“有没有人æ��å‡ºè¿™æ ·çš„ç–‘é—®ï¼š
Serializable明明就是一个空的接�,它是怎么���有实现了该接�的方法�能进行�列化与��列化的呢?
+````
+Serializable接�的定义:
- Serializable接�的定义:
-
- public interface Serializable {
- }
- 读者å�¯ä»¥å°�试把code 1ä¸çš„继承Serializable的代ç �去掉,å†�执行code 2,会抛出java.io.NotSerializableException。
+public interface Serializable {
+}
+````
+
+读者å�¯ä»¥å°�试把code 1ä¸çš„继承Serializable的代ç �去掉,å†�执行code 2,会抛出java.io.NotSerializableException。
其实这个问题也很好回ç”,我们å†�回到刚刚ObjectOutputStreamçš„writeObjectçš„è°ƒç”¨æ ˆï¼š
writeObject ---> writeObject0 --->writeOrdinaryObject--->writeSerialData--->invokeWriteObject
writeObject0æ–¹æ³•ä¸æœ‰è¿™ä¹ˆä¸€æ®µä»£ç �:
-
- if (obj instanceof String) {
- writeString((String) obj, unshared);
- } else if (cl.isArray()) {
- writeArray(obj, desc, unshared);
- } else if (obj instanceof Enum) {
- writeEnum((Enum>) obj, desc, unshared);
- } else if (obj instanceof Serializable) {
- writeOrdinaryObject(obj, desc, unshared);
- } else {
- if (extendedDebugInfo) {
- throw new NotSerializableException(
- cl.getName() + "\n" + debugInfoStack.toString());
- } else {
- throw new NotSerializableException(cl.getName());
- }
- }
+````
+if (obj instanceof String) {
+ writeString((String) obj, unshared);
+} else if (cl.isArray()) {
+ writeArray(obj, desc, unshared);
+} else if (obj instanceof Enum) {
+ writeEnum((Enum>) obj, desc, unshared);
+} else if (obj instanceof Serializable) {
+ writeOrdinaryObject(obj, desc, unshared);
+} else {
+ if (extendedDebugInfo) {
+ throw new NotSerializableException(
+ cl.getName() + "\n" + debugInfoStack.toString());
+ } else {
+ throw new NotSerializableException(cl.getName());
+ }
+}
+````
在进行åº�列化æ“�作时,会判æ–è¦�被åº�列化的类是å�¦æ˜¯Enumã€�Arrayå’ŒSerializable类型,如果ä¸�是则直接抛出NotSerializableException。
-
## �列化知识点总结
> 1ã€�如果一个类想被åº�列化,需è¦�实现Serializable接å�£ã€‚å�¦åˆ™å°†æŠ›å‡ºNotSerializableExceptionå¼‚å¸¸ï¼Œè¿™æ˜¯å› ä¸ºï¼Œåœ¨åº�列化æ“�作过程ä¸ä¼šå¯¹ç±»åž‹è¿›è¡Œæ£€æŸ¥ï¼Œè¦�求被åº�列化的类必须属于Enumã€�Arrayå’ŒSerializable类型其ä¸çš„任何一ç§�。
@@ -558,20 +548,3 @@ https://segmentfault.com/a/1190000012220863
https://my.oschina.net/wuxinshui/blog/1511484
https://blog.csdn.net/hukailee/article/details/81107412
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
diff --git "a/docs/java/basic/6\343\200\201\346\212\275\350\261\241\347\261\273\345\222\214\346\216\245\345\217\243.md" "b/docs/Java/basic/\346\212\275\350\261\241\347\261\273\345\222\214\346\216\245\345\217\243.md"
similarity index 91%
rename from "docs/java/basic/6\343\200\201\346\212\275\350\261\241\347\261\273\345\222\214\346\216\245\345\217\243.md"
rename to "docs/Java/basic/\346\212\275\350\261\241\347\261\273\345\222\214\346\216\245\345\217\243.md"
index e3bd41a..40cd496 100644
--- "a/docs/java/basic/6\343\200\201\346\212\275\350\261\241\347\261\273\345\222\214\346\216\245\345\217\243.md"
+++ "b/docs/Java/basic/\346\212\275\350\261\241\347\261\273\345\222\214\346\216\245\345\217\243.md"
@@ -15,9 +15,7 @@
* [设计�想区别](#设计�想区别)
* [如何回ç”é�¢è¯•题:接å�£å’ŒæŠ½è±¡ç±»çš„区别?](#如何回ç”é�¢è¯•题:接å�£å’ŒæŠ½è±¡ç±»çš„区别)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
> https://github.com/h2pl/Java-Tutorial
@@ -32,8 +30,6 @@
å¦‚æžœå¯¹æœ¬ç³»åˆ—æ–‡ç« æœ‰ä»€ä¹ˆå»ºè®®ï¼Œæˆ–è€…æ˜¯æœ‰ä»€ä¹ˆç–‘é—®çš„è¯�,也å�¯ä»¥å…³æ³¨å…¬ä¼—å�·ã€�Java技术江湖】è�”ç³»ä½œè€…ï¼Œæ¬¢è¿Žä½ å�‚与本系列å�šæ–‡çš„åˆ›ä½œå’Œä¿®è®¢ã€‚
-
-
@@ -50,7 +46,7 @@
包�一个或多个抽象方法的类也必须被声明为抽象类。
使用abstract修饰符�表示抽象方法以�抽象类。
-
+````
//有抽象方法的类也必须被声明为abstract
public abstract class Test1 {
@@ -58,10 +54,11 @@
public abstract void f();
}
+````
抽象类除了包å�«æŠ½è±¡æ–¹æ³•外,还å�¯ä»¥åŒ…å�«å…·ä½“çš„å�˜é‡�和具体的方法。类å�³ä½¿ä¸�包å�«æŠ½è±¡æ–¹æ³•,也å�¯ä»¥è¢«å£°æ˜Žä¸ºæŠ½è±¡ç±»ï¼Œé˜²æ¢è¢«å®žä¾‹åŒ–。
抽象类ä¸�能被实例化,也就是ä¸�能使用new关键嗿�¥å¾—到一个抽象类的实例,抽象方法必须在å�ç±»ä¸è¢«å®žçŽ°ã€‚
-
+````
//有抽象方法的类也必须被声明为abstract
public class Test1 {
@@ -72,7 +69,6 @@
Driver driver=new Driver("驾驶员");
driver.work();
}
-
}
//一个抽象类
abstract class People{
@@ -87,8 +83,7 @@
@Override
public void work() {
System.out.println("我的�业是"+this.work);
- }
-
+ }
}
class Driver extends People{
private String work;
@@ -99,29 +94,30 @@
public void work() {
System.out.println("我的�业是"+this.work);
}
-
}
+````
+
> �行结果:
> 我的�业是教师
> 我的�业是驾驶员
> å‡ ç‚¹è¯´æ˜Ž:
抽象类ä¸�能直接使用,需è¦�å�类去实现抽象类,然å�Žä½¿ç”¨å…¶å�类的实例。然而å�¯ä»¥åˆ›å»ºä¸€ä¸ªå�˜é‡�,其类型也是一个抽象类,并让他指å�‘具体å�类的一个实例,也就是å�¯ä»¥ä½¿ç”¨æŠ½è±¡ç±»æ�¥å……当形å�‚,实际实现类为实å�‚,也就是多æ€�的应用。
-
+````
People people=new Teacher("教师");
people.work();
-
+````
ä¸�èƒ½æœ‰æŠ½è±¡æž„é€ æ–¹æ³•æˆ–æŠ½è±¡é�™æ€�方法。
如果é�žè¦�使用new关键在æ�¥åˆ›å»ºä¸€ä¸ªæŠ½è±¡ç±»çš„实例的è¯�,å�¯ä»¥è¿™æ ·ï¼š
-
+````
People people=new People() {
@Override
public void work() {
//实现这个方法的具体功能
}
};
-
+````
个人ä¸�推è��è¿™ç§�方法,代ç �读起æ�¥æœ‰ç‚¹ç´¯ã€‚
在下列情况下,一个类将�为抽象类:
@@ -147,14 +143,14 @@
### 一个抽象类�故事
下�看一个关于抽象类的�故事
-
-é—®ä½ ä¸ªé—®é¢˜ï¼Œä½ çŸ¥é�“什么是“东西â€�å�—?什么是“物体â€�å�—?
-â€œéº»çƒ¦ä½ ï¼Œå°�王。帮我把那个东西拿过æ�¥å¥½å�—â€�
-在生活ä¸ï¼Œä½ 肯定用过这个è¯�ï¼�ï¼�东西。
-å°�çŽ‹ï¼šâ€œä½ è¦�è®©æˆ‘å¸®ä½ æ‹¿é‚£ä¸ªæ°´æ�¯å�—?â€�
-ä½ è¦�的是水æ�¯ç±»çš„对象。而东西是水æ�¯çš„父类。通常东西类没有实例对象,但我们有时需è¦�东西的引用指å�‘它的å�类实例。
-
-ä½ çœ‹ä½ çš„æˆ¿é—´ä¹±æˆ�ä»€ä¹ˆæ ·å�了,以å�Žä¸�è¦�把东西乱放了,知é�“么?
+
+ é—®ä½ ä¸ªé—®é¢˜ï¼Œä½ çŸ¥é�“什么是“东西â€�å�—?什么是“物体â€�å�—?
+ â€œéº»çƒ¦ä½ ï¼Œå°�王。帮我把那个东西拿过æ�¥å¥½å�—â€�
+ 在生活ä¸ï¼Œä½ 肯定用过这个è¯�ï¼�ï¼�东西。
+ å°�çŽ‹ï¼šâ€œä½ è¦�è®©æˆ‘å¸®ä½ æ‹¿é‚£ä¸ªæ°´æ�¯å�—?â€�
+ ä½ è¦�的是水æ�¯ç±»çš„对象。而东西是水æ�¯çš„父类。通常东西类没有实例对象,但我们有时需è¦�东西的引用指å�‘它的å�类实例。
+
+ ä½ çœ‹ä½ çš„æˆ¿é—´ä¹±æˆ�ä»€ä¹ˆæ ·å�了,以å�Žä¸�è¦�把东西乱放了,知é�“么?
上é�¢è®²çš„å�ªæ˜¯å�类和父类。而没有说明抽象类的作用。抽象类是æ�®æœ‰ä¸€ä¸ªæˆ–多个抽象方法的类,必须声明为抽象类。抽象类的特点是,ä¸�能创建实例。
@@ -165,6 +161,7 @@
### 一个抽象类�游�
接下�,我们�写一个�游�。俄罗斯方��我们�分�一下它需�什么类?
+
我知é�“它è¦�在一个矩形的房å�里完æˆ�。这个房å�的上é�¢å‡ºçŽ°ä¸€ä¸ªæ–¹å�—,慢慢的下è�½ï¼Œå½“它接触到地é�¢æˆ–是其它方å�—的尸体时,它就å�œæ¢ä¸‹è�½äº†ã€‚ç„¶å�Žæˆ¿å�的上é�¢å�ˆä¼šå‡ºçŽ°ä¸€ä¸ªæ–°çš„æ–¹å�—,与å‰�一个方å�—ä¸€æ ·ï¼Œä¹Ÿä¼šæ…¢æ…¢çš„ä¸‹è�½ã€‚在它还没有æ»äº¡ä¹‹å‰�,我å�¯ä»¥å°½é‡�çš„ç§»åŠ¨å’Œç¿»è½¬å®ƒã€‚è¿™æ ·å�¯ä»¥ä½¿å®ƒèµ·åˆ°è�½åœ°æ—¶èµ·åˆ°ä¸€å®šçš„作用,如果好的è¯�,还å�¯ä»¥å‡�ä¸‹å°‘å‡ è¡Œå‘¢ã€‚è¿™çœ‹èµ·æ�¥å¥½è±¡äººç”Ÿä¸€æ ·ï¼Œå®ƒåœ¨ä¸ºå�Žæ�¥äººåŠªåŠ›ç�€ã€‚
当然,我们ä¸�是真的è¦�写一个游æˆ�。所以我们简化它。我抽象出两个必须的类,一个是那个房间,或者就它地图也行。å�¦ä¸€ä¸ªæ˜¯æ–¹å�—。我å�‘现方å�—有很多ç§�,数一下,共6ç§�。它们都是四个å°�矩形构æˆ�的。但是它们还有很多ä¸�å�Œï¼Œä¾‹å¦‚:它们的翻转方法ä¸�å�Œã€‚先把这个问题放到一边去,我们回到房å�这个类ä¸ã€‚
@@ -182,7 +179,7 @@
把那些和“东西â€�å·®ä¸�多的类写æˆ�抽象的。而水æ�¯ä¸€æ ·çš„类就å�¯ä»¥ä¸�是抽象的了。当然水æ�¯ä¹Ÿæœ‰å‡ å�ƒå�—é’±ä¸€ä¸ªçš„å’Œå‡ å�—钱一个的。水æ�¯ä¹Ÿæœ‰å�类,例如,我用的水æ�¯éƒ½å¾ˆé«˜æ¡£ï¼Œå¤§å¤šéƒ½æ˜¯ä¸€æ¬¡æ€§çš„纸水æ�¯ã€‚
-è®°ä½�一点,é�¢å�‘对象ä¸�是æ�¥è‡ªäºŽJava,é�¢å�‘å¯¹è±¡å°±åœ¨ä½ çš„ç”Ÿæ´»ä¸ã€‚而Javaçš„é�¢å�‘å¯¹è±¡æ˜¯æ–¹ä¾¿ä½ è§£å†³å¤�æ�‚的问题。这ä¸�是说é�¢å�‘对象很简å�•,虽然é�¢å�‘对象很å¤�æ�‚,但Java知é�“ï¼Œä½ å¾ˆäº†è§£é�¢å�‘å¯¹è±¡ï¼Œå› ä¸ºå®ƒå°±åœ¨ä½ èº«è¾¹ã€‚
+è®°ä½�一点,é�¢å�‘对象ä¸�是æ�¥è‡ªäºŽJava,é�¢å�‘å¯¹è±¡å°±åœ¨ä½ çš„ç”Ÿæ´»ä¸ã€‚而Javaçš„é�¢å�‘å¯¹è±¡æ˜¯æ–¹ä¾¿ä½ è§£å†³å¤�æ�‚的问题。这ä¸�是说é�¢å�‘对象很简å�•,虽然é�¢å�‘对象很å¤�æ�‚,但Java知é�“ï¼Œä½ å¾ˆäº†è§£é�¢å�‘å¯¹è±¡ï¼Œå› ä¸ºå®ƒå°±åœ¨ä½ èº«è¾¹ã€‚
## 接�介�
@@ -230,7 +227,7 @@
我们æ�¥ä¸¾ä¸ªä¾‹å�,定义一个抽象类People,一个普通å�ç±»Student,两个接å�£ã€‚å�ç±»Student继承父类People,并实现接å�£Study,Write
代ç �演示:
-
+````
package demo;
//构建一个抽象类People
abstract class People{
@@ -307,7 +304,7 @@
student.stu();
}
}
-
+````
代ç �讲解:上述例å�结å�ˆäº†æŠ½è±¡ç±»å’ŒæŽ¥å�£çš„知识,内容较多,å�Œå¦ä»¬å�¯ä»¥å¤šçœ‹å¤šæ•²ä¸€ä¸‹ï¼Œå¦ä¹ å¦ä¹ 。
接�的实现:类� implements 接��,有多个接��,用“,�隔开��。
@@ -320,7 +317,7 @@
如电脑�以和�个设备连接,�供统一的USB接�,其他设备�能通过USB接�和电脑相连
代ç �实现:
-
+````
package demo;
interface USB
@@ -378,12 +375,12 @@
computer.plugin(usb) ; //实例化接�类, 在电脑上使用U盘
}
}
+````
代ç �讲解:我们修改了主函数å�Žï¼Œå�‘现,使用了两次的å�‘上转型给了USB,虽然使用的都是usb对象,但赋值的å�类对象ä¸�ä¸€æ ·ï¼Œå®žçŽ°çš„æ–¹æ³•ä½“ä¹Ÿä¸�å�Œï¼Œè¿™å°±å¾ˆåƒ�çŽ°å®žç”Ÿæ´»ï¼Œæ— è®ºæˆ‘ä½¿ç”¨çš„æ˜¯æ‰“å�°æœºï¼Œè¿˜æ˜¯U盘,我都是通过USB接å�£å’Œç”µè„‘连接的,这就是接å�£çš„ä½œç”¨ä¹‹ä¸€â€”â€”åˆ¶å®šæ ‡å‡†
我们æ�¥ä¸ªå›¾ç»§ç»å¸®åЩ大家ç�†è§£ä¸€ä¸‹ï¼š
-
-
+
上é�¢çš„图:我们å¦ä¹ å‰�é�¢çš„ç« èŠ‚å¤šæ€�å�¯ä»¥çŸ¥é�“对象的多æ€�å�¯ä»¥é€šè¿‡åЍæ€�绑定æ�¥å®žçŽ°ï¼Œå�³ä½¿ç”¨å�‘上转型,我们知é�“类,数组,接å�£éƒ½æ˜¯å¼•用类型å�˜é‡�,什么是引用类型å�˜é‡�?
引用类型å�˜é‡�都会有一个地å�€çš„æ¦‚念,å�³æŒ‡å�‘性的概念,当USB usb = new Print(),æ¤æ—¶usb对象是指å�‘new Print()的,当usb = new Flash()å�Žï¼Œè¿™æ—¶å€™usbå�˜é‡�就会指å�‘new Flash(),我们会说这是å�类对象赋值给了父类对象usb,而在内å˜ä¸ï¼Œæˆ‘们应该说,usb指å�‘了new Flash();
@@ -397,7 +394,7 @@
由于创建过程都由工厂统一管ç�†ï¼Œæ‰€ä»¥å�‘生业务逻辑å�˜åŒ–,ä¸�需è¦�找到所有需è¦�创建B的地方去é€�个修æ£ï¼Œå�ªéœ€è¦�在工厂里修改å�³å�¯ï¼Œé™�低维护æˆ�本。å�Œç�†ï¼Œæƒ³æŠŠæ‰€æœ‰è°ƒç”¨B的地方改æˆ�Bçš„å�ç±»C,å�ªéœ€è¦�在对应生产Bçš„å·¥åŽ‚ä¸æˆ–者工厂的方法ä¸ä¿®æ”¹å…¶ç”Ÿäº§çš„对象为Cå�³å�¯ï¼Œè€Œä¸�需è¦�找到所有的new B()改为newC()。
代ç �演示:
-
+````
package demo;
import java.util.Scanner;
@@ -452,9 +449,12 @@
sc.close();
}
}
+````
代ç �讲解:上述代ç �部分我们讲一下factoryè¿™ä¸ªç±»ï¼Œç±»ä¸æœ‰ä¸€ä¸ªgetInstance方法,我们用了static关键å—修饰,在使用的时候我们就在mainä¸ä½¿ç”¨ç±»å��.方法å��调用。
-
+````
Fruit f = factory.getInstance(ans); //�始化�数
+
+````
在Factoryçš„getInstance()方法ä¸ï¼Œæˆ‘们就å�¯ä»¥é€šè¿‡é€»è¾‘的实现,将对象的创建和使用的过程分开了。
@@ -466,50 +466,57 @@ Fruit f = factory.getInstance(ans); //�始化�数
### åŸºæœ¬è¯æ³•区别
在 Java ä¸ï¼ŒæŽ¥å�£å’ŒæŠ½è±¡ç±»çš„å®šä¹‰è¯æ³•是ä¸�ä¸€æ ·çš„ã€‚è¿™é‡Œä»¥åŠ¨ç‰©ç±»ä¸ºä¾‹æ�¥è¯´æ˜Žï¼Œå…¶ä¸å®šä¹‰æŽ¥å�£çš„示æ„�代ç �如下:
-
-public interface Animal
+````
+public interface Animal
{
//所有动物都会�
public void eat();
//所有动物都会飞
public void fly();
-}
+}
+````
定义抽象类的示æ„�代ç �如下:
-public abstract class Animal
+````
+public abstract class Animal
{
//所有动物都会�
public abstract void eat();
//所有动物都会飞
public void fly(){};
-}
+}
+````
å�¯ä»¥çœ‹åˆ°ï¼Œåœ¨æŽ¥å�£å†…å�ªèƒ½æ˜¯åŠŸèƒ½çš„å®šä¹‰ï¼Œè€ŒæŠ½è±¡ç±»ä¸åˆ™å�¯ä»¥åŒ…括功能的定义和功能的实现。在接å�£ä¸ï¼Œæ‰€æœ‰çš„属性肯定是 publicã€�static å’Œ final,所有的方法都是 abstract,所以å�¯ä»¥é»˜è®¤ä¸�å†™ä¸Šè¿°æ ‡è¯†ç¬¦ï¼›åœ¨æŠ½è±¡ç±»ä¸ï¼Œæ—¢å�¯ä»¥åŒ…å�«æŠ½è±¡çš„定义,也å�¯ä»¥åŒ…å�«å…·ä½“的实现方法。
在具体的实现类上,接å�£å’ŒæŠ½è±¡ç±»çš„实 现类定义方å¼�也是ä¸�ä¸€æ ·çš„ï¼Œå…¶ä¸æŽ¥å�£å®žçŽ°ç±»çš„ç¤ºæ„�代ç �如下:
-public class concreteAnimal implements Animal
+````
+public class concreteAnimal implements Animal
{
//所有动物都会�
public void eat(){}
//所有动物都会飞
public void fly(){}
-}
+}
+````
抽象类的实现类示æ„�代ç �如下:
-public class concreteAnimal extends Animal
+````
+public class concreteAnimal extends Animal
{
//所有动物都会�
public void eat(){}
//所有动物都会飞
public void fly(){}
-}
+}
+````
å�¯ä»¥çœ‹åˆ°ï¼Œåœ¨æŽ¥å�£çš„实现类ä¸ä½¿ç”¨ implements 关键å—;而在抽象类的实现类ä¸ï¼Œåˆ™ä½¿ç”¨ extends 关键å—。一个接å�£çš„实现类å�¯ä»¥å®žçŽ°å¤šä¸ªæŽ¥å�£ï¼Œè€Œä¸€ä¸ªæŠ½è±¡ç±»çš„实现类则å�ªèƒ½å®žçŽ°ä¸€ä¸ªæŠ½è±¡ç±»ã€‚
@@ -521,48 +528,53 @@ Fruit f = factory.getInstance(ans); //�始化�数
ä»�然以å‰�é�¢åŠ¨ç‰©ç±»çš„è®¾è®¡ä¸ºä¾‹æ�¥è¯´æ˜ŽæŽ¥å�£å’ŒæŠ½è±¡ç±»å…³äºŽè®¾è®¡æ€�想的区别,该动物类默认所有的动物都具有å�ƒçš„功能,其ä¸å®šä¹‰æŽ¥å�£çš„示æ„�代ç �如下:
-public interface Animal
+````
+public interface Animal
{
//所有动物都会�
public void eat();
-}
+}
+````
定义抽象类的示æ„�代ç �如下:
-public abstract class Animal
+````
+public abstract class Animal
{
//所有动物都会�
public abstract void eat();
-}
+}
+````
ä¸�管是实现接å�£ï¼Œè¿˜æ˜¯ç»§æ‰¿æŠ½è±¡ç±»çš„具体动物,都具有å�ƒçš„功能,具体的动物类的示æ„�代ç �如下。
接å�£å®žçŽ°ç±»çš„ç¤ºæ„�代ç �如下:
-public class concreteAnimal implements Animal
+````
+public class concreteAnimal implements Animal
{
//所有动物都会�
public void eat(){}
-}
+}
抽象类的实现类示æ„�代ç �如下:
-public class concreteAnimal extends Animal
+public class concreteAnimal extends Animal
{
//所有动物都会�
public void eat(){}
-}
+}
当然,具体的动物类ä¸�光具有å�ƒçš„功能,比如有些动物还会飞,而有些动物å�´ä¼šæ¸¸æ³³ï¼Œé‚£ä¹ˆè¯¥å¦‚何设计这个抽象的动物类呢?å�¯ä»¥åˆ«åœ¨æŽ¥å�£å’ŒæŠ½è±¡ç±»ä¸å¢žåŠ é£žçš„åŠŸèƒ½ï¼Œå…¶ä¸å®šä¹‰æŽ¥å�£çš„示æ„�代ç �如下:
-public interface Animal
+public interface Animal
{
//所有动物都会�
public void eat();
//所有动物都会飞
public void fly();
-}
+}
定义抽象类的示æ„�代ç �如下:
@@ -577,38 +589,38 @@ Fruit f = factory.getInstance(ans); //�始化�数
è¿™æ ·ä¸€æ�¥ï¼Œä¸�管是接å�£è¿˜æ˜¯æŠ½è±¡ç±»çš„实现类,都具有飞的功能,这显然ä¸�能满足è¦�æ±‚ï¼Œå› ä¸ºå�ªæœ‰ä¸€éƒ¨åˆ†åŠ¨ç‰©ä¼šé£žï¼Œè€Œä¼šé£žçš„å�´ä¸�一定是动物,比如飞机也会飞。那该如何设计呢?有很多ç§�方案,比如å†�设计一个动物的接å�£ç±»ï¼Œè¯¥æŽ¥å�£å…·æœ‰é£žçš„功能,示æ„�代ç �如下:
-public interface AnimaiFly
+public interface AnimaiFly
{
//所有动物都会飞
public void fly();
-}
+}
那些具体的动物类,如果有飞的功能的è¯�,除了实现å�ƒçš„æŽ¥å�£å¤–,å†�实现飞的接å�£ï¼Œç¤ºæ„�代ç �如下:
-public class concreteAnimal implements Animal,AnimaiFly
+public class concreteAnimal implements Animal,AnimaiFly
{
//所有动物都会�
public void eat(){}
//动物会飞
public void fly();
-}
+}
那些ä¸�需è¦�飞的功能的具体动物类å�ªå®žçް具体å�ƒçš„功能的接å�£å�³å�¯ã€‚å�¦å¤–一ç§�解决方案是å†�设计一个动物的抽象类,该抽象类具有飞的功能,示æ„�代ç �如下:
-public abstract class AnimaiFly
+public abstract class AnimaiFly
{
//动物会飞
public void fly();
-}
+}
ä½†æ¤æ—¶æ²¡æœ‰åŠžæ³•å®žçŽ°é‚£äº›æ—¢æœ‰å�ƒçš„功能,å�ˆæœ‰é£žçš„åŠŸèƒ½çš„å…·ä½“åŠ¨ç‰©ç±»ã€‚å› ä¸ºåœ¨ Java ä¸å…·ä½“的实现类å�ªèƒ½å®žçŽ°ä¸€ä¸ªæŠ½è±¡ç±»ã€‚ä¸€ä¸ªæŠ˜ä¸çš„解决办法是,让这个具有飞的功能的抽象类,继承具有å�ƒçš„功能的抽象类,示æ„�代ç �如下:
-public abstract class AnimaiFly extends Animal
+public abstract class AnimaiFly extends Animal
{
//动物会飞
public void fly();
-}
+}
æ¤æ—¶ï¼Œå¯¹é‚£äº›å�ªéœ€è¦�å�ƒçš„功能的具体动物类æ�¥è¯´ï¼Œç»§æ‰¿ Animal 抽象类å�³å�¯ã€‚对那些既有å�ƒçš„功能å�ˆæœ‰é£žçš„功能的具体动物类æ�¥è¯´ï¼Œåˆ™éœ€è¦�继承 AnimalFly 抽象类。
@@ -618,57 +630,58 @@ Fruit f = factory.getInstance(ans); //�始化�数
具有å�ƒçš„功能的抽象动物类用抽象类æ�¥å®žçŽ°ï¼Œç¤ºæ„�代ç �如下:
-public abstract class Animal
+public abstract class Animal
{
//所有动物都会�
public abstract void eat();
-}
+}
具有飞的功能的类用接å�£å®žçŽ°ï¼Œç¤ºæ„�代ç �如下:
-public interface AnimaiFly
+public interface AnimaiFly
{
//动物会飞
public void fly();
-}
+}
既具有å�ƒçš„功能å�ˆå…·æœ‰é£žçš„功能的具体的动物类,则继承 Animal 动物抽象类,实现 AnimalFly 接å�£ï¼Œç¤ºæ„�代ç �如下:
-public class concreteAnimal extends Animal implements AnimaiFly
+public class concreteAnimal extends Animal implements AnimaiFly
{
//所有动物都会�
public void eat(){}
//动物会飞
public void fly();
-}
+}
或者具有å�ƒçš„功能的抽象动物类用接å�£æ�¥å®žçŽ°ï¼Œç¤ºæ„�代ç �如下:
-public interface Animal
+public interface Animal
{
//所有动物都会�
public abstract void eat();
-}
+}
具有飞的功能的类用抽象类实现,示æ„�代ç �如下:
-public abstract class AnimaiFly
+public abstract class AnimaiFly
{
//动物会飞
public void fly(){};
-}
+}
既具有å�ƒçš„功能å�ˆå…·æœ‰é£žçš„功能的具体的动物类,则实现 Animal 动物类接å�£ï¼Œç»§æ‰¿ AnimaiFly 抽象类,示æ„�代ç �如下:
-public class concreteAnimal extends AnimaiFly implements Animal
+public class concreteAnimal extends AnimaiFly implements Animal
{
//所有动物都会�
public void eat(){}
//动物会飞
public void fly();
-}
+}
+````
这些解决方案有什么ä¸�å�Œå‘¢ï¼Ÿå†�回过头æ�¥çœ‹æŽ¥å�£å’ŒæŠ½è±¡ç±»çš„区别:抽象类是对一组具有相å�Œå±žæ€§å’Œæ–¹æ³•的逻辑上有关系的事物的一ç§�抽象,而接å�£åˆ™æ˜¯å¯¹ä¸€ç»„具有相å�Œå±žæ€§å’Œæ–¹æ³•的逻辑上ä¸�相关的事物的一ç§�æŠ½è±¡ï¼Œå› æ¤æŠ½è±¡ç±»è¡¨ç¤ºçš„æ˜¯â€œis aâ€�关系,接å�£è¡¨ç¤ºçš„æ˜¯â€œlike aâ€�关系。
@@ -717,21 +730,4 @@ https://www.runoob.com/java/java-interfaces.html
https://blog.csdn.net/fengyunjh/article/details/6605085
https://blog.csdn.net/xkfanhua/article/details/80567557
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
diff --git "a/docs/java/basic/14\343\200\201\346\236\232\344\270\276\347\261\273.md" "b/docs/Java/basic/\346\236\232\344\270\276\347\261\273.md"
similarity index 69%
rename from "docs/java/basic/14\343\200\201\346\236\232\344\270\276\347\261\273.md"
rename to "docs/Java/basic/\346\236\232\344\270\276\347\261\273.md"
index 2891f98..5fc7cb6 100644
--- "a/docs/java/basic/14\343\200\201\346\236\232\344\270\276\347\261\273.md"
+++ "b/docs/Java/basic/\346\236\232\344\270\276\347\261\273.md"
@@ -1,5 +1,4 @@
# 目录
-
* [�探枚举类](#�探枚举类)
* [枚举类-è¯æ³•](#枚举类-è¯æ³•)
* [枚举类的具体使用](#枚举类的具体使用)
@@ -20,9 +19,7 @@
* [枚举 API](#枚举-api)
* [总结](#总结)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
---
æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
@@ -94,136 +91,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));
}
-
+}
+````
## 使用枚举类的注�事项
-
+
枚举类型对象之间的值比较,是å�¯ä»¥ä½¿ç”¨==,直接æ�¥æ¯”较值,是å�¦ç›¸ç‰çš„,ä¸�是必须使用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 +232,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 +288,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 +333,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这三个方法,这三个方法和枚举通过é�™æ€�代ç �å�—æ�¥è¿›è¡Œåˆ�始化一起。
@@ -507,20 +505,3 @@ https://segmentfault.com/a/1190000012220863
https://my.oschina.net/wuxinshui/blog/1511484
https://blog.csdn.net/hukailee/article/details/81107412
-## 微信公众�
-
-### Java技术江湖
-
-如果大家想è¦�å®žæ—¶å…³æ³¨æˆ‘æ›´æ–°çš„æ–‡ç« ä»¥å�Šåˆ†äº«çš„干货的è¯�,å�¯ä»¥å…³æ³¨æˆ‘的公众å�·ã€�Java技术江湖】一ä½�阿里 Java 工程师的技术å°�站,作者黄å°�斜,专注 Java 相关技术:SSMã€�SpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�集群ã€�Linuxã€�网络ã€�多线程,å�¶å°”讲点Dockerã€�ELK,å�Œæ—¶ä¹Ÿåˆ†äº«æŠ€æœ¯å¹²è´§å’Œå¦ä¹ ç»�验,致力于Javaå…¨æ ˆå¼€å�‘ï¼�
-
-**Java工程师必备å¦ä¹ 资æº�:** 一些Java工程师常用å¦ä¹ 资æº�,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“Javaâ€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
-
-### 个人公众�:黄�斜
-
-作者是 985 硕士,蚂èš�金æœ� JAVA 工程师,专注于 JAVA å�Žç«¯æŠ€æœ¯æ ˆï¼šSpringBootã€�MySQLã€�分布å¼�ã€�ä¸é—´ä»¶ã€�å¾®æœ�务,å�Œæ—¶ä¹Ÿæ‡‚点投资ç�†è´¢ï¼Œå�¶å°”讲点算法和计算机ç�†è®ºåŸºç¡€ï¼Œå�šæŒ�å¦ä¹ 和写作,相信终身å¦ä¹ 的力é‡�ï¼�
-
-**程åº�员3T技术å¦ä¹ 资æº�:** 一些程åº�员å¦ä¹ 技术的资æº�大礼包,关注公众å�·å�Žï¼Œå�Žå�°å›žå¤�å…³é”®å— **“资料â€�** å�³å�¯å…�è´¹æ— å¥—è·¯èŽ·å�–。
-
-
diff --git "a/docs/java/basic/13\343\200\201\346\263\233\345\236\213.md" "b/docs/Java/basic/\346\263\233\345\236\213.md"
similarity index 58%
rename from "docs/java/basic/13\343\200\201\346\263\233\345\236\213.md"
rename to "docs/Java/basic/\346\263\233\345\236\213.md"
index 2251e75..f9a9ba6 100644
--- "a/docs/java/basic/13\343\200\201\346\263\233\345\236\213.md"
+++ "b/docs/Java/basic/\346\263\233\345\236\213.md"
@@ -15,9 +15,7 @@
* [泛型上下边界](#泛型上下边界)
* [泛型常��试题](#泛型常��试题)
* [å�‚è€ƒæ–‡ç« ](#å�‚è€ƒæ–‡ç« )
- * [微信公众�](#微信公众�)
- * [Java技术江湖](#java技术江湖)
- * [个人公众�:黄�斜](#个人公众�:黄�斜)
+
æœ¬ç³»åˆ—æ–‡ç« å°†æ•´ç�†åˆ°æˆ‘在GitHub上的《Javaé�¢è¯•指å�—》仓库,更多精彩内容请到我的仓库里查看
> https://github.com/h2pl/Java-Tutorial
@@ -44,48 +42,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 +96,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 +146,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 +171,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 +261,7 @@ public void showKeyValue(Generic obj){
// showKeyValue这个方法编译器会为我们报错:Generic
// cannot be applied to Generic
// showKeyValue(gInteger);
-。
+````
### 泛型方法
@@ -274,167 +269,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 +438,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 extends Number> 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 extends Number> obj){
- System.out.println(obj);
- }
-
- //å�ªèƒ½ä¼ å…¥Integer的父类或者Integer
- public void showKeyValue2(Generic super Integer> 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 super Integer> 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