├── .gitignore ├── README.md ├── document ├── 20230725-JAVA招聘JD(欢迎投简历).md ├── B站历史视频汇总.md ├── IDEA插件.xmind ├── Interivew Question For Ali.xmind ├── Java基础-基础知识.md ├── Java基础-集合类.md ├── Jenkins脑图2.xmind ├── RocketMQ限速.xmind ├── ZSXQ.xmind ├── 偶像!给你一个可以写在简历上的亮点.pdf ├── 公众号历史文章汇总.md ├── 哎哟!这个Bug,有点东西.md ├── 在进行技术方案:代码评审时,我们应该关注哪些方面?.md ├── 如何入门Java.md ├── 如何防止接口被盗刷.md ├── 强息书单.xmind ├── 慢SQL治理.md └── 虚拟列触发的Bug.md └── pictures └── 个人微信.png /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | /**/build/ 4 | 5 | 6 | ### IntelliJ IDEA ### 7 | .idea 8 | *.iws 9 | *.iml 10 | *.ipr 11 | /out/ 12 | /**/out/ 13 | .shelf/ 14 | .ideaDataSources/ 15 | dataSources/ 16 | 17 | ### OS ### 18 | .DS_Store 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 《JavaCode》提供一个一站式Java服务,包括但不限于以下服务 2 | 3 | - **Java入门和学习路径** 4 | - **Java知识基础** 5 | - **Java面试题** 6 | - **Java面经** 7 | - **简历修改和美化** 8 | - **模拟面试** 9 | - **职业指导** 10 | 11 | 12 | 13 | 如要进群、简历修改、模拟面试、职业指导或请教问题,请[联系我](#联系我)(备注:Github) 14 | 15 | >如若资料有误,望各位小伙伴指正。同时也十分欢迎各位朋友为《JavaCode》添砖加瓦,贡献学习资料。 16 | 17 | 18 | 19 | ## 最新文章 20 | 21 | [哎哟!这个Bug,有点东西](document/哎哟!这个Bug,有点东西.md) 22 | 23 | [如何入门Java](document/如何入门Java.md) 24 | 25 | [Java基础-基础知识](document/Java基础-基础知识.md) 26 | 27 | [Java基础-集合类](document/Java基础-集合类.md) 28 | 29 | 30 | [在进行技术方案:代码评审时,我们应该关注哪些方面](document/在进行技术方案:代码评审时,我们应该关注哪些方面?.md) 31 | 32 | [如何防止接口被盗刷](document/如何防止接口被盗刷.md) 33 | 34 | ## 招聘 35 | 36 | [20230725-JAVA招聘](document/20230725-JAVA招聘JD(欢迎投简历).md) 37 | 38 | ## 面经 39 | 40 | - [阿里巴巴5面面经(已获Offer)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701572&idx=1&sn=62bb14c25af161798b1345e47a62dc39&chksm=f3228718c4550e0e943f913bfaa6dbd1c40142693a873beca275432e005100d28e2ba942c435&token=797347776&lang=zh_CN#rd) 41 | 42 | - [你试过裸面大厂吗?](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701341&idx=1&sn=b4d7ca6df76c95ca17234bc56f02f8cf&chksm=f3228601c4550f17ff1ef93ad71cfd1965fef76449f0a2b6b7616f2d9ff90b2c39825439e061&token=797347776&lang=zh_CN#rd) 43 | 44 | - [面试——Java字节面经(已获Offer)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700844&idx=1&sn=1bb4733b552f20ea0fd7292de360c7a1&chksm=f3228430c4550d26f9d40e3a7d5080f6f0b1bd37ec6dcc497b8d4d19303b5cc0ce65d026a8d3&token=797347776&lang=zh_CN#rd) 45 | 46 | - [面试——美团面经(已获Offer)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700839&idx=1&sn=aa9633bacf94d0927300b966b8860238&chksm=f322843bc4550d2d1985c22135fd0e9af95778a4ec95d22193a606b9cf03b2285d749d86887b&token=797347776&lang=zh_CN#rd) 47 | 48 | 49 | 50 | ## Java 51 | 52 | - [what!!!小白都懂的死锁,你不懂?](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701540&idx=1&sn=6235aa65a8c47f2e5202f842925f54c8&chksm=f32286f8c4550fee0e6e052a4ff302fffc3ace16462e01108720f724f4d5b9a2477e20a7a68b&token=797347776&lang=zh_CN#rd) 53 | - [用泊松分布来解释为什么HashMap的链表变树的阈值是8](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700884&idx=1&sn=f9485215a29599d044536545e3000227&chksm=f3228448c4550d5e9d8678ddcfed47d8e2a75ae55c6a0fd11e6d3fe4074df49b46676bf94064&token=797347776&lang=zh_CN#rd) 54 | - [双亲委派模型](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700857&idx=1&sn=ee2cd21a36a68a90cb1352062c78c908&chksm=f3228425c4550d332e7499579f63f868d485ffa62ee9400f13991ba834ab2dcd7b8e26ba3431&token=797347776&lang=zh_CN#rd) 55 | - [面试Java——集合之HashMap和ConcurrentHashMap](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700834&idx=1&sn=a175f772cdf68d15cde839d456fff4c1&chksm=f322843ec4550d286efe6194771792dc89b0a582c51ce8c1b98c68bb53601295bc52d8c48aa4&token=797347776&lang=zh_CN#rd) 56 | 57 | 58 | 59 | ## JVM 60 | 61 | - [JVM-弱引用的适用场景-1](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701215&idx=1&sn=f67cf58f52f0b0f387d49d077fed30a4&chksm=f3228583c4550c951255e3b05bf6fcd5923c294912f3d9282f519c9ad20cd34fc8a60abc2642&token=797347776&lang=zh_CN#rd) 62 | - [JVM-强引用 软引用 弱引用 虚引用 底层原理(JVM源码)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701205&idx=1&sn=fb5bc89720466a52ee3c092f85ec6797&chksm=f3228589c4550c9f4c8be2fba71f9df4d1f2e10a20a4d25784432d6de052d7c40ede6251a83e&token=797347776&lang=zh_CN#rd) 63 | - [JVM-结合MAT工具来分析OOM问题](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701120&idx=1&sn=29277c37dd9526b053b78e6656322a4e&chksm=f322855cc4550c4a7ee9191ae5a63c90204195c554b9815396e92815dee44e20c80640b4a311&token=797347776&lang=zh_CN#rd) 64 | 65 | - [JVM-对象进入老年代的四种方式-4(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701161&idx=1&sn=330f466501c5c34d52187218b1fdbbbe&chksm=f3228575c4550c638e7e01ccdc46b2e0c9dcbdf0acde74bfd7c9edc156809b3584cbe2c22ced&token=797347776&lang=zh_CN#rd) 66 | 67 | - [JVM-对象进入老年代的四种方式-3(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701146&idx=1&sn=61a20acc65ef852d2802eb0967254f73&chksm=f3228546c4550c50b234aac5968b0b8bbbf6392ac398b94f4acfa916e659a225c4f594d7417b&token=797347776&lang=zh_CN#rd) 68 | 69 | - [JVM-对象进入老年代的四种方式-2(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701102&idx=1&sn=2b8c5fafdeb134ded48a744434ee088a&chksm=f3228532c4550c24c767ce958f0db3543e03c8d3f0a15856967cbc6d30823ab9604368ed7e66&token=797347776&lang=zh_CN#rd) 70 | 71 | - [JVM-对象进入老年代的四种方式-1(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701093&idx=1&sn=dd20e694eda51631337b98012f1abce6&chksm=f3228539c4550c2f59a798d952ecd0b7d8ce4f91294a15879fe9097f93f910fb3aae28621998&token=797347776&lang=zh_CN#rd) 72 | 73 | - [JVM-对象进入老年代的四种方式(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701073&idx=1&sn=91515983107c5a4f30a81e715989fba8&chksm=f322850dc4550c1b137b6952f1eb1dfa867707d542a2a0374a00241eb96dd75cf665bfcbbd17&token=797347776&lang=zh_CN#rd) 74 | 75 | - [《分享》关于JVM的学习资料推荐](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700911&idx=1&sn=deba5187438260cedf7c00e8edf6911c&chksm=f3228473c4550d656b575137d2b6205ee1971b98979bede88d2aee20600597ccdeed9fba2c43&token=797347776&lang=zh_CN#rd) 76 | 77 | 78 | 79 | ## 设计模式 80 | 81 | - [设计模式——优化退款案例(策略模式&模板模式&工厂模式)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701180&idx=1&sn=d90036a2e54f415790a71b38b3b81211&chksm=f3228560c4550c76ff56ee88f61430a61ca48a562983949b9bebfbf04d49568a7d6e54c50eca&token=797347776&lang=zh_CN#rd) 82 | 83 | 84 | 85 | ## 运维 86 | 87 | - [服务炸了!!!Cpu 500%](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701519&idx=1&sn=b7682fd83c4d19cfd239f6680f194a5f&chksm=f32286d3c4550fc56b2bb7bac36bb6f2f266bb465e843eaa7255b47b08836a9af7dd5e44147a&token=797347776&lang=zh_CN#rd) 88 | - [生产事故——磁盘使用率爆仓](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700964&idx=1&sn=e7632ef25d63366de8dbeb5c5c504c7e&chksm=f32284b8c4550daef0d5f8b2051ec92dd2b9b4549832bbafcf10e602dd82e250efdaf41ea954&token=797347776&lang=zh_CN#rd) 89 | 90 | 91 | 92 | ## RocketMQ 93 | 94 | - [RocketMQ-幂等性](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701426&idx=1&sn=ce408d3e08c9cf523b6573629dabed8c&chksm=f322866ec4550f789df3fbcd86bd853b28ccbaa04e00265e63c74115695d5872b9cfc6d25a3b&token=797347776&lang=zh_CN#rd) 95 | 96 | - [RocketMQ-刷盘机制](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701413&idx=1&sn=ba21ed496905eee8dd08b41abb8cc44d&chksm=f3228679c4550f6f205bd3e883b0374a70782d6dcdc18e312879ce03f9f5d4da546089915d5f&token=797347776&lang=zh_CN#rd) 97 | 98 | - [RocketMQ-存储机制](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701402&idx=1&sn=d3d02e9e4e9711fa2566537b7e2dc21c&chksm=f3228646c4550f50aef4231b29960445cad3ba78c8a0571c23e033f2f27693c0b11648d0558b&token=797347776&lang=zh_CN#rd) 99 | - [RocketMQ-批量消息](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701389&idx=1&sn=2800dcc8e9e7f43d8fa8cde7aafc1a7f&chksm=f3228651c4550f4756ee7844d06ab9348ac862526fdc86845272802c27ed10a346c244a89878&token=797347776&lang=zh_CN#rd) 100 | - [RocketMQ-消息过滤](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701377&idx=1&sn=08f85efc34c5dc23ebb0a9f3979fb6b7&chksm=f322865dc4550f4be8349812061507bd0a01a7f276046dcf94f4eb322ee12c88baf17e25dae1&token=797347776&lang=zh_CN#rd) 101 | - [RocketMQ-事务消息(分布式事务)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701364&idx=1&sn=aed7c14e68cd10fb9898712045b29749&chksm=f3228628c4550f3e91adc5407d4dd6a4567402403f62fa4fb5a87b6252852701bdbe98b168a0&token=797347776&lang=zh_CN#rd) 102 | - [RocketMQ-延迟消息](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701333&idx=1&sn=a7cd2554aebd204858a5f0c281391ef3&chksm=f3228609c4550f1f11932e5221b4f6b0b4526198b528677cc9534bce69754009f6e7bf3e4ce7&token=797347776&lang=zh_CN#rd) 103 | - [RocketMQ-顺序消息](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701319&idx=1&sn=0cffa4ef1cfae09d2ecb64e0227026c7&chksm=f322861bc4550f0d6375950f4e8d27fa71839826de100639791d17a71ca5fc6e90011fc7441d&token=797347776&lang=zh_CN#rd) 104 | - [RocketMQ-架构和角色](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701286&idx=1&sn=50d490036ab87493df546f0c9befb097&chksm=f32285fac4550cecece83abe828b9e657e596ba898007074ca4ffbf3f1bfb8ad76893cd85681&token=797347776&lang=zh_CN#rd) 105 | - [RocketMQ-集群模式和广播模式](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701277&idx=1&sn=c0934761a5e14307105b5a4ec215392e&chksm=f32285c1c4550cd7bf65a36abe6a1c6b3520c354a5d5bec8c76bc11eadc0630ff0096642b4eb&token=797347776&lang=zh_CN#rd) 106 | - [RocketMQ-发送消息](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701268&idx=1&sn=2522be2727b40a52403b3867ed284b7b&chksm=f32285c8c4550cde35494e67402591ec3e18a64515f90f64309e8ff3df738845b206f5665205&token=797347776&lang=zh_CN#rd) 107 | 108 | 109 | 110 | ## Redis 111 | 112 | - [不懂缓存一致性,易把代码写成bug](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701009&idx=1&sn=6db4cd4e8ff5751f151c77d3f6bc9d70&chksm=f32284cdc4550ddbbbfc30d02918786134d1b278f9ab7c47af469b14ca66b629fcb467cc2ce8&token=797347776&lang=zh_CN#rd) 113 | - [Redis——缓存并发 缓存雪崩 缓存穿透](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700815&idx=2&sn=d9d3d74a342a3f6acef78f8e927d847d&chksm=f3228413c4550d05c5628ad7201aa29499c9f90af360f37a95e683406cb39b9f0e4168ee8cc9&token=797347776&lang=zh_CN#rd) 114 | - [Redis——集群](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700785&idx=1&sn=f7a3030f33cc0fa688cab331ff41bb5b&chksm=f32283edc4550afbd46d3754b266ab2fd9a512a9a5f4ca1fe3d20d6c8dafd1351ab65e1f7953&token=797347776&lang=zh_CN#rd) 115 | - [Redis——监视器](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700780&idx=2&sn=d1e991cf5b72ab5802cc3951915148dd&chksm=f32283f0c4550ae64e4b8937e511f31b8f9f0954fa83e547b849b4c0a12f9048daeea3b75188&token=797347776&lang=zh_CN#rd) 116 | - [Redis——慢查询日志](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700780&idx=1&sn=027d28a4cc7168d6f1bdf0b934af528d&chksm=f32283f0c4550ae640f7ae5131aeae3b70ff276570a5b7db086500b0d3559b5f2233533c28f8&token=797347776&lang=zh_CN#rd) 117 | - [Redis——哨兵模式的实现机制](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700770&idx=1&sn=5f46858a7875c84e119db3d7b7429ae9&chksm=f32283fec4550ae8bd303cb110e9c0d7822e849c8df6b08cff8848acc95abcd0efe70d466d64&token=797347776&lang=zh_CN#rd) 118 | - [Redis——事务](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700769&idx=1&sn=3a68ea45b9553bfbba57f1a71308e661&chksm=f32283fdc4550aeb0ef567523f4991974b6596ab65014a74ac6dd89a5be0c14ab9b246d8db95&token=797347776&lang=zh_CN#rd) 119 | - [Redis——心跳机制](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700753&idx=2&sn=5e49758a665dad2e7a2059167be50cac&chksm=f32283cdc4550adb191add60b4426f9a3d67678620cb6b45a06be199d2db5f3c6a1fed0506cd&token=797347776&lang=zh_CN#rd) 120 | - [Redis——复制的实现](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700753&idx=1&sn=bc9c2780e90e27490552aa49eb8d011c&chksm=f32283cdc4550adb403966e623d1cea80cb4cb91ed87dc53d0f65560f721e96ed27a26b64909&token=797347776&lang=zh_CN#rd) 121 | - [Redis——事件驱动模型](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700744&idx=1&sn=987556b1c3fc1f64e703e205f6f093ed&chksm=f32283d4c4550ac2d287a782a2a7248cfc7d6cf96f0a9405294d5ec2a4bf1a2d7f2c65398651&token=797347776&lang=zh_CN#rd) 122 | - [Redis——RDB和AOF那些事](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700738&idx=1&sn=38a7f53988b5b03e44a0b8c40af3c08c&chksm=f32283dec4550ac85b8ff3b20b13519da027be08aac5adca1d9243d9469d74b8929fe493998e&token=797347776&lang=zh_CN#rd) 123 | - [Redis——服务器的serverCron函数](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700733&idx=1&sn=ecae0524192326d2b07a6ff1ff5baa27&chksm=f32283a1c4550ab7d3229cb22414093055ca8a737f5589bcad72da9b0bff2ec6f8139faa9bcb&token=797347776&lang=zh_CN#rd) 124 | - [Redis——服务器的启动过程](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700721&idx=1&sn=b28582e3081a89e1081cf06d4e81b568&chksm=f32283adc4550abba2dc9185da074e253fd12aaaa71e7ed0c1ba29c0d9644ed385e21e523eaf&token=797347776&lang=zh_CN#rd) 125 | 126 | 127 | 128 | ## 数据库 129 | 130 | - [面试MySQL——索引](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700815&idx=1&sn=c49612769eff5a7054eafcc6e2584178&chksm=f3228413c4550d0587286f28b345ca56c2392a55c4a9bab28191fb020324ec23f2f25dabfb30&token=797347776&lang=zh_CN#rd) 131 | 132 | - [慢SQL治理](document/慢SQL治理.md) 133 | 134 | 135 | 136 | ## 大厂面试题 137 | 138 | - [《大厂面试题》难道我是天生的架构师?这可是千万级库存](https://www.bilibili.com/video/BV1qR4y1r7L3/) 139 | - [《大厂面试题》Redis主从同步引起的超卖问题,怎么弄](https://www.bilibili.com/video/BV1kP411T7ar/) 140 | - [《大厂面试题》每天请求量100亿,负载均衡怎么设计](https://www.bilibili.com/video/BV1XP4y1979J/) 141 | - [《大厂面试题》同时使用Thread的run和Runnable的run方法,会走哪一个呀?](https://www.bilibili.com/video/BV1XW4y1E7pb/) 142 | - [《大厂面试题》实现多线程的方法是1种2种还是4种?](https://www.bilibili.com/video/BV1qe4y177B7/) 143 | - [《大厂面试题》你知道深克隆和浅克隆有什么区别吗](https://www.bilibili.com/video/BV1ed4y1i7n3/) 144 | - [《大厂面试题》HashSet为什么一定要重写equals和hashCode方法?不能只重写其中一个方法吗?](https://www.bilibili.com/video/BV1dG4y1H7AZ/) 145 | - [《大厂面试题》Java的Object对象有哪些方法](https://www.bilibili.com/video/BV1DP41177cT/) 146 | - [《大厂面试题》在先升后降的数组,用最快的算法找最大值](https://www.bilibili.com/video/BV1uW4y1e7y5/) 147 | - [《大厂面试题》拼夕夕算法题:在先升后降的数组,找输入值的索引](https://www.bilibili.com/video/BV1Le4y1H7jv/) 148 | - [《大厂面试题》怎么判断这条SQL是否要回表](https://www.bilibili.com/video/BV1tD4y117i4/) 149 | - [《大厂面试题》Broker挂了后,到底有什么影响](https://www.bilibili.com/video/BV1XN4y1N7SZ/) 150 | - [《大厂面试题》MQ和多线程异步有什么区别](https://www.bilibili.com/video/BV1pe411K7Zx/) 151 | - [《大厂面试题》Innodb和MyIsam有什么区别](https://www.bilibili.com/video/BV1jd4y1M78V/) 152 | - [《大厂面试题》亿级用户消息推送](https://www.bilibili.com/video/BV15e4y1k7mr/) 153 | - [《大厂面试题》为什么SQL会使用错索引?](https://www.bilibili.com/video/BV1SG4y167ys/) 154 | - [《大厂面试题》如何判断一条SQL是否走索引](https://www.bilibili.com/video/BV1ya41157oE/) 155 | - [《大厂面试题》索引是不是越多越好哇](https://www.bilibili.com/video/BV1mG411t7LJ/) 156 | - [《大厂面试题》RR级别到底解决幻读没](https://www.bilibili.com/video/BV1NW4y1h7yL/) 157 | - [《大厂面试题》为什么要页分裂?不分行不行](https://www.bilibili.com/video/BV1sF411w7p3/) 158 | - [《大厂面试题》如何设计一个短链系统](https://www.bilibili.com/video/BV1Ud4y1T7T3/) 159 | - [《大厂面试题》update t set t.a=123 where t.a=1 这SQL,你不会以为只加了行锁吧?](https://www.bilibili.com/video/BV1iF411A7be/) 160 | - [《大厂面试题》一行数据在磁盘到底是如何存储的](https://www.bilibili.com/video/BV1tg411C7Sw/) 161 | - [《大厂面试题》算法题:一个排序数组,求每个元素平方后不重复的元素个数](https://www.bilibili.com/video/BV1st4y1V78r/) 162 | - [《大厂面试题》如何注册和触发一个定时任务](https://www.bilibili.com/video/BV1HU4y1q7YF/) 163 | - [《大厂面试题》MySQL的limit到底应该怎么优化](https://www.bilibili.com/video/BV1UY4y1j7Ji/) 164 | - [《大厂面试题》字节三面,你猜过了吗](https://www.bilibili.com/video/BV1WY4y1j7iW/) 165 | - [《大厂面试题》字节二面,你猜过了吗](https://www.bilibili.com/video/BV19g411o7Qp/) 166 | - [《大厂面试题》每天新增100W数据,表应该怎么设计](https://www.bilibili.com/video/BV1qS4y177U8/) 167 | - [《大厂面试题》三数之和,只会暴力解法?快看过来](https://www.bilibili.com/video/BV1K3411F7Q6/) 168 | - [《大厂面试题》RPC和HTTP到底有什么区别](https://www.bilibili.com/video/BV16r4y1E79K/) 169 | - [《大厂面试题》字节跳动一面,你猜过了没?](https://www.bilibili.com/video/BV1Ja411Q7ag/) 170 | - [《大厂面试题》ArrayList和LinkedList区别](https://www.bilibili.com/video/BV19B4y1H7cA/) 171 | - [《大厂面试题》为什么SQL使用了索引,却还是慢查询(续集)](https://www.bilibili.com/video/BV1ZB4y1v75U/) 172 | - [《大厂面试题》RocketMQ和Kafka的区别和相同点](https://www.bilibili.com/video/BV1AT411G7Hd/) 173 | - [《大厂面试题》CPU 100%(生产事故)](https://www.bilibili.com/video/BV1N3411A7QJ/) 174 | - [《大厂面试题》不用分布式事务,如何保证数据一致性](https://www.bilibili.com/video/BV1vY4y1n7pJ/) 175 | - [《大厂面试题》不分表,还有其他办法减少表空间?](https://www.bilibili.com/video/BV1RW4y1B78C/) 176 | - [《大厂面试题》@Transaction注解原理流程 不止AOP(b版本)](https://www.bilibili.com/video/BV1Sv4y1M7wN/) 177 | - [《大厂面试题》为什么SQL使用了索引,却还是慢查询](https://www.bilibili.com/video/BV1Jr4y1G7Y9/) 178 | - [《大厂面试题》spring单例bean是线程安全的吗](https://www.bilibili.com/video/BV1BS4y1H7An/) 179 | - [《大厂面试题》Spring AOP 用到哪些设计模式](https://www.bilibili.com/video/BV1MY4y137C3/) 180 | - [《大厂面试题》Thread.sleep(0)和Thread.sleep(1)到底有什么区别](https://www.bilibili.com/video/BV1WU4y197J7/) 181 | - [《大厂面试题》spring事务什么时候会失效(下集)](https://www.bilibili.com/video/BV1dg411Q7mP/) 182 | - [《大厂面试题》spring事务什么时候会失效(上集)](https://www.bilibili.com/video/BV19L4y1N76m/) 183 | - [《大厂面试题》@Autowired和@Resource区别](https://www.bilibili.com/video/BV1F34y157MZ/) 184 | - [《大厂面试题》@PostConstruct和initmethod真的一样吗?](https://www.bilibili.com/video/BV1CS4y1e7xo/) 185 | - [《大厂面试题》IOC和DI到底是什么关系](https://www.bilibili.com/video/BV1JF411F7Xs/) 186 | - [《大厂面试题》Spring是如何解决循环依赖](https://www.bilibili.com/video/BV1cW4y1k7Ge/) 187 | 188 | 189 | 190 | ## 技术分享 191 | 192 | - [《技术分享》Redis的LRU算法深入探究,你学废了吗](https://www.bilibili.com/video/BV1kg411478U/) 193 | 194 | - [《技术分享》一条命令的执行过程Redis](https://www.bilibili.com/video/BV1U8411J7G7/) 195 | 196 | - [《技术分享》正向代理VS反向代理](https://www.bilibili.com/video/BV1d84y1C7fP/) 197 | 198 | - [《技术分享》最牛的是异步IO,为什么Netty却用IO多路复用](https://www.bilibili.com/video/BV1QR4y1Z7dz/) 199 | 200 | - [《技术分享》错误观点:Callable和线程池](https://www.bilibili.com/video/BV1Re4y1y742/) 201 | 202 | - [《技术分享》删库跑路你不敢,那敢不敢压爆数据库???](https://www.bilibili.com/video/BV1Fd4y1P7gU/) 203 | 204 | 205 | 206 | 207 | 208 | ## 其他 209 | 210 | - [《晋升指南》互联网大厂晋升都问什么呀?](https://www.bilibili.com/video/BV1p84y117jj/) 211 | 212 | - [《知识分享》Arrays.aslist就是个坑](https://www.bilibili.com/video/BV1RY411f7Bj/) 213 | 214 | - [《MQ消息零丢失方案》消费者的消息零丢失方案](https://www.bilibili.com/video/BV1ZG411b7dw/) 215 | 216 | - [《MQ消息零丢失方案》Broker是怎么保证消息不丢失的?](https://www.bilibili.com/video/BV1Ut4y137Sw/) 217 | 218 | - [《MQ消息零丢失方案》为什么发送消息零丢失方案,一定要用事务消息](https://www.bilibili.com/video/BV1VB4y1v75d/) 219 | 220 | - [《MQ消息零丢失方案》RocketMQ事务消息原理机制](https://www.bilibili.com/video/BV1rY4y177Zb/) 221 | 222 | - [《MQ消息零丢失方案》生产者到底是怎么确保消息不丢失的?](https://www.bilibili.com/video/BV1CS4y1E7js/) 223 | 224 | - [《MQ消息零丢失方案》那些场景会丢消息](https://www.bilibili.com/video/BV1BB4y1H7VW/) 225 | 226 | 227 | 228 | 229 | 230 | ## 公众号历史文章汇总 231 | 232 | [公众号历史文章汇总](document/公众号历史文章汇总.md) 233 | 234 | 235 | 236 | ## B站历史视频汇总 237 | 238 | [B站历史视频汇总](document/B站历史视频汇总.md) 239 | 240 | ## 联系我 241 | 242 | WeChat:bigheadit0 243 | 244 | ![个人微信](pictures/个人微信.png) 245 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /document/20230725-JAVA招聘JD(欢迎投简历).md: -------------------------------------------------------------------------------- 1 | ## 岗位职责: 2 | 3 | - 1、参与本地生活服务产品相关核心业务(开放平台、服务产品签约售卖、消费链路等)系统分析与设计工作,负责核心功能代码开发,重点项目架构设计开发; 4 | - 2、深入理解业务需求,分析和发现系统的优化点,负责推动产品性能和架构优化; 5 | - 3、搭建完善物流业务指标体系,监测预警业务发展动态,对业务情况做诊断、归因、决策分析解读 6 | - 4、参与服务产品基础平台、业务平台的架构设计及推动落地。 7 | 8 | ## 岗位要求: 9 | 10 | - 1、java基础扎实,理解IO、多线程、集合等基础框架,对JVM原理有一定了解 11 | 12 | - 2、3年及以上使用JAVA开发的经验,对于你用过的开源框架,能了解它的原理和机制;对于SpringBoot,mybatis等开源框架熟悉 13 | 14 | - 3、熟悉分布式系统的设计和应用,熟悉分布式、缓存、消息等机制;能对分布式常用技术进行合理应用,解决问题 15 | 16 | - 4、掌握多线程及高性能的设计与编码及性能调优;有高并发应用开发经验 17 | 18 | - 5、掌握Linux操作系统和大型数据库(Oracle、mysql);对SQL优化有丰富的经验 19 | 20 | - 6、学习能力强,适应能力好;具备耐心、细心的品质 21 | 22 | - 7、喜欢去看及尝试最新的技术,追求编写优雅的代码,从技术趋势和思路上能影响技术团队 23 | 24 | - 8、具备供应链、ERP、仓配体系经验优先 25 | 26 | - 9、具有一线互联网电商、供应链、交易、物流开发等相关经验优先 27 | 28 | 29 | 30 | 31 | 32 | ## 要求 33 | 34 | 工作年限:3-5年 35 | 36 | 学历:本科或以上 37 | 38 | 工作地点:杭州 39 | 40 | 41 | 42 | # **重点!重点!重点!** 43 | 44 | 简历发送到邮箱: yebing.thl@alibaba-inc.com 45 | 46 | 文件格式:PDF 47 | 48 | 文件命名:姓名+JAVA+工作年限 49 | 50 | 51 | 52 | **需要的小伙伴,尽快投简历,条件合适的,可快速安排面试** 53 | 54 | 55 | 56 | **PS:如果不会修改简历的,可以先发我看一下** 57 | -------------------------------------------------------------------------------- /document/B站历史视频汇总.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 大厂面试题 4 | 5 | - [《大厂面试题》难道我是天生的架构师?这可是千万级库存](https://www.bilibili.com/video/BV1qR4y1r7L3/) 6 | - [《大厂面试题》Redis主从同步引起的超卖问题,怎么弄](https://www.bilibili.com/video/BV1kP411T7ar/) 7 | - [《大厂面试题》每天请求量100亿,负载均衡怎么设计](https://www.bilibili.com/video/BV1XP4y1979J/) 8 | - [《大厂面试题》同时使用Thread的run和Runnable的run方法,会走哪一个呀?](https://www.bilibili.com/video/BV1XW4y1E7pb/) 9 | - [《大厂面试题》实现多线程的方法是1种2种还是4种?](https://www.bilibili.com/video/BV1qe4y177B7/) 10 | - [《大厂面试题》你知道深克隆和浅克隆有什么区别吗](https://www.bilibili.com/video/BV1ed4y1i7n3/) 11 | - [《大厂面试题》HashSet为什么一定要重写equals和hashCode方法?不能只重写其中一个方法吗?](https://www.bilibili.com/video/BV1dG4y1H7AZ/) 12 | - [《大厂面试题》Java的Object对象有哪些方法](https://www.bilibili.com/video/BV1DP41177cT/) 13 | - [《大厂面试题》在先升后降的数组,用最快的算法找最大值](https://www.bilibili.com/video/BV1uW4y1e7y5/) 14 | - [《大厂面试题》拼夕夕算法题:在先升后降的数组,找输入值的索引](https://www.bilibili.com/video/BV1Le4y1H7jv/) 15 | - [《大厂面试题》怎么判断这条SQL是否要回表](https://www.bilibili.com/video/BV1tD4y117i4/) 16 | - [《大厂面试题》Broker挂了后,到底有什么影响](https://www.bilibili.com/video/BV1XN4y1N7SZ/) 17 | - [《大厂面试题》MQ和多线程异步有什么区别](https://www.bilibili.com/video/BV1pe411K7Zx/) 18 | - [《大厂面试题》Innodb和MyIsam有什么区别](https://www.bilibili.com/video/BV1jd4y1M78V/) 19 | - [《大厂面试题》亿级用户消息推送](https://www.bilibili.com/video/BV15e4y1k7mr/) 20 | - [《大厂面试题》为什么SQL会使用错索引?](https://www.bilibili.com/video/BV1SG4y167ys/) 21 | - [《大厂面试题》如何判断一条SQL是否走索引](https://www.bilibili.com/video/BV1ya41157oE/) 22 | - [《大厂面试题》索引是不是越多越好哇](https://www.bilibili.com/video/BV1mG411t7LJ/) 23 | - [《大厂面试题》RR级别到底解决幻读没](https://www.bilibili.com/video/BV1NW4y1h7yL/) 24 | - [《大厂面试题》为什么要页分裂?不分行不行](https://www.bilibili.com/video/BV1sF411w7p3/) 25 | - [《大厂面试题》如何设计一个短链系统](https://www.bilibili.com/video/BV1Ud4y1T7T3/) 26 | - [《大厂面试题》update t set t.a=123 where t.a=1 这SQL,你不会以为只加了行锁吧?](https://www.bilibili.com/video/BV1iF411A7be/) 27 | - [《大厂面试题》一行数据在磁盘到底是如何存储的](https://www.bilibili.com/video/BV1tg411C7Sw/) 28 | - [《大厂面试题》算法题:一个排序数组,求每个元素平方后不重复的元素个数](https://www.bilibili.com/video/BV1st4y1V78r/) 29 | - [《大厂面试题》如何注册和触发一个定时任务](https://www.bilibili.com/video/BV1HU4y1q7YF/) 30 | - [《大厂面试题》MySQL的limit到底应该怎么优化](https://www.bilibili.com/video/BV1UY4y1j7Ji/) 31 | - [《大厂面试题》字节三面,你猜过了吗](https://www.bilibili.com/video/BV1WY4y1j7iW/) 32 | - [《大厂面试题》字节二面,你猜过了吗](https://www.bilibili.com/video/BV19g411o7Qp/) 33 | - [《大厂面试题》每天新增100W数据,表应该怎么设计](https://www.bilibili.com/video/BV1qS4y177U8/) 34 | - [《大厂面试题》三数之和,只会暴力解法?快看过来](https://www.bilibili.com/video/BV1K3411F7Q6/) 35 | - [《大厂面试题》RPC和HTTP到底有什么区别](https://www.bilibili.com/video/BV16r4y1E79K/) 36 | - [《大厂面试题》字节跳动一面,你猜过了没?](https://www.bilibili.com/video/BV1Ja411Q7ag/) 37 | - [《大厂面试题》ArrayList和LinkedList区别](https://www.bilibili.com/video/BV19B4y1H7cA/) 38 | - [《大厂面试题》为什么SQL使用了索引,却还是慢查询(续集)](https://www.bilibili.com/video/BV1ZB4y1v75U/) 39 | - [《大厂面试题》RocketMQ和Kafka的区别和相同点](https://www.bilibili.com/video/BV1AT411G7Hd/) 40 | - [《大厂面试题》CPU 100%(生产事故)](https://www.bilibili.com/video/BV1N3411A7QJ/) 41 | - [《大厂面试题》不用分布式事务,如何保证数据一致性](https://www.bilibili.com/video/BV1vY4y1n7pJ/) 42 | - [《大厂面试题》不分表,还有其他办法减少表空间?](https://www.bilibili.com/video/BV1RW4y1B78C/) 43 | - [《大厂面试题》@Transaction注解原理流程 不止AOP(b版本)](https://www.bilibili.com/video/BV1Sv4y1M7wN/) 44 | - [《大厂面试题》为什么SQL使用了索引,却还是慢查询](https://www.bilibili.com/video/BV1Jr4y1G7Y9/) 45 | - [《大厂面试题》spring单例bean是线程安全的吗](https://www.bilibili.com/video/BV1BS4y1H7An/) 46 | - [《大厂面试题》Spring AOP 用到哪些设计模式](https://www.bilibili.com/video/BV1MY4y137C3/) 47 | - [《大厂面试题》Thread.sleep(0)和Thread.sleep(1)到底有什么区别](https://www.bilibili.com/video/BV1WU4y197J7/) 48 | - [《大厂面试题》spring事务什么时候会失效(下集)](https://www.bilibili.com/video/BV1dg411Q7mP/) 49 | - [《大厂面试题》spring事务什么时候会失效(上集)](https://www.bilibili.com/video/BV19L4y1N76m/) 50 | - [《大厂面试题》@Autowired和@Resource区别](https://www.bilibili.com/video/BV1F34y157MZ/) 51 | - [《大厂面试题》@PostConstruct和initmethod真的一样吗?](https://www.bilibili.com/video/BV1CS4y1e7xo/) 52 | - [《大厂面试题》IOC和DI到底是什么关系](https://www.bilibili.com/video/BV1JF411F7Xs/) 53 | - [《大厂面试题》Spring是如何解决循环依赖](https://www.bilibili.com/video/BV1cW4y1k7Ge/) 54 | 55 | 56 | 57 | ## 技术分享 58 | 59 | - [《技术分享》Redis的LRU算法深入探究,你学废了吗](https://www.bilibili.com/video/BV1kg411478U/) 60 | 61 | - [《技术分享》一条命令的执行过程Redis](https://www.bilibili.com/video/BV1U8411J7G7/) 62 | 63 | - [《技术分享》正向代理VS反向代理](https://www.bilibili.com/video/BV1d84y1C7fP/) 64 | 65 | - [《技术分享》最牛的是异步IO,为什么Netty却用IO多路复用](https://www.bilibili.com/video/BV1QR4y1Z7dz/) 66 | 67 | - [《技术分享》错误观点:Callable和线程池](https://www.bilibili.com/video/BV1Re4y1y742/) 68 | 69 | - [《技术分享》删库跑路你不敢,那敢不敢压爆数据库???](https://www.bilibili.com/video/BV1Fd4y1P7gU/) 70 | 71 | 72 | 73 | 74 | 75 | ## 其他 76 | 77 | - [《晋升指南》互联网大厂晋升都问什么呀?](https://www.bilibili.com/video/BV1p84y117jj/) 78 | 79 | - [《知识分享》Arrays.aslist就是个坑](https://www.bilibili.com/video/BV1RY411f7Bj/) 80 | 81 | - [《MQ消息零丢失方案》消费者的消息零丢失方案](https://www.bilibili.com/video/BV1ZG411b7dw/) 82 | 83 | - [《MQ消息零丢失方案》Broker是怎么保证消息不丢失的?](https://www.bilibili.com/video/BV1Ut4y137Sw/) 84 | 85 | - [《MQ消息零丢失方案》为什么发送消息零丢失方案,一定要用事务消息](https://www.bilibili.com/video/BV1VB4y1v75d/) 86 | 87 | - [《MQ消息零丢失方案》RocketMQ事务消息原理机制](https://www.bilibili.com/video/BV1rY4y177Zb/) 88 | 89 | - [《MQ消息零丢失方案》生产者到底是怎么确保消息不丢失的?](https://www.bilibili.com/video/BV1CS4y1E7js/) 90 | 91 | - [《MQ消息零丢失方案》那些场景会丢消息](https://www.bilibili.com/video/BV1BB4y1H7VW/) 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /document/IDEA插件.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron-TangCode/JavaCode/168fc1b8bd31cccb36a1663133203dbe3e8be954/document/IDEA插件.xmind -------------------------------------------------------------------------------- /document/Interivew Question For Ali.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron-TangCode/JavaCode/168fc1b8bd31cccb36a1663133203dbe3e8be954/document/Interivew Question For Ali.xmind -------------------------------------------------------------------------------- /document/Java基础-基础知识.md: -------------------------------------------------------------------------------- 1 | # Java基础-基础语法 2 | 3 | ### 数据类型 4 | 5 | Java 是一种**静态类型**语言,它包括了两种数据类型: 6 | 7 | - 基本数据类型(Primitive Data Types):int, char, byte, short, long, float, double, boolean。 8 | - 引用数据类型(Reference Data Types):类(Class)、接口(Interface)和数组(Array)。 9 | 10 | **补充** 11 | 12 | 1、其中String,Integer,Long这些都属于类,因此属于「引用数据类型」 13 | 14 | 2、基本数据类型占用的字节 15 | 16 | | 基本数据类型 | 字节数 | 数据范围 | 17 | | ------------ | ------ | ---------------------------------------- | 18 | | int | 4 | -2147483648~2147483647 | 19 | | char | 2 | 0~65535 | 20 | | byte | 1 | -128~127 | 21 | | short | 2 | -32768~31767 | 22 | | long | 8 | -9223372036854775808~9223372036854775807 | 23 | | float | 4 | 1.4e-45f ~ 3.4028235e+38f | 24 | | double | 8 | 4.9e-324 ~ 1.7976931348623157e+308 | 25 | | boolean | 1 | true / false | 26 | 27 | 28 | 29 | ### 变量 30 | 31 | Java 中的变量必须先声明后使用,声明时需要指定变量的数据类型。 32 | 33 | 变量的命名规则 34 | 35 | 1. **字母数字字符和下划线**:变量名可以包含字母、数字、下划线(_)和美元符号($),但不能以数字开头。 36 | 2. **区分大小写**:Java是区分大小写的编程语言,这意味着`variable`和`Variable`是两个不同的变量名。 37 | 3. **不可以是关键字**:变量名不能使用Java的保留关键字。例如,你不能将变量命名为`int`或`class`。 38 | 4. **长度限制**:理论上,变量名的长度没有限制,但为了代码的可读性和可维护性,应该使用适当长度的变量名。 39 | 5. **Unicode字符**:变量名可以使用任何Unicode字符,但不推荐使用,因为它会使代码难以阅读和理解。 40 | 41 | 此外,虽然不是硬性规则,还有一些命名约定应该遵守,以提高代码的可读性和一致性: 42 | 43 | - **驼峰命名法**:在Java中,变量名通常采用所谓的驼峰命名法。对于局部变量和实例变量,通常使用小驼峰式命名法(lowerCamelCase),即变量名的第一个单词首字母小写,之后每个单词的首字母都大写,比如`localVariable`、`studentName`。 44 | - **有意义的名称**:变量名应该有描述性,能够表明变量的用途,如`employeeSalary`,`totalCount`。 45 | - **常量命名**:如果变量是常量(即使用`final`关键字修饰的变量),则应该全部使用大写字母,并且单词之间用下划线分隔,如`MAX_CODE`。 46 | 47 | 例子: 48 | 49 | ```java 50 | 1int count; // 符合规则,使用小写字母开头 51 | 2String myName; // 符合规则,使用小驼峰式命名法 52 | 3final double PI_VALUE = 3.14159; // 符合规则,常量全部大写,单词间用下划线分隔 53 | ``` 54 | 55 | 56 | 57 | ### 修饰符 58 | 59 | Java 提供了多种修饰符来设置类、变量和方法的访问规则和其他功能。主要分为访问控制修饰符(public, private, protected)和非访问控制修饰符(static, final, abstract 等) 60 | 61 | 1. **访问修饰符**:在Java中,访问权限修饰符决定了类、变量、方法和构造器的可访问性。主要有四种访问修饰符: 62 | - `public`:公开的,可以被任何其他类访问。 63 | - `protected`:受保护的,可以被同一个包内的类以及不同包中的子类访问。 64 | - `default`(没有修饰符):默认访问,仅能被同一个包内的类访问。 65 | - `private`:私有的,只能在定义它们的类内部访问。 66 | 2. **非访问修饰符**:这些修饰符不控制访问级别,但提供了其他功能。主要包括: 67 | - `static`:静态修饰符,用于创建类的静态成员,它们可以在未实例化类的情况下访问。 68 | - `final`:表示最终的,可以修饰类、方法和变量。修饰类时,表明类不能被继承;修饰方法时,表明方法不能被重写;修饰变量时,表示变量的值一旦赋值后不能被改变。 69 | - `abstract`:抽象的,用于创建抽象类和抽象方法。抽象类不能被实例化,抽象方法必须由子类提供实现。 70 | - `synchronized`:表示同步,用于多线程编程中,可以用于方法或代码块。加了此关键字的方法或代码块在任何时刻只能有一个线程执行。 71 | - `transient`:瞬态的,用在序列化过程中,表示某个属性不需要序列化。 72 | - `volatile`:易变的,用于告知虚拟机该变量可能会被多个线程同时访问,从而确保每次都从主内存中读取变量值。 73 | 3. **类成员修饰符**:类成员包括变量、方法和构造器,它们可以使用访问修饰符和非访问修饰符。 74 | 4. **类修饰符**:用于修饰类的声明。除了上述修饰符外,还可以使用`strictfp`关键字,它可以保证类中的浮点运算在不同平台上结果一致。 75 | 5. **常见的访问修饰符组合及其含义**:比如`public static final`经常用来定义常量。 76 | 6. **修饰符的规则和最佳实践**:比如使用最小访问原则,即只为其他类提供必要的访问权限,以及理解哪些修饰符组合是合法的(例如,方法不能同时是`abstract`和`final`) 77 | 78 | 79 | 80 | ### 运算符 81 | 82 | Java 支持多种运算符来对数据进行操作,包括算术运算符(+,-,*,/,% 等)、关系运算符(==,!=,>,<,>=,<=)、逻辑运算符(&&,||, !)、赋值运算符(=, +=, -= 等)和位运算符。 83 | 84 | 1. **算术运算符**: 85 | - 加法(`+`) 86 | - 减法(`-`) 87 | - 乘法(`*`) 88 | - 除法(`/`) 89 | - 取余(模运算)(`%`) 90 | - 自增(`++`) 91 | - 自减(`--`) 92 | 2. **关系运算符**: 93 | - 等于(`==`) 94 | - 不等于(`!=`) 95 | - 大于(`>`) 96 | - 小于(`<`) 97 | - 大于等于(`>=`) 98 | - 小于等于(`<=`) 99 | 3. **逻辑运算符**: 100 | - 逻辑与(`&&`) 101 | - 逻辑或(`||`) 102 | - 逻辑非(`!`) 103 | 4. **位运算符**: 104 | - 位与(`&`) 105 | - 位或(`|`) 106 | - 位异或(`^`) 107 | - 位非(取反)(`~`) 108 | - 左移(`<<`) 109 | - 右移(`>>`) 110 | - 无符号右移(`>>>`) 111 | 5. **赋值运算符**: 112 | - 简单赋值(`=`) 113 | - 加法赋值(`+=`) 114 | - 减法赋值(`-=`) 115 | - 乘法赋值(`*=`) 116 | - 除法赋值(`/=`) 117 | - 取余赋值(`%=`) 118 | - 左移赋值(`<<=`) 119 | - 右移赋值(`>>=`) 120 | - 位与赋值(`&=`) 121 | - 位或赋值(`|=`) 122 | - 位异或赋值(`^=`) 123 | 6. **条件运算符**(也称为三元运算符): 124 | - `? :`,用于简单的条件赋值,形式为 `条件 ? 表达式1 : 表达式2`,如果条件为真,则结果为表达式1,否则为表达式2。 125 | 7. **类型相关的运算符**: 126 | - 类型转换运算符,例如 `(int)`, `(double)` 等,用于将表达式显式转换为其他类型。 127 | - `instanceof`,用于检查一个对象是否是特定类的实例。 128 | 8. **运算符的优先级和结合性**: 129 | - 理解不同运算符之间的优先级关系,比如乘除的优先级高于加减。 130 | - 理解同一优先级运算符的计算顺序,也就是结合性,比如赋值运算符的结合性是从右到左。 131 | 9. **运算符的重载**: 132 | - Java中唯一支持运算符重载的是加号(`+`),主要用于字符串的连接 133 | 134 | **注意点** 135 | 136 | - =和==的区别 137 | 138 | 139 | 140 | 141 | 142 | ### 控制流程语句 143 | 144 | 控制程序流程的语句,包括条件语句(if-else, switch-case)和循环语句(for, while, do-while)等 145 | 146 | 1. **条件语句**:这些语句根据条件的真假来决定程序的执行路径。 147 | - `if`语句:用于基于条件执行代码块。 148 | - `if...else`语句:当`if`条件为真时执行一个代码块,否则执行`else`部分的代码。 149 | - `else if`链:用于创建多个条件分支。 150 | - `switch`语句:选择多个代码块之一去执行。`switch`可以使用`case`语句来定义不同的分支,以及`default`来定义当没有匹配的`case`时的默认行为。 151 | 2. **循环语句**:这些语句允许代码重复执行,直到满足某个条件。 152 | - `while`循环:当条件为真时,循环会一直执行。 153 | - `do-while`循环:与`while`循环类似,但保证至少执行一次循环体,然后再检查条件。 154 | - `for`循环:允许在循环声明中初始化变量,定义循环条件以及更新循环变量。 155 | - `for-each`循环:Java 5引入的增强型`for`循环,用于遍历数组或集合中的元素。 156 | 3. **跳转语句**:这些语句用于改变执行流程,跳过某些代码的执行。 157 | - `break`:立即退出最近的包围`switch`语句或循环。 158 | - `continue`:跳过当前循环的剩余部分,并开始下一个循环迭代。 159 | - `return`:退出当前方法,并可选地返回一个值(如果方法不是`void`类型的话)。 160 | 4. **异常处理**:用于处理程序运行时可能出现的意外情况或错误。 161 | - `try`块:包围可能会抛出异常的代码。 162 | - `catch`块:捕捉异常并定义如何处理它们。 163 | - `finally`块:无论是否捕捉到异常,`finally`块中的代码总是会被执行。 164 | - `throw`:用于手动抛出异常。 165 | - `throws`:在方法签名中声明可能抛出的异常。 166 | 5. **控制流程的最佳实践**:理解如何有效地使用控制流程语句,例如: 167 | - 避免过度使用`break`和`continue`,因为它们可能会使循环逻辑变得难以跟踪。 168 | - 使用有意义的条件表达式以提高代码的可读性。 169 | - 在`switch`语句中不要忘记`break`,以避免无意的“穿透”到下一个`case`。 170 | - 尽量使循环和条件语句简单,避免嵌套过深,从而提高代码的可理解性。 171 | - 在适当的时候使用异常处理来增强程序的健壮性。 172 | 173 | 174 | 175 | ### 数组 176 | 177 | 定义:数组是用来存储固定大小的同类型元素的集合。 178 | 179 | 1. **数组的基本概念**: 180 | - 定义:数组是一种存储**固定**大小的**同类型**元素的**顺序**集合。 181 | - 数组是一个对象。 182 | 2. **数组的声明、创建和初始化**: 183 | - 如何声明数组,例如 `int[] myArray;`。 184 | - 如何创建数组实例,例如 `myArray = new int[10];`,这里分配了一个可以存储10个整数的空间。 185 | - 如何同时声明和创建数组,例如 `int[] myArray = new int[10];`。 186 | - 如何对数组进行初始化,例如 `int[] myArray = {1, 2, 3, 4, 5};`。 187 | - 数组一旦创建后,大小就是固定的。 188 | 3. **数组元素的访问和修改**: 189 | - 如何通过下标(索引)访问数组元素,例如 `int x = myArray[0];`。 190 | - 如何通过下标修改数组元素的值,例如 `myArray[0] = 10;`。 191 | - **数组下标是从0开始的,最大的索引是数组长度减1**。 192 | 4. **数组的特性和属性**: 193 | - 如何使用数组的`length`属性来获取数组的大小,例如 `int size = myArray.length;`。 194 | - Java数组在内存中的连续存储特性 195 | 5. **数组的遍历**: 196 | - 使用传统的`for`循环遍历数组。 197 | - 使用增强的`for`循环(也称为`for-each`循环)来遍历数组,例如 `for(int element : myArray) {...}`。 198 | 6. **多维数组**: 199 | - Java支持多维数组(数组的数组),例如二维数组 `int[][] matrix;`。 200 | - 如何声明、创建和初始化多维数组。 201 | 7. **常见操作和算法**: 202 | - 常见的数组操作,如排序、搜索、复制、反转等。 203 | - 如何使用Java标准库中的`Arrays`类进行数组操作,例如 `Arrays.sort(myArray);`。 204 | 8. **数组和函数**: 205 | - 如何将数组作为参数传递给函数。 206 | - 如何从函数返回数组。 207 | 9. **数组的局限性和替代方案**: 208 | - 数组的局限性,例如无法动态改变大小、缺乏某些方便的操作方法等。 209 | - Java集合框架(如`ArrayList`),它提供了更加灵活的数据结构。 210 | 211 | 212 | 213 | 214 | 215 | ### 方法 216 | 217 | 方法是一组用来执行特定任务的语句的集合。方法可以带有参数并且可以返回值。 218 | 219 | 1. **方法的定义和调用**: 220 | 221 | - 方法是一段具有特定功能的代码块,可以被调用执行。 222 | - 如何定义一个方法,包括指定方法名、返回类型、参数列表和方法体。 223 | 224 | **示例**: 225 | 226 | ```java 227 | 1// 定义一个方法,计算两个整数的和 228 | 2public int add(int num1, int num2) { 229 | 3 return num1 + num2; 230 | 4} 231 | 5 232 | 6// 调用方法 233 | 7public static void main(String[] args) { 234 | 8 MyClass myClass = new MyClass(); 235 | 9 int result = myClass.add(5, 10); 236 | 10 System.out.println("Sum is: " + result); 237 | 11} 238 | ``` 239 | 240 | 2. **参数传递**: 241 | 242 | - 如何向方法传递参数。 243 | - java中参数传递是按值传递,对于基本数据类型传递的是值副本,对于对象传递的是引用副本。 244 | 245 | **示例**: 246 | 247 | ```java 248 | 1public void greet(String name) { 249 | 2 System.out.println("Hello, " + name); 250 | 3} 251 | 4 252 | 5// 调用方法 253 | 6public static void main(String[] args) { 254 | 7 MyClass myClass = new MyClass(); 255 | 8 myClass.greet("Alice"); 256 | 9} 257 | ``` 258 | 259 | 3. **方法重载(Overloading)**: 260 | 261 | - 定义:多个具有相同名称但参数列表不同的方法。 262 | 263 | 参数列表不同可以体现在以下几个方面: 264 | 265 | 1. **参数的数量不同**:方法的参数个数可以不同。 266 | - 示例:`void display(int a)` 和 `void display(int a, int b)` 267 | 2. **参数的类型不同**:即使参数的数量相同,但数据类型不同,也构成方法重载。 268 | - 示例:`void display(int a)` 和 `void display(String a)` 269 | 3. **参数的顺序不同**:参数的数据类型顺序不同,即使它们的数量和类型相同。 270 | - 示例:`void display(int a, String b)` 和 `void display(String a, int b)` 271 | 272 | 以下是一个具体的Java方法重载的例子: 273 | 274 | ```java 275 | public class OverloadingExample { 276 | 277 | // 方法1:一个参数 278 | public void print(String content) { 279 | System.out.println(content); 280 | } 281 | 282 | // 方法2:两个参数,类型相同 283 | public void print(String content1, String content2) { 284 | System.out.println(content1 + ", " + content2); 285 | } 286 | 287 | // 方法3:两个参数,类型不同 288 | public void print(String content, int repeat) { 289 | for (int i = 0; i < repeat; i++) { 290 | System.out.println(content); 291 | } 292 | } 293 | 294 | // 方法4:两个参数,顺序不同 295 | public void print(int repeat, String content) { 296 | for (int i = 0; i < repeat; i++) { 297 | System.out.print(content); 298 | } 299 | System.out.println(); 300 | } 301 | 302 | public static void main(String[] args) { 303 | OverloadingExample example = new OverloadingExample(); 304 | example.print("Hello World"); // 调用方法1 305 | example.print("Hello", "World"); // 调用方法2 306 | example.print("Hello World", 3); // 调用方法3 307 | example.print(3, "Hello World"); // 调用方法4 308 | } 309 | } 310 | 311 | ``` 312 | 313 | 4. **递归方法**: 314 | 315 | - 定义:方法自己调用自己,这称为递归。 316 | 317 | **示例**: 318 | 319 | ```java 320 | 1public int factorial(int n) { 321 | 2 if (n <= 1) { 322 | 3 return 1; 323 | 4 } 324 | 5 return n * factorial(n - 1); 325 | 6} 326 | ``` 327 | 328 | 5. **返回值**: 329 | 330 | - 方法可以有返回值,也可以没有返回值(使用`void`)。 331 | - 如何使用`return`语句从方法返回值。 332 | 333 | **示例**: 334 | 335 | ```java 336 | 1public boolean isEven(int number) { 337 | 2 return number % 2 == 0; 338 | 3} 339 | ``` 340 | 341 | 6. **变长参数(Varargs)**: 342 | 343 | - 如何定义接受任意数量参数的方法。 344 | 345 | **示例**: 346 | 347 | ```java 348 | 1public void printNumbers(int... numbers) { 349 | 2 for (int number : numbers) { 350 | 3 System.out.print(number + " "); 351 | 4 } 352 | 5 System.out.println(); 353 | 6} 354 | ``` 355 | 356 | 7. **作用域**: 357 | 358 | - 局部变量的作用域限制在方法内部。 359 | 360 | **示例**: 361 | 362 | ```java 363 | 1public void testScope() { 364 | 2 int localVar = 5; // localVar 的作用域限于 testScope 方法内 365 | 3 System.out.println(localVar); 366 | 4} 367 | ``` 368 | 369 | 370 | 371 | ### 类与对象 372 | 373 | Java 是一种面向对象的编程语言,类(Class)是对象的模板,对象(Object)是类的实例。 374 | 375 | ```java 376 | // 定义一个简单的类 377 | 2public class Person { 378 | 3 // 字段定义(属性) 379 | 4 private String name; 380 | 5 private int age; 381 | 6 382 | 7 // 构造方法 383 | 8 public Person(String name, int age) { 384 | 9 this.name = name; 385 | 10 this.age = age; 386 | 11 } 387 | 12 388 | 13 // 方法定义(行为) 389 | 14 public void introduce() { 390 | 15 System.out.println("Hello, my name is " + name + " and I am " + age + " years old."); 391 | 16 } 392 | 17 393 | 18 // Getter 和 Setter 方法 394 | 19 public String getName() { 395 | 20 return name; 396 | 21 } 397 | 22 398 | 23 public void setName(String name) { 399 | 24 this.name = name; 400 | 25 } 401 | 26 402 | 27 public int getAge() { 403 | 28 return age; 404 | 29 } 405 | 30 406 | 31 public void setAge(int age) { 407 | 32 this.age = age; 408 | 33 } 409 | 34 410 | 35 // 静态方法示例 411 | 36 public static void sayHello() { 412 | 37 System.out.println("Hello!"); 413 | 38 } 414 | 39} 415 | 40 416 | 41// 类的使用 417 | 42public class Main { 418 | 43 public static void main(String[] args) { 419 | 44 // 创建对象 420 | 45 Person person1 = new Person("Alice", 25); 421 | 46 Person person2 = new Person("Bob", 30); 422 | 47 423 | 48 // 调用对象的方法 424 | 49 person1.introduce(); 425 | 50 person2.introduce(); 426 | 51 427 | 52 // 访问静态方法 428 | 53 Person.sayHello(); 429 | 54 } 430 | 55} 431 | ``` 432 | 433 | ### 继承 434 | 435 | 1. **继承的基本概念**: 436 | - 继承是OOP中的一个核心概念,子类可以继承父类的属性和方法。 437 | 2. **方法重写(Override)**: 438 | - 子类可以重写父类的方法以提供特定的实现。 439 | - 如何使用`@Override`注解来显式标记一个方法为重写父类方法。 440 | 3. **super关键字的使用**: 441 | - `super`关键字如何用于在子类中访问父类的构造方法、属性和方法。 442 | 4. **构造方法和继承**: 443 | - 子类如何通过`super()`调用父类的构造方法。 444 | - 默认情况下,子类的构造方法会自动调用父类无参的构造方法。 445 | 5. **继承的访问控制**: 446 | - 不同访问修饰符对继承的影响,如`public`、`protected`、默认(包访问权限)和`private`。 447 | 6. **final关键字**: 448 | - `final`关键字的作用,它可以防止类被继承、方法被重写或属性被改变。 449 | 7. **抽象类和方法**: 450 | - 抽象类不能被实例化,子类必须实现(重写)父类的抽象方法。 451 | 452 | ```java 453 | // 父类 454 | class Animal { 455 | protected String name; 456 | 457 | public Animal(String name) { 458 | this.name = name; 459 | } 460 | 461 | public void eat() { 462 | System.out.println(name + " is eating."); 463 | } 464 | 465 | public void sleep() { 466 | System.out.println(name + " is sleeping."); 467 | } 468 | } 469 | 470 | // 子类继承父类 471 | class Dog extends Animal { 472 | public Dog(String name) { 473 | super(name); // 调用父类的构造方法 474 | } 475 | 476 | // 方法重写 477 | @Override 478 | public void eat() { 479 | System.out.println(name + " is eating dog food."); 480 | } 481 | 482 | // 子类特有方法 483 | public void bark() { 484 | System.out.println(name + " is barking."); 485 | } 486 | } 487 | 488 | // 使用继承 489 | public class Main { 490 | public static void main(String[] args) { 491 | Dog dog = new Dog("Buddy"); 492 | dog.eat(); // 输出:Buddy is eating dog food. 493 | dog.sleep(); // 输出:Buddy is sleeping. 494 | dog.bark(); // 输出:Buddy is barking. 495 | } 496 | } 497 | ``` 498 | 499 | `Animal`类是一个基类,它有两个方法:`eat`和`sleep`。`Dog`类通过`extends`关键字继承了`Animal`类,并重写了`eat`方法以提供特定于狗的吃食行为。此外,`Dog`类还定义了一个它自己特有的方法,`bark`。 500 | 501 | 502 | 503 | ### 接口 504 | 505 | 1. **接口的定义和基本概念**: 506 | - 接口(Interface)是一种完全抽象的类,它允许多个类实现相同的方法。 507 | 2. **接口中的方法**: 508 | - 接口可以包含抽象方法(在Java 8之前)和默认方法(Java 8+),以及静态方法(Java 8+)。 509 | 3. **默认方法和静态方法**: 510 | - 默认方法允许你在接口中定义具有实现的方法,而不需要在每个实现类中重写它们。 511 | - 静态方法属于接口,不可被实现类继承或重写。 512 | 4. **实现接口**: 513 | - 如何使用`implements`关键字来实现一个或多个接口。 514 | - 一个类可以实现多个接口。 515 | 5. **接口的继承**: 516 | - 接口可以继承一个或多个其他接口,并且子接口继承父接口的所有方法。 517 | 6. **接口与多态**: 518 | - 接口如何被用于实现多态性,即通过接口引用可以指向不同实现该接口的类的对象。 519 | 520 | ```java 521 | // 定义一个接口 522 | interface Movable { 523 | // 抽象方法 524 | void move(); 525 | 526 | // 默认方法(Java 8+) 527 | default void description() { 528 | System.out.println("I can move!"); 529 | } 530 | } 531 | 532 | // 实现接口的类 533 | class Car implements Movable { 534 | @Override 535 | public void move() { 536 | System.out.println("Car is moving."); 537 | } 538 | } 539 | 540 | class Human implements Movable { 541 | @Override 542 | public void move() { 543 | System.out.println("Human is walking."); 544 | } 545 | } 546 | 547 | // 使用接口 548 | public class Main { 549 | public static void main(String[] args) { 550 | Movable movable1 = new Car(); 551 | Movable movable2 = new Human(); 552 | 553 | movable1.move(); // 输出:Car is moving. 554 | movable2.move(); // 输出:Human is walking. 555 | 556 | // 调用默认方法 557 | movable1.description(); // 输出:I can move! 558 | movable2.description(); // 输出:I can move! 559 | } 560 | } 561 | ``` 562 | 563 | `Movable`是一个接口,它定义了一个抽象方法`move`和一个默认方法`description`。`Car`和`Human`都实现了`Movable`接口,并提供了`move`方法的具体实现。 564 | 565 | 通过实现接口,可以使`Car`和`Human`类在保持独立性的同时共享`Movable`接口的行为规范。此外,可以通过`Movable`接口的引用来指向任何实现了该接口的对象,体现了多态性的概念。 566 | 567 | ### 异常处理 568 | 569 | 1. **异常的概念**: 570 | - 异常是程序运行过程中出现的非预期事件,它会打断正常的程序流程。 571 | 2. **异常的分类**: 572 | - 学习Java中异常的两大类:`Error`和`Exception`。 573 | - `Error`是指程序无法处理的严重问题,如`OutOfMemoryError`。 574 | - `Exception`分为两种:检查型异常(checked exceptions)和非检查型异常(unchecked exceptions)。 575 | 3. **try-catch-finally**: 576 | - 使用`try`块捕获可能出现异常的代码。 577 | - 使用`catch`块处理异常。 578 | - 使用`finally`块执行无论是否发生异常都需要执行的代码。 579 | 4. **抛出异常**: 580 | - 使用`throw`关键字手动抛出异常的情况。 581 | - 创建和使用自定义异常。 582 | 5. **异常的传播**: 583 | - 未被当前方法捕获的异常将被传递到调用栈中的上一层方法。 584 | 6. **throws关键字**: 585 | - 当方法不处理检查型异常时,如何使用`throws`关键字在方法签名中声明异常。 586 | 7. **自定义异常**: 587 | - 如何继承`Exception`或`RuntimeException`类创建自定义异常。 588 | 589 | ```java 590 | // 自定义异常 591 | class MyException extends Exception { 592 | public MyException(String message) { 593 | super(message); 594 | } 595 | } 596 | 597 | public class Main { 598 | public static void main(String[] args) { 599 | try { 600 | // 可能抛出异常的代码块 601 | checkValue(-5); 602 | } catch (MyException e) { 603 | // 捕获并处理异常 604 | System.err.println("Caught Exception: " + e.getMessage()); 605 | } finally { 606 | // 无论是否发生异常都会执行的代码 607 | System.out.println("Finally block is executed."); 608 | } 609 | } 610 | 611 | // 使用throws声明方法可能抛出的异常 612 | public static void checkValue(int value) throws MyException { 613 | if (value < 0) { 614 | // 手动抛出异常 615 | throw new MyException("Value can't be negative!"); 616 | } 617 | System.out.println("Value is: " + value); 618 | } 619 | } 620 | ``` 621 | 622 | 我们定义了一个自定义异常`MyException`,然后在`main`方法中使用了`try-catch-finally`结构来处理`checkValue`方法可能抛出的异常。 623 | 624 | `checkValue`方法检查传入的值是否为负数,如果是,它将抛出一个`MyException`。如果在`try`块中抛出异常,`catch`块将会捕获它并打印详细信息。无论是否捕获到异常,`finally`块都会被执行,这通常用于资源清理等操作。 625 | 626 | ### 包(Package) 627 | 628 | 1. **包的概念**: 629 | - 包(Package)是Java用于组织类和接口的一种命名空间。 630 | - 包可以避免命名冲突,方便管理大型软件项目中的类结构,并可提供访问保护。 631 | 2. **创建包**: 632 | - 使用`package`关键字定义包。通常,包的命名规则遵循公司或组织的反向互联网域名,以确保全球唯一性。 633 | 3. **导入包**: 634 | - 使用`import`关键字导入其他包中的类或接口。 635 | - 可以使用单个导入声明或使用通配符`*`导入一个包下的所有类。 636 | 4. **类路径**: 637 | - Java如何使用类路径(classpath)来定位和加载类文件。 638 | - 如何设置类路径,让Java虚拟机能找到你的类文件。 639 | 5. **访问修饰符与包**: 640 | - 掌握不同访问修饰符(`public`、`protected`、默认(无修饰符)和`private`)对类和类成员在包内外的可见性影响。 641 | 642 | 示例 643 | 644 | 1.**创建包**: 645 | 646 | 假设你要为一个名为`com.mycompany.myapp`的应用程序创建一个包含用户类的包: 647 | 648 | ```java 649 | 1// 在文件 User.java 的顶部声明包 650 | 2package com.mycompany.myapp; 651 | 3 652 | 4public class User { 653 | 5 private String name; 654 | 6 private int age; 655 | 7 656 | 8 public User(String name, int age) { 657 | 9 this.name = name; 658 | 10 this.age = age; 659 | 11 } 660 | 12 661 | 13 // ... 其他方法 ... 662 | 14} 663 | ``` 664 | 665 | 2.**导入包**: 666 | 667 | 现在,假设你要在另一个包中创建一个类,这个类需要使用`User`类: 668 | 669 | ```java 670 | 1// 在文件 UserService.java 的顶部导入 User 类 671 | 2package com.mycompany.myapp.service; 672 | 3 673 | 4import com.mycompany.myapp.User; 674 | 5 675 | 6public class UserService { 676 | 7 public void printUserDetails(User user) { 677 | 8 // ... 使用 User 类的方法 ... 678 | 9 } 679 | 10 680 | 11 // ... 其他方法 ... 681 | 12} 682 | ``` 683 | 684 | 或者,如果你想要导入`com.mycompany.myapp`包下的所有类,你可以这样写: 685 | 686 | ```java 687 | 1import com.mycompany.myapp.*; 688 | ``` 689 | 690 | 3.**设置类路径**: 691 | 692 | 在命令行中编译和运行Java程序时,你可能需要设置类路径,例如: 693 | 694 | ``` 695 | 1# 设置编译时的类路径 696 | 2javac -cp .;lib/* com/mycompany/myapp/User.java 697 | 3 698 | 4# 设置运行时的类路径(Windows系统使用分号;Linux/macOS使用冒号) 699 | 5java -cp .;lib/* com.mycompany.myapp.Main 700 | ``` 701 | 702 | `.`表示当前目录,`lib/*`表示`lib`目录下所有的JAR文件。分号`;`是Windows系统的路径分隔符,而Linux和macOS使用冒号`:`作为路径分隔符。 703 | 704 | 705 | 706 | 707 | 708 | ### 多态 709 | 710 | 1. **多态的概念**: 711 | - 多态允许你将对象视作它们的基类类型,而实际上运行的是对象的实际类型的方法。 712 | 2. **继承或接口** 713 | - 继承多态和接口多态 714 | 3. **方法覆盖(Override)**: 715 | - 子类可以重写父类的方法。在多态中,子类对象会调用重写后的方法,而非父类中定义的版本。 716 | 4. **向上转型(Upcasting)**: 717 | - 将子类对象赋值给父类引用的过程,这种转换总是安全的。 718 | 5. **方法动态绑定**: 719 | - 在多态中,方法调用是在运行时而不是编译时确定的。Java虚拟机(JVM)在运行时确定要调用对象的实际类型的方法。 720 | 6. **向下转型(Downcasting)和类型转换**: 721 | - 当你需要访问子类特有的成员时,如果你拥有的是一个父类引用,你可以将其向下转型到子类,但这可能不安全,因此通常需要进行类型检查。 722 | 723 | ```java 724 | // 父类 725 | class Animal { 726 | public void makeSound() { 727 | System.out.println("Some sound"); 728 | } 729 | } 730 | 731 | // 子类 732 | class Dog extends Animal { 733 | // 方法覆盖 734 | @Override 735 | public void makeSound() { 736 | System.out.println("Bark"); 737 | } 738 | 739 | // 子类特有的方法 740 | public void fetch() { 741 | System.out.println("Fetches the ball"); 742 | } 743 | } 744 | 745 | public class Main { 746 | public static void main(String[] args) { 747 | // 向上转型 748 | Animal myDog = new Dog(); // Dog对象被视作Animal类型 749 | 750 | // 动态绑定方法调用 751 | myDog.makeSound(); // 输出: Bark 752 | 753 | // 尝试访问子类特有的方法 - 错误的做法 754 | // myDog.fetch(); // 编译错误: Animal类中没有定义fetch方法 755 | 756 | // 向下转型 757 | if (myDog instanceof Dog) { // 检查myDog是否是Dog类的实例 758 | Dog dog = (Dog) myDog; // 安全的向下转型 759 | dog.fetch(); // 现在可以调用子类特有的方法 760 | } 761 | } 762 | } 763 | ``` 764 | 765 | `Animal`是一个父类,它有一个方法`makeSound`。`Dog`是`Animal`的子类,并重写了`makeSound`方法。在`main`方法中,我们创建了一个`Dog`对象,但是将它赋值给了`Animal`类型的变量`myDog`,这是一个向上转型的过程,`myDog`的静态类型是`Animal`,但它的动态类型是`Dog`。因此,当调用`myDog.makeSound()`时,会执行`Dog`类中覆盖后的方法。 766 | 767 | 注意,在向上转型后,`myDog`引用无法直接调用`Dog`类中特有的方法,如`fetch`。为了调用这些方法,我们需要先进行类型检查(使用`instanceof`关键字),然后将`myDog`向下转型为`Dog`类型。 768 | 769 | ### 泛型 770 | 771 | 1.什么是泛型? 772 | 773 | Java 泛型(Generics)是 Java 语言中的一个特性,它允许在编译时提供类型检查并消除强制类型转换 774 | 775 | 2.泛型的特点 776 | 777 | - **类型安全**:泛型提供编译时类型检查,这意味着只能将正确的类型的对象添加到集合中。这减少了运行时出现`ClassCastException`的可能性。 778 | 779 | - **消除强制类型转换**:由于泛型提供了类型检查,因此不需要在获取集合中的元素时进行显式的类型转换。 780 | 781 | - **泛化代码**:通过泛型,可以编写更加通用的代码,以处理不同类型的数据。例如,可以编写一个排序列表的方法,这个方法可以对任何类型的列表工作,而不仅仅是特定类型的列表。 782 | 783 | - **类型参数**:可以在类、接口和方法创建时声明类型参数。这些类型参数在使用时由具体的类型替换。 784 | 785 | 3.泛型的基本语法涉及到几个关键符号: 786 | 787 | - ``:表示一个类型参数,`T` 是一个占位符,可以在实例化类或调用方法时被实际的类型(如`Integer`、`String`等)替换。 788 | - ``:表示不确定的类型,也被称为通配符。 789 | - ``:有界类型参数,`T` 必须是 `B` 类型或者 `B` 的子类型。 790 | - ``:`T` 必须是 `B` 类型或者 `B` 的父类型。 791 | 792 | 4.泛型的使用场景 793 | 794 | 泛型类(Generic Classes):创建可以操作不同数据类型的类。 795 | 796 | ```java 797 | 1public class Box { 798 | 2 private T t; // T stands for "Type" 799 | 3 800 | 4 public void set(T t) { 801 | 5 this.t = t; 802 | 6 } 803 | 7 804 | 8 public T get() { 805 | 9 return t; 806 | 10 } 807 | 11} 808 | 12// 使用: 809 | 13Box integerBox = new Box<>(); 810 | 14integerBox.set(10); // 装入整数 811 | 15Integer someInteger = integerBox.get(); 812 | 16 813 | 17Box stringBox = new Box<>(); 814 | 18stringBox.set("Hello World"); // 装入字符串 815 | 19String someString = stringBox.get(); 816 | ``` 817 | 818 | 泛型接口(Generic Interfaces):创建通用接口。 819 | 820 | ```java 821 | 1interface Pair { 822 | 2 public K getKey(); 823 | 3 public V getValue(); 824 | 4} 825 | 5 826 | 6class OrderedPair implements Pair { 827 | 7 private K key; 828 | 8 private V value; 829 | 9 830 | 10 public OrderedPair(K key, V value) { 831 | 11 this.key = key; 832 | 12 this.value = value; 833 | 13 } 834 | 14 835 | 15 public K getKey() { return key; } 836 | 16 public V getValue() { return value; } 837 | 17} 838 | 18// 使用: 839 | 19Pair p1 = new OrderedPair<>(1, "Apple"); 840 | 20Pair p2 = new OrderedPair<>(2, "Orange"); 841 | ``` 842 | 843 | 泛型方法(Generic Methods):创建可用于多种数据类型的方法。 844 | 845 | ```java 846 | 1public class Util { 847 | 2 public static boolean compare(Pair p1, Pair p2) { 848 | 3 return p1.getKey().equals(p2.getKey()) && 849 | 4 p1.getValue().equals(p2.getValue()); 850 | 5 } 851 | 6} 852 | 7// 使用: 853 | 8Pair p1 = new OrderedPair<>(1, "Apple"); 854 | 9Pair p2 = new OrderedPair<>(1, "Apple"); 855 | 10boolean same = Util.compare(p1, p2); // 返回 true 856 | ``` 857 | 858 | 泛型通配符(Generic Wildcards):使用通配符(?)来表示未知的类型。 859 | 860 | - 无界通配符(Unbounded Wildcard):`?` 861 | - 有界通配符(Bounded Wildcard) 862 | - 上界通配符(Upper Bounded Wildcard):`` 863 | - 下界通配符(Lower Bounded Wildcard):`` 864 | 865 | ```java 866 | 1public void printList(List list) { 867 | 2 for (Object elem : list) 868 | 3 System.out.print(elem + " "); 869 | 4 System.out.println(); 870 | 5} 871 | 6 872 | 7List li = Arrays.asList(1, 2, 3); 873 | 8List ls = Arrays.asList("one", "two", "three"); 874 | 9printList(li); // 正确,输出 1 2 3 875 | 10printList(ls); // 正确,输出 one two three 876 | ``` 877 | 878 | 类型擦除(Type Erasure):了解Java泛型背后的原理,即泛型信息只存在于编译阶段,在运行时会被擦除,并用具体的类或桥接方法来替换。 879 | 880 | 881 | 882 | ### 反射 883 | 884 | 1.什么是反射? 885 | 886 | Java反射是Java编程语言提供的一组API,它允许程序在运行时对类和对象进行自省(introspection)和操作。通过反射API,你可以在运行时获取类的信息(比如类的方法、构造函数、属性、注解等),创建和操作对象,甚至修改字段内容和调用方法。 887 | 888 | 2.反射有什么特点? 889 | 890 | - **运行时行为**:反射允许程序在运行时动态地查询和操作类和对象的信息。 891 | 892 | - **灵活性**:通过反射,可以编写不依赖于特定类的通用代码。 893 | 894 | - **封装性破坏**:反射有能力操作类的私有成员,因而可以破坏封装性。 895 | 896 | - **性能开销**:相比于直接代码调用,使用反射执行方法或访问属性会有额外的性能开销。 897 | 898 | 3.反射能解决什么问题? 899 | 900 | - **动态加载**:在运行时加载、检查、使用编译期间未知的类。 901 | 902 | - **检查类属性**:程序可以在运行时检查对象的属性,使得代码可以在不知道具体类信息的情况下工作。 903 | 904 | - **动态代理机制**:反射机制是实现动态代理的基础,可以在运行时创建代理对象,动态地处理对真实对象的方法调用。 905 | 906 | - **泛型擦除后的类型获取**:在运行时获取泛型信息,尽管Java中的泛型信息在编译时会被擦除。 907 | 908 | 反射的使用场景? 909 | 910 | - **开发框架和库**:许多流行的开发框架,如Spring、Hibernate等,都大量使用反射来实现依赖注入、ORM映射等功能。 911 | 912 | - **插件和模块化系统**:反射允许动态加载模块或插件,增加系统的可扩展性。 913 | 914 | - **单元测试框架**:如JUnit,使用反射来动态调用测试方法。 915 | 916 | - **动态代理**:创建动态代理对象,用于添加额外的操作,如事务管理、日志记录等。 917 | 918 | - **IDE工具**:在集成开发环境中,有时需要使用反射来进行代码的分析或调试。 919 | 920 | 示例 921 | 922 | 1. **获取 Class 对象**:反射的起点是获取代表类的 `Class` 对象。 923 | 924 | ``` 925 | 1// 获取 Class 对象的三种方式 926 | 2Class c1 = Class.forName("java.lang.String"); // 使用类的全限定名 927 | 3Class c2 = String.class; // 使用类字面量 928 | 4Class c3 = "Hello, World!".getClass(); // 调用实例的 getClass() 方法 929 | ``` 930 | 931 | 2. **检查类的信息**:你可以使用 `Class` 对象来获取类的信息,如方法、构造器、成员变量、父类等。 932 | 933 | ``` 934 | 1Class clazz = Class.forName("java.lang.String"); 935 | 2// 获取所有公共方法 936 | 3Method[] methods = clazz.getMethods(); 937 | 4 938 | 5// 获取所有构造器 939 | 6Constructor[] constructors = clazz.getConstructors(); 940 | 7 941 | 8// 获取所有公共字段 942 | 9Field[] fields = clazz.getFields(); 943 | 10 944 | 11// 获取父类 945 | 12Class superclass = clazz.getSuperclass(); 946 | ``` 947 | 948 | 3. **创建实例**:使用 `Class` 对象的 `newInstance()` 方法或者获取构造函数并调用 `newInstance()` 方法来创建类的实例。 949 | 950 | ``` 951 | 1Class clazz = Class.forName("java.util.ArrayList"); 952 | 2Object instance = clazz.newInstance(); // 创建 ArrayList 的实例 953 | ``` 954 | 955 | 4. **访问字段**:使用 `Field` 类的方法来访问和修改对象的字段。 956 | 957 | ``` 958 | 1Class clazz = Class.forName("java.lang.String"); 959 | 2Field field = clazz.getField("CASE_INSENSITIVE_ORDER"); 960 | 3Object value = field.get(null); // 静态字段,所以传入 null 961 | ``` 962 | 963 | 5. **调用方法**:使用 `Method` 类的 `invoke()` 方法来调用对象的方法。 964 | 965 | ``` 966 | 1Class clazz = Class.forName("java.lang.String"); 967 | 2Method method = clazz.getMethod("substring", int.class, int.class); 968 | 3String str = "Hello, World!"; 969 | 4Object result = method.invoke(str, 7, 12); // 调用 str 的 substring 方法 970 | ``` 971 | 972 | 6. **操作数组**:反射提供了 `Array` 类来动态创建和操作数组。 973 | 974 | ``` 975 | 1int[] intArray = (int[]) Array.newInstance(int.class, 5); // 创建数组 976 | 2Array.set(intArray, 0, 123); // 设置数组元素 977 | 3int value = Array.getInt(intArray, 0); // 获取数组元素 978 | ``` 979 | 980 | 7. **处理异常**:反射相关的方法可能会抛出 `IllegalAccessException`, `InstantiationException`, `ClassNotFoundException`, `NoSuchMethodException`, `NoSuchFieldException` 等异常,需要妥善处理。 981 | 982 | ### 序列化 983 | 984 | 1. **序列化接口**: 985 | - `java.io.Serializable`接口。任何需要序列化的类都需要实现这个接口,它是一个标记接口,不包含任何方法。 986 | 2. **ObjectOutputStream 和 ObjectInputStream**: 987 | - 如何使用`ObjectOutputStream`类来序列化对象(写入字节流)。 988 | - 如何使用`ObjectInputStream`类来反序列化对象(从字节流读取)。 989 | 3. **transient关键字**: 990 | - `transient`关键字。使用这个关键字标记的成员变量不会被序列化。 991 | 4. **序列化ID**: 992 | - `serialVersionUID`的作用。这是一个用来辅助序列化和反序列化过程的版本控制标识符。如果你没有显式声明,Java会根据类的详情自动生成一个,但是最好是自己声明以避免因版本不一致导致反序列化失败。 993 | 5. **序列化的注意事项**: 994 | - 不是所有的对象都可以序列化,例如IO流对象和线程对象就不可以序列化。 995 | - 序列化对于单例模式和类加载器的影响。 996 | 997 | ```java 998 | import java.io.*; 999 | 1000 | // Person类实现了Serializable接口以便可以被序列化 1001 | class Person implements Serializable { 1002 | // 序列化版本号 1003 | private static final long serialVersionUID = 1L; 1004 | 1005 | // 成员变量 1006 | public String name; 1007 | public int age; 1008 | 1009 | // 标记为transient的变量不会被序列化 1010 | transient public String password; 1011 | 1012 | // 构造方法 1013 | public Person(String name, int age, String password) { 1014 | this.name = name; 1015 | this.age = age; 1016 | this.password = password; 1017 | } 1018 | 1019 | // 自定义的toString方法 1020 | @Override 1021 | public String toString() { 1022 | return "Person{name='" + name + "', age=" + age + ", password='" + password + "'}"; 1023 | } 1024 | } 1025 | 1026 | public class SerializationDemo { 1027 | public static void main(String[] args) { 1028 | // 创建Person对象 1029 | Person person = new Person("Alice", 30, "secret"); 1030 | 1031 | // 序列化对象 1032 | try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) { 1033 | oos.writeObject(person); 1034 | System.out.println("Object has been serialized: " + person); 1035 | } catch (IOException e) { 1036 | e.printStackTrace(); 1037 | } 1038 | 1039 | // 反序列化对象 1040 | try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) { 1041 | Person deserializedPerson = (Person) ois.readObject(); 1042 | System.out.println("Object has been deserialized: " + deserializedPerson); 1043 | } catch (IOException | ClassNotFoundException e) { 1044 | e.printStackTrace(); 1045 | } 1046 | } 1047 | } 1048 | ``` 1049 | 1050 | 我们定义了一个`Person`类,它实现了`Serializable`接口,并声明了一个`serialVersionUID`。我们创建了一个`Person`对象,使用`ObjectOutputStream`将其序列化到一个文件“person.ser”中。然后,我们使用`ObjectInputStream`读取这个文件,并将字节流反序列化为一个新的`Person`对象。 1051 | 1052 | 请注意,虽然`password`成员被标记为`transient`,因此它不会被序列化。在反序列化过程中,`password`字段的值将为`null`, 因为它没有在序列化数据中保留。 1053 | 1054 | ## 什么是静态类型语言? 1055 | 1056 | **定义** 1057 | 1058 | Java 被称为一种静态类型语言(statically typed language),这意味着所有的变量和表达式的类型在编译时期就已经确定,并且在整个程序运行期间不会改变。这与动态类型语言(dynamically typed languages)不同,后者允许变量的类型在程序运行时改变或者在声明时不显式指定类型。 1059 | 1060 | **静态类型语言有什么特点** 1061 | 1062 | 1. 类型检查:编译器在编译阶段就会对代码进行类型检查,如果类型不匹配,编译器会报错。例如,如果你尝试将一个字符串赋值给一个整型变量,编译器会抛出错误。 1063 | 1064 | 2. 变量声明:在 Java 中,每个变量在使用前都需要声明,并且在声明时指定其数据类型。例如: 1065 | 1066 | ``` 1067 | 1int number = 5; // 显式声明number是int类型 1068 | ``` 1069 | 1070 | 3. 性能:静态类型语言通常在性能上有优势,因为编译器对类型的了解使得可以生成更优化的机器码。 1071 | 1072 | 4. 可读性和可维护性:静态类型有助于提高代码的可读性和可维护性。因为数据类型是显式声明的,所以读代码的人可以更容易地理解每个变量的预期用途。 1073 | 1074 | 5. 工具支持:静态类型语言通常提供更好的开发工具支持,如自动完成、重构工具和更严格的编码规范检查,因为编译器在编码时就了解了代码结构。 1075 | 1076 | **对比:动态类型语言有哪些特点的特性** 1077 | 1078 | 1. 类型推断:动态类型语言依赖于运行时来确定实际的数据类型,并且在声明变量时不一定需要指定数据类型。 1079 | 2. 灵活性:动态类型语言通常更灵活,因为它们在运行时允许类型更改或不要求在初始声明时就确定类型。 1080 | 3. 编写速度:动态类型语言可能会加快初期开发速度,因为程序员可以快速编写代码,而不需要花时间声明类型。 1081 | 1082 | **例子** 1083 | 1084 | 举例来说,对比 **Python(一种动态类型语言)和 Java(一种静态类型语言)**: 1085 | 1086 | ``` 1087 | 1# Python (动态类型) 1088 | 2number = "123" # 初始为字符串 1089 | 3number = 123 # 同一变量可以改变类型,赋值为整数 1090 | 1// Java (静态类型) 1091 | 2String number = "123"; // 显式声明为String类型 1092 | 3number = 123; // 编译错误,不能将整数赋值给字符串类型的变量 1093 | ``` 1094 | 1095 | 在 Java 中,类型是在编译时确定的,并且一旦声明,变量的类型就不能更改。这有助于捕捉错误并提高代码的稳定性,但也使得语言在某些方面不如动态类型语言灵活。 1096 | 1097 | 1098 | 1099 | ## 深入分析修饰符和包 1100 | 1101 | Java的访问修饰符用于控制类、方法、变量等成员的访问级别。Java中的访问修饰符主要有四种:`public`、`protected`、默认(无修饰符,也称为包私有)和`private`。这些修饰符决定了其他类对这些成员的访问权限。 1102 | 1103 | 1. **public**: 1104 | - 可以被任何其他类访问,不论这些类是否在同一个包内或是不同包中。 1105 | 2. **protected**: 1106 | - 可以被同一个包内的所有类访问,以及不同包中的子类访问。 1107 | 3. **默认(无修饰符,包私有)**: 1108 | - 只能被同一个包内的类访问。 1109 | 4. **private**: 1110 | - 只能在声明它们的类中访问。 1111 | 1112 | **访问级别总结**: 1113 | 1114 | | Modifier | Class | Package | Subclass | World | 1115 | | ----------- | :---: | :-----: | :------: | :---: | 1116 | | public | Y | Y | Y | Y | 1117 | | protected | Y | Y | Y | N | 1118 | | no modifier | Y | Y | N | N | 1119 | | private | Y | N | N | N | 1120 | 1121 | **Y 表示允许访问,N 表示不允许。** 1122 | 1123 | **示例**: 1124 | 1125 | ```java 1126 | // 文件:com/company/package1/FirstClass.java 1127 | package com.company.package1; 1128 | 1129 | public class FirstClass { 1130 | public int publicVar = 1; 1131 | protected int protectedVar = 2; 1132 | int packagePrivateVar = 3; // 默认,无修饰符 1133 | private int privateVar = 4; 1134 | 1135 | public void publicMethod() { 1136 | // ... 1137 | } 1138 | 1139 | protected void protectedMethod() { 1140 | // ... 1141 | } 1142 | 1143 | void packagePrivateMethod() { // 默认,无修饰符 1144 | // ... 1145 | } 1146 | 1147 | private void privateMethod() { 1148 | // ... 1149 | } 1150 | } 1151 | 1152 | // 文件:com/company/package1/SecondClass.java 1153 | package com.company.package1; 1154 | 1155 | public class SecondClass { 1156 | FirstClass firstClass = new FirstClass(); 1157 | 1158 | public void accessFirstClass() { 1159 | System.out.println(firstClass.publicVar); 1160 | System.out.println(firstClass.protectedVar); 1161 | System.out.println(firstClass.packagePrivateVar); 1162 | // System.out.println(firstClass.privateVar); // 错误:privateVar在FirstClass中是私有的 1163 | } 1164 | } 1165 | 1166 | // 文件:com/company/package2/Subclass.java 1167 | package com.company.package2; 1168 | 1169 | import com.company.package1.FirstClass; 1170 | 1171 | public class Subclass extends FirstClass { 1172 | public void accessFirstClass() { 1173 | System.out.println(publicVar); 1174 | System.out.println(protectedVar); 1175 | // System.out.println(packagePrivateVar); // 错误:packagePrivateVar不可见 1176 | // System.out.println(privateVar); // 错误:privateVar在FirstClass中是私有的 1177 | } 1178 | } 1179 | 1180 | // 文件:com/company/package2/NonSubclass.java 1181 | package com.company.package2; 1182 | 1183 | import com.company.package1.FirstClass; 1184 | 1185 | public class NonSubclass { 1186 | FirstClass firstClass = new FirstClass(); 1187 | 1188 | public void accessFirstClass() { 1189 | System.out.println(firstClass.publicVar); 1190 | // System.out.println(firstClass.protectedVar); // 错误:protectedVar在FirstClass中不可见 1191 | // System.out.println(firstClass.packagePrivateVar); // 错误:packagePrivateVar不可见 1192 | // System.out.println(firstClass.privateVar); // 错误:privateVar在FirstClass中是私有的 1193 | } 1194 | } 1195 | ``` 1196 | 1197 | `FirstClass`定义了四个具有不同访问修饰符的变量和方法。`SecondClass`在同一个包`com.company.package1`中,因此可以访问`FirstClass`的`publicVar`、`protectedVar`和`packagePrivateVar`,但不能访问`privateVar`。 1198 | 1199 | `Subclass`是`FirstClass`的子类,位于不同包`com.company.package2`,可以访问`FirstClass`的`publicVar`和`protectedVar`,但不能访问`packagePrivateVar`和`privateVar`。 1200 | 1201 | `NonSubclass`不是`FirstClass`的子类,也位于不同包`com.company.package2`,只能访问`FirstClass`的`publicVar`,不能访问其他变量。 1202 | 1203 | 1204 | 1205 | ## 继承多态和接口多态 1206 | 1207 | 在Java中,多态(Polymorphism)通常指的是一个引用变量(比如父类或接口类型的变量)在运行时可以引用多种类型的对象,并且可以通过这个引用变量调用这些对象共有的方法,而实际执行的是各自对象的方法版本。Java 中的多态主要分为两种形式: 1208 | 1209 | 1. 继承多态(Inheritance Polymorphism):通过类的继承关系来实现。当一个子类继承自父类时,它可以继承父类的方法和属性。如果子类重写了父类的方法(即方法覆盖,Method Overriding),则可以通过父类的引用来调用这些方法,运行时会执行子类的版本,这体现了多态性。 1210 | 1211 | ```java 1212 | 1class Animal { 1213 | 2 void sound() { 1214 | 3 System.out.println("Animal sound"); 1215 | 4 } 1216 | 5} 1217 | 6 1218 | 7class Dog extends Animal { 1219 | 8 @Override 1220 | 9 void sound() { 1221 | 10 System.out.println("Woof woof"); 1222 | 11 } 1223 | 12} 1224 | 13 1225 | 14public class Test { 1226 | 15 public static void main(String[] args) { 1227 | 16 Animal animal = new Dog(); 1228 | 17 animal.sound(); // 输出: Woof woof 1229 | 18 } 1230 | 19} 1231 | ``` 1232 | 1233 | 1. 接口多态(Interface Polymorphism):通过接口实现。在Java中,接口定义了一组方法规范,但不提供实现。当一个类实现一个接口时,它必须实现接口中的所有方法。你可以使用接口类型的引用来指向实现了该接口的任何类的对象。当通过这个引用调用接口中的方法时,执行的是实际对象的实现方法,这也是多态的一种表现。 1234 | 1235 | ```java 1236 | 1interface Movable { 1237 | 2 void move(); 1238 | 3} 1239 | 4 1240 | 5class Car implements Movable { 1241 | 6 public void move() { 1242 | 7 System.out.println("Car is moving"); 1243 | 8 } 1244 | 9} 1245 | 10 1246 | 11public class Test { 1247 | 12 public static void main(String[] args) { 1248 | 13 Movable movable = new Car(); 1249 | 14 movable.move(); // 输出: Car is moving 1250 | 15 } 1251 | 16} 1252 | ``` 1253 | 1254 | 无论是继承还是接口,多态都允许你通过一个基类型的引用(父类或接口)来操作不同的子类型对象,而具体执行哪个对象的方法,则取决于对象的实际类型,这是在运行时动态决定的。这种机制使得你可以编写更通用和可扩展的代码。 1255 | 1256 | 1257 | 1258 | ## 序列化对于单例模式和类加载器的影响 1259 | 1260 | **序列化对于单例模式的影响:** 1261 | 1262 | 在单例模式中,我们的目标是确保一个类只有一个实例,并提供全局访问点来获取这个实例。然而,序列化和反序列化机制默认的行为会破坏单例模式的规则,因为每次反序列化时都会创建一个新的实例。 1263 | 1264 | 为了解决这个问题,我们可以在单例类中添加一个`readResolve`方法,它在反序列化时会被调用,你可以通过它来返回单例实例。 1265 | 1266 | ```java 1267 | 1import java.io.*; 1268 | 2 1269 | 3class Singleton implements Serializable { 1270 | 4 private static final long serialVersionUID = 1L; 1271 | 5 1272 | 6 // 静态属性存储单例实例 1273 | 7 private static Singleton instance = new Singleton(); 1274 | 8 1275 | 9 // 私有构造函数,防止外部直接创建实例 1276 | 10 private Singleton() {} 1277 | 11 1278 | 12 // 全局访问点 1279 | 13 public static Singleton getInstance() { 1280 | 14 return instance; 1281 | 15 } 1282 | 16 1283 | 17 // 保护单例状态,返回现有实例 1284 | 18 protected Object readResolve() { 1285 | 19 return getInstance(); 1286 | 20 } 1287 | 21} 1288 | ``` 1289 | 1290 | 在上述代码中,`readResolve`方法保证了即使在序列化过程中,我们仍然维护单例的状态,保证只有一个实例存在。 1291 | 1292 | **序列化对类加载器的影响:** 1293 | 1294 | Java序列化机制在反序列化对象时,使用了定义了该对象的类的类加载器来创建实例。如果在不同的环境(不同的虚拟机或者不同的类加载器设置)中序列化和反序列化对象,可能会导致一些问题。 1295 | 1296 | 例如,在使用了不同类加载器的环境中,即使两个类来自同一份字节码文件,它们也被认为是不同的类,如果尝试将一个环境中序列化的对象在另一个环境中反序列化,可能会抛出`ClassNotFoundException`或者`InvalidClassException`。 1297 | 1298 | 为了解决这个问题,你需要确保使用相同的类加载器来序列化和反序列化对象。如果这不可能(例如,在分布式应用中),你可能需要在应用的不同部分之间共享类的字节码。 1299 | 1300 | 示例: 1301 | 1302 | 假设我们有两个类加载器A和B,它们分别加载了相同的类。我们使用类加载器A序列化一个对象,然后尝试使用类加载器B来反序列化它。 1303 | 1304 | ```java 1305 | 1public class ClassLoaderDemo { 1306 | 2 public static void main(String[] args) throws Exception { 1307 | 3 // 假设这是类加载器A加载的Person类 1308 | 4 ClassLoader classLoaderA = new CustomClassLoader(); 1309 | 5 Class classA = classLoaderA.loadClass("Person"); 1310 | 6 Object personA = classA.newInstance(); 1311 | 7 1312 | 8 // 序列化对象 1313 | 9 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 1314 | 10 ObjectOutputStream oos = new ObjectOutputStream(bos); 1315 | 11 oos.writeObject(personA); 1316 | 12 1317 | 13 // 假设这是类加载器B加载的Person类 1318 | 14 ClassLoader classLoaderB = new CustomClassLoader(); 1319 | 15 Class classB = classLoaderB.loadClass("Person"); 1320 | 16 1321 | 17 // 尝试使用类加载器B来反序列化对象 1322 | 18 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); 1323 | 19 ObjectInputStream ois = new ObjectInputStream(bis) { 1324 | 20 @Override 1325 | 21 protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { 1326 | 22 // 指定使用类加载器B 1327 | 23 return classLoaderB.loadClass(desc.getName()); 1328 | 24 } 1329 | 25 }; 1330 | 26 1331 | 27 // 会抛出ClassCastException,因为类加载器A和B加载的Person类是不同的 1332 | 28 Object personB = classB.cast(ois.readObject()); 1333 | 29 } 1334 | 30} 1335 | ``` 1336 | 1337 | 在这个示例中,尽管`Person`类的字节码相同,但由于使用了两个不同的类加载器,所以类加载器A和B加载的`Person`类被视为不同的类。尝试将使用类加载器A序列化的对象传递给使用类加载器B反序列化会导致`ClassCastException`。在实际应用中,解决这个问题通常需要确保序列化和反序列化使用相同的类加载器,或者共享相同的类字节码。 1338 | -------------------------------------------------------------------------------- /document/Java基础-集合类.md: -------------------------------------------------------------------------------- 1 | # Java基础-集合类 2 | 3 | 1. 集合框架的基本概念 4 | 5 | - 集合与数组的区别 6 | - 集合的优点(动态扩容、提供多种数据结构等) 7 | 8 | 2. 接口与实现 9 | 10 | - Collection 接口:是最基本的集合接口,其他集合接口都继承自 Collection。 11 | 12 | - List 接口:一个有序的集合,可以包含重复的元素,提供索引访问方式。 例子:ArrayList、LinkedList 13 | 14 | ```java 15 | List list = new ArrayList<>(); 16 | list.add("Java"); 17 | list.add("Python"); 18 | list.add("C++"); 19 | ``` 20 | 21 | - Set 接口:一个不允许有重复元素的集合。 例子:HashSet、LinkedHashSet、TreeSet 22 | 23 | ```java 24 | Set set = new HashSet<>(); 25 | set.add("Java"); 26 | set.add("Java"); // 重复元素,不会被加入 27 | ``` 28 | 29 | - Queue 接口:提供先进先出队列的操作。 例子:LinkedList、PriorityQueue 30 | 31 | ```java 32 | Queue queue = new LinkedList<>(); 33 | queue.offer("Java"); 34 | queue.poll(); // 移除并返回队列头部的元素 35 | ``` 36 | 37 | - Map 接口:提供键值对映射,一个键对应一个值。 例子:HashMap、TreeMap、LinkedHashMap 38 | 39 | ```java 40 | Map map = new HashMap<>(); 41 | map.put("Java", 1); 42 | map.put("Python", 2); 43 | ``` 44 | 45 | 3. 迭代器(Iterator) 46 | 47 | - 使用迭代器遍历集合元素。 例子: 48 | 49 | ```java 50 | Iterator iterator = list.iterator(); 51 | while (iterator.hasNext()) { 52 | String element = iterator.next(); 53 | System.out.println(element); 54 | } 55 | ``` 56 | 57 | 4. 泛型(Generics) 58 | 59 | - 泛型的引入是为了指定集合中元素的类型,以避免类型转换错误。 例子: 60 | 61 | ```java 62 | List strings = new ArrayList<>(); // 指定集合元素只能是 String 类型 63 | ``` 64 | 65 | 5. 集合的排序 66 | 67 | - 使用 Collections.sort() 方法或其他相关方法对集合进行排序。 例子: 68 | 69 | ```java 70 | Collections.sort(list); // 对 List 集合进行排序 71 | ``` 72 | 73 | 6. 集合的同步 74 | 75 | - Java 集合框架中有些实现是非同步的,可以使用 Collections 类中的静态方法来包装成同步集合。 例子: 76 | 77 | ```java 78 | List syncList = Collections.synchronizedList(new ArrayList<>()); 79 | ``` 80 | 81 | 7. 性能考量 82 | 83 | - 理解不同集合实现的性能特点,例如 ArrayList 与 LinkedList 的插入、移除和随机访问的性能差异。 84 | 85 | 86 | 87 | ##### 数组和集合的区别 88 | 89 | 在 Java 中,集合(Collections)和数组(Arrays)都是用来存储对象引用的容器,但它们之间有一些显著的区别: 90 | 91 | 1. 大小可变性: 92 | - 数组的大小是固定的。一旦数组被创建,其大小就不能改变。 93 | - 集合的大小是可变的。集合可以根据需要动态地增长或缩减。 94 | 2. 类型安全性: 95 | - 数组是类型安全的,它们在声明时就确定了存储的数据类型。 96 | - 集合可以使用泛型来实现类型安全,但在泛型出现之前,集合可以存储任意类型的对象,这可能导致运行时错误。 97 | 3. 性能: 98 | - 数组有更好的性能,因为它们是固定大小和连续存储的,这使得数组的随机访问非常快。 99 | - 集合提供更复杂的数据结构,如链表、树和哈希表等,这些数据结构对特定操作有优化,但可能不如数组在随机访问上高效。 100 | 4. 功能丰富性: 101 | - 数组功能相对简单,主要支持基本的索引访问。 102 | - 集合框架提供了大量的功能,如自动扩容、排序、搜索、插入和删除元素等,以及更丰富的接口和实现。 103 | 5. 遍历方式: 104 | - 数组可以通过普通的 for 循环和 for-each 循环进行遍历。 105 | - 集合可以通过迭代器(Iterator)、for-each 循环,以及(对于 List)列表迭代器(ListIterator)进行遍历。 106 | 6. 内存占用: 107 | - 数组通常占用较少的内存,因为它们是连续存储的,并且没有额外的空间开销。 108 | - 集合因为其动态扩容和更复杂的数据结构,可能会占用更多的内存。 109 | 110 | 下面是一个简单的比较示例: 111 | 112 | ```java 113 | 1// 数组示例 114 | 2int[] numbersArray = new int[5]; // 大小固定为 5 115 | 3numbersArray[0] = 1; 116 | 4// ... 117 | 5 118 | 6// 集合示例 119 | 7List numbersList = new ArrayList<>(); // 大小可动态改变 120 | 8numbersList.add(1); 121 | 9// ... 122 | ``` 123 | 124 | 7.应用场景: 125 | 126 | - 集合提供了可动态扩展的丰富接口和更加灵活的数据结构,适合用在需要频繁插入、删除和排序等操作的场景。 127 | - 数组由于其性能优势,适用于大小固定,重视随机访问效率的场景。 128 | 129 | 130 | 131 | ##### Map、List、Set、Collection的关系 132 | 133 | 在 Java 中,Map、List、Set 和 Collection 属于 Java 集合框架的一部分,它们之间的关系如下: 134 | 135 | 1. Collection 接口: 136 | - Collection 是 Java 集合框架中的根接口,但它不包括 Map 接口。 137 | - 它定义了所有单列集合共有的操作,如添加元素、删除元素、清空集合、判断集合是否包含某元素等。 138 | - 任何实现了 Collection 接口的集合类(不包括 Map)都有这些基本操作。 139 | 2. List 接口: 140 | - List 继承自 Collection 接口,是一个有序集合,可以包含重复的元素,且每个元素都有其对应的索引。 141 | - List 的典型实现有 ArrayList、LinkedList 等。 142 | - List 允许对元素进行位置(索引)的精确控制,可以通过索引访问元素。 143 | 3. Set 接口: 144 | - Set 也是继承自 Collection 接口,是一个不允许有重复元素的集合,也是无序的(TreeSet 是有序的,但它的顺序是元素的排序顺序,而不是插入顺序)。 145 | - Set 的实现类有 HashSet、LinkedHashSet(保持插入顺序)和 TreeSet(有序集合,基于红黑树)等。 146 | - Set 通常用于存放不重复的元素集。 147 | 4. Map 接口: 148 | - Map 并不继承自 Collection 接口,它是一个完全独立的接口。 149 | - Map 存储键值对(key-value pairs),每个键映射到一个值,键不允许重复(必须唯一),值可以重复。 150 | - Map 的实现类有 HashMap、LinkedHashMap(保持插入顺序)和 TreeMap(有序映射,基于红黑树)等。 151 | 152 | 在 Java 集合框架中,Collection 和 Map 是两大主要的根接口,分别代表了两种不同的存储和操作数据的方式。Collection 主要是单个元素的集合,而 Map 是键值对的集合。List 和 Set 是 Collection 的两个主要子接口,它们定义了集合的特定行为。 153 | 154 | 下面是一个简单的图表说明了它们之间的关系: 155 | 156 | ```java 157 | Iterable 158 | | 159 | Collection 160 | / \ 161 | / \ 162 | List Set 163 | / | \ / | \ 164 | ArrayList LinkedList HashSet LinkedHashSet TreeSet 165 | 166 | Map 167 | / | \ 168 | HashMap LinkedHashMap TreeMap 169 | ``` 170 | 171 | 注意,虽然 Map 不是 Collection 的子接口,但它是 Java 集合框架的一部分,并且它具有与 Collection 相似的功能,如存储和操作一组对象。 -------------------------------------------------------------------------------- /document/Jenkins脑图2.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron-TangCode/JavaCode/168fc1b8bd31cccb36a1663133203dbe3e8be954/document/Jenkins脑图2.xmind -------------------------------------------------------------------------------- /document/RocketMQ限速.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron-TangCode/JavaCode/168fc1b8bd31cccb36a1663133203dbe3e8be954/document/RocketMQ限速.xmind -------------------------------------------------------------------------------- /document/ZSXQ.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron-TangCode/JavaCode/168fc1b8bd31cccb36a1663133203dbe3e8be954/document/ZSXQ.xmind -------------------------------------------------------------------------------- /document/偶像!给你一个可以写在简历上的亮点.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron-TangCode/JavaCode/168fc1b8bd31cccb36a1663133203dbe3e8be954/document/偶像!给你一个可以写在简历上的亮点.pdf -------------------------------------------------------------------------------- /document/公众号历史文章汇总.md: -------------------------------------------------------------------------------- 1 | ## 面经 2 | 3 | - [阿里巴巴5面面经(已获Offer)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701572&idx=1&sn=62bb14c25af161798b1345e47a62dc39&chksm=f3228718c4550e0e943f913bfaa6dbd1c40142693a873beca275432e005100d28e2ba942c435&token=797347776&lang=zh_CN#rd) 4 | 5 | - [你试过裸面大厂吗?](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701341&idx=1&sn=b4d7ca6df76c95ca17234bc56f02f8cf&chksm=f3228601c4550f17ff1ef93ad71cfd1965fef76449f0a2b6b7616f2d9ff90b2c39825439e061&token=797347776&lang=zh_CN#rd) 6 | 7 | - [面试——Java字节面经(已获Offer)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700844&idx=1&sn=1bb4733b552f20ea0fd7292de360c7a1&chksm=f3228430c4550d26f9d40e3a7d5080f6f0b1bd37ec6dcc497b8d4d19303b5cc0ce65d026a8d3&token=797347776&lang=zh_CN#rd) 8 | 9 | - [面试——美团面经(已获Offer)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700839&idx=1&sn=aa9633bacf94d0927300b966b8860238&chksm=f322843bc4550d2d1985c22135fd0e9af95778a4ec95d22193a606b9cf03b2285d749d86887b&token=797347776&lang=zh_CN#rd) 10 | 11 | 12 | 13 | ## Java 14 | 15 | - [what!!!小白都懂的死锁,你不懂?](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701540&idx=1&sn=6235aa65a8c47f2e5202f842925f54c8&chksm=f32286f8c4550fee0e6e052a4ff302fffc3ace16462e01108720f724f4d5b9a2477e20a7a68b&token=797347776&lang=zh_CN#rd) 16 | - [用泊松分布来解释为什么HashMap的链表变树的阈值是8](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700884&idx=1&sn=f9485215a29599d044536545e3000227&chksm=f3228448c4550d5e9d8678ddcfed47d8e2a75ae55c6a0fd11e6d3fe4074df49b46676bf94064&token=797347776&lang=zh_CN#rd) 17 | - [双亲委派模型](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700857&idx=1&sn=ee2cd21a36a68a90cb1352062c78c908&chksm=f3228425c4550d332e7499579f63f868d485ffa62ee9400f13991ba834ab2dcd7b8e26ba3431&token=797347776&lang=zh_CN#rd) 18 | - [面试Java——集合之HashMap和ConcurrentHashMap](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700834&idx=1&sn=a175f772cdf68d15cde839d456fff4c1&chksm=f322843ec4550d286efe6194771792dc89b0a582c51ce8c1b98c68bb53601295bc52d8c48aa4&token=797347776&lang=zh_CN#rd) 19 | 20 | 21 | 22 | ## JVM 23 | 24 | - [JVM-弱引用的适用场景-1](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701215&idx=1&sn=f67cf58f52f0b0f387d49d077fed30a4&chksm=f3228583c4550c951255e3b05bf6fcd5923c294912f3d9282f519c9ad20cd34fc8a60abc2642&token=797347776&lang=zh_CN#rd) 25 | - [JVM-强引用 软引用 弱引用 虚引用 底层原理(JVM源码)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701205&idx=1&sn=fb5bc89720466a52ee3c092f85ec6797&chksm=f3228589c4550c9f4c8be2fba71f9df4d1f2e10a20a4d25784432d6de052d7c40ede6251a83e&token=797347776&lang=zh_CN#rd) 26 | - [JVM-结合MAT工具来分析OOM问题](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701120&idx=1&sn=29277c37dd9526b053b78e6656322a4e&chksm=f322855cc4550c4a7ee9191ae5a63c90204195c554b9815396e92815dee44e20c80640b4a311&token=797347776&lang=zh_CN#rd) 27 | 28 | - [JVM-对象进入老年代的四种方式-4(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701161&idx=1&sn=330f466501c5c34d52187218b1fdbbbe&chksm=f3228575c4550c638e7e01ccdc46b2e0c9dcbdf0acde74bfd7c9edc156809b3584cbe2c22ced&token=797347776&lang=zh_CN#rd) 29 | 30 | - [JVM-对象进入老年代的四种方式-3(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701146&idx=1&sn=61a20acc65ef852d2802eb0967254f73&chksm=f3228546c4550c50b234aac5968b0b8bbbf6392ac398b94f4acfa916e659a225c4f594d7417b&token=797347776&lang=zh_CN#rd) 31 | 32 | - [JVM-对象进入老年代的四种方式-2(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701102&idx=1&sn=2b8c5fafdeb134ded48a744434ee088a&chksm=f3228532c4550c24c767ce958f0db3543e03c8d3f0a15856967cbc6d30823ab9604368ed7e66&token=797347776&lang=zh_CN#rd) 33 | 34 | - [JVM-对象进入老年代的四种方式-1(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701093&idx=1&sn=dd20e694eda51631337b98012f1abce6&chksm=f3228539c4550c2f59a798d952ecd0b7d8ce4f91294a15879fe9097f93f910fb3aae28621998&token=797347776&lang=zh_CN#rd) 35 | 36 | - [JVM-对象进入老年代的四种方式(实战篇)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701073&idx=1&sn=91515983107c5a4f30a81e715989fba8&chksm=f322850dc4550c1b137b6952f1eb1dfa867707d542a2a0374a00241eb96dd75cf665bfcbbd17&token=797347776&lang=zh_CN#rd) 37 | 38 | - [《分享》关于JVM的学习资料推荐](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700911&idx=1&sn=deba5187438260cedf7c00e8edf6911c&chksm=f3228473c4550d656b575137d2b6205ee1971b98979bede88d2aee20600597ccdeed9fba2c43&token=797347776&lang=zh_CN#rd) 39 | 40 | 41 | 42 | ## 设计模式 43 | 44 | - [设计模式——优化退款案例(策略模式&模板模式&工厂模式)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701180&idx=1&sn=d90036a2e54f415790a71b38b3b81211&chksm=f3228560c4550c76ff56ee88f61430a61ca48a562983949b9bebfbf04d49568a7d6e54c50eca&token=797347776&lang=zh_CN#rd) 45 | 46 | 47 | 48 | ## 运维 49 | 50 | - [服务炸了!!!Cpu 500%](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701519&idx=1&sn=b7682fd83c4d19cfd239f6680f194a5f&chksm=f32286d3c4550fc56b2bb7bac36bb6f2f266bb465e843eaa7255b47b08836a9af7dd5e44147a&token=797347776&lang=zh_CN#rd) 51 | - [生产事故——磁盘使用率爆仓](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700964&idx=1&sn=e7632ef25d63366de8dbeb5c5c504c7e&chksm=f32284b8c4550daef0d5f8b2051ec92dd2b9b4549832bbafcf10e602dd82e250efdaf41ea954&token=797347776&lang=zh_CN#rd) 52 | 53 | 54 | 55 | ## RocketMQ 56 | 57 | - [RocketMQ-幂等性](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701426&idx=1&sn=ce408d3e08c9cf523b6573629dabed8c&chksm=f322866ec4550f789df3fbcd86bd853b28ccbaa04e00265e63c74115695d5872b9cfc6d25a3b&token=797347776&lang=zh_CN#rd) 58 | 59 | - [RocketMQ-刷盘机制](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701413&idx=1&sn=ba21ed496905eee8dd08b41abb8cc44d&chksm=f3228679c4550f6f205bd3e883b0374a70782d6dcdc18e312879ce03f9f5d4da546089915d5f&token=797347776&lang=zh_CN#rd) 60 | 61 | - [RocketMQ-存储机制](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701402&idx=1&sn=d3d02e9e4e9711fa2566537b7e2dc21c&chksm=f3228646c4550f50aef4231b29960445cad3ba78c8a0571c23e033f2f27693c0b11648d0558b&token=797347776&lang=zh_CN#rd) 62 | - [RocketMQ-批量消息](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701389&idx=1&sn=2800dcc8e9e7f43d8fa8cde7aafc1a7f&chksm=f3228651c4550f4756ee7844d06ab9348ac862526fdc86845272802c27ed10a346c244a89878&token=797347776&lang=zh_CN#rd) 63 | - [RocketMQ-消息过滤](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701377&idx=1&sn=08f85efc34c5dc23ebb0a9f3979fb6b7&chksm=f322865dc4550f4be8349812061507bd0a01a7f276046dcf94f4eb322ee12c88baf17e25dae1&token=797347776&lang=zh_CN#rd) 64 | - [RocketMQ-事务消息(分布式事务)](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701364&idx=1&sn=aed7c14e68cd10fb9898712045b29749&chksm=f3228628c4550f3e91adc5407d4dd6a4567402403f62fa4fb5a87b6252852701bdbe98b168a0&token=797347776&lang=zh_CN#rd) 65 | - [RocketMQ-延迟消息](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701333&idx=1&sn=a7cd2554aebd204858a5f0c281391ef3&chksm=f3228609c4550f1f11932e5221b4f6b0b4526198b528677cc9534bce69754009f6e7bf3e4ce7&token=797347776&lang=zh_CN#rd) 66 | - [RocketMQ-顺序消息](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701319&idx=1&sn=0cffa4ef1cfae09d2ecb64e0227026c7&chksm=f322861bc4550f0d6375950f4e8d27fa71839826de100639791d17a71ca5fc6e90011fc7441d&token=797347776&lang=zh_CN#rd) 67 | - [RocketMQ-架构和角色](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701286&idx=1&sn=50d490036ab87493df546f0c9befb097&chksm=f32285fac4550cecece83abe828b9e657e596ba898007074ca4ffbf3f1bfb8ad76893cd85681&token=797347776&lang=zh_CN#rd) 68 | - [RocketMQ-集群模式和广播模式](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701277&idx=1&sn=c0934761a5e14307105b5a4ec215392e&chksm=f32285c1c4550cd7bf65a36abe6a1c6b3520c354a5d5bec8c76bc11eadc0630ff0096642b4eb&token=797347776&lang=zh_CN#rd) 69 | - [RocketMQ-发送消息](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701268&idx=1&sn=2522be2727b40a52403b3867ed284b7b&chksm=f32285c8c4550cde35494e67402591ec3e18a64515f90f64309e8ff3df738845b206f5665205&token=797347776&lang=zh_CN#rd) 70 | 71 | 72 | 73 | ## Redis 74 | 75 | - [不懂缓存一致性,易把代码写成bug](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650701009&idx=1&sn=6db4cd4e8ff5751f151c77d3f6bc9d70&chksm=f32284cdc4550ddbbbfc30d02918786134d1b278f9ab7c47af469b14ca66b629fcb467cc2ce8&token=797347776&lang=zh_CN#rd) 76 | - [Redis——缓存并发 缓存雪崩 缓存穿透](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700815&idx=2&sn=d9d3d74a342a3f6acef78f8e927d847d&chksm=f3228413c4550d05c5628ad7201aa29499c9f90af360f37a95e683406cb39b9f0e4168ee8cc9&token=797347776&lang=zh_CN#rd) 77 | - [Redis——集群](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700785&idx=1&sn=f7a3030f33cc0fa688cab331ff41bb5b&chksm=f32283edc4550afbd46d3754b266ab2fd9a512a9a5f4ca1fe3d20d6c8dafd1351ab65e1f7953&token=797347776&lang=zh_CN#rd) 78 | - [Redis——监视器](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700780&idx=2&sn=d1e991cf5b72ab5802cc3951915148dd&chksm=f32283f0c4550ae64e4b8937e511f31b8f9f0954fa83e547b849b4c0a12f9048daeea3b75188&token=797347776&lang=zh_CN#rd) 79 | - [Redis——慢查询日志](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700780&idx=1&sn=027d28a4cc7168d6f1bdf0b934af528d&chksm=f32283f0c4550ae640f7ae5131aeae3b70ff276570a5b7db086500b0d3559b5f2233533c28f8&token=797347776&lang=zh_CN#rd) 80 | - [Redis——哨兵模式的实现机制](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700770&idx=1&sn=5f46858a7875c84e119db3d7b7429ae9&chksm=f32283fec4550ae8bd303cb110e9c0d7822e849c8df6b08cff8848acc95abcd0efe70d466d64&token=797347776&lang=zh_CN#rd) 81 | - [Redis——事务](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700769&idx=1&sn=3a68ea45b9553bfbba57f1a71308e661&chksm=f32283fdc4550aeb0ef567523f4991974b6596ab65014a74ac6dd89a5be0c14ab9b246d8db95&token=797347776&lang=zh_CN#rd) 82 | - [Redis——心跳机制](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700753&idx=2&sn=5e49758a665dad2e7a2059167be50cac&chksm=f32283cdc4550adb191add60b4426f9a3d67678620cb6b45a06be199d2db5f3c6a1fed0506cd&token=797347776&lang=zh_CN#rd) 83 | - [Redis——复制的实现](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700753&idx=1&sn=bc9c2780e90e27490552aa49eb8d011c&chksm=f32283cdc4550adb403966e623d1cea80cb4cb91ed87dc53d0f65560f721e96ed27a26b64909&token=797347776&lang=zh_CN#rd) 84 | - [Redis——事件驱动模型](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700744&idx=1&sn=987556b1c3fc1f64e703e205f6f093ed&chksm=f32283d4c4550ac2d287a782a2a7248cfc7d6cf96f0a9405294d5ec2a4bf1a2d7f2c65398651&token=797347776&lang=zh_CN#rd) 85 | - [Redis——RDB和AOF那些事](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700738&idx=1&sn=38a7f53988b5b03e44a0b8c40af3c08c&chksm=f32283dec4550ac85b8ff3b20b13519da027be08aac5adca1d9243d9469d74b8929fe493998e&token=797347776&lang=zh_CN#rd) 86 | - [Redis——服务器的serverCron函数](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700733&idx=1&sn=ecae0524192326d2b07a6ff1ff5baa27&chksm=f32283a1c4550ab7d3229cb22414093055ca8a737f5589bcad72da9b0bff2ec6f8139faa9bcb&token=797347776&lang=zh_CN#rd) 87 | - [Redis——服务器的启动过程](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700721&idx=1&sn=b28582e3081a89e1081cf06d4e81b568&chksm=f32283adc4550abba2dc9185da074e253fd12aaaa71e7ed0c1ba29c0d9644ed385e21e523eaf&token=797347776&lang=zh_CN#rd) 88 | 89 | 90 | 91 | ## 数据库 92 | 93 | - [面试MySQL——索引](https://mp.weixin.qq.com/s?__biz=MzI3MzEwOTM2Mw==&mid=2650700815&idx=1&sn=c49612769eff5a7054eafcc6e2584178&chksm=f3228413c4550d0587286f28b345ca56c2392a55c4a9bab28191fb020324ec23f2f25dabfb30&token=797347776&lang=zh_CN#rd) 94 | 95 | -------------------------------------------------------------------------------- /document/哎哟!这个Bug,有点东西.md: -------------------------------------------------------------------------------- 1 | # 哎哟!这个Bug,有点东西 2 | 3 | 4 | 5 | 有一个朋友和我聊天时,我们聊起了最近线上出现的Bug。他的分享中,比较经典的Bug是这样子的: 6 | 7 | 8 | 9 | 朋友突然收到业务的反馈,在创建账户时,显示如下异常: 10 | 11 | ![JSON问题-截图2](/Users/yebing/Downloads/JSON问题-截图2.jpg) 12 | 13 | 朋友说看到这个截图的第一反应就是这个Bug肯定和序列化有关系。 14 | 15 | 16 | 17 | 异常中提到了特定的信息: 18 | 19 | method: getManagerIdCard 20 | 21 | 22 | 23 | 也就是这个 getManagerIdCard方法序列化时出现了异常。我直接定位到商家实体类Merchant的getManagerIdCard方法。 24 | 25 | 26 | 27 | ```java 28 | public String getManagerIdCard() { 29 | return getExtInfo(ID_CARD, String.class); 30 | } 31 | // propertyMap里面存着,key:managerCardId value:123456789999999999X 32 | private T getExtInfo(String propertyName, Class clazz) { 33 | if (propertyMap == null) { 34 | propertyMap = (Map) JSONObject.parseObject(extInfo, Map.class); 35 | if (propertyMap == null) { 36 | return null; 37 | } 38 | } 39 | Object propertyJson = propertyMap.get(propertyName); 40 | if (Objects.isNull(propertyJson)) { 41 | return null; 42 | } 43 | return JSON.parseObject(propertyJson.toString(), clazz); 44 | } 45 | ``` 46 | 47 | 48 | 49 | 朋友和测试同学沟通后发现,这个功能当时已经测试过的,但当时测试用例是这样子的: 50 | 51 | managerIdCard:012345678912345678 52 | 53 | 54 | 55 | 但目前抛异常的入参显示的managerIdCard为:01234567891234567**X** 56 | 57 | 58 | 59 | 看到这里,导致Bug的原因已经很明显了。 60 | 61 | 62 | 63 | 就是最后一句代码的问题 64 | 65 | ```java 66 | JSON.parseObject(propertyJson.toString(), clazz); 67 | ``` 68 | 69 | 代入参数值后: 70 | 71 | ```java 72 | JSON.parseObject("01234567891234567X", String.class); 73 | ``` 74 | 75 | 看到这里我当时表示非常疑惑,朋友也表示当时的他也很疑惑 76 | 77 | 78 | 79 | 但这代码放在Idea上跑,你就会发现,会报错 80 | 81 | ```java 82 | Exception in thread "main" com.alibaba.fastjson.JSONException: not close json text, token : error 83 | at com.alibaba.fastjson.parser.DefaultJSONParser.close(DefaultJSONParser.java:1527) 84 | at com.alibaba.fastjson.JSON.parseObject(JSON.java:400) 85 | at com.alibaba.fastjson.JSON.parseObject(JSON.java:300) 86 | at com.alibaba.fastjson.JSON.parseObject(JSON.java:573) 87 | ``` 88 | 89 | 但如果把参数值替换为: 90 | 91 | ```java 92 | JSON.parseObject("012345678912345678", String.class); 93 | ``` 94 | 95 | 这代码跑起来是正常的。 96 | 97 | 98 | 99 | 经过一番折腾后,才发现在 fastjson 中,`JSON.parseObject` 方法用于将 JSON 字符串解析成 Java 对象。当你传递一个 JSON 字符串时,它应该是一个合法的 JSON 格式。对于字符串,这意味着它应该被双引号包围。例如: 100 | 101 | ```java 102 | String jsonString = "\"111111X\""; 103 | String parsedString = JSON.parseObject(jsonString, String.class); 104 | ``` 105 | 106 | 这段代码会正常运行,因为 `"\"111111X\""` 是一个合法的 JSON 字符串。 107 | 108 | 109 | 110 | 我看到这里,又有问题了,那为啥JSON.parseObject("012345678912345678", String.class)就不报错呀 111 | 112 | 113 | 114 | 其实是这样子的。fastjson 在某些版本中对于解析纯数字字符串时可能会较为宽松,允许没有双引号包围的数字字符串,因此 `"111111"` 可能意外地通过了解析(这并不符合标准的 JSON 规范,但是 fastjson 可能在这方面有自己的实现逻辑)。而 `"111111X"` 由于包含非数字字符,无法被解释为一个数字,因此会触发解析错误。 115 | 116 | 117 | 118 | 问题复盘完了,那接下来应该如何修复?关于这个问题,你可以思考一下,把想法写在留言区,下期文章分享修复方案 119 | 120 | 121 | 122 | 源代码: 123 | 124 | ```java 125 | public String getManagerIdCard() { 126 | return getExtInfo(ID_CARD, String.class); 127 | } 128 | // propertyMap里面存着,key:managerCardId value:123456789999999999X 129 | private T getExtInfo(String propertyName, Class clazz) { 130 | if (propertyMap == null) { 131 | propertyMap = (Map) JSONObject.parseObject(extInfo, Map.class); 132 | if (propertyMap == null) { 133 | return null; 134 | } 135 | } 136 | Object propertyJson = propertyMap.get(propertyName); 137 | if (Objects.isNull(propertyJson)) { 138 | return null; 139 | } 140 | return JSON.parseObject(propertyJson.toString(), clazz); 141 | } 142 | ``` 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /document/在进行技术方案:代码评审时,我们应该关注哪些方面?.md: -------------------------------------------------------------------------------- 1 | # 在进行技术方案/代码评审时,我们应该关注哪些方面? 2 | 3 | 4 | 5 | ## 背景 6 | 7 | 作为开发,技术方案和代码评审,这两件事,必不可少。开发前,需要写技术方案。上线前,需要进行代码评审。但如果我们CR别人的代码或者参与别人的技术方案会议时,我们也不知道从哪些方面进行评判这个技术方案好or 不好。 8 | 9 | 下面,我提供了两个大的方向进行去度量这个技术方案/代码CR。分别是:容错设计和系统设计。 10 | 11 | 至于需求的具体设计,这个每个需求都不一样。这里我只考虑共性:容错设计和系统设计。 12 | 13 | ## 关注容错设计 14 | 15 | - 可灰度 16 | - 可灰度,那就弄好开关。还可以更细粒度进行灰度,比如按照城市,渠道,来源等粒度进行灰度 17 | - 不可灰度,需要关注下是否存在新老逻辑不兼容的情况。比如数据的一致性。 18 | - 可观察 19 | - 是否可以通过日志,监控来发现是否出问题。 20 | - 如果有监控,监控能否报出来。 21 | - 是否涉及资损,如果有。是否有实时监控+离线核对+离线报表 22 | - 可回滚/可应急 23 | - 上线后,这个代码能否回滚。如果回滚,是否会导致数据不一致。 24 | - 如果不可回滚,能否通过关闭灰度开关 25 | - Try-catch 26 | - 代码的改动,发生的异常,是否应该阻断。这里其实就是强弱依赖的问题。 27 | 28 | ## 关注系统架构设计 29 | 30 | - 线程安全 31 | - 简单点来讲,就是看看代码是否存在线程安全问题 32 | - 数据库变更 33 | - 关注表的字段设置是否合理,表是否影响上下游。 34 | - 为什么需要新增表?为什么分表?为什么不分表? 35 | - 表是否有主键、uk、ctime、utime?字段为什么是default null?为什么是 not null default 0? 36 | - 修改的表下游数据采集是否受影响? 37 | - 是否涉及表同步?上线顺序? 38 | - 关注是否有缓存,如果有缓存,需要关注数据库和缓存的一致性问题 39 | - 系统交互 40 | - 数据一致:关注上下游的数据是否一致 41 | - 强弱依赖:关注上下游的依赖是否为强依赖。如果是弱依赖,是否可以考虑降级 42 | - 版本:关注上下游的版本是否一致,比如服务端和客户端是否兼容 43 | - 上线顺序:还有关注一下,上线的时候,是否有上线顺序 44 | - 数据安全:和外部服务交互的时候,考虑一下数据的安全性问题。比如是否需要进行加密,IP白名单,因为并不是所有的调用方都能进行调用的,需要先进行鉴权。 45 | - RT和QPS:涉及到交互时,对于下游,即依赖的外部应用。在调用接口之前,需要了解清楚下游接口的RT和QPS。如果下游RT很高,容易拖垮我们自己的应用。这里,我们如果遇到弱依赖,可以加开关,必要时,可进行降级。如果下游的QPS,不足以支撑我们自己的应用。我们就别调了。必要时,可让下游应用给我们的功能进行定制开发。或者,如果我们访问下游的数据是不频繁变动的,可进行缓存,目的是为了降低下游的QPS压力。 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /document/如何入门Java.md: -------------------------------------------------------------------------------- 1 | # 如何入门Java? 2 | 3 | 如何入门Java?拆文解字:「如何」「入门」「Java」,三个关键词。 4 | 5 | 首先,下定义:什么是入门? 6 | 7 | 我直接CHATGPT: 8 | 9 | > "入门"这个词可以根据不同的语境有多种意义。 10 | > 11 | > 1. 初学某种技能或知识: "入门"在这个情境下意味着开始学习某种技能或知识领域的基础,例如,“入门级中文课程”是指为初学者设计的基础课程。 12 | > 2. 传统文化或宗教中的成为弟子: 在某些文化或宗教中,“入门”意味着正式成为一个师傅或宗教领袖的弟子,开始学习和练习特定的教义或技艺。 13 | > 3. 接触新领域或行业: 当某人“入门”一个新领域或行业时,这意味着他们开始了解并参与该领域的活动,可能是通过就业、实习或其他方式。 14 | > 4. 日常用语中的字面意思: "入门"在日常用语中也可以简单指的是走进一个房间或建筑的入口。 15 | > 5. 技术或产品: 对于技术或产品来说,“入门级”往往指的是基础型或适合初学者的版本,比如“入门级相机”通常是指功能较为基础、操作简单的相机,适合刚开始学习摄影的人使用。 16 | 17 | 在这里,我给入门的定义是第一种: 18 | 19 | **"入门"在这个情境下意味着开始学习某种技能或知识领域的基础。** 20 | 21 | 第二个问题:什么是Java? 22 | 23 | 同理,GPT一下: 24 | 25 | > Java是一种广泛使用的编程语言,由Sun Microsystems(现已并入甲骨文公司,即Oracle Corporation)在1995年推出。它是一种面向对象的语言,意味着它基于表示对象的类和对象的概念,这些对象可以包含数据(属性)和操作数据的方法。 26 | > 27 | > Java具有以下几个关键特性: 28 | > 29 | > 1. **可移植性**:Java的设计理念是“一次编写,到处运行”(Write Once, Run Anywhere),这得益于Java虚拟机(JVM)。编写的Java代码首先被编译成一种平台无关的字节码,然后可以在任何安装了JVM的设备上运行,不论底层操作系统是什么。 30 | > 2. **面向对象**:Java是一种面向对象的编程语言,这意味着它鼓励程序员使用对象来建模现实世界问题。面向对象编程有几个关键概念,如封装、继承和多态。 31 | > 3. **安全性**:Java提供了强大的安全机制,可以防止各种攻击,比如运行时的类型检查、自动垃圾收集、异常处理等。 32 | > 4. **多线程**:Java天生支持多线程编程,这意味着你可以创建同时运行的多个执行路径,以实现并行处理和更高效的应用程序性能。 33 | > 5. **健壮性**:Java的强类型机制、异常处理和垃圾收集等特性都有助于创建稳定、可靠的应用程序。 34 | > 6. **分布式**:Java在网络方面的内置支持使得创建分布式应用相对容易。 35 | > 7. **高性能**:虽然Java程序执行的是字节码,通过即时编译器(JIT)技术,其运行速度可以接近原生代码。 36 | > 37 | > Java被广泛应用于不同类型的软件开发,包括桌面应用程序、移动应用程序(尤其是Android)、服务器端应用程序(如Web应用程序、企业级应用等)、嵌入式系统等。Java生态系统由一个庞大的标准类库(Java Standard Edition, Java SE)、各种开源库、框架、开发工具以及一个活跃的开发者社区组成。 38 | 39 | 相信你看完上面的解释,或许你记住了「面向对象」,亦或许什么也没记住,也不清楚什么是JAVA。 40 | 41 | 我直接下一个定义,去掉所有定语:**JAVA是一门语言**。 42 | 43 | 我举个例子: 44 | 45 | - 我现在和你沟通,你在阅读我事先写好的文字,那我们沟通的语言叫中文; 46 | - Now,I am talking to you about what is java? 那我们沟通的语言叫英文; 47 | - 我宜家同你倾紧Java是咩? 那我们沟通的语言叫粤语。 48 | 49 | 上面的沟通,都是「人」和「人」之间的沟通,有中文,英文,粤语。 50 | 51 | 如果我们现在需要实现「人」和「机器」之间的沟通,这时我们需要Java,Python,Go,C++等语言。 52 | 53 | 54 | 55 | 总之,到现在,你可能对什么是Java有一定的体感了。简单直白地说:**Java就是一门语言**。 56 | 57 | 58 | 59 | 至于Java是什么样的语言?有什么特点? 60 | 61 | 62 | 63 | 这个时候,可以把刚刚去掉的「定语」补回来。 64 | 65 | 66 | 67 | 「面向对象」「高性能」「一次编译,到处运行」等等。**这些先不用关注,现在是入门,不是深入**。 68 | 69 | 70 | 71 | 第三个关键词:如何? 72 | 73 | > “如何”是一个中文疑问副词,用来询问方法、方式或过程。它可以用在不同的语境中,常见的用法包括询问某事应该怎么做、怎样进行,或者询问某种状态或结果是怎么产生的。以下是一些例子来展示“如何”的不同用法: 74 | > 75 | > 1. 询问指导或步骤:你可以问“我应该如何解决这个数学问题?”来获取解题的方法。 76 | > 2. 询问建议或方案:比如,“我们如何提高工作效率?”是在寻求改善工作效率的建议。 77 | > 3. 询问具体情况:例如,“这个装置是如何工作的?”是想要了解装置的工作原理。 78 | > 4. 询问原因:当你问“这是如何发生的?”时,你可能在寻求一个事件发生背后的原因。 79 | > 80 | > 在英语中,相对应的疑问词通常是“how”,可以用在相似的语境中来询问方法、过程或原因。 81 | 82 | 这里"如何"指: 83 | 84 | - 学习什么内容,什么课程,什么知识点 85 | - 学习的顺序,学习的步骤,先学什么,后学什么 86 | - 学习的方法或方式:看书,看视频,看文章,甚至听书。。 87 | - 学到什么程度 88 | 89 | 90 | 91 | 结合上面的「入门」「Java」来进行解释 92 | 93 | > 学习什么内容,什么课程,什么知识点 94 | 95 | 入门java指学习java基础知识,所以什么高阶知识,求你先别学,否则就学《Java从入门到放弃》 96 | 97 | 知识点如下: 98 | 99 | 基本工具学习: 100 | 101 | - IDEA、Eclipse 102 | 103 | - maven 104 | - git 105 | 106 | java基础知识 107 | 108 | - 基础语法(条件,循环,三元表达式等等) 109 | - 面向对象(类型初始化、多态、抽象、封装、泛型、反射、序列化) 110 | - 集合类(List、Map、Set等等) 111 | - 基本文件读写操作 112 | - 网络编程基础知识 113 | - 线程基础知识(Thread、同步、Threadlocal、Wait、Notify,Sleep等等) 114 | - 异常处理 115 | - JDBC相关 116 | 117 | java web编程基础 118 | 119 | - Http协议基础知识:协议、GET/POST、Header、Http Cache、跨域 120 | - Cookie、Session原理及区别 121 | - Servlet工作原理 122 | - Velocity基础 123 | - Tomcat基础知识 124 | 125 | 126 | 127 | 学习的顺序: 128 | 129 | Java基础知识>Idea或Eclipse>Maven>Git>java web编程基础 130 | 131 | 132 | 133 | 学习的方式 134 | 135 | - 完全取决于个人,哪个课程,哪个书,哪个老师,你能听得明白就行。和老师、课程、书籍是否出名无关。 136 | 137 | 138 | 139 | 学到什么程度 140 | 141 | - 会用就行。你跟着书,跟着视频,跟着老师,把学过的代码敲一遍,不敲的话,永远学不会。 142 | 143 | -------------------------------------------------------------------------------- /document/如何防止接口被盗刷.md: -------------------------------------------------------------------------------- 1 | # 如何防止接口被盗刷 2 | 3 | 接口被盗刷,就是指某些用户对某个接口进行频繁访问。 4 | 5 | 6 | 7 | 有哪些方法可以对防止接口被盗刷? 8 | 9 | - 验证码,比如登录的时候,就使用到验证码,这种方法可以有效防止普通用户频繁访问,但是如果用户是一个黑客,是可以绕过验证码,直接访问后端的接口的。这个时候可以用到限流。 10 | 11 | ![image-20240128182509762](/Users/aaron/Library/Application Support/typora-user-images/image-20240128182509762.png) 12 | 13 | - 限流:就是限制一段时间内接口的访问频率。比如QPS 50 ,即每秒50次。超过这个频率就拒绝访问接口。 14 | - IP黑名单 15 | - 如果是已某些IP用户是恶意用户,可以通过IP黑名单进行限制访问 16 | 17 | 18 | 19 | 针对使用限流方案,目前最佳实践是:sentinel和hystrix 20 | 21 | Hytstrix:https://github.com/Netflix/Hystrix 22 | 23 | Sentinel:https://github.com/alibaba/Sentinel -------------------------------------------------------------------------------- /document/强息书单.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron-TangCode/JavaCode/168fc1b8bd31cccb36a1663133203dbe3e8be954/document/强息书单.xmind -------------------------------------------------------------------------------- /document/慢SQL治理.md: -------------------------------------------------------------------------------- 1 | # 慢SQL治理 2 | 3 | 4 | 5 | ## 1、什么是慢SQL? 6 | 7 | - 就是执行时间较长的SQL。那具体是多长?比如超过100ms的SQL就被称为慢SQL。但这个阈值,需要根据不同的业务来进行设置。 8 | 9 | 10 | ## 2、慢SQL为什么慢? 11 | 12 | - 查询语句的写法不合理:SQL查询语句的写法可能存在问题,比如。你使用了复杂的子查询、嵌套查询或者多个连接操作,导致查询的效率低下。**强烈建议采用:简单查询** 13 | - 数据库表设计不合理:数据库表的设计可能存在问题,例如表关联过多、字段冗余、数据重复等,导致查询数据时需要进行大量的计算和操作,影响查询速度。**这个其实我们很难发现,因为我们一般都以为自己建的表合理** 14 | - **缺乏合适的索引或走错索引**:索引的作用是加速数据的查找和排序,如果查询涉及的字段没有创建索引或者索引不合理,会导致查询速度变慢。**绝大部分SQL慢的原因就是索引问题** 15 | - 数据库服务器配置不合理:数据库服务器的配置参数可能没有经过合理的调整,导致数据库性能下降,影响SQL查询的执行速度。比如:**连接数,线程数,缓冲区**参数等 16 | - 数据库统计信息不准确:数据库的统计信息用于优化查询计划,如果统计信息没有及时更新或者不准确,可能导致查询计划选择不合理,从而影响查询速度。 17 | - 数据量过大:当数据库中的数据量过大时,查询操作的成本会增加,导致查询速度变慢。 18 | - 锁竞争:当多个查询同时访问同一个数据对象时,可能会发生锁竞争,导致查询等待其他操作的释放,从而影响查询速度。 19 | 20 | ## 3、慢SQL有什么影响? 21 | 22 | - 响应时间延长:慢SQL会导致查询的响应时间延长,使用户在等待查询结果时需要更长的时间。这会**降低用户体验**,尤其是在高并发或需要实时响应的场景下。 23 | - 服务器负载增加:慢SQL的执行时间较长,会占用服务器的资源,例如**CPU、内存和磁盘IO**等。如果大量慢SQL同时执行,会导致服务器的负载增加,降低系统的性能和并发处理能力。 24 | - 数据库性能下降:慢SQL会导致数据库性能下降,包括**查询速度变慢、响应时间延长、并发处理能力降低**等。这会影响到整个系统的性能和稳定性。 25 | - 系统可用性降低:当慢SQL集中发生时,可能会导致数据库服务器资源耗尽,从而导致系统崩溃或无法提供正常的服务。这会对系统的可用性产生严重影响。 26 | - 用户流失和损失:对于在线服务或电商平台等业务,慢SQL可能会导致**用户流失和损失**。如果用户在等待查询结果的过程中感到不耐烦或无法得到满意的响应,可能会选择离开或转向竞争对手。 27 | 28 | ## 4、如何治理慢SQL? 29 | 30 | - 发现->分析->修复方案->验证 31 | - 发现,分为主动发现和被动发现。 32 | - 主动发现:就是自己每天去数据库看日志,或者每天看SQL的监控平台。(数字化) 33 | - 被动发现:一旦发现慢SQL,系统会主动通知开发人员。这里的通知包括:邮件,电话,短信等。(自动化) 34 | - 分析&修复方案,是SQL原因,索引,数据库,数据量,硬件等 35 | - 优化查询语句:对于慢SQL,可以通过优化查询语句的写法来提升查询性能。例如,避免使用复杂的子查询或嵌套查询,尽量简化查询逻辑等。 36 | - 业务原因,其实就是结合业务来分析where 条件查询。看看是什么场景用的SQL。 37 | - 比如:有一些所谓根据名字进行模糊查询。like %name%。这种,快不了。只能MYSQL换ES 38 | - **创建合适的索引**:合理创建索引可以加速查询速度。通过分析查询的条件和频率,确定需要创建的索引类型和字段,提高数据库的查询效率。 39 | - 调整数据库配置参数:根据具体情况,可以调整数据库服务器的配置参数,如**内存缓冲区大小、并发连接数、查询缓存**等,以提升数据库的性能和响应速度。 40 | - 更新统计信息:数据库的统计信息对于优化查询计划很重要。定期更新统计信息,确保其准确性,让数据库能够选择最优的查询执行计划。 41 | - **常用命令:** 42 | - ANALYZE TABLE 43 | - OPTIMIZE TABLE table_name; 44 | - ALTER TABLE table_name ENGINE=InnoDB; 45 | - 重构数据库表结构:如果数据库表设计存在问题,例如表关联过多、字段冗余等,可以考虑进行数据库表结构的重构,以提高查询性能。 46 | - 使用缓存技术:对于一些频繁查询但数据变化不频繁的数据,可以考虑使用缓存技术,将查询结果缓存起来,避免重复查询数据库。 47 | - 分析和监控工具:使用性能分析和监控工具,对慢SQL进行定位和分析,了解慢SQL的具体原因和执行情况,从而有针对性地进行优化。 48 | - 增加硬件资源:如果以上方法无法满足需求,可以考虑增加硬件资源,如升级服务器、增加内存、使用**SSD**等,提高数据库的处理能力。 49 | - 验证 50 | - 性能测试:可以使用性能测试工具或者编写测试代码,模拟实际场景下的并发请求,测试修复后的SQL查询语句的执行时间和系统的响应性能。通过性能测试的结果,可以判断慢SQL是否得到了有效的修复。 51 | - 监控和分析工具:使用数据库监控工具或性能分析工具,监测和分析数据库的性能指标,例如查询响应时间、查询执行计划、索引使用情况等。通过比较修复前后的性能指标,可以判断慢SQL是否得到了改善。 52 | - 日志记录和观察:在修复慢SQL的过程中,可以在日志中记录修复前后的查询执行时间和相关信息。通过观察日志的变化,可以了解修复慢SQL的效果。 53 | - 反馈和回馈:如果修复慢SQL的工作是由团队或合作伙伴完成的,可以及时向他们反馈修复后的查询执行情况,并邀请他们进行验证和反馈。通过他们的反馈,可以了解慢SQL是否被有效修复。 -------------------------------------------------------------------------------- /document/虚拟列触发的Bug.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 背景:新增虚拟列导致异地机房同步延迟问题 4 | 5 | 6 | 7 | 表现:业务受影响。 8 | 9 | 10 | 11 | 因为N个数据库实例放在同一个服务器实例上,其中一个数据库实例因新增虚拟列,使得异地机房无法同步。从而导致数据库CPU从20%升到105%,数据库QPS从6K飙升到45K,还有慢查询,逻辑读,物理读,连接数全都飙升。 12 | 13 | (新增一张主从同步的图:直角三角形) 14 | 15 | 16 | 17 | 因为N个数据库实例在同一个服务器实例上,好吧,因为一颗老鼠屎搅浑一锅粥,直接一锅端。恰好这N个数据库都是核心数据库。结果就是整个业务崩溃。万幸的是,业务低峰期。不幸的是,持续了一个多小时,及时已经把流量已经切到从库了。但奈何影响还是存在的。 18 | 19 | 20 | 21 | 接下来就复盘,大家应该会有很多疑问 22 | 23 | 1、为什么新增虚拟列,会导致异地机房无法同步数据问题? 24 | 25 | D:首先,mysql在5.7版本是已经支持虚拟列的。但异地多活的数据库机房,不支持虚拟列的数据同步。 26 | 27 | 2、为什么允许新增虚拟列,但却不能进行数据同步? 28 | 29 | D:就是SQL都校验通过了,最后却说不能进行异地机房同步,这个锅,业务不背,数据库背吧。因为数据库规范里面没说不允许建虚拟索引,还有SQL校验都通过了。 30 | 31 | 3、为什么会把N个核心数据库放在同一个服务器实例上啊? 32 | 33 | D:一说没资源,二说没时间。 34 | 35 | 4、什么是虚拟列,为啥不新增普通列? 36 | 37 | > MySQL中的虚拟列是一种特殊的列,分VIRTUAL 和 STORED 2种类型。 38 | > 39 | > **VIRTUAL 虚拟列:** 40 | > 41 | > - VIRTUAL 虚拟列是通过表达式动态计算得出的值,并不实际存储在磁盘上。 42 | > - 每次查询时,虚拟列的值都会根据定义的表达式进行计算。 43 | > - 虚拟列的值是实时计算的,不占用额外的存储空间。 44 | > - 适用于那些能够通过其他列计算得出的值,而且计算开销较小的情况。 45 | > 46 | > **STORED 虚拟列:** 47 | > 48 | > STORED 虚拟列也是通过表达式计算得出的值,但与 VIRTUAL 不同,STORED 虚拟列的值在插入或更新数据时计算并存储在磁盘上。 49 | > 存储列的值只有在写入时计算一次,并且在查询时直接读取存储的值,不需要再进行实时计算。 50 | > 适用于那些频繁被查询而计算开销较高的场景,可以在写入数据时计算一次,然后在查询时直接读取存储的值,提高查询性能 51 | > 52 | > 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /pictures/个人微信.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron-TangCode/JavaCode/168fc1b8bd31cccb36a1663133203dbe3e8be954/pictures/个人微信.png --------------------------------------------------------------------------------