1. 程式人生 > >Java中a=a+b 與 a+=b區別

Java中a=a+b 與 a+=b區別

就單純的執行這兩條語句,不考慮編譯器的優化的話,a=a+b的執行效率是低於a+=b的,因為它多進行了一步中間變數的操作,而且會多佔用一個變數的空間。而Java編譯器預設對其進行了優化,優化之後兩條語句都當做 a+=b來執行了,所以實際上是沒有任何卻別的。

其次說一下有關型別轉換的區別。

相信大家都碰到過這種情況:

public class Test {
 
 public static void main(String[] args){
  int a = 2;
  float b = 6;
  a+=b; //right
//  a=a+b; //error
  a=(int) (a+b); //right
 }
}

當使用a=a+b的時候,會丟擲”Exception in thread "main" java.lang.Error: Unresolved compilation problem: Type mismatch: cannot convert from float to int“的異常,這是可以理解的,如果不使用(int)強制型別轉換的話,float 是不能直接復值給int 變數的。

我們將a=a+b註釋掉,javac編譯完之後,再使用反編譯軟體(例如XJad)開啟Test.class檔案,會發現原始碼被解析成這樣子:

public class Test
{

 public Test()
 {
 }

 public static void main(String args[])
 {
  int a = 2;
  float b = 6F;
  a = (int)((float)a + b);
  a = (int)((float)a + b);
 }
}

a+=b進行了強制型別轉換,和 a=(int)((float)a+b)是等價的

到這裡我們就明白了為什麼a=a+b會丟擲異常了。

原因:在Java中,在基本型別進行算術運算的時候,會發生小位元組型別向大位元組型別轉換的現象。如圖中 int 型別和float型別進行加法運算時會將 a 先轉換為float型別,然後再和b相加。這樣結果型別變成了float型別,如果這時候試圖把float型別賦值給a時便會拋異常

另外,對於short,byte,char 比int 位元組數小的變數型別來說,運算結果會自動轉換為int型別,如

  byte a = 1 , b=2;
  b=a+b;

  byte a = 1;
  short b =2;
  b=a+b;

都會丟擲”Exception in thread "main" java.lang.Error: Unresolved compilation problem: Type mismatch: cannot convert from int to byte“類似的異常,可以看出a+b結果變成了int型別。

這是由於Java編譯器會在編譯期或者執行期將byte和short型別的資料帶符號擴充套件為相應的int型別資料,將boolean和char型別資料零位擴充套件為相應的int型別資料。因此,在處理boolean 、byte、short 和 char 型別的陣列是,也會用相應的int型別的位元組碼指令來處理。因此,大多數對於上述型別資料的操作,實際上都是使用相應的 int 型別作為運算型別。

如果是final 修飾的變數,進行運算的時候則不會出現型別轉換異常。

public class Test {
 final int d = 3; 
 public static void main(String[] args){
  final short  a = 1;
  final short  b =2;
  short c=a+b;
 }
}

編譯後使用反編譯軟體開啟後,程式碼被解析成了這樣:

public class Test
{

 final int d = 3;

 public Test()
 {
 }

 public static void main(String args[])
 {
  short a = 1;
  short b = 2;
  short c = 3;
 }
}

可以看到,對於final 修飾的基本型別的變數來說,他們之間的運算直接就被硬編碼成了直接賦值語句,連中間結果都沒有了,型別轉換的異常也就沒了。

此外,我們可以注意到,對於方法內的final 變數 a , b 來說,編碼時被直接省略了。而Test 類的final 成員變數 d 依然保留著final 屬性。

所以說,是否使用final修飾方法中普通變數對JVM來說沒有區別!使用final修飾方法中普通變數主要是為了給Java前端編譯器(如javac)看的!也就是說方法中被final修飾的普通變數在前端編譯時被javac檢查並保證該變數不會在作用域內被改變新值,但被編譯成位元組碼後用於修飾方法中普通變數的final就已經不存在了!說的再具體點就是你用或不用final修飾方法中普通變數而生成的位元組碼檔案(.class檔案)沒有區別。

PS:對於final 修飾的類成員來說,由於其生命週期在物件銷燬之前,所以它佔用的應該是堆記憶體。(這個不確定 --)


http://www.linuxidc.com/Linux/2014-09/106764.htm

相關推薦

深入理解Java的字段屬性的區別

ring rgs name 私有變量 pub tail 博文 們的 方式 轉載出處 http://blog.csdn.net/chenchunlin526/article/details/69939337 1、Java中的屬性和字段有什麽區別? 答:Java中的屬性(p

深入理解Java的欄位屬性的區別

1、Java中的屬性和欄位有什麼區別?  答:Java中的屬性(property),通常可以理解為get和set方法。 而欄位(field),通常叫做“類成員”,或 "類成員變數”,有時也叫“域”,理解為“資料成員”,用來承載資料的。 這兩個概念是完全不同的。 2、屬性

從結構上分析Java的 if/elseswitch的區別

聽同事說了一句能用if/else就別用switch,感覺這就話不對,但是又提不出什麼依據進行判斷,不能明白其中是不是有什麼深層次的原因,今天就探究一下這方面的原因。我們要明白我們的程式到底是誰幫助我們做的? 我們首先得明白計算機的五大組成部分控制器,運算器,儲存器,輸入,輸

javaBigDecimal的equalscompareTo的區別

這兩天在處理支付金額校驗的時候出現了點問題,有個金額比較我用了BigDecimal的equals方法來比較兩個金額是否相等,結果導致金額比較出現錯誤(比如3.0與3.00的比較等)。 【注:以下所講都是以sun jdk 1.4.2版本為例,其他版本實現未必一致,請忽略】

java方法的過載重寫的區別

    (1) 父類與子類之間的多型性,對父類的函式進行重新定義。如果在子類中定義某方法與其父類有相同的名稱和引數,我們說該方法被重寫 (Overriding)。在Java中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。 (adsbygoogle = window.ads

javalist的addaddall方法區別

在做專案時我遇到過這樣的問題,java.lang.ClassCastException: java.util.ArrayList cannot be cast to com.alibaba.getter.jstorm.biz.domain.Page。知道是型別轉換錯誤,但

Java,關於a=a+ba+=b區別

/** * short a = 1; a = a + 1;有什麼錯? short a= 1; a += 1;有什麼錯? */ public class test2 { public static void main(String[] args) {

Javaa=a+b a+=b區別

就單純的執行這兩條語句,不考慮編譯器的優化的話,a=a+b的執行效率是低於a+=b的,因為它多進行了一步中間變數的操作,而且會多佔用一個變數的空間。而Java編譯器預設對其進行了優化,優化之後兩條語句都當做 a+=b來執行了,所以實際上是沒有任何卻別的。 其次說一下有關型

Javaa=a+b a+=b區別 以及和型別轉換的關係

很久之前學習過 a=a+b 和a+=b的一些區別,進來再次回想起來,發現理解的還不透徹,所以又查資料找檔案重新學習了一番。 比較這兩種運算子的區別,可以有以下兩個方面的比較: 執行效率和型別轉換。 首先說一下執行效率問題 就單純的執行這兩條語句,不考慮編譯器的優化的話,a

MATLABa./ba/b區別以及左除和右除

>> a=[1 2;3 4];>> b=[1 2;3 4]; >> a/bans = 1 0 0 1>> a./bans = 1 1 1 1 a/b相當於a乘b的逆a./b是a的每個元素與b的每個元素對應相除 >>

python: pythona+=ba=a+b有什麼區別

看到一個比較有意思的問題,就是python中a+=b與a=a+b有什麼區別總體上講,a+=b是改變了a原始的值,而a=a+b是計算出a+b後,a在指向那個值。這個也跟a和b的型別有關。當a和b是int或者string不可改變的時候,二者效果一樣。>>> a=

TensorFlow 辨異 —— tf.add(a, b) a+b(tf.assign =)、tf.nn.bias_add tf.add(轉)

fad codes live tin csdn hat targe ops 操作 1. tf.add(a, b) 與 a+b 在神經網絡前向傳播的過程中,經常可見如下兩種形式的代碼: tf.add(tf.matmul(x, w), b) tf.matmul(x, w) +

python_數據操作a += b a = a + b區別

log tails 對象 類型 生成 tps 區別 https div a = [1,2,3] b = a print(a,b) print(id(a),id(b)) # [1, 2, 3] [1, 2, 3] # 2346301641544 2346301641544

TensorFlow 辨異 tf add a b a b tf assign tf nn bia

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

理解Java字符流字節流的區別

png 技術 print 復制代碼 bar 顯式 數字 length ava 1. 什麽是流 Java中的流是對字節序列的抽象,我們可以想象有一個水管,只不過現在流動在水管中的不再是水,而是字節序列。和水流一樣,Java中的流也具有一個“流動的方向”,通常可以從中讀

java註解的使用實例(一)

title 編譯器 new ng2 警告 元素 epc 目前 而且 http://www.cnblogs.com/pepcod/archive/2013/02/16/2913474.html 註解目前非常的流行,很多主流框架都支持註解,而且自己編寫代碼的時候也會盡量的去用註

java容器的學習理解

優化 是我 move 查找 map 常常 ise 線性 arr   以前一直對於java中容器的概念不理解,雖然學習過,但始終沒有認真理解過,這幾天老師提出了這樣一個問題,你怎麽理解java中的容器。瞬間就蒙了。於是各種搜資料學習了一下,下面是我學習後整理出來的的一些心得。

JavaJavadoc的{@link}@see的簡單區別

java http 技術 pan lan 分享圖片 參考 article 圖片 {@link}與@see這兩個Javadoc註解都可以直接鏈接類和方法。用法基本一致。 但是@see必須頂頭寫,而{@link可以任意地方},如下所示: 參考: http:

接口(三)java的接口嵌套接口

strong span class .... 定義 成員 抽象 數列 多個 一、接口 1. 接口簡介 接口: 是java的一種抽象類型,是抽象方法的集合。接口比抽象類更加抽象的抽象類型。 接口語法: [修飾符] [abstract] interface 接口名 [exten

[Js-Java SE]Java的Native關鍵字JNI

pan 基礎 好文 native ava 文章 aid java se targe 一篇精細基礎到令人發指的好文章mark 鏈接: https://pan.baidu.com/s/1-9X8YFBdmFyaWDJoSZyBtQ 密碼: 90sf[Js-Java SE]Jav