[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"site-config":3,"primary-menu":6,"cat-java-basic":85,"catposts-java-basic":99,"post-detail-post-jb-string-immutable-6381213f":271},{"config":4,"socialLinks":5},null,[],{"metadata":7,"spec":10,"menuItems":20},{"name":8,"creationTimestamp":9},"primary","2026-09-12T06:13:55.024154Z",{"displayName":11,"menuItems":12},"主菜单",[13,14,15,16,17,18,19],"88c3f10b-321c-4092-86a8-70db00251b74","menu-item-izrtmxer","c4c814d1-0c2c-456b-8c96-4864965fee94","menu-item-column","menu-item-tools","menu-item-zsxq","menu-item-ocrxlczu",[21,30,40,49,58,67,76],{"displayName":22,"metadata":23,"spec":25,"status":28,"children":29},"首页",{"name":13,"creationTimestamp":24},"2026-09-12T06:13:54.422830Z",{"displayName":22,"href":26,"priority":27,"menuName":8},"\u002F",0,{"displayName":22,"href":26},[],{"displayName":31,"metadata":32,"spec":34,"status":38,"children":39},"Java面试八股",{"name":14,"creationTimestamp":33},"2026-09-13T09:42:02.854891Z",{"displayName":31,"href":35,"target":36,"priority":37,"menuName":8},"\u002Fjava-interview","_self",1,{"displayName":31,"href":35},[],{"displayName":41,"metadata":42,"spec":44,"status":47,"children":48},"文章",{"name":15,"creationTimestamp":43},"2026-09-12T06:13:54.457307Z",{"displayName":41,"href":45,"priority":46,"menuName":8},"\u002Farchives",2,{"displayName":41,"href":45},[],{"displayName":50,"metadata":51,"spec":53,"status":56,"children":57},"项目实战",{"name":16,"creationTimestamp":52},"2026-09-14T00:35:08.138170Z",{"displayName":50,"href":54,"target":36,"priority":55,"menuName":8},"\u002Fcolumn",3,{"displayName":50,"href":54},[],{"displayName":59,"metadata":60,"spec":62,"status":65,"children":66},"在线工具",{"name":17,"creationTimestamp":61},"2026-09-14T00:35:08.171474Z",{"displayName":59,"href":63,"target":36,"priority":64,"menuName":8},"\u002Ftools",4,{"displayName":59,"href":63},[],{"displayName":68,"metadata":69,"spec":71,"status":74,"children":75},"知识星球",{"name":18,"creationTimestamp":70},"2026-09-14T00:35:08.199145Z",{"displayName":68,"href":72,"target":36,"priority":73,"menuName":8},"\u002Fzsxq",5,{"displayName":68,"href":72},[],{"displayName":77,"metadata":78,"spec":80,"status":83,"children":84},"特价云服务器",{"name":19,"creationTimestamp":79},"2026-09-25T15:30:59.201614Z",{"displayName":77,"href":81,"target":36,"priority":82,"menuName":8},"\u002Fserver",6,{"displayName":77,"href":81},[],{"metadata":86,"spec":91,"status":96,"postCount":98},{"name":87,"creationTimestamp":88,"labels":89},"java-basic","2026-09-13T09:13:25.495129Z",{"haloweb.section":90},"interview",{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},"Java 基础面试题","","Java 基础面试题：语言特性、面向对象、异常体系、泛型、反射与常用 API。",false,{"permalink":97,"postCount":98,"visiblePostCount":98},"\u002Fcategories\u002Fjava-basic",8,[100,124,145,166,187,208,229,250],{"metadata":101,"spec":104,"status":113,"categories":118},{"name":102,"creationTimestamp":103},"post-jb-interface-vs-abstract-de319222","2026-09-13T10:00:54.430321Z",{"title":105,"slug":106,"cover":93,"excerpt":107,"publishTime":109,"categories":110,"tags":111,"priority":27,"pinned":95,"deleted":95,"visible":112,"allowComment":108},"接口和抽象类有什么区别？","jb-interface-vs-abstract",{"raw":93,"autoGenerate":108},true,"2026-09-13T10:00:54.500384Z",[87],[],"PUBLIC",{"permalink":114,"excerpt":115,"lastModifyTime":116,"phase":117},"\u002Farchives\u002Fjb-interface-vs-abstract","一、核心区别 维度 抽象类 接口 关键字 abstract class interface 继承 单继承 多实现 构造方法 有 无 成员变量 任意 仅 public static final 方法实现 可有抽象\u002F具体方法 默认方法、静态方法（JDK 8+） 设计目的 \"is-a\" 共性抽取 \"can","2026-09-16T09:13:43.230261Z","PUBLISHED",[119],{"metadata":120,"spec":122,"status":123,"postCount":98},{"name":87,"creationTimestamp":88,"labels":121},{"haloweb.section":90},{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},{"permalink":97,"postCount":98,"visiblePostCount":98},{"metadata":125,"spec":128,"status":135,"categories":139},{"name":126,"creationTimestamp":127},"post-jb-overload-vs-override-76d8b85a","2026-09-13T10:00:54.236416Z",{"title":129,"slug":130,"cover":93,"excerpt":131,"publishTime":132,"categories":133,"tags":134,"priority":27,"pinned":95,"deleted":95,"visible":112,"allowComment":108},"重载（overload）和重写（override）的区别？","jb-overload-vs-override",{"raw":93,"autoGenerate":108},"2026-09-13T10:00:54.292575Z",[87],[],{"permalink":136,"excerpt":137,"lastModifyTime":138,"phase":117},"\u002Farchives\u002Fjb-overload-vs-override","一、定义 重载：同一个类中，方法名相同，参数列表（类型\u002F个数\u002F顺序）不同。与返回值无关。 重写：子类重新实现父类的方法，方法签名（名称、参数、返回值）必须一致。 二、对比 维度 重载 重写 位置 同类 父子类 参数列表 必须不同 必须相同 返回值 可不同 相同或协变 权限 可不同 不能更严格 绑定时","2026-09-16T09:13:41.019008Z",[140],{"metadata":141,"spec":143,"status":144,"postCount":98},{"name":87,"creationTimestamp":88,"labels":142},{"haloweb.section":90},{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},{"permalink":97,"postCount":98,"visiblePostCount":98},{"metadata":146,"spec":149,"status":156,"categories":160},{"name":147,"creationTimestamp":148},"post-jb-final-keyword-80890cb4","2026-09-13T10:00:54.018756Z",{"title":150,"slug":151,"cover":93,"excerpt":152,"publishTime":153,"categories":154,"tags":155,"priority":27,"pinned":95,"deleted":95,"visible":112,"allowComment":108},"final 关键字有哪些用法？","jb-final-keyword",{"raw":93,"autoGenerate":108},"2026-09-13T10:00:54.080507Z",[87],[],{"permalink":157,"excerpt":158,"lastModifyTime":159,"phase":117},"\u002Farchives\u002Fjb-final-keyword","一、修饰类 final 修饰的类不能被继承，如 String、Math。常用于工具类或不希望被扩展的类。 二、修饰方法 final 方法不能被子类重写，防止子类改变父类行为。构造方法隐式为 final。 三、修饰变量 成员变量：必须在声明时、构造方法或初始化块中赋值，赋值后不可改。 局部变量：使用前","2026-09-16T09:13:42.613292Z",[161],{"metadata":162,"spec":164,"status":165,"postCount":98},{"name":87,"creationTimestamp":88,"labels":163},{"haloweb.section":90},{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},{"permalink":97,"postCount":98,"visiblePostCount":98},{"metadata":167,"spec":170,"status":177,"categories":181},{"name":168,"creationTimestamp":169},"post-jb-string-immutable-6381213f","2026-09-13T10:00:53.805615Z",{"title":171,"slug":172,"cover":93,"excerpt":173,"publishTime":174,"categories":175,"tags":176,"priority":27,"pinned":95,"deleted":95,"visible":112,"allowComment":108},"String 为什么是不可变的？","jb-string-immutable",{"raw":93,"autoGenerate":108},"2026-09-13T10:00:53.873603Z",[87],[],{"permalink":178,"excerpt":179,"lastModifyTime":180,"phase":117},"\u002Farchives\u002Fjb-string-immutable","一、不可变的体现 String 内部用 final char[]（JDK 9 后是 byte[]）存储字符，且没有提供修改内部数组的方法，一旦创建内容就不能改。所谓\"修改\"其实是创建新对象。 二、设计原因 字符串常量池复用：相同字面量共享同一对象，节省内存。 线程安全：不可变对象天然线程安全，多线程","2026-09-16T09:13:41.662582Z",[182],{"metadata":183,"spec":185,"status":186,"postCount":98},{"name":87,"creationTimestamp":88,"labels":184},{"haloweb.section":90},{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},{"permalink":97,"postCount":98,"visiblePostCount":98},{"metadata":188,"spec":191,"status":198,"categories":202},{"name":189,"creationTimestamp":190},"post-jb-int-vs-integer-5ddd4c42","2026-09-13T10:00:53.622572Z",{"title":192,"slug":193,"cover":93,"excerpt":194,"publishTime":195,"categories":196,"tags":197,"priority":27,"pinned":95,"deleted":95,"visible":112,"allowComment":108},"int 和 Integer 有什么区别？","jb-int-vs-integer",{"raw":93,"autoGenerate":108},"2026-09-13T10:00:53.684952Z",[87],[],{"permalink":199,"excerpt":200,"lastModifyTime":201,"phase":117},"\u002Farchives\u002Fjb-int-vs-integer","一、本质区别 int 是 Java 的 8 种基本数据类型之一，直接存数值，占 4 字节，默认值 0。 Integer 是 int 的包装类，是对象，存的是指向堆中对象的引用，默认值 null。 二、自动装箱与拆箱 Integer a = 10;          \u002F\u002F 自动装箱：Integer.v","2026-09-16T09:13:40.094479Z",[203],{"metadata":204,"spec":206,"status":207,"postCount":98},{"name":87,"creationTimestamp":88,"labels":205},{"haloweb.section":90},{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},{"permalink":97,"postCount":98,"visiblePostCount":98},{"metadata":209,"spec":212,"status":219,"categories":223},{"name":210,"creationTimestamp":211},"post-why-override-equals-and-hashcode-4d166dda","2026-09-13T09:11:40.565423Z",{"title":213,"slug":214,"cover":93,"excerpt":215,"publishTime":216,"categories":217,"tags":218,"priority":27,"pinned":95,"deleted":95,"visible":112,"allowComment":108},"为什么重写 equals 时一定要重写 hashCode？","why-override-equals-and-hashcode",{"raw":93,"autoGenerate":108},"2026-09-13T09:11:40.612965Z",[87],[],{"permalink":220,"excerpt":221,"lastModifyTime":222,"phase":117},"\u002Farchives\u002Fwhy-override-equals-and-hashcode","一、先说结论 这是 Java 的通用约定：如果两个对象通过 equals 比较相等，那么它们的 hashCode 必须相同。只重写 equals 不重写 hashCode，会破坏这个约定，导致对象在 HashMap、HashSet 等集合中行为异常。 二、HashMap 的存取过程 HashMap ","2026-09-16T09:13:39.635536Z",[224],{"metadata":225,"spec":227,"status":228,"postCount":98},{"name":87,"creationTimestamp":88,"labels":226},{"haloweb.section":90},{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},{"permalink":97,"postCount":98,"visiblePostCount":98},{"metadata":230,"spec":233,"status":240,"categories":244},{"name":231,"creationTimestamp":232},"post-string-stringbuilder-stringbuffer-0b7b9e93","2026-09-13T09:11:40.343284Z",{"title":234,"slug":235,"cover":93,"excerpt":236,"publishTime":237,"categories":238,"tags":239,"priority":27,"pinned":95,"deleted":95,"visible":112,"allowComment":108},"String、StringBuilder 和 StringBuffer 的区别？","string-stringbuilder-stringbuffer",{"raw":93,"autoGenerate":108},"2026-09-13T09:11:40.408558Z",[87],[],{"permalink":241,"excerpt":242,"lastModifyTime":243,"phase":117},"\u002Farchives\u002Fstring-stringbuilder-stringbuffer","一、可变性不同 String 是不可变类，内部用 final 修饰字符数组。对字符串做拼接实际上会创建新的 String 对象。 StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder，内容可变，拼接时直接修改内部数组。 二、线程安全不同 St","2026-09-16T09:13:39.164827Z",[245],{"metadata":246,"spec":248,"status":249,"postCount":98},{"name":87,"creationTimestamp":88,"labels":247},{"haloweb.section":90},{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},{"permalink":97,"postCount":98,"visiblePostCount":98},{"metadata":251,"spec":254,"status":261,"categories":265},{"name":252,"creationTimestamp":253},"post-double-equals-vs-equals-03a956b5","2026-09-13T09:11:40.146587Z",{"title":255,"slug":256,"cover":93,"excerpt":257,"publishTime":258,"categories":259,"tags":260,"priority":27,"pinned":95,"deleted":95,"visible":112,"allowComment":108},"== 和 equals 的区别是什么？","double-equals-vs-equals",{"raw":93,"autoGenerate":108},"2026-09-13T09:11:40.197516Z",[87],[],{"permalink":262,"excerpt":263,"lastModifyTime":264,"phase":117},"\u002Farchives\u002Fdouble-equals-vs-equals","一、== 的作用 == 是 Java 的运算符，它的比较规则取决于两边的类型： 基本数据类型（byte、short、int、long、float、double、char、boolean）：比较的是字面值是否相等。 引用数据类型：比较的是两个引用是否指向堆中的同一个对象（即内存地址是否相同）。 int","2026-09-16T09:13:38.582777Z",[266],{"metadata":267,"spec":269,"status":270,"postCount":98},{"name":87,"creationTimestamp":88,"labels":268},{"haloweb.section":90},{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},{"permalink":97,"postCount":98,"visiblePostCount":98},{"metadata":272,"spec":273,"status":277,"categories":278,"content":284},{"name":168,"creationTimestamp":169},{"title":171,"slug":172,"cover":93,"excerpt":274,"publishTime":174,"categories":275,"tags":276,"priority":27,"pinned":95,"deleted":95,"visible":112,"allowComment":108},{"raw":93,"autoGenerate":108},[87],[],{"permalink":178,"excerpt":179,"lastModifyTime":180,"phase":117},[279],{"metadata":280,"spec":282,"status":283,"postCount":98},{"name":87,"creationTimestamp":88,"labels":281},{"haloweb.section":90},{"displayName":92,"slug":87,"cover":93,"description":94,"priority":27,"hideFromList":95,"preventParentPostCascadeQuery":95},{"permalink":97,"postCount":98,"visiblePostCount":98},{"content":285,"raw":285},"\u003Ch2>一、不可变的体现\u003C\u002Fh2>\n\u003Cp>String 内部用 \u003Ccode>final char[]\u003C\u002Fcode>（JDK 9 后是 \u003Ccode>byte[]\u003C\u002Fcode>）存储字符，且没有提供修改内部数组的方法，一旦创建内容就不能改。所谓\"修改\"其实是创建新对象。\u003C\u002Fp>\n\u003Ch2>二、设计原因\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\u003Cstrong>字符串常量池复用\u003C\u002Fstrong>：相同字面量共享同一对象，节省内存。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>线程安全\u003C\u002Fstrong>：不可变对象天然线程安全，多线程下无需同步。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>hashCode 缓存\u003C\u002Fstrong>：String 的 hashCode 在首次计算后缓存，作为 HashMap 键时性能稳定。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>安全性\u003C\u002Fstrong>：作为参数传递时不会被意外篡改，如数据库连接串、文件名。\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2>三、注意事项\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-java\">String s = &quot;hello&quot;;\ns += &quot; world&quot;;   \u002F\u002F 不是修改原对象，而是新建 &quot;hello world&quot;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>频繁拼接字符串会产生大量临时对象，应使用 StringBuilder。\u003C\u002Fp>"]