1. 程式人生 > >Java中執行“巨集替換”的變數

Java中執行“巨集替換”的變數

對於一個final變數,不管它是類變數、例項變數,還是區域性變數,只要定義該變數時使用了final修飾符修飾,並在定義該final類變數時指定了初始值,而且該初始值可以在編譯時就被確定下來,那麼這個final變數本質上已經不再是變數,而是相當於一個直接量。

public class FinalTest{
	
	public static void main(String[] args){
		<strong>final int a=5+2;
		final double b=1.2/3;
		final String str="瘋狂" + "Java";
		final String book="瘋狂Java講義"+99.0;</strong>
		//下面的book2變數的值因為呼叫了方法,所以無法在編譯時確定下來
		final String book2="瘋狂Java講義"+String.valueOf(99.0);                //              1
		System.out.println(book=="瘋狂Java講義99.0");
		System.out.println(book2=="瘋狂Java講義99.0");
		
	}
}
上面程式中的粗體字程式碼定義了四個final變數,程式為這四個變數賦予初始值,指定的初始值要麼是算術表示式,要麼是字串連線運算。即使字串連線運算中包含隱式型別(將數值轉換為字串)轉換,編譯器依然可以在編譯時就確定a、b、str、book這四個變數的值,因此它們都是“巨集變數”

“巨集變數”:final修飾符的一個重要用途就是定義“巨集變數”。當定義final變數時就為該變數指定了初始值,而且該初始值可以在編譯時就確定下來,那麼這個final變數本質上就是一個“巨集變數”,編譯器會把程式所有用到該變數的地方直接替換成該變數的值。

從表面上看,1行程式碼定義的book2與book沒有太大的區別,只是定義book2變數時的顯式將數值99.0轉換為字串。但由於該變數的值需要呼叫String類的方法,因此編譯器無法在編譯時確定book2的值,book2不會被當成“巨集變數”類處理。

例如下列示例:

public class FinalTest{
	
	public static void main(String[] args){
		String s1="瘋狂Java";
		String s2="瘋狂"+"Java";
		System.out.println(s1==s2);
		
		String str1="瘋狂";
		String str2="Java";
		<span style="color:#ff0000;">String s3=str1+str2;</span>
		System.out.println(s1==s3);
	}
}
對於s3而言,它的值由str1和str2進行連線後得到。由於str1/str2只是兩個普通變數,編譯器不會執行“巨集替換”,因此編譯器無法在編譯時確定s3的值,不會讓s3指向字串池中快取的“瘋狂Java”。由此可見,s1==s3將輸出false

為了讓s1==s3輸出為true也很簡單,只要編譯器可以對str1和str2兩個變數執行“巨集替換”這樣編譯器既可以在編譯階段就確定s3的值,就會讓s3指向字串池中快取的“瘋狂Java".即把程式改成如下形式:

public class FinalTest{
	
	public static void main(String[] args){
		String s1="瘋狂Java";
		String s2="瘋狂"+"Java";
		System.out.println(s1==s2);
		
		<strong>final String str1="瘋狂";
		final String str2="Java";</strong>
		String s3=str1+str2;
		System.out.println(s1==s3);
	}
}
如下列示例:
public class FinalTest{
	final static String str1;
	final static String str2="Java";
	static {
		str1="Java";
	}
	public static void main(String[] args){
		System.out.println(str1+str1=="JavaJava");
		System.out.println(str2+str2=="JavaJava");
	}
}
上面程式定義了兩個final類變數,但是隻有str2在定義該變數時指定了初始值,str1則在靜態初始化塊中指定了初始值,因此係統不會對str1進行巨集替換,但會對str2執行”巨集替換“。




相關推薦

Java執行巨集替換”的變數

對於一個final變數,不管它是類變數、例項變數,還是區域性變數,只要定義該變數時使用了final修飾符修飾,並在定義該final類變數時指定了初始值,而且該初始值可以在編譯時就被確定下來,那麼這個final變數本質上已經不再是變數,而是相當於一個直接量。 public c

Java執行緒區域性變數ThreadLocal使用教程及原始碼分析

       在Java多執行緒程式設計中有時候會遇見執行緒本地區域性變數ThreadLocal這個類,下面就來講講ThreadLocal的使用及原始碼分析。        ThreadLocal 是Thread Local Varial(執行緒區域性變數)的意思,每個執行

Java(靜態)變數、(靜態)程式碼塊的執行順序包含父類

1、parent類(父類) public class parent { public static int parentParamOne = 1; public static String parentParamTwo = "two1111"; static{

final變數巨集替換

原始碼1: public class Java15 { public static void main(String[] args) { String s1="瘋狂java"; String s2="瘋狂"+"java";

java執行js代碼

engine byname manage gin 執行 腳本 post get 對象 //#1、用scriptEngineManger ScriptEngineManager engine=new ScriptEngineManager(); //#2

利用Jexl實現數據庫的計算公式在Java執行

bject urn arp key cal object num regex ply public class JexlEngineUtils { public static BigDecimal evaluateExpression ( Map <

沉澱再出發:java執行緒池解析

沉澱再出發:java中執行緒池解析 一、前言    在多執行緒執行的環境之中,如果執行緒執行的時間短但是啟動的執行緒又非常多,執行緒運轉的時間基本上浪費在了建立和銷燬上面,因此有沒有一種方式能夠讓一個執行緒執行完自己的任務之後又被重複使用呢?執行緒池的出現就是為了解決這個問題。到了現在

Java執行緒池基本api及其作用

1.執行緒池相關的類 2.重要類的api及其方法 Executors.newCachedThreadPool() 建立一個可快取的執行緒池 Executors.newSingleThreadExecutor();建立一個只有一個執行緒執行的 不可修改的執行緒池  

JavaFinal修飾一個變數時,是引用不能變還是引用的物件不能變

Java中,使用Final修飾一個變數,是引用不能變,還是引用物件不能變?   是引用物件的地址不能變,引用變數所指的物件的內容可以改變。   final變數永遠指向這個物件,是一個常量指標,而不是指向常量的指標。   比如: final StringBuffer sb=new Stri

JavaThreadLocal,成員變數和區域性變數

一.成員變數和區域性變數 1.程式例子: public class HelloThreadTest { public static void main(String[] args) { HelloThread r = new HelloThread();

Java執行緒的同步非同步、以及執行緒的安全

  什麼是執行緒同步?     這裡的“同”是協同的意思,並不是共同。那麼就很好理解同步了,就是一起操作但並不是同時操作。比如流水線組裝汽車,可以視作一個執行緒,只有裝好了上一步的門,才可以裝下一步的門窗玻璃。沒有裝門能裝上玻璃嗎?顯然不行。所以執

Java執行緒安全的單例模式

Java中執行緒安全的單例 深入研究Servlet執行緒安全性問題 來源:網路整理 作者:2017年12月01日 14:03 0 分享 訂閱 關鍵詞:Servlet執行緒     Servlet(Server Applet)是Java Servle

java執行緒池的生命週期

執行緒池生命週期包括: RUNNING:接收新的任務並處理佇列中的任務 SHUTDOWN:不接收新的任務,但是處理佇列中的任務 STOP:不接收新的任務,不處理佇列中的任務,同時中斷處理中的任務 TIDYING:所有的任務處理完成,有效的執行緒數是0 TERMINATED:termin

Java執行緒池,你真的會用嗎

轉載自   Java中執行緒池,你真的會用嗎 在《深入原始碼分析Java執行緒池的實現原理》這篇文章中,我們介紹過了Java中執行緒池的常見用法以及基本原理。 在文中有這樣一段描述: 可以通過Executors靜態工廠構建執行緒池,但一般不建議這樣使用。 關於這個

JAVA執行緒到底起到什麼作用!

這是javaeye上非常經典的關於執行緒的帖子,寫的非常通俗易懂的,適合任何讀計算機的同學. 執行緒同步 我們可以在計算機上執行各種計算機軟體程式。每一個執行的程式可能包括多個獨立執行的執行緒(Thread)。 執行緒(Thread)是一份獨立執行的程式,有自己專用的執行棧。執行緒有可能和其他執行緒

java執行緒池的生命週期與執行緒中斷

執行緒池生命週期包括: RUNNING:接收新的任務並處理佇列中的任務 SHUTDOWN:不接收新的任務,但是處理佇列中的任務 STOP:不接收新的任務,不處理佇列中的任務,同時中斷處理中的任務 TIDYING:所有的任務處理完成,有效的執行緒數是0 TE

java執行緒安全和非執行緒安全的集合

  執行緒安全 非執行緒安全 Collection Vector ArrayList、LinkedList   H

Java執行緒有幾種狀態

線上程的生命週期裡,執行緒總共有6種狀態,這是Java5之後在公共內部列舉類Thread.State裡面宣告的。他們分別是 NEW:新建,表示的是執行緒被創建出來但還未被投入使用。 RUNNABLE:就緒,這個執行緒已經在JVM裡被執行,有可能是正在執行也有可能是等待CPU分配資源進入了就緒

java執行緒同步的幾種方法

方法一: 使用synchronized關鍵字  由於java的每個物件都有一個內建鎖,當用此關鍵字修飾方法時, 內建鎖會保護整個方法。在呼叫該方法前,需要獲得內建鎖,否則就處於阻塞狀態。 注: synchronized關鍵字也可以修飾靜態方法,此時如果呼叫該靜態方法,將會

java執行緒的建立

java中執行緒的建立 package com.carlinfo.bigdata; /** * java中執行緒的建立 */ public class Ops3 { public static void main(String[] args) { /**