是Java吗;参考传递”;或;传递值“;?
我一直认为Java使用按引用传递 然而,我看到一些博客文章(例如)声称它不是(博客文章说Java使用传递值) 我想我不明白他们的区别是Java吗;参考传递”;或;传递值“;?,java,methods,parameter-passing,pass-by-reference,pass-by-value,Java,Methods,Parameter Passing,Pass By Reference,Pass By Value,我一直认为Java使用按引用传递 然而,我看到一些博客文章(例如)声称它不是(博客文章说Java使用传递值) 我想我不明白他们的区别 原因是什么?Java总是按值传递,没有例外,从来都是 那么,怎么会有人对此感到困惑,认为Java是通过引用传递的,或者认为他们有一个Java作为通过引用传递的例子呢?关键的一点是Java从不提供在任何情况下直接访问对象本身的值。对对象的唯一访问是通过对该对象的引用。因为Java对象总是通过引用来访问,而不是直接访问,所以通常将字段、变量和方法参数称为对象,而从字面
原因是什么?Java总是按值传递,没有例外,从来都是 那么,怎么会有人对此感到困惑,认为Java是通过引用传递的,或者认为他们有一个Java作为通过引用传递的例子呢?关键的一点是Java从不提供在任何情况下直接访问对象本身的值。对对象的唯一访问是通过对该对象的引用。因为Java对象总是通过引用来访问,而不是直接访问,所以通常将字段、变量和方法参数称为对象,而从字面上讲,它们只是对对象的引用这种混淆源于这种(严格地说,是不正确的)命名变化。 因此,在调用方法时
- 对于基元参数(
,int
等),传递值是基元的实际值(例如,3)long
- 对于对象,传递值是对对象的引用的值
doSomething(foo)
和public void doSomething(foo foo){..}
两个foo复制了指向相同对象的引用
自然地,通过值传递对对象的引用与通过引用传递对象非常相似(在实践中没有区别)。Java通过值传递引用
public class PassByCopy{
public static void changeName(Dog d){
d.name = "Fido";
}
public static void main(String[] args){
Dog d = new Dog("Maxx");
System.out.println("name= "+ d.name);
changeName(d);
System.out.println("name= "+ d.name);
}
}
class Dog{
public String name;
public Dog(String s){
this.name = s;
}
}
因此,您无法更改传入的引用。基本上,重新指定对象参数不会影响参数,例如
private void foo(Object bar) {
bar = null;
}
public static void main(String[] args) {
String baz = "Hah!";
foo(baz);
System.out.println(baz);
}
将打印出
“Hah!”
,而不是null
。之所以这样做是因为bar
是baz
值的副本,它只是对“哈!”
的引用。如果它是实际的引用本身,那么foo
会将baz
重新定义为null
Java按值传递对对象的引用。Java总是按值传递。不幸的是,当我们处理对象时,我们实际上是在处理被称为引用的对象句柄,这些句柄也是通过值传递的。这种术语和语义很容易使许多初学者感到困惑
public static void changeReference(Foo a)
事情是这样的:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the "Max" dog when foo(...) returns
aDog.getName().equals("Max"); // true
aDog.getName().equals("Fifi"); // false
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// change d inside of foo() to point to a new Dog instance "Fifi"
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
void getValues(int[] arg1, int[] arg2) {
arg1[0] = 1;
arg2[0] = 2;
}
void caller() {
int[] x = new int[1];
int[] y = new int[1];
getValues(x, y);
System.out.println("Result: " + x[0] + " " + y[0]);
}
在上面的示例中,aDog.getName()
仍将返回“Max”
。main
中的值aDog
在函数foo
中不会随Dog
“Fifi”而改变,因为对象引用是通过值传递的。如果它是通过引用传递的,那么main
中的aDog.getName()
将在调用foo
后返回“fififi”
同样地:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
foo(aDog);
// when foo(...) returns, the name of the dog has been changed to "Fifi"
aDog.getName().equals("Fifi"); // true
// but it is still the same dog:
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// this changes the name of d to be "Fifi"
d.setName("Fifi");
}
在上面的示例中,
Fifi
是调用foo(aDog)
后狗的名字,因为对象的名字是在foo(…)
中设置的。对于foo
在d
上执行的任何操作,实际上都是在aDog
上执行的,但是不可能更改变量aDog
本身的值。长话短说,对象具有一些非常特殊的属性
一般来说,Java有直接通过值传递的基本类型(int
、bool
、char
、double
),等等。然后Java就有了对象(从Java.lang.Object
派生的所有东西)。实际上,对象总是通过引用来处理的(引用是一个你不能触摸的指针)。这意味着实际上,对象是通过引用传递的,因为引用通常不感兴趣。但是,这确实意味着您不能更改指向哪个对象,因为引用本身是通过值传递的
这听起来是不是既奇怪又令人困惑?让我们考虑一下C是如何实现按引用传递和按值传递的。在C语言中,默认约定是按值传递<代码>无效foo(int x)按值传递intvoid foo(int*x)
是一个函数,它不需要inta
,而是指向int:foo(&a)
。可以将其与&
运算符一起使用,以传递变量地址
把这个带到C++,我们有参考文献。引用基本上是(在此上下文中)隐藏表达式指针部分的语法糖:
void foo(int&x)
由foo(a)
调用,其中编译器本身知道它是引用,并且应该传递非引用a
的地址。在java中,所有引用对象的变量实际上都是引用类型,实际上,通过引用来强制调用大多数目的和目的,而没有细粒度的控制(和复杂性),例如C++( < p>)。或者,也许我记得,我曾经和最初的海报有着相同的印象,那就是:Java总是按值传递。Java中的所有对象(在Java中,除了原语以外的任何对象)都是引用。这些引用是按值传递的。正如许多人之前提到的
下面是另一个帮助您理解差异()的示例:
印刷品:
之前:a=2,b=3之后:a=2,b=3 这是因为iA和iB是新的局部引用变量,它们与传递的引用具有相同的值(它们分别指向a和b)。因此,尝试更改iA或iB的引用只会在本地范围内更改,而不会超出此方法。我一直认为它是“通过复制”。它是原语值的副本
Dog myDog = new Dog("Rover");
foo(myDog);
public void foo(Dog someDog) {
someDog.setName("Max"); // AAA
someDog = new Dog("Fifi"); // BBB
someDog.setName("Rowlf"); // CCC
}
void cppMethod(int val, int &ref, Dog obj, Dog &objRef, Dog *objPtr, Dog *&objPtrRef)
{
val = 7; // Modifies the copy
ref = 7; // Modifies the original variable
obj.SetName("obj"); // Modifies the copy of Dog passed
objRef.SetName("objRef"); // Modifies the original Dog passed
objPtr->SetName("objPtr"); // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
objPtrRef->SetName("objRefPtr"); // Modifies the original Dog pointed to
// by the original pointer passed.
objPtrRef = new Dog("newObjPtrRef"); // Modifies the original pointer passed
}
int main()
{
int a = 0;
int b = 0;
Dog d0 = Dog("d0");
Dog d1 = Dog("d1");
Dog *d2 = new Dog("d2");
Dog *d3 = new Dog("d3");
cppMethod(a, b, d0, d1, d2, d3);
// a is still set to 0
// b is now set to 7
// d0 still have name "d0"
// d1 now has name "objRef"
// d2 now has name "objPtr"
// d3 now has name "newObjPtrRef"
}
public static void javaMethod(int val, Dog objPtr)
{
val = 7; // Modifies the copy
objPtr.SetName("objPtr") // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
}
public static void main()
{
int a = 0;
Dog d0 = new Dog("d0");
javaMethod(a, d0);
// a is still set to 0
// d0 now has name "objPtr"
}
void getValues(int& arg1, int& arg2) {
arg1 = 1;
arg2 = 2;
}
void caller() {
int x;
int y;
getValues(x, y);
cout << "Result: " << x << " " << y << endl;
}
void getValues(int[] arg1, int[] arg2) {
arg1[0] = 1;
arg2[0] = 2;
}
void caller() {
int[] x = new int[1];
int[] y = new int[1];
getValues(x, y);
System.out.println("Result: " + x[0] + " " + y[0]);
}
public static void swap(StringBuffer s1, StringBuffer s2) {
StringBuffer temp = s1;
s1 = s2;
s2 = temp;
}
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("Hello");
StringBuffer s2 = new StringBuffer("World");
swap(s1, s2);
System.out.println(s1);
System.out.println(s2);
}
public static void appendWorld(StringBuffer s1) {
s1.append(" World");
}
public static void main(String[] args) {
StringBuffer s = new StringBuffer("Hello");
appendWorld(s);
System.out.println(s);
}
public static void appendWorld(String s){
s = s+" World";
}
public static void main(String[] args) {
String s = new String("Hello");
appendWorld(s);
System.out.println(s);
}
class StringWrapper {
public String value;
public StringWrapper(String value) {
this.value = value;
}
}
public static void appendWorld(StringWrapper s){
s.value = s.value +" World";
}
public static void main(String[] args) {
StringWrapper s = new StringWrapper("Hello");
appendWorld(s);
System.out.println(s.value);
}
1. Person person;
2. person = new Person("Tom");
3. changeName(person);
4.
5. //I didn't use Person person below as an argument to be nice
6. static void changeName(Person anotherReferenceToTheSamePersonObject) {
7. anotherReferenceToTheSamePersonObject.setName("Jerry");
8. }
Foo f = new Foo("f");
public static void changeReference(Foo a)
changeReference(f);
Foo b = new Foo("b");
public void test() {
MyClass obj = null;
init(obj);
//After calling init method, obj still points to null
//this is because obj is passed as value and not as reference.
}
private void init(MyClass objVar) {
objVar = new MyClass();
}
int x = 3;
float y = 101.1f;
boolean amIAwesome = true;
int problems = 99;
String name = "Jay-Z";
JButton[] marxBros = new JButton[3];
marxBros[0] = new JButton("Groucho");
marxBros[1] = new JButton("Zeppo");
marxBros[2] = new JButton("Harpo");
private static void shout(String name){
System.out.println("There goes " + name + "!");
}
public static void main(String[] args){
String hisName = "John J. Jingleheimerschmitz";
String myName = hisName;
shout(myName);
}
public class PassByValue {
public static void main(String[] args) {
Test t = new Test();
t.name = "initialvalue";
new PassByValue().changeValue(t);
System.out.println(t.name);
}
public void changeValue(Test f) {
f.name = "changevalue";
}
}
class Test {
String name;
}
changevalue
Test t = new Test();
new PassByValue().changeValue(t);
public class PassByValue {
public static void main(String[] args) {
Test t = new Test();
t.name = "initialvalue";
new PassByValue().changeRefence(t);
System.out.println(t.name);
}
public void changeRefence(Test f) {
f = null;
}
}
class Test {
String name;
}
public static void tricky(Point arg1, Point arg2) {
arg1.x = 100;
arg1.y = 100;
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
}
public static void main(String [] args) {
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");
tricky(pnt1,pnt2);
System.out.println("X1: " + pnt1.x + " Y1:" + pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
}
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");
X1: 0 Y1: 0
X2: 0 Y2: 0
tricky(pnt1,pnt2); public void tricky(Point arg1, Point arg2);
arg1.x = 100;
arg1.y = 100;
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
X1: 0 Y1: 0
X2: 0 Y2: 0
X1: 100 Y1: 100
X2: 0 Y2: 0
(Name)[Location] -> [Value at the Location]
---------------------
(Ref2Foo)[223] -> 47
(Foo)[47] -> 5
public void method (String param) {}
...
String var = new String("ref");
method(var);
method(var.toString());
method(new String("ref"));
public class PassByValueString {
public static void main(String[] args) {
new PassByValueString().caller();
}
public void caller() {
String value = "Nikhil";
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
output : output
value : Nikhil
valueflag : false
public class PassByValueNewString {
public static void main(String[] args) {
new PassByValueNewString().caller();
}
public void caller() {
String value = new String("Nikhil");
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
output : output
value : Nikhil
valueflag : false
public class PassByValueObjectCase1 {
private class Student {
int id;
String name;
public Student() {
}
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}
public static void main(String[] args) {
new PassByValueObjectCase1().caller();
}
public void caller() {
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student);
}
public String method(Student student) {
student.setName("Anand");
return "output";
}
}
output : output
student : Student [id=10, name=Anand]
public class PassByValueObjectCase2 {
public static void main(String[] args) {
new PassByValueObjectCase2().caller();
}
public void caller() {
// student has the actual reference to a Student object created
// can we change this actual reference outside the local scope? Let's see
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student); // Will it print Nikhil or Anand?
}
public String method(Student student) {
student = new Student(20, "Anand");
return "output";
}
}
output : output
student : Student [id=10, name=Nikhil]
Account account1 = new Account();
public class Test
{
public static void reverseArray(int[] array1)
{
// ...
}
public static void main(String[] args)
{
int[] array1 = { 1, 10, -7 };
int[] array2 = { 5, -190, 0 };
reverseArray(array1);
}
}
array1[0] = 5;
array1 = array2;
public class Test
{
public static int[] reverseArray(int[] array1)
{
int[] array2 = { -7, 0, -1 };
array1[0] = 5; // array a becomes 5, 10, -7
array1 = array2; /* array1 of reverseArray starts
pointing to c instead of a (not shown in image below) */
return array2;
}
public static void main(String[] args)
{
int[] array1 = { 1, 10, -7 };
int[] array2 = { 5, -190, 0 };
array1 = reverseArray(array1); /* array1 of
main starts pointing to c instead of a */
}
}
using namespace std;
#include <iostream>
void change (char *&str){ // the '&' makes this a reference parameter
str = NULL;
}
int main()
{
char *str = "not Null";
change(str);
cout<<"str is " << str; // ==>str is <null>
}
public class ValueDemo{
public void change (String str){
str = null;
}
public static void main(String []args){
ValueDemo vd = new ValueDemo();
String str = "not null";
vd.change(str);
System.out.println("str is " + str); // ==> str is not null!!
// Note that if "str" was
// passed-by-reference, it
// WOULD BE NULL after the
// call to change().
}
}
program passByRefDemo;
type
iptr = ^integer;
var
ptr: iptr;
procedure setToNil(var ptr : iptr);
begin
ptr := nil;
end;
begin
new(ptr);
ptr^ := 10;
setToNil(ptr);
if (ptr = nil) then
writeln('ptr seems to be nil'); { ptr should be nil, so this line will run. }
end.