String是值传递还是引用传递转载

原创
小哥 3年前 (2022-10-27) 阅读数 45 #大杂烩

String它是值传递还是引用传递

在今天的工作中,我的同事发现了一个有趣的问题。他放了一张String类型的参数被传递到方法中,并且被引用的值在方法中被更改。 然后,他在方法外部使用此值,并发现如下所示String它仍然是以前的值,并且没有更改。

在这里,我想向大家介绍一下,我们都知道java传递参数时的值 传递引用传递 。当参数是基本类型时,它是一个值传递, 当参数是封装类型时,通过引用传递。例如:

基本类型参数

1

2

3

4

5

6

7

8

9

10

11

public class Test {

public static void main(String[] args) {

int num = 0 ;

changeNum(num);

System.out.println( "num=" +num);

}

private static void changeNum( int num) {

num = 1 ;

}

}

打印的结果是 num=0

包类型参数

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

36

public class Test {

public static void main(String[] args) {

Product p = new Product();

p.setProName( "before" );

p.setNum( 0 );

changeProduct(p);

System.out.println( "p.proName=" +p.getProName());

System.out.println( "p.num=" +p.getNum());

}

private static void changeProduct(Product p) {

p.setProName( "after" );

p.setNum( 1 );

}

}

class Product {

private int num;

private String proName;

public int getNum() {

return num;

}

public void setNum( int num) {

this .num = num;

}

public String getProName() {

return proName;

}

public void setProName(String proName) {

this .proName = proName;

}

}

运行的结果是: p.proName=afterp.num=1

上面的两个例子是明显的值传递和引用传递。但如果参数是String是什么类型的?让我们来看一些具体的例子:

1

2

3

4

5

6

7

8

9

10

11

public class Test {

public static void main(String[] args) {

String str = "ab" ;

changeString(str);

System.out.println( "str=" +str);

}

private static void changeString(String str) {

str = "cd" ;

}

}

让我们猜猜运行的结果是什么?遵循上一个示例,String它应该是封装类型,它应该是引用传递,它可以改变值, 运行的结果应该是“cd“。让我们实际运行它并查看一下,

str=ab ,这怎么解释呢?是吗String它是基本型的吗?这也说不通。

这就要从java讨论了潜在的机制,java内存模型被划分为

1.将基本类型的变量放置在堆栈中;
2.在封装类型中,对象被放置在堆中,对象的引用被放置在堆栈中。

java当方法传递参数时,将复制变量,然后将其传递到方法体以供执行。 这句话很难理解,也是为了解释这一点 问题的实质。让我们首先根据这句话解释一下基本的传播类型。

  1. 已分配虚拟机num一个内存地址和一个值0.
  2. 该虚拟机复制一个num,我们叫他num’,num’和num内存地址不同,但存储的值都是0。
  3. 虚拟机讲num‘传入该方法,则该方法将。num‘的值已更改1.
  4. 方法结束,方法外打印num价值,这是由于num内存中的值未更改,或0,印刷也是如此。0.

我们来解释一下包裹类型的投递:

  1. 该虚拟机在堆中打开一个。Product的内存空间,它包含在proName和num。
  2. 在堆栈中分配虚拟机。p内存地址,它是1中的Product内存地址的。
  3. 该虚拟机复制一个p,我们叫他p’,p和p的内存地址不同,但它们存储的值是相同的,两者1中Product内存地址的。
  4. 将p‘传入方法后,方法就会改变。1中的proName和num。
  5. 方法结束,方法外打印p中变量价值,这是由于p和p‘所有存在于1中Product地址的地址,1中Product中的价值, 所以,过时的打印p方法执行后的值为。我们看到的效果是包类型的值发生了更改。

最后,让我们来解释一下String分娩过程中的步骤:

  1. 虚拟机打开堆中的内存块并并存值。“ab”。
  2. 在堆栈中分配虚拟机。str一段记忆,这是1地址在。
  3. 虚拟机复制副本str,我们叫str’,str和str内存是不同的,但存储的值是1的地址。
  4. 将str‘传入方法体
  5. 方法体打开堆中的内存块并并存值。“cd”
  6. 方法体将str‘价值变化,存入5的内存地址
  7. 方法结束,方法外打印str,由于str存的是1所有打印的结果都是“ab”

所以我们理解java该方法传递参数的全过程。事实上,它仍然是上面更重要的一句话 java当方法传递参数时,将复制变量,然后将其传递到方法体以供执行。

欢迎来到我的个人博客 www.liubo-tech.cn

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

热门