首页

k8猫系:实用指南

一键匹配 👉 点击这里 👈

</title<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?9ee4cf84cdf5f7446d26edc5598e4a6d"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> </head><body> 我是原始Java程序员,在一篇之前的文章中,我们提到了关于JAVA网络的一个话题,现在我看到有关虚拟机的博客或者文章,也提到了 类加载器(ClassLoader),我想做一个简单的学习记录,我之前看网络文章,有时候不太明白为什么一直要依赖于父加载器的代理模型,这一一来不知道的时候就会去看一下,大多数时间我们其实并没有遇到双亲委托模式的问题,也或者说在编程工作中一般使用第三方类库很少会涉及到自定义类加载器,不过自定义类加载器也是比较常见的一种技术,在Android开发中应用广泛,另外有时候我们在项目中也会用到自定义类加载器来做一些模块打包隔离的工作,所以重新探索一下类加载器的工作<a href="/article/sp-136" title="原则">原则</a>是值得的。在类加载过程中,如果遇到了几个比较关键的步骤,分别是,在类加载过程中现在只关注,父加载器代理类加载过程,Hot<a href="/article/sp-137" title="SP">SP</a>ot虚拟机中类加载器属于java.lang.ClassLoader的子类,Java程序在运行时,需要对类进行加载,类加载器用于加载class文件,且class文件加载到内存后会经过验证、准备等步骤,然后才能被创建为Class对象来供程序使用,类加载的过程主要包括验证、准备、解析、初始化、卸载5个阶段,其中前4个是加载时的过程,那类加载过程的时机是当程序第一次通过调用static、instanceof或者new等关键字要求加载类时,虚拟机需要的步骤包括:检查该类的类加载器是否有权利加载,每个类型的类加载器都是由父加载器来代理的,父加载器先进行加载如果没有找到,或者父加载器为null说明是根加载器去进行加载,而之类加载器是通过双亲委托机制进行加载的,即在代理过程中,先由父加载器进行尝试加载,如果父加载器没有加载成功那么子加载器才会尝试去加载,这样保证了内置类加载器的优先性, 我还没有理解这里的验证部分,不过可以先把代理机制给解释清楚,所以这里在学习类加载器的过程中,我们知道了两类类加载器:根加载器和引导加载器,根加载器也叫做启动类加载器,负责加载核心类库的class文件,引导加载器也叫做系统加载器,负责加载扩展类库或者应用类库,根引导加载器是JVM运行时数据区(运行时常量池)的一部分,他本身不是Java类,是由C++编写的,因此根引导加载器是唯一的没有继承 这里,我的学习笔记的观点有些混乱了,这时候再次小白思考一下,虚拟机规定所有加载类加载器必须继承定义各自的父类加载器,启动类加载器是由原生代码来实现,而不是继承ClassLoader类的,这可能是一个错误的理解,定位问题的来源:我们看到HotSpot的源代码中,ClassLoader是一个Java类,但是双亲委托时,启动类加载器是由C++编写,代码 this.handlesPackage( name, package2); this.allowStackFromClassLoaderAssertion;; 而用户自定义类加载器是继承ClassLoader类的,所以啊,BootstrapClassLoader并不是ClassLoader的实例,而且它也没有父类加载器,BootstrapClassLoader是JVM运行时数据区(运行时常量池)的一部分,ClassLoader.getSystemClassLoader()是获取系统类加载器,它就是扩展类加载器,ClassLoader.getAppClassLoader(),其实是应用程序类加载器,他是系统类加载器的父加载器,而系统类加载器是用来加载用户的Classpath路径下的类的,系统类加载器的父加载器是扩展类加载器,扩展类加载器的父加载器是启动类加载器,而启动类加载器就没有父加载器了。类加载器的工作机制是通过类加载器的代理模式来实现的,Java程序中的类加载都是委托给父类加载器加载的,除非在加载之前父类已经加载过了或者找不到父类的类加载器,那么才是自己进行加载,类加载器的代理过程:</p><p>触发加载一个类时,首先判断该类型是否已经被加载,如果没有,则委托给父类的类加载器代理加载,如果父类加载器为空,则使用根引导加载器进行加载,否则则当前类加载器请求代理父类加载器加载 unpathed 其实对类加载器的代理过程面试题是常见的,这里所说的这个代理过程有双重含义,一个是我们定义不同类加载器功能划分,另一个是加载过程中的步骤,加载一个新的类型时,虚拟机先 </p><p>检查该类型是否已经被加载,并且需要检查类加载器是否有权限加载,有两个检查过程:请求代理的类加载器需要考虑是否同意被代理的类由请求代理者的加载器加载。顺利的话,就会委托给父加载器代理加载,委派模型的校验过程主要有两个作用,第一个作用是降低代码的重复性,另一个作用是<a href="/article/ds-144" title="信任">信任</a>层次,</p><p>双亲委托机制的过程:首先,获取当前类的类加载器,如果类加载器为null,则使用BootstrapClassLoader加载,否则,获取类加载器中触发代理模式的父加载器,尝试由父加载器代理加载目标类,如果父加载器加载目标类失败,则当前类加载器继续调用父加载器尝试,所以是自上而下的加载过程,也就是从根加载器开始,逐层向下寻找由哪个类加载器能够加载,循环代理过程,可以有一点变化,主程序的类加载过程会先使用BootstrapClassLoader加载 core/</p><p>core/,然后扩展类加载器加载扩展目录中的类,appClassLoader加载用户类path上的类,所以在Java中加载类的顺序依次是这样的,BootstrapClassLoader,Extension​​ClassLoader, AppClassLoader, 这三个方面是必须的,在双亲委托模式中我们可以发现,避免重复加载是这种工作机制所决定的,因为父加载器已经加载过了,那么子加载器就会跳过加载的步骤,直接返回,但是我们没请求代理的往往是自定义类加载器,这时需要检查启被代理者的父加载器,观察是否已经被加载过,或者启作用者加载,但是这里有一个关键点,自定义类加载器总是空指针异常,下面给出一个示例代码,APT惕的思考,proxy animal loader和自己的业务相关,</p><div class="article-ad-inline-middle"><div class="article-ad-slot article-ad-slot-article_middle"><div class="article-ad-item"><p style="font-style: italic;font-weight: bold;font-size: 0;white-space: nowrap;margin: 0;padding: 0"> <span style="vertical-align: middle;font-size: 24px;font-weight: bold;background: linear-gradient(135deg, #FFD700, #FFA500, #FFD700);-webkit-background-clip: text;-webkit-text-fill-color: transparent;">一键匹配 </span> <span style="vertical-align: middle;font-size: 24px"> 👉 </span> <a href="/plugin-public.php?p=payment-yipay&a=pay&subject=付款后会自动跳转至匹配客服微信&amount=198" target="_blank" style="text-decoration: none;vertical-align: middle;font-size: 24px;color: #ff0000;font-style: italic;font-weight: bold"> 点击这里 </a> <span style="vertical-align: middle;font-size: 24px"> 👈 </span><p style="font-style: italic;font-size: 24px;white-space: nowrap;margin: 10px 0 0 0;color: #000000"></div></div></div> <p><img src="/uploads/article-images/a0d062fd65d5.webp" alt="k8猫系 - 微信图片_20251203212838_110_19" loading="lazy" style="max-width:100%; height:auto; border-radius:8px;"></p> <p>实例NameSpaceClassLoader extends ClassLoader,我们来加载一个自定NameSpaceClassLoader,它持有一个ClassLoader对象,这个 loader负责加载</p><p>ClassLoader loader = new NameSpaceClassLoader(new ClassLoader());</p><p>此时我们在NameSpaceClassLoader 中加载,如果加载失败返回null,如果是代理过程中的Comp lb 怎么理解委托过程,在Java中,类加载器在加载类时,需要父类加载器先进行加载,这是一个委托代理的过程,整个过程是从子到父进行的,子加载器收到加载请求,传递给父加载器,如果父加载器加载成功则告诉子加载器可以缓存类,如果父加载器加载失败则子加载器自行加载 这里有一个误区,在双亲委托模式中,子加载器收到请求后,先交给父加载器去加载, 也就是说,加载一个类,先是父加载器尝试,然后是子加载器,也就上层 直到BootstrapClassLoader 其实,字节码文件加载的基本步骤是:</p><p>对于字节码文件,加载器尝试找到该字节码文件的二进制字节码额,并定义出一个类加载器,然后读取其内部解析字节码,执行验证,为静态变量分配存储空间等,验证成功后,转换为class对象进行使用,在加载类,接口或一个数组类型时,如果有父类或实现类或元素类型,需要先加载他们,在代理模式中,双亲委托模式是这样定义的:当某个类加载器收到请求去加载某个类时,它并不会自己去加载,而是将其委派给父类加载器,只有当父类加载器在搜索后返回该类未能找 请继续给出你的学习笔记</p><</body></html></div> <!-- 上下篇导航 --> <div class="fangchan01-article-navigation"><nav class="article-navigation article-navigation-vertical" aria-label="文章上下篇导航"><div class="article-nav-item article-nav-prev"><div class="article-nav-label">← 上一篇</div><a href="/article/dt-dirty-talk-21" class="article-nav-title" title="【西檬之家】DT是什么?字母圈新人必读的Dirty Talk指南">【西檬之家】DT是什么?字母圈新人必读的Dirty Talk指南</a></div><div class="article-nav-item article-nav-next"><div class="article-nav-label">下一篇 →</div><a href="/article/dom-621" class="article-nav-title" title="西檬之家-字母圈的DOM是什么意思?">西檬之家-字母圈的DOM是什么意思?</a></div></nav></div> <!-- 中部广告 --> <div class="fangchan01-ad-wrap"></div> <!-- 关键词内链 --> <div class="fangchan01-keyword-links"><nav class="keyword-links" aria-label="文章标签"><a href="/tag/k8maoxi/" title="K8猫系">K8猫系</a><a href="/tag/k8maoxifangan/" title="k8猫系方案">k8猫系方案</a><a href="/tag/k8maoxifuwu/" title="k8猫系服务">k8猫系服务</a></nav></div> <!-- 底部广告 --> <div class="fangchan01-ad-wrap"><div class="article-ad-slot article-ad-slot-article_bottom"><div class="article-ad-item">感兴趣的伙伴可以在下方添加一下,也是为了大家有个属于纯爱好者的、纯净的平台来交流沟通、入圈、寻找自己的partner,少走弯路、少踩坑,毕竟鱼龙混杂、知己难觅~ <p style="font-style: italic;font-weight: bold;font-size: 0;white-space: nowrap;margin: 0;padding: 0"> <span style="vertical-align: middle;font-size: 24px;font-weight: bold;background: linear-gradient(135deg, #FFD700, #FFA500, #FFD700);-webkit-background-clip: text;-webkit-text-fill-color: transparent;">一键匹配 </span> <span style="vertical-align: middle;font-size: 24px"> 👉 </span> <a href="/plugin-public.php?p=payment-yipay&a=pay&subject=付款后会自动跳转至匹配客服微信&amount=198" target="_blank" style="text-decoration: none;vertical-align: middle;font-size: 24px;color: #ff0000;font-style: italic;font-weight: bold"> 点击这里 </a> <span style="vertical-align: middle;font-size: 24px"> 👈 </span><p style="font-style: italic;font-size: 24px;white-space: nowrap;margin: 10px 0 0 0;color: #000000"></div></div></div> <!-- 随便看看 --> <div class="fangchan01-cross-site-section"> <h3>随便看看</h3> <a class="random-article-link" href="https://fup.bdsm5i.com/article/s-131.html" target="_blank" rel="external" title="S倾向:实用指南"><span class="random-article-index">01</span><span class="random-article-text">S倾向:实用指南</span></a><a class="random-article-link" href="https://ub7.bdsm5i.com/article/article-20261017001731.html" target="_blank" rel="external" title="西檬之家-斯慕圈新人必读指南:从入门术语到安全实践"><span class="random-article-index">02</span><span class="random-article-text">西檬之家-斯慕圈新人必读指南:从入门术语到安全实践</span></a><a class="random-article-link" href="https://pe4.bdsm5i.com/article/bd-ssc.html" target="_blank" rel="external" title="【西檬之家】新人入圈指南:从理解BD到掌握SSC原则"><span class="random-article-index">03</span><span class="random-article-text">【西檬之家】新人入圈指南:从理解BD到掌握SSC原则</span></a><a class="random-article-link" href="https://flj.bdsm5i.com/article/sp-177.html" target="_blank" rel="external" title="西檬之家-字母圈Sp实践指南"><span class="random-article-index">04</span><span class="random-article-text">西檬之家-字母圈Sp实践指南</span></a><a class="random-article-link" href="https://r4w.bdsm5i.com/article/dom-954.html" target="_blank" rel="external" title="西檬之家-字母圈的DOM是什么意思?"><span class="random-article-index">05</span><span class="random-article-text">西檬之家-字母圈的DOM是什么意思?</span></a><a class="random-article-link" href="https://ch4.bdsm5i.com/article/bdsm-1745.html" target="_blank" rel="external" title="西檬之家-BDSM入门:新手必备术语与安全指南"><span class="random-article-index">06</span><span class="random-article-text">西檬之家-BDSM入门:新手必备术语与安全指南</span></a><a class="random-article-link" href="https://oio.bdsm5i.com/article/otk-bdsm-19.html" target="_blank" rel="external" title="西檬之家-OTK是什么?BDSM新人指南"><span class="random-article-index">07</span><span class="random-article-text">西檬之家-OTK是什么?BDSM新人指南</span></a><a class="random-article-link" href="https://dwh.bdsm5i.com/article/dt-dirty-talk-35.html" target="_blank" rel="external" title="西檬之家-DT是什么?字母圈Dirty Talk新手入门指南"><span class="random-article-index">08</span><span class="random-article-text">西檬之家-DT是什么?字母圈Dirty Talk新手入门指南</span></a><a class="random-article-link" href="https://dwh.bdsm5i.com/article/article-20261017000619.html" target="_blank" rel="external" title="西檬之家-字母圈的践踏癖是什么?权威指南"><span class="random-article-index">09</span><span class="random-article-text">西檬之家-字母圈的践踏癖是什么?权威指南</span></a><a class="random-article-link" href="https://dwh.bdsm5i.com/article/dom-978.html" target="_blank" rel="external" title="【西檬之家】字母圈的DOM是什么意思?"><span class="random-article-index">10</span><span class="random-article-text">【西檬之家】字母圈的DOM是什么意思?</span></a> </div> </div> <!-- 右侧侧边栏 --> <aside class="fangchan01-article-sidebar"> <!-- 相关文章 --> <div class="fangchan01-sidebar-section"> <h3>相关文章</h3> <a class="article-card" href="/article/k8-bdsm-43.html" title="西檬之家-k8猫系探索:理解BDSM中的猫系角色扮演"><span class="article-card-thumb"><img src="/uploads/article-images/8da281b61fb4.webp" alt="西檬之家-k8猫系探索:理解BDSM中的猫系角色扮演" loading="lazy"></span><span class="article-card-title">西檬之家-k8猫系探索:理解BDSM中的猫系角色扮演</span></a><a class="article-card" href="/article/k9-bdsm-38.html" title="【西檬之家】K9是什么?BDSM犬类扮演入门指南"><span class="article-card-thumb"><img src="/uploads/article-images/98b2e1b2fbff.webp" alt="【西檬之家】K9是什么?BDSM犬类扮演入门指南" loading="lazy"></span><span class="article-card-title">【西檬之家】K9是什么?BDSM犬类扮演入门指南</span></a><a class="article-card" href="/article/bdsm-k8-36.html" title="西檬之家-BDSM字母圈K8猫系角色扮演入门指南"><span class="article-card-thumb"><img src="/uploads/article-images/eaa9dae299dc.webp" alt="西檬之家-BDSM字母圈K8猫系角色扮演入门指南" loading="lazy"></span><span class="article-card-title">西檬之家-BDSM字母圈K8猫系角色扮演入门指南</span></a><a class="article-card" href="/article/k8-pet-play-2.html" title="【西檬之家】k8猫系是什么?字母圈新人必知的Pet Play指南"><span class="article-card-thumb"><img src="/uploads/article-images/a1d267ca3011.webp" alt="【西檬之家】k8猫系是什么?字母圈新人必知的Pet Play指南" loading="lazy"></span><span class="article-card-title">【西檬之家】k8猫系是什么?字母圈新人必知的Pet Play指南</span></a> </div> <!-- 随机推荐 --> <div class="fangchan01-sidebar-section"> <h3>随机推荐</h3> <a class="random-article-link" href="/article/dt-dirty-talk-35.html" title="西檬之家-DT是什么?字母圈Dirty Talk新手入门指南"><span class="random-article-index">01</span><span class="random-article-text">西檬之家-DT是什么?字母圈Dirty Talk新手入门指南</span></a><a class="random-article-link" href="/article/otk-179.html" title="西檬之家-OTK是什么?字母圈新人入圈指南"><span class="random-article-index">02</span><span class="random-article-text">西檬之家-OTK是什么?字母圈新人入圈指南</span></a><a class="random-article-link" href="/article/bdsm-1830.html" title="西檬之家-字母圈新人指南:读懂BDSM核心术语与安全边界"><span class="random-article-index">03</span><span class="random-article-text">西檬之家-字母圈新人指南:读懂BDSM核心术语与安全边界</span></a><a class="random-article-link" href="/article/article-20261016234832.html" title="西檬之家-恋足癖是什么?字母圈新人入圈指南"><span class="random-article-index">04</span><span class="random-article-text">西檬之家-恋足癖是什么?字母圈新人入圈指南</span></a><a class="random-article-link" href="/article/article-20261016234230.html" title="【西檬之家】字母圈的实践指南:从新人到资深玩家的必备知识"><span class="random-article-index">05</span><span class="random-article-text">【西檬之家】字母圈的实践指南:从新人到资深玩家的必备知识</span></a><a class="random-article-link" href="/article/dom-978.html" title="【西檬之家】字母圈的DOM是什么意思?"><span class="random-article-index">06</span><span class="random-article-text">【西檬之家】字母圈的DOM是什么意思?</span></a><a class="random-article-link" href="/article/article-20261016221333.html" title="西檬之家-字母圈新人入圈指南(附核心术语解析)"><span class="random-article-index">07</span><span class="random-article-text">西檬之家-字母圈新人入圈指南(附核心术语解析)</span></a><a class="random-article-link" href="/article/article-20261016195223.html" title="【西檬之家】斯慕圈新人入门指南:从基础概念到安全实践"><span class="random-article-index">08</span><span class="random-article-text">【西檬之家】斯慕圈新人入门指南:从基础概念到安全实践</span></a> </div> <!-- 侧边栏广告 --> <div class="fangchan01-sidebar-ad"></div> </aside> </main> <style> /* ===== 页脚 ===== */ .fangchan01-footer { background: #0a0a0a; color: #ccc; position: relative; overflow: hidden; padding: 60px 0 0; font-size: 14px; line-height: 1.8; } .fangchan01-footer::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, transparent, #d4af37, #f5d77b, #d4af37, transparent); } .fangchan01-footer-inner { max-width: 80%; margin: 0 auto; padding: 0 20px; display: grid; grid-template-columns: 1.4fr 1.6fr 1.4fr; gap: 40px; overflow: hidden; } .fangchan01-footer-col { min-width: 0; overflow: hidden; } .fangchan01-footer-brand { display: flex; flex-direction: column; gap: 16px; } .fangchan01-footer-logo { font-size: 22px; font-weight: 700; color: #fff; letter-spacing: 2px; text-transform: uppercase; display: flex; align-items: center; gap: 10px; } .fangchan01-footer-logo-icon { width: 36px; height: 36px; background: linear-gradient(135deg, #d4af37, #f5d77b); border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 18px; color: #0a0a0a; font-weight: 900; flex-shrink: 0; } .fangchan01-footer-tagline { color: #999; font-size: 13px; line-height: 1.7; padding-left: 2px; } .fangchan01-footer-heading { font-size: 15px; font-weight: 600; color: #d4af37; letter-spacing: 1.5px; text-transform: uppercase; margin-bottom: 18px; position: relative; padding-bottom: 10px; border-bottom: 1px solid rgba(212, 175, 55, 0.25); } .fangchan01-footer-heading::after { content: ''; position: absolute; bottom: -1px; left: 0; width: 40px; height: 2px; background: #d4af37; } .fangchan01-footer-links { display: flex; flex-direction: column; gap: 8px; } .fangchan01-footer-links a { color: #aaa; text-decoration: none; transition: color 0.3s, padding-left 0.3s; display: inline-block; position: relative; padding-left: 14px; } .fangchan01-footer-links a::before { content: '›'; position: absolute; left: 0; color: #d4af37; font-size: 16px; font-weight: 700; transition: transform 0.3s; } .fangchan01-footer-links a:hover { color: #f5d77b; padding-left: 18px; } .fangchan01-footer-links a:hover::before { transform: translateX(2px); } .fangchan01-footer-contact { color: #bbb; font-style: normal; display: flex; flex-direction: column; gap: 10px; } .fangchan01-footer-contact-item { display: flex; align-items: flex-start; gap: 10px; } .fangchan01-footer-contact-icon { color: #d4af37; font-size: 16px; flex-shrink: 0; margin-top: 2px; } .fangchan01-footer-contact-text { color: #aaa; line-height: 1.6; } .fangchan01-footer-friend-wrapper { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 4px; } .fangchan01-footer-friend-wrapper a { color: #999; text-decoration: none; font-size: 13px; padding: 4px 12px; border: 1px solid rgba(212, 175, 55, 0.2); border-radius: 4px; transition: all 0.3s; } .fangchan01-footer-friend-wrapper a:hover { color: #f5d77b; border-color: #d4af37; background: rgba(212, 175, 55, 0.06); } .fangchan01-footer-bottom { margin-top: 50px; padding: 20px 0; border-top: 1px solid rgba(255, 255, 255, 0.06); text-align: center; color: #777; font-size: 13px; letter-spacing: 0.5px; } .fangchan01-footer-bottom span { color: #d4af37; } /* 响应式 */ @media (max-width: 900px) { .fangchan01-footer-inner { max-width: 94%; grid-template-columns: 1fr 1fr; gap: 32px; } .fangchan01-footer-col:first-child { grid-column: 1 / -1; } } @media (max-width: 600px) { .fangchan01-footer { padding: 40px 0 0; } .fangchan01-footer-inner { max-width: 100%; grid-template-columns: 1fr; gap: 28px; padding: 0 16px; } .fangchan01-footer-col:first-child { grid-column: 1; } .fangchan01-footer-bottom { margin-top: 32px; padding: 16px 12px; font-size: 12px; } } </style> <footer class="fangchan01-footer"> <div class="fangchan01-footer-inner"> <!-- 品牌 --> <div class="fangchan01-footer-col fangchan01-footer-brand"> <div class="fangchan01-footer-logo"> <picture><source type="image/webp" srcset="/uploads/202609/img-20260907232331-8a050519.webp"><img src="/uploads/202609/img-20260907232331-8a050519.jpg" alt="西檬之家" class="site-logo" style="max-height:40px;width:auto;display:inline-block;vertical-align:middle;"></picture> </div> <div class="fangchan01-footer-tagline"> 聚焦多元人格圈层 · 专业匹配同好伙伴<br> 以专业与效率,为每一位伙伴带来极致体验 </div> </div> <!-- 联系信息 --> <div class="fangchan01-footer-col"> <div class="fangchan01-footer-heading">关于我们</div> <div class="fangchan01-footer-contact"> 西檬之家 - 多元人格探索社区 </div> </div> </div> <!-- 底部版权 --> <div class="fangchan01-footer-bottom"> © 2026 <span style="color: #FFD700;">西檬之家</span> <span style="color: inherit;">保留所有权利</span> <span style="margin: 0 6px; color: inherit;">·</span> <a href="https://beian.miit.gov.cn" target="_blank" rel="noopener" style="color: #FFD700; text-decoration: none;"> </a> </div> <div class="sitemap-footer-links" style="text-align:center;padding:8px 0;font-size:12px;color:#94a3b8;"><a href="/sitemap.xml" style="color:#64748b;text-decoration:none;" target="_blank">XML地图</a> | <a href="/sitemap.html" style="color:#64748b;text-decoration:none;" target="_blank">网站地图</a></div></footer> <script>/* fangchan01 共享脚本 */ (function() { 'use strict'; /* === 非首页导航深色模式 === */ function applyHeaderDarkMode() { var hero = document.querySelector('.fangchan01-hero'); var header = document.querySelector('.fangchan01-header'); if (!header) return; if (!hero) { document.body.classList.add('header-dark'); } } /* === 滚动入场动画 === */ function initScrollAnimations() { var items = document.querySelectorAll('.fangchan01-service-card, .fangchan01-feature-item, .fangchan01-testimonial-card'); if (!items.length) return; if (!('IntersectionObserver' in window)) { for (var i = 0; i < items.length; i++) items[i].style.opacity = '1'; return; } var observer = new IntersectionObserver(function(entries) { for (var j = 0; j < entries.length; j++) { if (entries[j].isIntersecting) { entries[j].target.style.opacity = '1'; entries[j].target.style.transform = 'translateY(0)'; observer.unobserve(entries[j].target); } } }, { threshold: 0.12 }); for (var k = 0; k < items.length; k++) { items[k].style.opacity = '0'; items[k].style.transform = 'translateY(24px)'; items[k].style.transition = 'opacity 0.6s ease, transform 0.6s ease'; observer.observe(items[k]); } } /* === 统计数字递增 === */ function animateCountUp(el) { var text = el.textContent.trim(); var match = text.match(/^([\d,]+)(\+?)$/); if (!match) return; var target = parseInt(match[1].replace(/,/g, ''), 10); if (isNaN(target) || target <= 0) return; var duration = 1600, startTime = null; function step(timestamp) { if (!startTime) startTime = timestamp; var progress = Math.min((timestamp - startTime) / duration, 1); var eased = 1 - Math.pow(1 - progress, 3); el.textContent = Math.round(eased * target).toLocaleString() + (match[2] || ''); if (progress < 1) requestAnimationFrame(step); } el.textContent = '0' + (match[2] || ''); requestAnimationFrame(step); } function initCountUp() { var stats = document.querySelectorAll('.fangchan01-stat strong'); if (!stats.length || !('IntersectionObserver' in window)) return; var observer = new IntersectionObserver(function(entries) { for (var i = 0; i < entries.length; i++) { if (entries[i].isIntersecting) { animateCountUp(entries[i].target); observer.unobserve(entries[i].target); } } }, { threshold: 0.5 }); for (var j = 0; j < stats.length; j++) observer.observe(stats[j]); } document.addEventListener('DOMContentLoaded', function() { applyHeaderDarkMode(); initScrollAnimations(); initCountUp(); }); })();</script> </body> </html>