日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java中形参不可以是对象吗_(重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...

發(fā)布時(shí)間:2025/3/21 编程问答 41 豆豆

1.0建立二叉樹的代碼,在java中必須創(chuàng)建二叉樹的方法必須用返回值,因?yàn)椴淮嬖赾語(yǔ)言中的引用傳遞,在java中只有值傳遞 代碼1為正確,代碼2(沒(méi)有使用返回值)為錯(cuò)誤。那么為什么之前的例子中將對(duì)象作為參數(shù)時(shí),對(duì)對(duì)象內(nèi)容的更改還是正確的,也沒(méi)有使用返回值,二者看似矛盾,其實(shí)并不矛盾,以前都沒(méi)有理解到這個(gè)本質(zhì),本質(zhì)就是參數(shù)中,確實(shí)是有一個(gè)臨時(shí)變量,交換形式對(duì)象參數(shù),實(shí)際的參數(shù)不會(huì)改變,但是改變形式參數(shù)的引用所指向的內(nèi)容,即這個(gè)對(duì)象本身改變,其實(shí)參所引用的對(duì)象也是同一個(gè)對(duì)象,當(dāng)然該對(duì)象也會(huì)發(fā)生變化,因?yàn)閷?shí)參和形參引用的都是同一個(gè)對(duì)象,只不過(guò)是兩份地址的拷貝。

即便是c語(yǔ)言如果不用引用傳遞-&,就是說(shuō)用指針,也需要用返回值的方法建立二叉樹,才能將已建立好的二叉樹頭指針?lè)祷亟o打印函數(shù)的參數(shù)。當(dāng)然java中可以采用對(duì)私有變量等操作,即不不使用參數(shù)傳遞,而僅僅是創(chuàng)建函數(shù)和打印函數(shù)共同操作的是同一個(gè)變量也可以吧,估計(jì)遞歸就不好用了,這個(gè)怎么做沒(méi)去想!~~~

錯(cuò)誤代碼:這個(gè)時(shí)候打印出來(lái)的樹的節(jié)點(diǎn)為空,printInOrder(tree1)輸出節(jié)點(diǎn)為空:

View Code

import java.util.*;

class TNode{

int data;

TNode lchild;

TNode rchild;

TNode(int a)

{

data=a;

lchild=null;

rchild=null;

}

}

public class BTree {

static TNode root=new TNode(1);

static void creatTree(TNode root)

{

Scanner in=new Scanner(System.in);

int a=in.nextInt();

if(a==0){

root=null;

return;

}

else{

root=new TNode(a);

creatTree(root.lchild);

creatTree(root.rchild);

}

}

static void printInOrder(TNode root){

if(root==null)

return;

else{

System.out.print(root.data);

printInOrder(root.lchild);

printInOrder(root.rchild);

}

}

public static void main(String[] args) {

//TODO Auto-generated method stub

creatTree(root);

printInOrder(root);

}

}

正確代碼:

View Code

import java.util.Scanner;

class Tode{

int data;

Tode lchild;

Tode rchild;

Tode(int a)

{

data=a;

lchild=null;

rchild=null;

}

}

public class TREE{

static Tode root=null;

static Tode creatTree(Tode root)

{

Scanner in=new Scanner(System.in);

int a=in.nextInt();

if(a==0){

return null ;

}

else{

root=new Tode(a);

root.lchild=creatTree(root.lchild);

root.rchild=creatTree(root.rchild);

return root;

}

}

static void printInOrder(Tode root){

if(root==null)

return;

else{

System.out.print(root.data);

printInOrder(root.lchild);

printInOrder(root.rchild);

}

}

public static void main(String[] args) {

//TODO Auto-generated method stub

Tode tree1=creatTree(root);

printInOrder(tree1);

}

}

1.1、疑惑解決了,原來(lái)認(rèn)為方法中傳入一個(gè)對(duì)象的話(數(shù)組也行),如果方法內(nèi)部對(duì)這個(gè)對(duì)象的內(nèi)部參數(shù)進(jìn)行了更改,則其實(shí)就是對(duì)外部的這個(gè)靜態(tài)對(duì)象也進(jìn)行了修改,相當(dāng)于c++中的真正的引用傳遞吧,但是傳入的是整型等普通類型,則還是不能夠更改,可以見(jiàn)下面的實(shí)例。如果傳入的對(duì)象是數(shù)組的話,也可以更改,因?yàn)閖ava中數(shù)組也是對(duì)象~,其實(shí)也不是 因?yàn)槭菍?duì)引用所指向的內(nèi)容進(jìn)行了修改,引用可以有多個(gè),但是引用所指向的內(nèi)容只有一份!!!!!!

以下程序的輸出結(jié)果是012

View Code

import java.util.*;

class node{

int data;

node lchild;

node rchild;

public node(int a){

data=a;

lchild=null;

rchild=null;

}

}

public class testclass2 {

public void changeroot(node root){

node newnode1=new node(1);

node newnode2=new node(2);

root.lchild=newnode1;

root.rchild=newnode2;

}

public void print(node root){

System.out.println(root.data);

System.out.print(root.lchild.data);

System.out.print(root.rchild.data);

}

public static void main(String[] args){

node root=new node(0);

testclass2 dd=new testclass2();

dd.changeroot(root);

dd.print(root);

}

}

1.2、下面是另一個(gè)例子,在算法例子中也常用到因?yàn)槭?對(duì)引用所指向的內(nèi)容進(jìn)行了修改,引用可以有多個(gè),但是引用所指向的內(nèi)容只有一份!!!!!!

以下程序輸出結(jié)果是2 4 3 4

View Code

void diguiInorderTraverse(node root){

root.lchild

}

解釋說(shuō)的通了,傳入root,對(duì)root修改,其實(shí)就相當(dāng)于

class A{

int b=2;

}

public class Testclass {

static A a=new A();

static void changeA(A a){

a.b=3;

}

static int b=4;

static void changeB(int b){

b=5;

}

public static void main(String[] args) {

//TODO Auto-generated method stub System.out.println(a.b);

System.out.println(b);

changeA(a);

changeB(b);

System.out.println(a.b);

System.out.println(b);

}

}

1.3、也就是說(shuō)root對(duì)象確實(shí)分配了一個(gè)臨時(shí)對(duì)象,傳入的都是地址的引用,所以對(duì)這個(gè)參數(shù)的改變,對(duì)引用所指向的內(nèi)容進(jìn)行了修改,引用可以有多個(gè),但是引用所指向的內(nèi)容只有一份!!!!!!

我看了一些引用調(diào)用和值調(diào)用的定義,很多人都把是傳遞值,還是傳遞地址?是改變參數(shù)自身內(nèi)容,還是改變參數(shù)所指向的地址中的內(nèi)容作為區(qū)別這兩種調(diào)用的標(biāo)志。這很不恰當(dāng),這些說(shuō)法很容易讓我們聯(lián)想到Java的對(duì)象參數(shù)傳遞是引用調(diào)用,實(shí)際上,Java的對(duì)象傳遞仍然是值調(diào)用。

引用調(diào)用:在參數(shù)傳遞的過(guò)程中,形參并不是實(shí)參的副本,而是實(shí)參本身。這種調(diào)用實(shí)參和形參在內(nèi)存中實(shí)際上都是同樣的一個(gè)區(qū)域,只是這個(gè)區(qū)域的表示(參數(shù)名)不同而已。

值調(diào)用:在參數(shù)傳遞過(guò)程中,創(chuàng)建了一個(gè)實(shí)參的副本——形參。形參和實(shí)參在內(nèi)存中是兩個(gè)完全不同的區(qū)域。因此形參內(nèi)容的改變并不能影響到實(shí)參。

方法調(diào)用(call by)是一個(gè)標(biāo)準(zhǔn)的計(jì)算機(jī)科學(xué)術(shù)語(yǔ)。方法調(diào)用根據(jù)參數(shù)傳遞的情況又分為值調(diào)用(call by reference)和引用調(diào)用(call by value)。江湖上有很多關(guān)于這兩種調(diào)用的定義,最通常的說(shuō)法是傳遞值的是值調(diào)用,傳遞地址的是引用調(diào)用。這其實(shí)很不恰當(dāng),這種這些說(shuō)法很容易讓我們聯(lián)想到Java的對(duì)象參數(shù)傳遞是引用調(diào)用,實(shí)際上,Java的對(duì)象參數(shù)傳遞仍然是值調(diào)用。

以下摘自該段落:

Java代碼

1.publicclassEmployee?{

2.

3.publicString?name=null;

4.

5.publicEmployee(String?n){

6.this.name=n;

7.}

8.//將兩個(gè)Employee對(duì)象交換

9.publicstaticvoidswap(Employee?e1,Employee?e2){

10.Employee?temp=e1;

11.e1=e2;

12.e2=temp;

13.System.out.println(e1.name+"?"+e2.name);//打印結(jié)果:李四張三

14.}

15.//主函數(shù)

16.publicstaticvoidmain(String[]?args)?{

17.Employee?worker=newEmployee("張三");

18.Employee?manager=newEmployee("李四");

19.swap(worker,manager);

20.System.out.println(worker.name+"?"+manager.name);//打印結(jié)果仍然是:張三李四

21.}

22.}

上面的結(jié)果讓人很失望,雖然形參對(duì)象e1,e2的內(nèi)容交換了,但實(shí)參對(duì)象worker,manager并沒(méi)有互換內(nèi)容。這里面最重要的原因就在于形參e1,e2是實(shí)參worker,manager的地址拷貝。

大家都知道,在Java中對(duì)象變量名實(shí)際上代表的是對(duì)象在堆中的地址(專業(yè)術(shù)語(yǔ)叫做對(duì)象引用)。在Java方法調(diào)用的時(shí)候,參數(shù)傳遞的是對(duì)象的引用。重要的是,形參和實(shí)參所占的內(nèi)存地址并不一樣,形參中的內(nèi)容只是實(shí)參中存儲(chǔ)的對(duì)象引用的一份拷貝。

如果大家對(duì)JVM內(nèi)存管理中Java棧的局部變量區(qū)有所了解的話(可以參見(jiàn)《》),就很好理解上面這句話。在JVM運(yùn)行上面的程序時(shí),運(yùn)行main方法和swap方法,會(huì)在Java棧中先后push兩個(gè)叫做棧幀的內(nèi)存空間。main棧幀中有一塊叫局部變量區(qū)的內(nèi)存用來(lái)存儲(chǔ)實(shí)參對(duì)象worker和manager的引用。而swap棧幀中的局部變量區(qū)則存儲(chǔ)了形參對(duì)象e1和e2的引用。雖然e1和e2的引用值分別與worker和manager相同,但是它們占用了不同的內(nèi)存空間。當(dāng)e1和e2的引用發(fā)生交換時(shí),下面的圖很清晰的看出完全不會(huì)影響worker和manager的引用值。

Java對(duì)象參數(shù)傳遞雖然傳遞的是地址(引用),但仍然是值調(diào)用。是時(shí)候需要給引用調(diào)用和值調(diào)用一個(gè)準(zhǔn)確的定義了。

值調(diào)用(call by value):在參數(shù)傳遞過(guò)程中,形參和實(shí)參占用了兩個(gè)完全不同的內(nèi)存空間。形參所存儲(chǔ)的內(nèi)容是實(shí)參存儲(chǔ)內(nèi)容的一份拷貝。實(shí)際上,Java對(duì)象的傳遞就符合這個(gè)定義,只不過(guò)形參和實(shí)參所儲(chǔ)存的內(nèi)容并不是常規(guī)意義上的變量值,而是變量的地址。咳,回過(guò)頭想想:變量的地址不也是一種值嗎!

引用調(diào)用(call by reference):在參數(shù)傳遞的過(guò)程中,形參和實(shí)參完全是同一塊內(nèi)存空間,兩者不分彼此。實(shí)際上,形參名和實(shí)參名只是編程中的不同符號(hào),在程序運(yùn)行過(guò)程中,內(nèi)存中存儲(chǔ)的空間才是最重要的。不同的變量名并不能說(shuō)明占用的內(nèi)存存儲(chǔ)空間不同。

大體上說(shuō),兩種調(diào)用的根本并不在于傳遞的是值還是地址(畢竟地址也是一個(gè)值),而是在于形參和實(shí)參是否占用同一塊內(nèi)存空間。事實(shí)上,C/C++的指針參數(shù)傳遞也是值調(diào)用,不信試試下面的C代碼吧!

C代碼

1.#include

2.voidswap(int*a1,int*b1){

3.int*t=a1;

4.a1=b1;

5.b1=t;

6.}

7.intmain(){

8.intx1=100;

9.intx2=200;

10.int*a=&x1;

11.int*b=&x2;

12.printf("%d?%d\n",*a,*b);

13.swap(a,b);

14.printf("%d?%d\n",*a,*b);

15.return0;

16.}

但C/C++是有引用調(diào)用的,這就是C/C++一種叫做引用的變量聲明方法:int a; int &ra=a;其中ra是a的別名,兩者在內(nèi)存中沒(méi)有區(qū)別,占用了同一個(gè)內(nèi)存空間。而通過(guò)引用(別名)的參數(shù)傳遞就符合引用調(diào)用的特點(diǎn)了。大家可以去試試

void swap(int &a1,int &b1);的運(yùn)行結(jié)果。

總結(jié)

以上是生活随笔為你收集整理的java中形参不可以是对象吗_(重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。