<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>找不着北 &#187; String常量</title>
	<atom:link href="http://www.loveazure.com/archives/tag/string%e5%b8%b8%e9%87%8f/feed" rel="self" type="application/rss+xml" />
	<link>http://www.loveazure.com</link>
	<description>Lost bearings in city</description>
	<lastBuildDate>Mon, 06 Sep 2010 04:32:34 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>关于Java的一些编译机制</title>
		<link>http://www.loveazure.com/archives/494</link>
		<comments>http://www.loveazure.com/archives/494#comments</comments>
		<pubDate>Mon, 26 Oct 2009 07:15:58 +0000</pubDate>
		<dc:creator>低调の华丽</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[String常量]]></category>
		<category><![CDATA[编译]]></category>
		<category><![CDATA[重载]]></category>

		<guid isPermaLink="false">http://www.loveazure.com/?p=494</guid>
		<description><![CDATA[No.1 前几天在JavaEye上看到有人讨论Java对String常量优化的问题，代码如下：

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package test;
&#160;
public class TestA &#123;
	public static void main&#40;String&#91;&#93; args&#41; &#123;
                String s=&#34;ab&#34;;
		String s1=&#34;a&#34;;
		String s2=&#34;b&#34;;
		String s3=s1+s2;
		String s4=&#34;a&#34;+&#34;b&#34;;
		System.out.println&#40;s3==s4&#41;;
		System.out.println&#40;s3==&#34;ab&#34;&#41;;
		System.out.println&#40;s4==&#34;ab&#34;&#41;;
	&#125;
&#125;

结果：false
false
true
s3和s4虽然值相同，但是显然s3和s4并没有指向同一个String常量池中的String常量。String s4=&#8221;a&#8221;+&#8221;b&#8221;;，字符串连接的行为是在编译期间，编译器给优化了。而String s3=s1+s2;中的字符串连接是在代码运行期间进行的。这也间接的说明一个问题，就是String常量池在代码运行前就已经分配好了，代码运行时生成的String对象不会增加到String常量池中。因为s4指向的对象是在代码运行时新生成的对象，所以s3和s4没有指向同一个对象。
推荐这篇文章《Java编译器对于String常量表达式的优化》
No.2 Java编译涉及到的基本变量的问题。下面的代码

1
2
3
4
5
6
7
8
9
10
11
package test;
&#160;
public class TestA &#123;
	public static void main&#40;String&#91;&#93; args&#41; &#123;
		short s=10;//这行代码可以通过编译
		new TestA&#40;&#41;.go&#40;11&#41;;//无法通过编译，需要进行类型转换
	&#125;
	short go&#40;short s&#41;&#123;
		return 12;//可以通过编译
	&#125;
&#125;

之前我一直无法理解为什么第5行和第9行可以通过编译，第6行不能通过编译，需要进行强制类型转换。因为这三行同样都是基本变量赋值的问题。后来我发现，这里面涉及到一个重载的问题。比如下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package test;
&#160;
public class TestA &#123;
	public static void [...]]]></description>
			<content:encoded><![CDATA[<p>No.1 前几天在JavaEye上看到有人讨论Java对String常量优化的问题，代码如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">test</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TestA <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> main<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #003399;">String</span> s<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;ab&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #003399;">String</span> s1<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #003399;">String</span> s2<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;b&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #003399;">String</span> s3<span style="color: #339933;">=</span>s1<span style="color: #339933;">+</span>s2<span style="color: #339933;">;</span>
		<span style="color: #003399;">String</span> s4<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;b&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>s3<span style="color: #339933;">==</span>s4<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>s3<span style="color: #339933;">==</span><span style="color: #0000ff;">&quot;ab&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>s4<span style="color: #339933;">==</span><span style="color: #0000ff;">&quot;ab&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>结果：false<br />
false<br />
true</p>
<p>s3和s4虽然值相同，但是显然s3和s4并没有指向同一个String常量池中的String常量。String s4=&#8221;a&#8221;+&#8221;b&#8221;;，字符串连接的行为是在编译期间，编译器给优化了。而String s3=s1+s2;中的字符串连接是在代码运行期间进行的。这也间接的说明一个问题，就是String常量池在代码运行前就已经分配好了，代码运行时生成的String对象不会增加到String常量池中。因为s4指向的对象是在代码运行时新生成的对象，所以s3和s4没有指向同一个对象。</p>
<p>推荐这篇文章《<a href="http://java.ccidnet.com/art/3539/20070912/1210357_1.html">Java编译器对于String常量表达式的优化</a>》</p>
<p>No.2 Java编译涉及到的基本变量的问题。下面的代码</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">test</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TestA <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> main<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">short</span> s<span style="color: #339933;">=</span><span style="color: #cc66cc;">10</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//这行代码可以通过编译</span>
		<span style="color: #000000; font-weight: bold;">new</span> TestA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">go</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//无法通过编译，需要进行类型转换</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">short</span> go<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">short</span> s<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">12</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//可以通过编译</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>之前我一直无法理解为什么第5行和第9行可以通过编译，第6行不能通过编译，需要进行强制类型转换。因为这三行同样都是基本变量赋值的问题。后来我发现，这里面涉及到一个重载的问题。比如下面的代码</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">test</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TestA <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> main<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">short</span> s<span style="color: #339933;">=</span><span style="color: #cc66cc;">10</span><span style="color: #339933;">;</span>
		<span style="color: #000000; font-weight: bold;">new</span> TestA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">go</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//go方法会取调用最匹配的重载方法</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">short</span> go<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">short</span> s<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">12</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//	short go(int i){</span>
<span style="color: #666666; font-style: italic;">//		return 12;</span>
<span style="color: #666666; font-style: italic;">//	}</span>
	<span style="color: #000066; font-weight: bold;">short</span> go<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">long</span> l<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">12</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>在go(int i)的方法注释掉之前，自然会调用go(int i)方法，注释掉之后，g(11)会调用最匹配的重载方法，而11既可以赋值给short型(强制类型转换)，也可以赋值给long型（隐式类型转换），这是不可能的，不存在两个重载方法都匹配的情况，那样的话编译器无法知道真正要调用的方法到底是哪个。所以编译器无法为你主动做强制类型转换,，只能调用go(long l)方法。所以java规定第6行那样的情况需要做强制类型转换。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.loveazure.com/archives/494/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
