JAVA的参数传递方式

简介: JAVA的参数传递方式

许多编程语言都允许按引用或按值传递参数。在Java中,我们只能按value传递参数。这施加了一些限制,并且引起了疑问。例如,如果在方法中更改了参数值,方法执行后该值会怎样?您可能还想知道Java如何管理内存堆中的对象值。该Java Challenger可帮助您解决有关Java中对象引用的这些以及其他常见问题。

java

对象引用按值传递

Java中的所有对象引用均按值传递。这意味着该值的副本将传递给方法。但是诀窍在于传递值的副本也会更改对象的实际值。要了解原因,请从以下示例开始:

publicclassObjectReferenceExample{

publicstaticvoidmain(String... doYourBest) {

Simpsonsimpson = newSimpson();

transformIntoHomer(simpson);

System.out.println(simpson.name);

}

staticvoidtransformIntoHomer(Simpson simpson) {

simpson.name = "Homer";

}

}

classSimpson{

Stringname;

}

您认为执行simpson.name该transformIntoHomer方法后会怎样?

在这种情况下,它将是荷马!原因是Java对象变量只是指向内存堆中实际对象的引用。因此,即使Java通过值将参数传递给方法,但如果变量指向对象引用,则实际对象也将被更改。

Java

原始类型是否按值传递?

像对象类型一样,基本类型也按值传递。您能否在下面的代码示例中推断出原始类型会发生什么?

publicclassPrimitiveByValueExample{

publicstaticvoidmain(String... primitiveByValue) {

inthomerAge = 30;

changeHomerAge(homerAge);

System.out.println(homerAge);

}

staticvoidchangeHomerAge(int homerAge) {

homerAge = 35;

}

}

如果您确定该值将更改为30,那么您是正确的。这是30,因为(再次)Java通过值传递对象参数。数字30只是值的副本,而不是实际值。基本类型在堆栈存储器中分配,因此仅本地值将被更改。在这种情况下,没有对象引用。

传递不可变的对象引用

如果我们对不可变的String对象进行了相同的测试该怎么办?

JDK包含许多不可变的类。实例包括包装类型

java

Integer,Double,Float,Long,Boolean,BigDecimal,和当然的非常公知的String类。在下一个示例中,请注意当我们更改a的值时会发生什么String。

publicclassStringValueChange{

publicstaticvoidmain(String... doYourBest) {

Stringname = "";

changeToHomer(name);

System.out.println(name);

}

staticvoidchangeToHomer(String name) {

name = "Homer";

}

}

您认为输出结果是什么?如果您猜到了“”,那就恭喜!发生这种情况是因为String对象是不可变的,这意味着内的字段String是最终字段,无法更改。使

java

String类不可变使我们可以更好地控制Java最常用的对象之一。如果a的值String可以更改,则会产生很多错误。还要注意,我们没有更改String类的属性;相反,我们只是String为其分配了一个新值。在这种情况下,“荷马”值将被传递到name在changeToHomer法。该方法完成执行后,String“本垒打”将有资格被垃圾回收changeToHomer。即使无法更改对象,局部变量也会更改。

传递可变对象引用

与不同String,JDK中的大多数对象都是可变的,例如StringBuilder类。下面的示例与上一个示例相似,但是功能StringBuilder而不是String:

staticclassMutableObjectReference{

publicstaticvoidmain(String... mutableObjectExample) {

StringBuildername = newStringBuilder("Homer ");

addSureName(name);

System.out.println(name);

}

staticvoidaddSureName(StringBuilder name) {

name.append("Simpson");

}

}

您能否推断出此示例的输出?在这种情况下,因为我们正在使用可变对象,所以输出将为“ Homer Simpson”。您可能会期望Java中其他可变对象具有相同的行为。

您已经了解到Java变量是通过值传递的,这意味着将传递值的副本。只要记住复制的值指向Java内存堆中的真实对象即可。按值传递仍然会更改实际对象的值。

接受对象引用挑战!

在此Java Challenger中,我们将测试您从对象引用中学到的知识。在下面的代码示例中,您将看到不可变String和可变的StringBuilder类。每个参数都作为参数传递给方法。知道Java仅按值传递,一旦执行了此类的main方法,您认为输出是什么?

publicclassDragonWarriorReferenceChallenger{

publicstaticvoidmain(String... doYourBest) {

StringBuilderwarriorProfession = newStringBuilder("Dragon ");

StringwarriorWeapon = "Sword ";

changeWarriorClass(warriorProfession, warriorWeapon);

System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon);

}

staticvoidchangeWarriorClass(StringBuilder warriorProfession, String weapon) {

warriorProfession.append("Knight");

weapon = "Dragon " + weapon;

weapon = null;

warriorProfession = null;

}

}

这些是选项,请在本文结尾处查看答案。

A:战士=空武器=空

B:战士=龙武器=龙

C:战士=龙骑士武器=龙剑

D:战士=龙骑士武器=剑

发生什么事了

上面示例中的第一个参数是warriorProfession变量,它是一个可变对象。第二个参数,武器是不可变的String:

staticvoidchangeWarriorClass(StringBuilder warriorProfession, String weapon) {

...

}

现在,让我们分析一下该方法内部发生的情况。在此方法的第一行,我们将Knight值附加到warriorProfession变量。请记住,这warriorProfession是一个可变的对象;因此实际对象将被更改,并且其值将为“ Dragon Knight”。

warriorProfession.append("Knight");

在第二条指令中,不可变的局部String变量将更改为“ Dragon Sword”。但是,真正的对象将永远不会更改,因为它String是不可变的并且其属性是最终的:

weapon = "Dragon " + weapon;最后,我们传递null

给这里的变量,而不传递给对象。只要它们仍然可以从外部访问,这些对象将保持不变-在这种情况下,可以通main方法访问。而且,尽管局部变量将为null,但对象将不会发生任何事情:

weapon = null;

warriorProfession = null;

从所有这些我们可以得出结论,可变StringBuilder和不变的最终值String将是:

System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon);

changeWarriorClass方法中唯一更改的值是warriorProfession,因为它是可变StringBuilder对象。请注意,它warriorWeapon没有改变,因为它是一个不可变的String对象。我们的挑战者代码的正确输出为:

D:战士=龙骑士武器=剑。

对象引用的常见错误

· 尝试通过引用更改不可变值。

· 尝试通过引用更改原始变量。

· 当您在方法中更改可变对象参数时,期望真实对象不会更改。

java

关于对象引用要记住什么

· Java总是按值传递参数变量。

· Java中的对象变量始终指向内存堆中的实际对象。

· 可变对象的值传递给方法时可以更改。

· 不可变对象的值即使传递了新值也无法更改。

· “按值传递”是指传递值的副本。

· “通过引用传递”是指在内存中传递变量的真实引用。

相关文章
|
7月前
|
存储 Java 编译器
【Java变量】 局部变量、成员变量(类变量,实例变量)、方法参数传递机制
【Java变量】 局部变量、成员变量(类变量,实例变量)、方法参数传递机制
94 0
|
4月前
|
存储 安全 Java
在 Java 中如何将 ArrayList 作为参数传递
【8月更文挑战第23天】
201 0
|
7月前
|
Java 编译器
滚雪球学Java(34):探究Java方法的神奇魔法和参数传递奥秘
【5月更文挑战第9天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
36 1
滚雪球学Java(34):探究Java方法的神奇魔法和参数传递奥秘
|
6月前
|
数据采集 Java 数据安全/隐私保护
使用Java进行网络采集:代理IP与参数传递详解
Java参数传递是按值传递,包括对象引用的值。当传递对象时,方法内部修改对象内容会影响原始对象,但不能改变原始引用。示例展示了如何在爬虫代理中使用此机制,通过`ProxySettings`类传递代理信息,方法内可访问但不能更改原始对象。理解这一机制对编写高效无错的Java代码至关重要。
使用Java进行网络采集:代理IP与参数传递详解
|
6月前
|
Java 数据安全/隐私保护
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
36 0
|
Java Spring
【Java】Spring boot快速上手(二):参数传递
【Java】Spring boot快速上手(二):参数传递
120 0
|
7月前
|
Java
【Java基础】类名、抽象类、接口名的参数传递及成员内部类、局部内部类和匿名内部类的使用
【Java基础】类名、抽象类、接口名的参数传递及成员内部类、局部内部类和匿名内部类的使用
82 0
|
Java
第一季:4方法的参数传递机制【Java面试题】
第一季:4方法的参数传递机制【Java面试题】
63 0
【java筑基】——为什么java中方法的参数传递机制没有引用传递
【java筑基】——为什么java中方法的参数传递机制没有引用传递
|
Java
Java:函数式接口(Functional Interface)实现将函数作为方法参数传递
Java:函数式接口(Functional Interface)实现将函数作为方法参数传递
1993 0