forked from itwanger/toBeBetterJavaer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimmutable.html
More file actions
141 lines (125 loc) · 54.7 KB
/
Copy pathimmutable.html
File metadata and controls
141 lines (125 loc) · 54.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="generator" content="VuePress 2.0.0-beta.46" />
<meta name="theme" content="VuePress Theme Hope" />
<meta property="og:url" content="https://tobebetterjavaer.com/basic-extra-meal/immutable.html"><meta property="og:site_name" content="Java 程序员进阶之路"><meta property="og:title" content="深入理解Java中的不可变对象"><meta property="og:type" content="article"><meta property="og:updated_time" content="2022-06-06T15:31:27.000Z"><meta property="og:locale" content="zh-CN"><meta property="article:tag" content="Java"><meta property="article:modified_time" content="2022-06-06T15:31:27.000Z"><script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?5230ac143650bf5eb3c14f3fb9b1d3ec";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script><link rel="stylesheet" href="//at.alicdn.com/t/font_3180624_7cy10l7jqqh.css"><link rel="icon" href="/favicon.ico"><link rel="icon" href="/assets/icon/chrome-mask-512.png" type="image/png" sizes="512x512"><link rel="icon" href="/assets/icon/chrome-mask-192.png" type="image/png" sizes="192x192"><link rel="icon" href="/assets/icon/chrome-512.png" type="image/png" sizes="512x512"><link rel="icon" href="/assets/icon/chrome-192.png" type="image/png" sizes="192x192"><link rel="manifest" href="/manifest.webmanifest" crossorigin="use-credentials"><meta name="theme-color" content="#46bd87"><link rel="apple-touch-icon" href="/assets/icon/apple-icon-152.png"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="msapplication-TileImage" content="/assets/icon/ms-icon-144.png"><meta name="msapplication-TileColor" content="#ffffff"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"><title>深入理解Java中的不可变对象 | Java 程序员进阶之路</title><meta name="description" content="一份通俗易懂、风趣幽默的Java学习指南,内容涵盖Java基础、Java并发编程、Java虚拟机、Java企业级开发、Java面试等核心知识点。学Java,就认准Java程序员进阶之路">
<style>
:root {
--bg-color: #fff;
}
html[data-theme="dark"] {
--bg-color: #1d2025;
}
html,
body {
background-color: var(--bg-color);
}
</style>
<script>
const userMode = localStorage.getItem("vuepress-theme-hope-scheme");
const systemDarkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
if (userMode === "dark" || (userMode !== "light" && systemDarkMode)) {
document.querySelector("html").setAttribute("data-theme", "dark");
}
</script>
<link rel="stylesheet" href="/assets/style.c081fa20.css">
<link rel="modulepreload" href="/assets/app.41bad062.js"><link rel="modulepreload" href="/assets/immutable.html.cc68b27e.js"><link rel="modulepreload" href="/assets/plugin-vue_export-helper.21dcd24c.js"><link rel="modulepreload" href="/assets/immutable.html.fdd47709.js">
</head>
<body>
<div id="app"><!--[--><!--[--><!--[--><span tabindex="-1"></span><a href="#main-content" class="skip-link sr-only">Skip to content</a><!--]--><div class="theme-container has-toc"><!--[--><!--[--><header class="navbar"><div class="navbar-left"><button class="toggle-sidebar-button" title="Toggle Sidebar"><span class="icon"></span></button><!----><a href="/" class="brand"><img class="logo" src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/logo-02.png" alt="Java 程序员进阶之路"><!----><span class="site-name hide-in-pad">Java 程序员进阶之路</span></a><!----></div><div class="navbar-center"><!----><nav class="nav-links"><div class="nav-item hide-in-mobile"><a href="/blog.html" class="nav-link" aria-label="博客"><span class="icon iconfont icon-gaishu" style=""></span>博客<!----></a></div><div class="nav-item hide-in-mobile"><a href="/home.html" class="nav-link" aria-label="进阶之路"><span class="icon iconfont icon-lujing" style=""></span>进阶之路<!----></a></div><div class="nav-item hide-in-mobile"><a href="/zhishixingqiu/" class="nav-link" aria-label="知识星球"><span class="icon iconfont icon-Artboard" style=""></span>知识星球<!----></a></div><div class="nav-item hide-in-mobile"><a href="/xuexiluxian/" class="nav-link" aria-label="学习路线"><span class="icon iconfont icon-luxian" style=""></span>学习路线<!----></a></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="珍藏资源"><span class="title"><span class="icon iconfont icon-youzhi" style=""></span>珍藏资源</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/download/java.html" class="nav-link" aria-label="电子书下载"><span class="icon iconfont icon-java" style=""></span>电子书下载<!----></a></li><li class="dropdown-item"><a href="/sidebar/sanfene/nixi.html" class="nav-link" aria-label="面渣逆袭"><span class="icon iconfont icon-zhunbei" style=""></span>面渣逆袭<!----></a></li><li class="dropdown-item"><a href="/download/nicearticle.html" class="nav-link" aria-label="优质文章"><span class="icon iconfont icon-youzhi" style=""></span>优质文章<!----></a></li><li class="dropdown-item"><a href="/download/history.html" class="nav-link" aria-label="网络日志"><span class="icon iconfont icon-rizhi" style=""></span>网络日志<!----></a></li><li class="dropdown-item"><a href="/nice-article/itmind/" class="nav-link" aria-label="破解合集"><span class="icon iconfont icon-zhongyaotishi" style=""></span>破解合集<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><a href="https://space.bilibili.com/513340480" rel="noopener noreferrer" target="_blank" aria-label="B站视频" class="nav-link"><span class="icon iconfont icon-bzhan" style=""></span>B站视频<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div></nav><!----></div><div class="navbar-right"><!----><div class="nav-item"><!----></div><div class="nav-item"><a class="repo-link" href="https://github.com/itwanger/toBeBetterJavaer" target="_blank" rel="noopener noreferrer"><svg xmlns="http://www.w3.org/2000/svg" class="icon github-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="github icon" style="width:1.25rem;height:1.25rem;vertical-align:middle;"><path d="M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"></path></svg></a></div><div class="nav-item hide-in-mobile"><button id="appearance-switch"><svg xmlns="http://www.w3.org/2000/svg" class="icon auto-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="auto icon" style="display:block;"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="dark icon" style="display:none;"><path d="M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="light icon" style="display:none;"><path d="M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"></path></svg></button></div><div id="docsearch-container"></div><!----><button class="toggle-navbar-button" aria-label="Toggle Navbar" aria-expanded="false" aria-controls="nav-screen"><span class="button-container"><span class="button-top"></span><span class="button-middle"></span><span class="button-bottom"></span></span></button></div></header><!----><!--]--><!----><div class="toggle-sidebar-wrapper"><span class="arrow left"></span></div><aside class="sidebar"><!--[--><!----><!--]--><ul class="sidebar-links"><li><!--[--><a href="/home.html" class="nav-link sidebar-link sidebar-page" aria-label="一、前言"><!---->一、前言<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">二、Java核心</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.1 Java概述</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.2 Java语法基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.3 数组&字符串</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">2.4 面向对象编程</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><a href="/oo/object-class.html" class="nav-link sidebar-link sidebar-page" aria-label="对象和类"><!---->对象和类<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/var.html" class="nav-link sidebar-link sidebar-page" aria-label="Java变量"><!---->Java变量<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/method.html" class="nav-link sidebar-link sidebar-page" aria-label="方法"><!---->方法<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/construct.html" class="nav-link sidebar-link sidebar-page" aria-label="构造方法"><!---->构造方法<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/nice-article/bokeyuan-jianxijavazhongdifangwenquanxiankongzhi.html" class="nav-link sidebar-link sidebar-page" aria-label="访问权限控制"><!---->访问权限控制<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/code-init.html" class="nav-link sidebar-link sidebar-page" aria-label="代码初始化块"><!---->代码初始化块<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/abstract.html" class="nav-link sidebar-link sidebar-page" aria-label="抽象类"><!---->抽象类<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/interface.html" class="nav-link sidebar-link sidebar-page" aria-label="接口"><!---->接口<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/inner-class.html" class="nav-link sidebar-link sidebar-page" aria-label="内部类"><!---->内部类<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/static.html" class="nav-link sidebar-link sidebar-page" aria-label="static"><!---->static<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/this-super.html" class="nav-link sidebar-link sidebar-page" aria-label="this 和 super"><!---->this 和 super<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/final.html" class="nav-link sidebar-link sidebar-page" aria-label="final"><!---->final<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/oo/instanceof.html" class="nav-link sidebar-link sidebar-page" aria-label="instanceof"><!---->instanceof<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a aria-current="page" href="/basic-extra-meal/immutable.html" class="router-link-active router-link-exact-active nav-link active sidebar-link sidebar-page active" aria-label="不可变对象"><!---->不可变对象<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/basic-extra-meal/immutable.html#_01、什么是不可变类" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="01、什么是不可变类"><!---->01、什么是不可变类<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/basic-extra-meal/immutable.html#_02、常见的不可变类" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="02、常见的不可变类"><!---->02、常见的不可变类<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/basic-extra-meal/immutable.html#_03、手撸不可变类" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="03、手撸不可变类"><!---->03、手撸不可变类<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/basic-extra-meal/immutable.html#_04、总结" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="04、总结"><!---->04、总结<!----></a><ul class="sidebar-sub-headers"></ul></li></ul><!--]--></li><li><!--[--><a href="/basic-extra-meal/varables.html" class="nav-link sidebar-link sidebar-page" aria-label="可变参数"><!---->可变参数<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/basic-extra-meal/generic.html" class="nav-link sidebar-link sidebar-page" aria-label="泛型"><!---->泛型<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/basic-extra-meal/annotation.html" class="nav-link sidebar-link sidebar-page" aria-label="注解"><!---->注解<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/basic-extra-meal/enum.html" class="nav-link sidebar-link sidebar-page" aria-label="枚举"><!---->枚举<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/basic-extra-meal/fanshe.html" class="nav-link sidebar-link sidebar-page" aria-label="反射"><!---->反射<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.5 集合框架(容器)</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.6 IO</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.7 异常处理</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.8 常用工具类</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.9 Java新特性</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.10 Java重要知识点</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.11 并发编程</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.12 JVM</span><span class="arrow right"></span></button><!----></section><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">三、Java企业级开发</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">四、数据库</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">五、计算机基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">六、求职面试</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">七、学习资源</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">八、学习建议</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">九、知识库搭建</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">十、联系作者</span><span class="arrow right"></span></button><!----></section><!--]--></li></ul><!--[--><!----><!--]--></aside><!--[--><main class="page" id="main-content"><!--[--><!----><nav class="breadcrumb disable"></nav><div class="page-title"><h1><!---->深入理解Java中的不可变对象</h1><div class="page-info"><span class="author-info" aria-label="作者🖊" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon author-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="author icon"><path d="M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z"></path></svg><span><a class="author-item" href="/about-the-author/" target="_blank" rel="noopener noreferrer">沉默王二</a></span><span property="author" content="沉默王二"></span></span><!----><span class="date-info" aria-label="写作日期📅" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon calendar-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="calendar icon"><path d="M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 01-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 01-33.473-33.473V143.657H180.6A134.314 134.314 0 0046.66 277.595v535.756A134.314 134.314 0 00180.6 947.289h669.74a134.36 134.36 0 00133.94-133.938V277.595a134.314 134.314 0 00-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 01-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 01-33.472 33.473z"></path></svg><span>2021年11月8日</span><meta property="datePublished" content="2021-11-08T13:04:25.000Z"></span><span class="category-info" aria-label="分类🌈" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon category-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="category icon"><path d="M148.41 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H148.41c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.311-40.31zM147.556 553.478H429.73c22.263 0 40.311 18.048 40.311 40.31v282.176c0 22.263-18.048 40.312-40.31 40.312H147.555c-22.263 0-40.311-18.049-40.311-40.312V593.79c0-22.263 18.048-40.311 40.31-40.311zM593.927 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H593.927c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.31-40.31zM730.22 920.502H623.926c-40.925 0-74.22-33.388-74.22-74.425V623.992c0-41.038 33.387-74.424 74.425-74.424h222.085c41.038 0 74.424 33.226 74.424 74.067v114.233c0 10.244-8.304 18.548-18.547 18.548s-18.548-8.304-18.548-18.548V623.635c0-20.388-16.746-36.974-37.33-36.974H624.13c-20.585 0-37.331 16.747-37.331 37.33v222.086c0 20.585 16.654 37.331 37.126 37.331H730.22c10.243 0 18.547 8.304 18.547 18.547 0 10.244-8.304 18.547-18.547 18.547z"></path></svg><ul class="categories-wrapper"><li class="category category0 clickable" role="navigation">Java核心</li><meta property="articleSection" content="Java核心"></ul></span><span aria-label="标签🏷" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon tag-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="tag icon"><path d="M939.902 458.563L910.17 144.567c-1.507-16.272-14.465-29.13-30.737-30.737L565.438 84.098h-.402c-3.215 0-5.726 1.005-7.634 2.913l-470.39 470.39a10.004 10.004 0 000 14.164l365.423 365.424c1.909 1.908 4.42 2.913 7.132 2.913s5.223-1.005 7.132-2.913l470.39-470.39c2.01-2.11 3.014-5.023 2.813-8.036zm-240.067-72.121c-35.458 0-64.286-28.828-64.286-64.286s28.828-64.285 64.286-64.285 64.286 28.828 64.286 64.285-28.829 64.286-64.286 64.286z"></path></svg><ul class="tags-wrapper"><li class="tag tag4 clickable" role="navigation">Java</li></ul><meta property="keywords" content="Java"></span><span class="reading-time-info" aria-label="阅读时间⌛" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon timer-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="timer icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"></path></svg><span>大约 6 分钟</span><meta property="timeRequired" content="PT6M"></span></div><hr></div><div class="toc-place-holder"><aside id="toc"><div class="toc-header">此页内容</div><div class="toc-wrapper"><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/basic-extra-meal/immutable.html#_01、什么是不可变类" class="router-link-active router-link-exact-active toc-link level3">01、什么是不可变类</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/basic-extra-meal/immutable.html#_02、常见的不可变类" class="router-link-active router-link-exact-active toc-link level3">02、常见的不可变类</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/basic-extra-meal/immutable.html#_03、手撸不可变类" class="router-link-active router-link-exact-active toc-link level3">03、手撸不可变类</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/basic-extra-meal/immutable.html#_04、总结" class="router-link-active router-link-exact-active toc-link level3">04、总结</a></li><!----><!--]--></ul></div></aside></div><!----><div class="theme-hope-content"><h1 id="深入理解java中的不可变对象" tabindex="-1"><a class="header-anchor" href="#深入理解java中的不可变对象" aria-hidden="true">#</a> 深入理解Java中的不可变对象</h1><blockquote><p>二哥,你能给我说说为什么 String 是 immutable 类(不可变对象)吗?我想研究它,想知道为什么它就不可变了,这种强烈的愿望就像想研究浩瀚的星空一样。但无奈自身功力有限,始终觉得雾里看花终隔一层。二哥你的文章总是充满趣味性,我想一定能够说明白,我也一定能够看明白,能在接下来写一写吗?</p></blockquote><p>收到读者小 R 的私信后,我就总感觉自己有一种义不容辞的责任,非要把 immutable 类说明白不可!</p><h3 id="_01、什么是不可变类" tabindex="-1"><a class="header-anchor" href="#_01、什么是不可变类" aria-hidden="true">#</a> 01、什么是不可变类</h3><p>一个类的对象在通过构造方法创建后如果状态不会再被改变,那么它就是一个不可变(immutable)类。它的所有成员变量的赋值仅在构造方法中完成,不会提供任何 setter 方法供外部类去修改。</p><p>还记得《神雕侠侣》中小龙女的古墓吗?随着那一声巨响,仅有的通道就被无情地关闭了。别较真那个密道,我这么说只是为了打开你的想象力,让你对不可变类有一个更直观的印象。</p><p>自从有了多线程,生产力就被无限地放大了,所有的程序员都爱它,因为强大的硬件能力被充分地利用了。但与此同时,所有的程序员都对它心生忌惮,因为一不小心,多线程就会把对象的状态变得混乱不堪。</p><p>为了保护状态的原子性、可见性、有序性,我们程序员可以说是竭尽所能。其中,synchronized(同步)关键字是最简单最入门的一种解决方案。</p><p>假如说类是不可变的,那么对象的状态就也是不可变的。这样的话,每次修改对象的状态,就会产生一个新的对象供不同的线程使用,我们程序员就不必再担心并发问题了。</p><h3 id="_02、常见的不可变类" tabindex="-1"><a class="header-anchor" href="#_02、常见的不可变类" aria-hidden="true">#</a> 02、常见的不可变类</h3><p>提到不可变类,几乎所有的程序员第一个想到的,就是 String 类。那为什么 String 类要被设计成不可变的呢?</p><p>1)常量池的需要</p><p>字符串常量池是 Java 堆内存中一个特殊的存储区域,当创建一个 String 对象时,假如此字符串在常量池中不存在,那么就创建一个;假如已经存,就不会再创建了,而是直接引用已经存在的对象。这样做能够减少 JVM 的内存开销,提高效率。</p><p>2)hashCode 的需要</p><p>因为字符串是不可变的,所以在它创建的时候,其 hashCode 就被缓存了,因此非常适合作为哈希值(比如说作为 HashMap 的键),多次调用只返回同一个值,来提高效率。</p><p>3)线程安全</p><p>就像之前说的那样,如果对象的状态是可变的,那么在多线程环境下,就很容易造成不可预期的结果。而 String 是不可变的,就可以在多个线程之间共享,不需要同步处理。</p><p>因此,当我们调用 String 类的任何方法(比如说 <code>trim()</code>、<code>substring()</code>、<code>toLowerCase()</code>)时,总会返回一个新的对象,而不影响之前的值。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token class-name">String</span> cmower <span class="token operator">=</span> <span class="token string">"沉默王二,一枚有趣的程序员"</span><span class="token punctuation">;</span>
cmower<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>cmower<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 沉默王二,一枚有趣的程序员</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>虽然调用 <code>substring()</code> 方法对 cmower 进行了截取,但 cmower 的值没有改变。</p><p>除了 String 类,包装器类 Integer、Long 等也是不可变类。</p><h3 id="_03、手撸不可变类" tabindex="-1"><a class="header-anchor" href="#_03、手撸不可变类" aria-hidden="true">#</a> 03、手撸不可变类</h3><p>看懂一个不可变类也许容易,但要创建一个自定义的不可变类恐怕就有点难了。但知难而进是我们作为一名优秀的程序员不可或缺的品质,正因为不容易,我们才能真正地掌握它。</p><p>接下来,就请和我一起,来自定义一个不可变类吧。一个不可变类,必须要满足以下 4 个条件:</p><p>1)确保类是 final 的,不允许被其他类继承。</p><p>2)确保所有的成员变量(字段)是 final 的,这样的话,它们就只能在构造方法中初始化值,并且不会在随后被修改。</p><p>3)不要提供任何 setter 方法。</p><p>4)如果要修改类的状态,必须返回一个新的对象。</p><p>按照以上条件,我们来自定义一个简单的不可变类 Writer。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">Writer</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">int</span> age<span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token class-name">Writer</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">,</span> <span class="token keyword">int</span> age<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> name<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Writer 类是 final 的,name 和 age 也是 final 的,没有 setter 方法。</p><p>OK,据说这个作者分享了很多博客,广受读者的喜爱,因此某某出版社找他写了一本书(Book)。Book 类是这样定义的:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Book</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">int</span> price<span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> name<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setName</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">getPrice</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> price<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setPrice</span><span class="token punctuation">(</span><span class="token keyword">int</span> price<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>price <span class="token operator">=</span> price<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token string">"Book{"</span> <span class="token operator">+</span>
<span class="token string">"name='"</span> <span class="token operator">+</span> name <span class="token operator">+</span> <span class="token char">'\''</span> <span class="token operator">+</span>
<span class="token string">", price="</span> <span class="token operator">+</span> price <span class="token operator">+</span>
<span class="token char">'}'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>2 个字段,分别是 name 和 price,以及 getter 和 setter,重写后的 <code>toString()</code> 方法。然后,在 Writer 类中追加一个可变对象字段 book。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">Writer</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">int</span> age<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">Book</span> book<span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token class-name">Writer</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">,</span> <span class="token keyword">int</span> age<span class="token punctuation">,</span> <span class="token class-name">Book</span> book<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>book <span class="token operator">=</span> book<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> name<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">Book</span> <span class="token function">getBook</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> book<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>并在构造方法中追加了 Book 参数,以及 Book 的 getter 方法。</p><p>完成以上工作后,我们来新建一个测试类,看看 Writer 类的状态是否真的不可变。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">WriterDemo</span> <span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Book</span> book <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Book</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
book<span class="token punctuation">.</span><span class="token function">setName</span><span class="token punctuation">(</span><span class="token string">"Web全栈开发进阶之路"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
book<span class="token punctuation">.</span><span class="token function">setPrice</span><span class="token punctuation">(</span><span class="token number">79</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Writer</span> writer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Writer</span><span class="token punctuation">(</span><span class="token string">"沉默王二"</span><span class="token punctuation">,</span><span class="token number">18</span><span class="token punctuation">,</span> book<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"定价:"</span> <span class="token operator">+</span> writer<span class="token punctuation">.</span><span class="token function">getBook</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
writer<span class="token punctuation">.</span><span class="token function">getBook</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setPrice</span><span class="token punctuation">(</span><span class="token number">59</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"促销价:"</span> <span class="token operator">+</span> writer<span class="token punctuation">.</span><span class="token function">getBook</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>程序输出的结果如下所示:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code>定价:<span class="token class-name">Book</span><span class="token punctuation">{</span>name<span class="token operator">=</span>'<span class="token class-name">Web</span>全栈开发进阶之路'<span class="token punctuation">,</span> price<span class="token operator">=</span><span class="token number">79</span><span class="token punctuation">}</span>
促销价:<span class="token class-name">Book</span><span class="token punctuation">{</span>name<span class="token operator">=</span>'<span class="token class-name">Web</span>全栈开发进阶之路'<span class="token punctuation">,</span> price<span class="token operator">=</span><span class="token number">59</span><span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><p>糟糕,Writer 类的不可变性被破坏了,价格发生了变化。为了解决这个问题,我们需要为不可变类的定义规则追加一条内容:</p><p>如果一个不可变类中包含了可变类的对象,那么就需要确保返回的是可变对象的副本。也就是说,Writer 类中的 <code>getBook()</code> 方法应该修改为:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token class-name">Book</span> <span class="token function">getBook</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Book</span> clone <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Book</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
clone<span class="token punctuation">.</span><span class="token function">setPrice</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">.</span><span class="token function">getPrice</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
clone<span class="token punctuation">.</span><span class="token function">setName</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> clone<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这样的话,构造方法初始化后的 Book 对象就不会再被修改了。此时,运行 WriterDemo,就会发现价格不再发生变化了。</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>定价:Book{name='Web全栈开发进阶之路', price=79}
促销价:Book{name='Web全栈开发进阶之路', price=79}
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="_04、总结" tabindex="-1"><a class="header-anchor" href="#_04、总结" aria-hidden="true">#</a> 04、总结</h3><p>不可变类有很多优点,就像之前提到的 String 类那样,尤其是在多线程环境下,它非常的安全。尽管每次修改都会创建一个新的对象,增加了内存的消耗,但这个缺点相比它带来的优点,显然是微不足道的——无非就是捡了西瓜,丢了芝麻。</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png" alt=""></p></div><!----><footer class="page-meta"><div class="meta-item edit-link"><a href="https://github.com/itwanger/toBeBetterJavaer/edit/master/docs/basic-extra-meal/immutable.md" rel="noopener noreferrer" target="_blank" aria-label="在 GitHub 上编辑此页" class="nav-link label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon edit-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="edit icon"><path d="M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"></path><path d="M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"></path></svg><!--]-->在 GitHub 上编辑此页<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="meta-item update-time"><span class="label">上次编辑于: </span><span class="info">2022/6/6 下午11:31:27</span></div><div class="meta-item contributors"><span class="label">贡献者: </span><!--[--><!--[--><span class="contributor" title="email: [email protected]">itwanger</span><!--]--><!--]--></div></footer><nav class="page-nav"><a href="/oo/instanceof.html" class="nav-link prev" aria-label="instanceof"><div class="hint"><span class="arrow left"></span>上一页</div><div class="link"><!---->instanceof</div></a><a href="/basic-extra-meal/varables.html" class="nav-link next" aria-label="可变参数"><div class="hint">下一页<span class="arrow right"></span></div><div class="link">可变参数<!----></div></a></nav><div class="giscus-wrapper input-top" style="display:block;">Loading...</div><!----><!--]--></main><!--]--><footer class="footer-wrapper"><div class="footer"><a href="https://beian.miit.gov.cn/" target="_blank">豫ICP备2021038026号-1</a><img src="https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/beian.png" height="15px" width="15px" /><a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=41030502000411"><span>豫公网安备 41030502000411号</span></a></div><div class="copyright">Copyright © 2022 沉默王二</div></footer><!--]--></div><!--]--><!----><!----><!--]--></div>
<script type="module" src="/assets/app.41bad062.js" defer></script>
</body>
</html>