<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>archive</title><link>https://archive-w.netlify.app/doc/base/</link><description>Recent content on archive</description><generator>Hugo</generator><language>zh-CN</language><atom:link href="https://archive-w.netlify.app/doc/base/index.xml" rel="self" type="application/rss+xml"/><item><title>OBJECT ORIENTED</title><link>https://archive-w.netlify.app/doc/base/OO/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/doc/base/OO/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="对象结构">
 对象结构
 &lt;a class="anchor" href="#%e5%af%b9%e8%b1%a1%e7%bb%93%e6%9e%84">#&lt;/a>
&lt;/h2>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/doc/base/object-header-01.png" alt="" width="60%">&lt;/p>
&lt;ul>
&lt;li>
&lt;h3 id="对象头">
 对象头
 &lt;a class="anchor" href="#%e5%af%b9%e8%b1%a1%e5%a4%b4">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>
&lt;h4 id="mark-word">
 Mark Word
 &lt;a class="anchor" href="#mark-word">#&lt;/a>
&lt;/h4>
&lt;p class="warn">Mark Word(标记字)，用于存储自身运行时的数据 例如&lt;code>GC标志位&lt;/code>、&lt;code>哈希码&lt;/code>、&lt;code>锁状态&lt;/code>等信息。Mark Word 的位长度为 JVM 的一个 Word 大小，也就是说 32 位 JVM 的 Mark word 为 32 位，64 位 JVM 为 64 位。Mark Word 的位长度不会受到 Oop 对象指针压缩选项的影响。&lt;/p>
&lt;p class="tip"> 结构信息：
&lt;br>Java 内置锁的涉及到很多重要信息，并且是存放于对象头的 Mark Word 字段中。
&lt;br>&lt;br>Java 内置锁的状态总共有四种，级别由低到高依次为:无锁、偏向锁、轻量级锁、重量级锁。为了让 Mark word 字段存储更多的信 息，JVM 将 Mark word 的最低两个位设置为 Java 内置锁状态位。
&lt;br>&lt;br>其实在 JDK 1.6 之前，Java 内置锁还是一个重量级锁，是一个效率比较低下的锁，在 JDK 1.6 之 后，JVM 为了提高锁的获取与释放效率，对 synchronized 的实现进行了优化，引入了偏向锁、轻量级锁的实现，从此以后 Java 内置锁的状态就有了四种(无锁、偏向锁、轻量级锁、重量级锁)， 并且四种状态会随着竞争的情况逐渐升级，而且是不可逆的过程，即不可降级，也就是说只能进 行锁升级(从低级别到高级别)。&lt;/p></description></item><item><title/><link>https://archive-w.netlify.app/doc/base/AQS/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/doc/base/AQS/</guid><description>&lt;h2 id="aqs-内部结构">
 AQS 内部结构
 &lt;a class="anchor" href="#aqs-%e5%86%85%e9%83%a8%e7%bb%93%e6%9e%84">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>内部类Node节点代码&lt;/p>
 &lt;details>&lt;summary>代码示例&lt;/summary>
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">static final class Node {
 /** Marker to indicate a node is waiting in shared mode */
 static final Node SHARED = new Node();
 /** Marker to indicate a node is waiting in exclusive mode */
 static final Node EXCLUSIVE = null;

 /** waitStatus value to indicate thread has cancelled */
 static final int CANCELLED = 1;
 /** waitStatus value to indicate successor's thread needs unparking */
 static final int SIGNAL = -1;
 /** waitStatus value to indicate thread is waiting on condition */
 static final int CONDITION = -2;
 /**
 * waitStatus value to indicate the next acquireShared should
 * unconditionally propagate
 */
 static final int PROPAGATE = -3;

 /**
 * Status field, taking on only the values:
 * SIGNAL: The successor of this node is (or will soon be)
 * blocked (via park), so the current node must
 * unpark its successor when it releases or
 * cancels. To avoid races, acquire methods must
 * first indicate they need a signal,
 * then retry the atomic acquire, and then,
 * on failure, block.
 * CANCELLED: This node is cancelled due to timeout or interrupt.
 * Nodes never leave this state. In particular,
 * a thread with cancelled node never again blocks.
 * CONDITION: This node is currently on a condition queue.
 * It will not be used as a sync queue node
 * until transferred, at which time the status
 * will be set to 0. (Use of this value here has
 * nothing to do with the other uses of the
 * field, but simplifies mechanics.)
 * PROPAGATE: A releaseShared should be propagated to other
 * nodes. This is set (for head node only) in
 * doReleaseShared to ensure propagation
 * continues, even if other operations have
 * since intervened.
 * 0: None of the above
 *
 * The values are arranged numerically to simplify use.
 * Non-negative values mean that a node doesn't need to
 * signal. So, most code doesn't need to check for particular
 * values, just for sign.
 *
 * The field is initialized to 0 for normal sync nodes, and
 * CONDITION for condition nodes. It is modified using CAS
 * (or when possible, unconditional volatile writes).
 */
 volatile int waitStatus;

 /**
 * Link to predecessor node that current node/thread relies on
 * for checking waitStatus. Assigned during enqueuing, and nulled
 * out (for sake of GC) only upon dequeuing. Also, upon
 * cancellation of a predecessor, we short-circuit while
 * finding a non-cancelled one, which will always exist
 * because the head node is never cancelled: A node becomes
 * head only as a result of successful acquire. A
 * cancelled thread never succeeds in acquiring, and a thread only
 * cancels itself, not any other node.
 */
 volatile Node prev;

 /**
 * Link to the successor node that the current node/thread
 * unparks upon release. Assigned during enqueuing, adjusted
 * when bypassing cancelled predecessors, and nulled out (for
 * sake of GC) when dequeued. The enq operation does not
 * assign next field of a predecessor until after attachment,
 * so seeing a null next field does not necessarily mean that
 * node is at end of queue. However, if a next field appears
 * to be null, we can scan prev's from the tail to
 * double-check. The next field of cancelled nodes is set to
 * point to the node itself instead of null, to make life
 * easier for isOnSyncQueue.
 */
 volatile Node next;

 /**
 * The thread that enqueued this node. Initialized on
 * construction and nulled out after use.
 */
 volatile Thread thread;

 /**
 * Link to next node waiting on condition, or the special
 * value SHARED. Because condition queues are accessed only
 * when holding in exclusive mode, we just need a simple
 * linked queue to hold nodes while they are waiting on
 * conditions. They are then transferred to the queue to
 * re-acquire. And because conditions can only be exclusive,
 * we save a field by using special value to indicate shared
 * mode.
 */
 Node nextWaiter;

 /**
 * Returns true if node is waiting in shared mode.
 */
 final boolean isShared() {
 return nextWaiter == SHARED;
 }

 /**
 * Returns previous node, or throws NullPointerException if null.
 * Use when predecessor cannot be null. The null check could
 * be elided, but is present to help the VM.
 *
 * @return the predecessor of this node
 */
 final Node predecessor() throws NullPointerException {
 Node p = prev;
 if (p == null)
 throw new NullPointerException();
 else
 return p;
 }

 Node() { // Used to establish initial head or SHARED marker
 }

 Node(Thread thread, Node mode) { // Used by addWaiter
 this.nextWaiter = mode;
 this.thread = thread;
 }

 Node(Thread thread, int waitStatus) { // Used by Condition
 this.waitStatus = waitStatus;
 this.thread = thread;
 }
}
&lt;/code>&lt;/pre>&lt;/div>
 &lt;/details>
&lt;/li>
&lt;li>
&lt;p>整体结构图&lt;/p></description></item><item><title/><link>https://archive-w.netlify.app/doc/base/exception/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/doc/base/exception/</guid><description>&lt;h2 id="java-中异常返回时机">
 java 中异常返回时机
 &lt;a class="anchor" href="#java-%e4%b8%ad%e5%bc%82%e5%b8%b8%e8%bf%94%e5%9b%9e%e6%97%b6%e6%9c%ba">#&lt;/a>
&lt;/h2>
&lt;h3 id="example">
 example
 &lt;a class="anchor" href="#example">#&lt;/a>
&lt;/h3>
&lt;h6 id="1" class="anchor_hr" style="font-size: 0rem; margin: 0; padding: 0; border-width: 0px;">&lt;/h6>&lt;h6 id="2" class="anchor_hr" style="font-size: 0rem; margin: 0; padding: 0; border-width: 0px;">&lt;/h6>&lt;h6 id="3" class="anchor_hr" style="font-size: 0rem; margin: 0; padding: 0; border-width: 0px;">&lt;/h6>&lt;h6 id="4" class="anchor_hr" style="font-size: 0rem; margin: 0; padding: 0; border-width: 0px;">&lt;/h6>&lt;h6 id="5" class="anchor_hr" style="font-size: 0rem; margin: 0; padding: 0; border-width: 0px;">&lt;/h6>&lt;h6 id="6" class="anchor_hr" style="font-size: 0rem; margin: 0; padding: 0; border-width: 0px;">&lt;/h6>&lt;div class="docsify-tabs docsify-tabs--classic">&lt;button anchorId="1" class="docsify-tabs__tab" data-tab="1">1&lt;/button>&lt;div class="docsify-tabs__content" data-tab-content="1">
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">// finally语句在return语句执行之后return返回之前执行的
public int exp1(){
 int b = 20;
 try {
 System.out.println(&amp;quot;try block&amp;quot;);
 return b += 80;
 }
 catch (Exception e) {
 System.out.println(&amp;quot;catch block&amp;quot;);
 }
 finally {
 System.out.println(&amp;quot;finally block&amp;quot;);
 if (b &amp;gt; 25) {
 System.out.println(&amp;quot;b&amp;gt;25, b = &amp;quot; + b);
 }
 }
 return b;
}

output:
try block
finally block
b&amp;gt;25, b = 100
100
&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>&lt;button anchorId="2" class="docsify-tabs__tab" data-tab="2">2&lt;/button>&lt;div class="docsify-tabs__content" data-tab-content="2">
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">// finally块中的return语句会覆盖try块中的return返回
public int exp2() {
 int b = 20;
 try {
 System.out.println(&amp;quot;try block&amp;quot;);
 return b += 80;
 } catch (Exception e) {
 System.out.println(&amp;quot;catch block&amp;quot;);
 } finally {
 System.out.println(&amp;quot;finally block&amp;quot;);
 if (b &amp;gt; 25) {
 System.out.println(&amp;quot;b&amp;gt;25, b = &amp;quot; + b);
 }
 return 200;
 }
 // return b;
}

output:
try block
finally block
b&amp;gt;25, b = 100
200
&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>&lt;button anchorId="3" class="docsify-tabs__tab" data-tab="3">3&lt;/button>&lt;div class="docsify-tabs__content" data-tab-content="3">
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">// 如果finally语句中没有return语句覆盖返回值，那么原来的返回值可能因为finally里的修改而改变也可能不变
public int exp3() {
 int b = 20;
 try {
 System.out.println(&amp;quot;try block&amp;quot;);
 return b += 80;
 } catch (Exception e) {
 System.out.println(&amp;quot;catch block&amp;quot;);
 } finally {
 System.out.println(&amp;quot;finally block&amp;quot;);
 if (b &amp;gt; 25) {
 System.out.println(&amp;quot;b&amp;gt;25, b = &amp;quot; + b);
 }
 b = 150;
 }
 return 2000;
}

output:
try block
finally block
b&amp;gt;25, b = 100
100
&lt;/code>&lt;/pre>&lt;/div>
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">public Map&amp;lt;String, String&amp;gt; exp3_1() {
 Map&amp;lt;String, String&amp;gt; map = new HashMap();
 map.put(&amp;quot;KEY&amp;quot;, &amp;quot;INIT&amp;quot;);
 try {
 map.put(&amp;quot;KEY&amp;quot;, &amp;quot;TRY&amp;quot;);
 return map;
 }
 catch (Exception e) {
 map.put(&amp;quot;KEY&amp;quot;, &amp;quot;CATCH&amp;quot;);
 }
 finally {
 map.put(&amp;quot;KEY&amp;quot;, &amp;quot;FINALLY&amp;quot;);
 map = null;
 }
 return map;
}

output:
FINALLY
&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>&lt;button anchorId="4" class="docsify-tabs__tab" data-tab="4">4&lt;/button>&lt;div class="docsify-tabs__content" data-tab-content="4">
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">// try块里的return语句在异常的情况下不会被执行(参考中的例子有错误)
public int exp4() {
 int b = 20;
 try {
 System.out.println(&amp;quot;try block&amp;quot;);
 b = b / 0;
 return b += 80;
 } catch (Exception e) {
 b += 15;
 System.out.println(&amp;quot;catch block&amp;quot;);
 } finally {
 System.out.println(&amp;quot;finally block&amp;quot;);
 if (b &amp;gt; 25) {
 System.out.println(&amp;quot;b&amp;gt;25, b = &amp;quot; + b);
 }
 b += 50;
 }
 return 204;
}

output:
try block
catch block
finally block
b&amp;gt;25, b = 35
204
&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>&lt;button anchorId="5" class="docsify-tabs__tab" data-tab="5">5&lt;/button>&lt;div class="docsify-tabs__content" data-tab-content="5">
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">// 当发生异常后，catch中的return执行情况与未发生异常时try中return的执行情况完全一样
public int exp5() {
 int b = 20;
 try {
 System.out.println(&amp;quot;try block&amp;quot;);
 b = b /0;
 return b += 80;
 } catch (Exception e) {
 System.out.println(&amp;quot;catch block&amp;quot;);
 return b += 15;
 } finally {
 System.out.println(&amp;quot;finally block&amp;quot;);
 if (b &amp;gt; 25) {
 System.out.println(&amp;quot;b&amp;gt;25, b = &amp;quot; + b);
 }
 b += 50;
 }
 //return b;
}

output:
try block
catch block
finally block
b&amp;gt;25, b = 35
35
&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>&lt;button anchorId="6" class="docsify-tabs__tab" data-tab="6">6&lt;/button>&lt;div class="docsify-tabs__content" data-tab-content="6">
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">// catch中的return先计算然后传值到finally中最后finally直接返回，也符合情况1。
public int exp6() {
 int b = 20;
 try {
 System.out.println(&amp;quot;try block&amp;quot;);
 b = b /0;
 return b += 80;
 } catch (Exception e) {
 System.out.println(&amp;quot;catch block&amp;quot;);
 return b += 15;
 } finally {
 System.out.println(&amp;quot;finally block&amp;quot;);
 if (b &amp;gt; 25) {
 System.out.println(&amp;quot;b&amp;gt;25, b = &amp;quot; + b);
 }
 return b += 50;
 }
 //return b;
}

output:
try block
catch block
finally block
b&amp;gt;25, b = 35
85
&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>&lt;/div>
&lt;h2 id="字节码查看异常执行顺序">
 字节码查看异常执行顺序
 &lt;a class="anchor" href="#%e5%ad%97%e8%8a%82%e7%a0%81%e6%9f%a5%e7%9c%8b%e5%bc%82%e5%b8%b8%e6%89%a7%e8%a1%8c%e9%a1%ba%e5%ba%8f">#&lt;/a>
&lt;/h2>
&lt;h2 id="reference">
 reference
 &lt;a class="anchor" href="#reference">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>


 &lt;a href="https://www.cnblogs.com/lanxuezaipiao/p/3440471.html" rel="noopener" target="_blank">Java finally语句到底是在return之前还是之后执行?&lt;/a>&lt;/li>
&lt;li>


 &lt;a href="https://blog.csdn.net/qq644266189/article/details/123034999" rel="noopener" target="_blank">java关键字finally底层原理&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title/><link>https://archive-w.netlify.app/doc/base/network/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/doc/base/network/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="tcp">
 TCP
 &lt;a class="anchor" href="#tcp">#&lt;/a>
&lt;/h2>
&lt;/li>
&lt;li>
&lt;h2 id="udp">
 UDP
 &lt;a class="anchor" href="#udp">#&lt;/a>
&lt;/h2>
&lt;/li>
&lt;li>
&lt;h2 id="inetaddress">
 InetAddress
 &lt;a class="anchor" href="#inetaddress">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>
&lt;h3 id="流程解析">
 流程解析
 &lt;a class="anchor" href="#%e6%b5%81%e7%a8%8b%e8%a7%a3%e6%9e%90">#&lt;/a>
&lt;/h3>
&lt;p class="warn"> 根据域名实例化一个InetAddress对象的流程解析。
&lt;br>比如：&lt;code>InetAddress byName = InetAddress.getByName(&amp;quot;wtfu.site&amp;quot;);&lt;/code>。如果是域名的话，会涉及到系统调用&lt;code>getaddrinfo&lt;/code>.里面包括DNS解析。
&lt;br>&lt;br>1. &lt;code>getAllByName(String host, InetAddress reqAddr)&lt;/code>
&lt;br>2. 不属于ip地址的话，会继续进入到&lt;code>getAllByName0()&lt;/code>
&lt;br>3. &lt;code>addresses = getAddressesFromNameService(host, reqAddr);&lt;/code>
&lt;br>4. &lt;code>addresses = nameService.lookupAllHostAddr(host);&lt;/code>
&lt;br>5. &lt;code>impl.lookupAllHostAddr(host); // impl为Inet6AddressImpl类型，且lookupAllHostAddr为native方法。&lt;/code>
&lt;br>6. 定位到c源码后如下：可以看到关键的&lt;code>getaddrinfo&lt;/code>系统调用。&lt;/p>
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="c" data-line="" class="language-c line-numbers" style="max-height: none">&lt;code class="language-c">//src/java.base/unix/native/libnet/Inet6AddressImpl.c
JNIEXPORT jobjectArray JNICALL
Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
 jstring host, jint characteristics) {
 error = getaddrinfo(hostname, NULL, &amp;amp;hints, &amp;amp;res);
}
&lt;/code>&lt;/pre>&lt;/div>
&lt;/li>
&lt;li>
&lt;h3 id="测试系统调用流程">
 测试系统调用流程
 &lt;a class="anchor" href="#%e6%b5%8b%e8%af%95%e7%b3%bb%e7%bb%9f%e8%b0%83%e7%94%a8%e6%b5%81%e7%a8%8b">#&lt;/a>
&lt;/h3>
&lt;ol>
&lt;li>
&lt;p>编写样例代码&lt;/p></description></item><item><title/><link>https://archive-w.netlify.app/doc/base/string/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://archive-w.netlify.app/doc/base/string/</guid><description>&lt;ul>
&lt;li>
&lt;h2 id="introstring">
 Intro(String)
 &lt;a class="anchor" href="#introstring">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>
&lt;h3 id="内存布局">
 内存布局
 &lt;a class="anchor" href="#%e5%86%85%e5%ad%98%e5%b8%83%e5%b1%80">#&lt;/a>
&lt;/h3>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/doc/base/string/string-memory-01.png" alt="" width="37%">
&lt;img src="https://archive-w.netlify.app/.images/doc/base/string/string-memory-02.png" alt="" width="62%">&lt;/p>
&lt;/li>
&lt;li>
&lt;h3 id="intern">
 intern()
 &lt;a class="anchor" href="#intern">#&lt;/a>
&lt;/h3>
&lt;p class="warn">&lt;code>String.intern()&lt;/code>方法表示获取一个字符串对象的值在常量池中的引用。如果常量池中存在，则直接返回引用。如果不存在，常量池创建并返回引用。
&lt;br>&lt;br>不同jdk版本创建并返回引用是有区别的：
&lt;br>JDK1.6，不存在则在&lt;strong>永久代字符串常量池&lt;/strong>创建&lt;code>等值字符串&lt;/code>，
&lt;br>JDK1.6之后，在&lt;strong>堆区字符串常量池&lt;/strong>创建的是&lt;code>堆中String obj的引用&lt;/code>。


 &lt;a href="https://stackoverflow.com/questions/27812666/why-string-intern-behave-differently-in-oracle-jdk-1-7" rel="noopener" target="_blank">参考1&lt;/a>，


 &lt;a href="https://blog.csdn.net/tyyking/article/details/82496901" rel="noopener" target="_blank">参考2&lt;/a>
&lt;br>&lt;br>另外字符串常量池的实现是


 &lt;a href="https://www.cnblogs.com/mic112/p/15520770.html#字符串常量池" rel="noopener" target="_blank">C++ 中的hashtable&lt;/a>。&lt;/p>
&lt;p class="tip">&lt;code>String s = new String(&amp;quot;ABC&amp;quot;)&lt;/code> 这行单纯代码层面来说，只创建一个对象。如果包含类加载的过程，有可能会创建两个，一个在常量池中，一个在堆里面。堆里面的引用常量池中的value。


 &lt;a href="https://stackoverflow.com/questions/19672427/string-s-new-stringxyz-how-many-objects-has-been-made-after-this-line-of" rel="noopener" target="_blank">参考&lt;/a>
&lt;br>&lt;br>不要使用JUnit之类的工具测试intern方法，有可能会有误差，


 
 

 
 
 
 
 
 
 
 &lt;a href='#case3' rel="noopener" class="internal-link" data-src="#case3">详细解释查看case3&lt;/a>&lt;/p>
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">/**
 * Returns a canonical representation for the string object.
 * &amp;lt;p&amp;gt;
 * A pool of strings, initially empty, is maintained privately by the
 * class {@code String}.
 * &amp;lt;p&amp;gt;
 * When the intern method is invoked, if the pool already contains a
 * string equal to this {@code String} object as determined by
 * the {@link #equals(Object)} method, then the string from the pool is
 * returned. Otherwise, this {@code String} object is added to the
 * pool and a reference to this {@code String} object is returned.
 * &amp;lt;p&amp;gt;
 * It follows that for any two strings {@code s} and {@code t},
 * {@code s.intern() == t.intern()} is {@code true}
 * if and only if {@code s.equals(t)} is {@code true}.
 * &amp;lt;p&amp;gt;
 * All literal strings and string-valued constant expressions are
 * interned. String literals are defined in section 3.10.5 of the
 * &amp;lt;cite&amp;gt;The Java&amp;amp;trade; Language Specification&amp;lt;/cite&amp;gt;.
 *
 * @return a string that has the same contents as this string, but is
 * guaranteed to be from a pool of unique strings.
 */
public native String intern();
&lt;/code>&lt;/pre>&lt;/div> &lt;div class="docsify-example-panels"> &lt;div class="docsify-example-panel title-panel">
&lt;h4 id="测试">
 测试
 &lt;a class="anchor" href="#%e6%b5%8b%e8%af%95">#&lt;/a>
&lt;/h4>
&lt;h6 id="case1" class="anchor_hr" style="font-size: 0rem; margin: 0; padding: 0; border-width: 0px;">&lt;/h6>&lt;h6 id="case2" class="anchor_hr" style="font-size: 0rem; margin: 0; padding: 0; border-width: 0px;">&lt;/h6>&lt;h6 id="case3" class="anchor_hr" style="font-size: 0rem; margin: 0; padding: 0; border-width: 0px;">&lt;/h6>&lt;div class="docsify-tabs docsify-tabs--classic">&lt;button anchorId="case1" class="docsify-tabs__tab" data-tab="case1">case1&lt;/button>&lt;div class="docsify-tabs__content" data-tab-content="case1">
&lt;div class="outer yosemite">&lt;div class="dot red">&lt;/div>&lt;div class="dot amber">&lt;/div>&lt;div class="dot green">&lt;/div>&lt;/div>
&lt;div class="code-toolbar">&lt;pre data-lang="java" data-line="" class="language-java line-numbers" style="max-height: none">&lt;code class="language-java">// source: https://blog.csdn.net/tyyking/article/details/82496901
String str2 = new String(&amp;quot;str&amp;quot;) + new String(&amp;quot;01&amp;quot;);
str2.intern(); 
String str1 = &amp;quot;str01&amp;quot;;
System.out.println(str2 == str1);

// 上述代码在JDK1.6及以后版本表现不同。假设str2的地址为`String@725`
// 1.6 调用`str2.intern()`会在永久代字符串常量池中复制等值字符串String@825，然后返回引用String@825。给str1赋值的时候发现字符串常量池有'str01'，则将引用String@825给str1。
// &amp;gt;1.6 调用`str2.intern()`会在堆区字符串常量池中放置对象str2的引用String@725，然后返回引用String@725。给str1赋值的时候发现字符串常量池有'str01'，则将引用String@725给str1。
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>&lt;img src="https://archive-w.netlify.app/.images/doc/base/string/string-intern-01.png" alt="" width="99%">
&lt;img src="https://archive-w.netlify.app/.images/doc/base/string/string-intern-02.png" alt="" width="99%">&lt;/p></description></item></channel></rss>