激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術(shù)|正則表達(dá)式|

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - Java形參和實(shí)參的實(shí)例之Integer類型與Int類型用法說(shuō)明

Java形參和實(shí)參的實(shí)例之Integer類型與Int類型用法說(shuō)明

2020-10-07 22:28chan_tom JAVA教程

這篇文章主要介紹了Java形參和實(shí)參的實(shí)例之Integer類型與Int類型用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

經(jīng)常會(huì)有這樣一道面試題,有兩個(gè)整形變量分別是a = 1 ,b = 2。編寫一個(gè)方法swap互換他們的值。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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?)? ?{???
 
    ?//請(qǐng)實(shí)現(xiàn)???
 
   ?}???
 
 }???

1、首先大家看到這到題目后,仔細(xì)看后,在main方法中變量a和b的類型是Integer,而不是Int類型,因?yàn)檫@里涉及到了java的基本類型,Int是屬于Java的基本類型,基本類型在調(diào)用swap的方法時(shí),是修改不了變量a和b的值,說(shuō)到這里涉及到另一個(gè)知識(shí)點(diǎn)了,那就是形參實(shí)參的區(qū)別,值傳遞和引用傳遞的區(qū)別,下面慢慢說(shuō)啊。

2、形參和實(shí)參的區(qū)別

實(shí)參顧名思義:就是實(shí)際參數(shù),用于調(diào)用時(shí)傳遞給方法的參數(shù)。實(shí)參在傳遞給別的方法之前是要被預(yù)先賦值的。

形參顧名思義:就是形式參數(shù),用于定義方法的時(shí)候使用的參數(shù),是用來(lái)接收調(diào)用者傳遞的參數(shù)的,形參只有在方法被調(diào)用的時(shí)候,虛擬機(jī)才會(huì)分配內(nèi)存單元,在方法調(diào)用結(jié)束之后便會(huì)釋放所分配的內(nèi)存單元。因此,形參只在方法內(nèi)部有效,所以針對(duì)引用對(duì)象的改動(dòng)也無(wú)法影響到方法外。

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

3、值傳遞和引用傳遞的區(qū)別

值傳遞調(diào)用過(guò)程只能把實(shí)參傳遞給形參,而不能把形參的值反向作用到實(shí)參上。在函數(shù)調(diào)用過(guò)程中,形參的值發(fā)生改變,而實(shí)參的值不會(huì)發(fā)生改變,函數(shù)接收的是原始值的一個(gè)copy,此時(shí)內(nèi)存中存在兩個(gè)相等的基本類型,即實(shí)際參數(shù)和形式參數(shù),后面方法中的操作都是對(duì)形參這個(gè)值的修改,不影響實(shí)際參數(shù)的值。說(shuō)到這里就明白了題目中聲明a和b的數(shù)據(jù)類型不為Int的原因了吧。

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

4、完成swap?方法實(shí)現(xiàn)

?
1
2
3
4
5
6
7
8
9
10
11
?static? ?void? swap?(?Integer? numa?,? ?Integer? numb?)? ?{???
 
?Integer? tmp ?=? numa?;???
 
numa ?=? numb?;???
 
numb ?=? tmp?;???
 
System?.?out?.?println?(?"numa="? ?+? numa ?+? ?",numb="? ?+? numb?);???
 
?}???

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

?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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的對(duì)象 值改為 2???
 
          field?.?set?(?numb?,? tmp?);? ?
 
         ?}? ?catch? ?(?Exception? e?)? ?{???
 
         e?.?printStackTrace?();???
 
         ?}???
 
 ?}???

是不是感覺(jué)大功告成了,但是運(yùn)行以后,a 和b的值都變?yōu)?。難道?Integer? tmp ?=? numa?;??? 是這句話的問(wèn)題嗎,因?yàn)閚uma對(duì)象的值已經(jīng)是2了,那這樣的話tmp對(duì)象也是2,所以a 和b的值都變?yōu)?,那咱們把這句話改一下試試對(duì)不對(duì)。

?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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的對(duì)象 值改為 2???
 
          field?.?set?(?numb?,? tmp?);? ?
 
         ?}? ?catch? ?(?Exception? e?)? ?{???
 
         e?.?printStackTrace?();???
 
         ?}???
 
 ?}???

這是應(yīng)該沒(méi)有問(wèn)題,但是運(yùn)行后,a 和b的值還都是2。我真想說(shuō)真二,這是為什么呢?這樣試一下,咱們把a(bǔ)和b的初始改為a = 199,b = 299,再試一下。經(jīng)過(guò)運(yùn)行后發(fā)現(xiàn)a 和b的值成功互換。這是為什么呢?難道和數(shù)值的大小有關(guān)系嗎?我們?cè)僮円环N寫法試試。?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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?();???
 
   ?}???
 
  ?}???

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

下面大家可以驗(yàn)證一下,理解默認(rèn)的Integer緩存int常量值的范圍

?
1
2
3
4
5
6
7
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

通過(guò)閱讀源碼發(fā)現(xiàn),Integer.valueOf 方式初始化一個(gè) Interger因?yàn)橛?緩存了 -128-127的數(shù)字,再看 field.set(numb,tmp); 我們打斷點(diǎn),發(fā)現(xiàn)通過(guò)反射設(shè)置 value時(shí) 竟然走了 Integer.valueOf 方法。

大家可以在代碼中驗(yàn)證一下,在 field?.?set?(?numa?,? numb?);???后增加 System.out.println("tmp3="+new Integer(tmp));

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

最后正確的swap方法是:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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?();???
 
     ?}???
 
 ?}???

補(bǔ)充知識(shí):java 傳遞參數(shù)的兩種方式講解

Java中沒(méi)有指針,所以也沒(méi)有引用傳遞了,僅僅有值傳遞不過(guò)可以通過(guò)對(duì)象的方式來(lái)實(shí)現(xiàn)引用傳遞 類似java沒(méi)有多繼承 但可以用多次implements 接口實(shí)現(xiàn)多繼承的功能

值傳遞:方法調(diào)用時(shí),實(shí)際參數(shù)把它的值傳遞給對(duì)應(yīng)的形式參數(shù),方法執(zhí)行中形式參數(shù)值的改變不影響實(shí)際參 數(shù)的值。

引用傳遞:也稱為傳地址。方法調(diào)用時(shí),實(shí)際參數(shù)的引用(地址,而不是參數(shù)的值)被傳遞給方法中相對(duì)應(yīng)的形式參數(shù),在方法執(zhí)行中,對(duì)形式參數(shù)的操作實(shí)際上就是對(duì)實(shí)際參數(shù)的操作,方法執(zhí)行中形式參數(shù)值的改變將會(huì)影響實(shí)際參數(shù)的值。

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

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

值傳遞的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
 }
}

輸出的結(jié)果是 a=3 b=4,傳遞的值并不會(huì)改變?cè)?/p>

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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]);
 }
}

輸出結(jié)果是6 6 也就是引用的值改變了原來(lái)的值

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

定義一個(gè)A對(duì)象:

?
1
2
3
4
5
package com.other.test;
 
public class A {
 int i = 0;
}

對(duì)上邊對(duì)象操作的類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 );
 }
}

當(dāng)把①注解掉時(shí),輸出的結(jié)果是1,當(dāng)①?zèng)]有注解是是0,原因是 a =new A();構(gòu)造了新的A對(duì)象就不是傳遞的那個(gè)對(duì)象了。

看看String的情況:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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';
 }
}

輸出的結(jié)果的是 old and dbc也就是傳遞String并不會(huì)改變?cè)担莿?chuàng)建了一個(gè)新值。 ch[]就是一個(gè)簡(jiǎn)單的數(shù)組的傳遞。

( 對(duì)象包括對(duì)象引用即地址和對(duì)象的內(nèi)容)

String 比較特別,看過(guò)String 代碼的都知道, String 是 final的。所以值是不變的。 函數(shù)中String對(duì)象引用的副本指向了另外一個(gè)新String對(duì)象,而數(shù)組對(duì)象引用的副本沒(méi)有改變,而是改變對(duì)象中數(shù)據(jù)的內(nèi)容.

對(duì)于對(duì)象類型,也就是Object的子類,如果你在方法中修改了它的成員的值,那個(gè)修改是生效的,方法調(diào)用結(jié)束后,它的成員是新的值,但是如果你把它指向一個(gè)其它的對(duì)象,方法調(diào)用結(jié)束后,原來(lái)對(duì)它的引用并沒(méi)用指向新的對(duì)象。

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

如果參數(shù)類型是原始類型,那么傳過(guò)來(lái)的就是這個(gè)參數(shù)的一個(gè)副本,也就是這個(gè)原始參數(shù)的值,這個(gè)跟之前所談的傳值是一樣的。如果在函數(shù)中改變了副本的值不會(huì)改變?cè)嫉闹?

如果參數(shù)類型是引用類型,那么傳過(guò)來(lái)的就是這個(gè)引用參數(shù)的副本,這個(gè)副本存放的是參數(shù)的地址。如果在函數(shù)中沒(méi)有改變這個(gè)副本的地址,而是改變了地址中的值,那么在函數(shù)內(nèi)的改變會(huì)影響到傳入的參數(shù)。如果在函數(shù)中改變了副本的地址,如new一個(gè),那么副本就指向了一個(gè)新的地址,此時(shí)傳入的參數(shù)還是指向原來(lái)的地址,所以不會(huì)改變參數(shù)的值。

以上這篇Java形參和實(shí)參的實(shí)例之Integer類型與Int類型用法說(shuō)明就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/tomy123456123456/article/details/86228612

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 一级网站 | 久色成人 | caoporn国产一区二区 | 国产激情视频在线 | 中文在线国产 | 欧美黑人一级 | 欧美在线a | 久久精品视频一区二区三区 | 国产精品久久久久久久久久久久午夜 | wwwxxx国产 | 国产1区2区3区在线观看 | 欧美大胆xxxx肉体摄影 | 久久亚洲美女视频 | 麻豆视频观看 | 视频在线亚洲 | 亚洲九九爱| 性爱视频在线免费 | 国产精品成人一区二区三区吃奶 | 黄色一级片在线免费观看 | 国产精品视频导航 | 在线成人免费观看视频 | 狠狠久久伊人中文字幕 | 911色_911色sss主站色播 | 国产日本在线播放 | 国产一级伦理片 | 午夜神马电影网 | asiass极品裸体女pics | 久久精品2019中文字幕 | 久久伊人国产精品 | 久久伊人国产精品 | 黑人日比 | 99精品国产在热久久婷婷 | 蜜桃av鲁一鲁一鲁一鲁 | 天天撸日日夜夜 | 精品国产一区二区亚洲人成毛片 | 久久久久久久黄色片 | 午夜激情视频网站 | 免费a级观看 | 深夜影院一级毛片 | 国产毛片视频 | 一级大片久久 |