亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java形參和實參的實例之Integer類型與Int類型

發布時間:2020-10-29 22:48:32 來源:億速云 閱讀:160 作者:Leah 欄目:開發技術

Java形參和實參的實例之Integer類型與Int類型?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。


class
 
Main
 
{



 
   
public
 
static
 
void
 main
(
String
[]
 args
)
 
{



 
      
Integer
 a 
=
 
1
;



 
      
Integer
 b 
=
 
2
;



 
      
System
.
out
.
println
(
"a="
 
+
 a 
+
 
",b="
 
+
 b
);



 
      swap
(
a
,
 b
);



 
     
System
.
out
.
println
(
"a="
 
+
 a 
+
 
",b="
 
+
 b
);

 
  
}



 
 
private
 
static
 
void
 swap
(
Integer
 numa
,
 
Integer
 numb
)
 
{



 
     
//請實現



 
    
}



 
  }




1、首先大家看到這到題目后,仔細看后,在main方法中變量a和b的類型是Integer,而不是Int類型,因為這里涉及到了java的基本類型,Int是屬于Java的基本類型,基本類型在調用swap的方法時,是修改不了變量a和b的值,說到這里涉及到另一個知識點了,那就是形參和實參的區別,值傳遞和引用傳遞的區別,下面慢慢說啊。

2、形參和實參的區別

實參顧名思義:就是實際參數,用于調用時傳遞給方法的參數。實參在傳遞給別的方法之前是要被預先賦值的。

形參顧名思義:就是形式參數,用于定義方法的時候使用的參數,是用來接收調用者傳遞的參數的,形參只有在方法被調用的時候,虛擬機才會分配內存單元,在方法調用結束之后便會釋放所分配的內存單元。因此,形參只在方法內部有效,所以針對引用對象的改動也無法影響到方法外。

以這到題目為例,方法swap
(
Integer
 numa
,
 
Integer
 numb
)中的numa和numb是形參,
而在main方法中 傳遞給swap
(
a
,
 b
)中的a和b是實參。

3、值傳遞和引用傳遞的區別

值傳遞調用過程只能把實參傳遞給形參,而不能把形參的值反向作用到實參上。在函數調用過程中,形參的值發生改變,而實參的值不會發生改變,函數接收的是原始值的一個copy,此時內存中存在兩個相等的基本類型,即實際參數和形式參數,后面方法中的操作都是對形參這個值的修改,不影響實際參數的值。說到這里就明白了題目中聲明a和b的數據類型不為Int的原因了吧。

引用傳遞也稱為 地址傳遞, 址傳遞,引用傳遞調用的機制中,實際參數的引用(地址,而不是參數的值)被傳遞給方法中相對應的形式參數,函數接收的是原始值的內存地址在方法執行中,形參和實參內容相同,指向同一塊內存地址,方法執行中對引用的操作將會影響到實際對象。說到這里就明白了題目中聲明a和b的數據類型為Integer的原因了吧。

4、完成swap
方法實現


 
static
 
void
 swap
(
Integer
 numa
,
 
Integer
 numb
)
 
{



 
  
Integer
 tmp 
=
 numa
;



 
  numa 
=
 numb
;



 
  numb 
=
 tmp
;



 
 
System
.
out
.
println
(
"numa="
 
+
 numa 
+
 
",numb="
 
+
 numb
);



 
  
}




是不是感覺挺簡單,但是運行后main方法中的a和b的值沒有互換,分別還是a = 1 ,b = 2。那這是為什么呢?因為Interger雖然是引用類型,但是Integer在方法中沒有提供value的get和set方法,也是對對象的安全保護,也就是傳遞過程中在Integer里面copy了一個副本指向值,而不是引用地址,是不是沒有辦法了,這就涉及到反射的用法,我們用反射改變Integer內部的value屬性值。




static
 
void
 swap
(
Integer
 numa
,
 
Integer
 numb
)
 
{



 
     
Integer
 tmp 
=
 numa
;



 
      
try
 
{



 
          
Field
 field 
=
 
Integer
.
class
.
getDeclaredField
(
"value"
);



 
          field
.
setAccessible
(
true
);



 
          field
.
set
(
numa
,
 numb
);
//成功的將numa 引用的 1的對象 值改為 2



 
          field
.
set
(
numb
,
 tmp
);
 

 
         
}
 
catch
 
(
Exception
 e
)
 
{



 
         e
.
printStackTrace
();



 
         
}



 
 
}




是不是感覺大功告成了,但是運行以后,a 和b的值都變為2。難道
Integer
 tmp 
=
 numa
;


 是這句話的問題嗎,因為numa對象的值已經是2了,那這樣的話tmp對象也是2,所以a 和b的值都變為2,那咱們把這句話改一下試試對不對。




static
 
void
 swap
(
Integer
 numa
,
 
Integer
 numb
)
 
{



 
     int tmp = numa.intValue();
 
      
try
 
{



 
          
Field
 field 
=
 
Integer
.
class
.
getDeclaredField
(
"value"
);



 
          field
.
setAccessible
(
true
);



 
          field
.
set
(
numa
,
 numb
);
//成功的將numa 引用的 1的對象 值改為 2



 
          field
.
set
(
numb
,
 tmp
);
 

 
         
}
 
catch
 
(
Exception
 e
)
 
{



 
         e
.
printStackTrace
();



 
         
}



 
 
}




這是應該沒有問題,但是運行后,a 和b的值還都是2。我真想說真二,這是為什么呢?這樣試一下,咱們把a和b的初始改為a = 199,b = 299,再試一下。經過運行后發現a 和b的值成功互換。這是為什么呢?難道和數值的大小有關系嗎?我們再變一種寫法試試。


static
 
void
 main
(
String
[]
 args
)
 
{



 
  
  Integer
 a 
=
 
new
 
Integer
(
1
);



 
   
Integer
 b 
=
 
new
 
Integer
(
2
);



 
  
  System
.
out
.
println
(
"a="
 
+
 a 
+
 
",b="
 
+
 b
);



 
   swap
(
a
,
 b
);



 
    
System
.
out
.
println
(
"a="
 
+
 a 
+
 
",b="
 
+
 b
);



 
   
}



 
   
 private
 
static
 
void
 swap
(
Integer
 numa
,
 
Integer
 numb
)
 
{



 
    
int
 tmp 
=
 numa
.
intValue
();



 
     
try
 
{



 
          
Field
 field 
=
 
Integer
.
class
.
getDeclaredField
(
"value"
);



 
         field
.
setAccessible
(
true
);



 
         field
.
set
(
numa
,
 numb
);



 
         field
.
set
(
numb
,
 tmp
);



 
         
}
 
catch
 
(
Exception
 e
)
 
{



 
         e
.
printStackTrace
();



 
   
}



 
  
}




運行以后,a 和b的值成功互換,a = 2, b = 1。那這又是為什么呢?難道和裝箱和拆箱有關系嗎,為什么 Integer a = 1 和 Integer a = new Integer(1) 效果不一樣了,當Integer a = 1;時,編譯器會將其轉化為Integer a = Integer.valueOf(1); 但是數值分別是199和299 怎么又正常了呢,通過看源碼Integer.valueOf 的方法

下面大家可以驗證一下,理解默認的Integer緩存int常量值的范圍

System.out.println(127==127); //true , int type compare
System.out.println(128==128); //true , int type compare
System.out.println(new Integer(127) == new Integer(127)); //false, object compare
System.out.println(Integer.parseInt("128")==Integer.parseInt("128")); //true, int type compare
System.out.println(Integer.valueOf("127")==Integer.valueOf("127")); //true ,object compare, because IntegerCache return a same object
System.out.println(Integer.valueOf("128")==Integer.valueOf("128")); //false ,object compare, because number beyond the IntegerCache
System.out.println(Integer.parseInt("128")==Integer.valueOf("128")); //true , int type compare

通過閱讀源碼發現,Integer.valueOf 方式初始化一個 Interger因為有 緩存了 -128-127的數字,再看 field.set(numb,tmp); 我們打斷點,發現通過反射設置 value時 竟然走了 Integer.valueOf 方法。

大家可以在代碼中驗證一下,在 field
.
set
(
numa
,
 numb
);


后增加 System.out.println("tmp3="+new Integer(tmp));

System.out.println("tmp4="+Integer.valueOf(tmp)); 運行后,發現打印的tmp3 = 1 ,tmp4 = 2 , 說到這里大家明白其中的原因了吧。

最后正確的swap方法是:

static
 
void
 swap
(
Integer
 numa
,
 
Integer
 numb
)
 
{



 
 
int
 tmp 
=
 numa
.
intValue
();



 
  
try
 
{



 
      
Field
 field 
=
 
Integer
.
class
.
getDeclaredField
(
"value"
);



 
      field
.
setAccessible
(
true
);



 
      field
.
set
(
numa
,
 numb
);



 
      field
.
set
(
numb
,
 
new
 
Integer
(
tmp
));


//避免從緩沖取值
 
  
}
 
catch
 
(
Exception
 e
)
 
{



 
      e
.
printStackTrace
();



 
     
}



 
 
}




補充知識:java 傳遞參數的兩種方式講解

Java中沒有指針,所以也沒有引用傳遞了,僅僅有值傳遞不過可以通過對象的方式來實現引用傳遞 類似java沒有多繼承 但可以用多次implements 接口實現多繼承的功能

值傳遞:方法調用時,實際參數把它的值傳遞給對應的形式參數,方法執行中形式參數值的改變不影響實際參 數的值。

引用傳遞:也稱為傳地址。方法調用時,實際參數的引用(地址,而不是參數的值)被傳遞給方法中相對應的形式參數,在方法執行中,對形式參數的操作實際上就是對實際參數的操作,方法執行中形式參數值的改變將會影響實際參數的值。

a.傳遞值的數據類型:八種基本數據類型和String(這樣理解可以,但是事實上String也是傳遞的地址,只是string對象和其他對象是不同的,string對象是不能被改變的,內容改變就會產生新對象。那么StringBuffer就可以了,但只是改變其內容。不能改變外部變量所指向的內存地址)。

b.傳遞地址值的數據類型:除String以外的所有復合數據類型,包括數組、類和接口

值傳遞的例子:

package com.other.test;
 
public class Test {
 public static void change(int i, int j) { 
 int temp = i; 
 i = j; 
 j = temp;
 } 
 
 public static void main(String[] args) { 
 int a = 3; 
 int b = 4; 
 change(a, b); 
 System.out.println("a=" + a); 
 System.out.println("b=" + b);
 }
}

輸出的結果是 a=3 b=4,傳遞的值并不會改變原值

引用傳遞的例子:(數組)

package com.other.test;
 
public class Test {
 public static void change(int[] counts) { 
 counts[0] = 6; 
 System.out.println(counts[0]);
 } 
 
 public static void main(String[] args) { 
 int[] count = { 1, 2, 3, 4, 5 }; 
 change(count);
 System.out.println(count[0]);
 } 
}

輸出結果是6 6 也就是引用的值改變了原來的值

引用傳遞的例子:(對象)

定義一個A對象:

package com.other.test;
 
public class A {
 int i = 0;
}

對上邊對象操作的類:

package com.other.test;
 
public class Test {
 public static void add(A a) { 
 //a = new A();  ①
 a.i++;
 } 
 
 public static void main(String args[]) { 
 A a = new A(); 
 add(a); 
 System.out.println(a.i );
 } 
}

當把①注解掉時,輸出的結果是1,當①沒有注解是是0,原因是 a =new A();構造了新的A對象就不是傳遞的那個對象了。

看看String的情況:

package com.other.test;
 
public class Test {
 String str = new String("old"); 
 char[] ch = { 'a', 'b', 'c' }; 
 public static void main(String args[]) { 
 Test ex = new Test(); 
 ex.change(ex.str, ex.ch); 
 System.out.print(ex.str + " and "); 
 System.out.println(ex.ch);
 } 
 
 public void change(String str, char ch[]) { 
 str = "new"; 
 ch[0] = 'd';
 }
}

輸出的結果的是 old and dbc也就是傳遞String并不會改變原值,而是創建了一個新值。 ch[]就是一個簡單的數組的傳遞。

( 對象包括對象引用即地址和對象的內容)

String 比較特別,看過String 代碼的都知道, String 是 final的。所以值是不變的。 函數中String對象引用的副本指向了另外一個新String對象,而數組對象引用的副本沒有改變,而是改變對象中數據的內容.

對于對象類型,也就是Object的子類,如果你在方法中修改了它的成員的值,那個修改是生效的,方法調用結束后,它的成員是新的值,但是如果你把它指向一個其它的對象,方法調用結束后,原來對它的引用并沒用指向新的對象。

Java參數,不管是原始類型還是引用類型,傳遞的都是副本(有另外一種說法是傳值,但是說傳副本更好理解吧,傳值通常是相對傳址而言)。

如果參數類型是原始類型,那么傳過來的就是這個參數的一個副本,也就是這個原始參數的值,這個跟之前所談的傳值是一樣的。如果在函數中改變了副本的值不會改變原始的值.

如果參數類型是引用類型,那么傳過來的就是這個引用參數的副本,這個副本存放的是參數的地址。如果在函數中沒有改變這個副本的地址,而是改變了地址中的值,那么在函數內的改變會影響到傳入的參數。如果在函數中改變了副本的地址,如new一個,那么副本就指向了一個新的地址,此時傳入的參數還是指向原來的地址,所以不會改變參數的值。

看完上述內容,你們掌握Java形參和實參的實例之Integer類型與Int類型的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

松溪县| 宝山区| 湘西| 思南县| 哈巴河县| 顺昌县| 体育| 陇川县| 招远市| 邹城市| 临沂市| 威宁| 仙居县| 平陆县| 郎溪县| 马边| 遂昌县| 山阳县| 张北县| 信宜市| 岚皋县| 桑日县| 龙江县| 吕梁市| 阿拉善左旗| 临桂县| 商丘市| 宜章县| 宁波市| 寿阳县| 九台市| 威宁| 绥江县| 两当县| 溆浦县| 绥滨县| 平顺县| 丰都县| 惠安县| 逊克县| 江北区|