passed into methods by value java专题

简介: java没有引用传递只有按值传递,没有引用传递只有按值传递,值传递。因为Primitive类型的值不能改变,所以method不能更改调用方传的primitive 值。因为method更改的是Primitive变量的copy,所以method的更改,调用方是不知道的 因为Reference Data Type的内存地址不能被method中操作更改,所以调用方中Reference Data 对象中的状态 也发生变化。


java没有引用传递只有按值传递,没有引用传递只有按值传递,值传递。
因为Primitive类型的值不能改变,所以method不能更改调用方传的primitive 值。因为method更改的是Primitive变量的copy,所以method的更改,调用方是不知道的

因为Reference Data Type的内存地址不能被method中操作更改,所以调用方中Reference Data 对象中的状态 也发生变化。因为method操作的对象,与调用方是相同的,即调用方是知道method中的更改的

只不过Primitive类型传的是实际的数据,Reference Data Type 传的是内存地址。

入参为Reference Data Type的方法中,可以更改这个对象状态的原因,就是因为入参对象的内存地址是不能改变,这样在method中更改这个对象的属性值,调用方的该对象的相关属性值也发生变化

 

Passing Reference Data Type Arguments

Reference data type parameters, such as objects, are also passed into methods by value

This means that when the method returns, the passed-in reference still references the same object as before.
However, the values of the object's fields can be changed in the method, if they have the proper access level.

import org.junit.Test;

public class CircleTest {
    @Test
    public void moveCircle() throws Exception {
        Circle circle=new Circle(10,10);
        circle.print(circle);
        circle.moveCircle(circle, 20, 20);
        circle.print(circle);
    }

}

输出:

moveCircle:Circle{x=10, y=10},hash code:1252585652
moveCircle:Circle{x=0, y=0},hash code:2036368507
moveCircle:Circle{x=30, y=30},hash code:1252585652

 

Let the method be invoked with these arguments:

moveCircle(myCircle, 20, 20)

 

Inside the method, circle initially refers to myCircle. The method changes the x and y coordinates of the object that circle references (i.e., myCircle) by 20 and 20, respectively. These changes will persist when the method returns.
Then circle is assigned a reference to a new Circle object with x = y = 0. This reassignment has no permanence, however, because the reference was passed in by value and cannot change.
Within the method, the object pointed to by circle has changed, but, when the method returns, myCircle still references the same Circle object as before the method was called.

 

public class Circle {
    private int x;
    private int y;

    public Circle(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void moveCircle(Circle circle, int deltaX, int deltaY) {
        // code to move origin of circle to x+deltaX, y+deltaY
        circle.setX(circle.getX() + deltaX);
        circle.setY(circle.getY() + deltaY);

        // code to assign a new reference to circle
        circle = new Circle(0, 0); //自这行后,moveCircle方法就丢失入参circle---即不能再操作入参circle。就像连续对一个primitive 变量赋值,后一次操作会覆盖前面的
        print(circle);
    }
    public void print(Circle circle) {
        System.out.println("moveCircle:"+circle+",hash code:"+circle.hashCode());
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    @Override
    public String toString() {
        return "Circle{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}

 

Passing Primitive Data Type Arguments

Primitive arguments, such as an int or a double, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost. Here is an example:

public class PassPrimitiveByValue {

    public static void main(String[] args) {
           
        int x = 3;
           
        // invoke passMethod() with 
        // x as argument
        passMethod(x);
           
        // print x to see if its 
        // value has changed
        System.out.println("After invoking passMethod, x = " + x);
           
    }
        
    // change parameter in passMethod()
    public static void passMethod(int p) {
        p = 10;
    }
}

When you run this program, the output is:

After invoking passMethod, x = 3

 

 

 

http://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html




 

 

通过下面代码解释:

 1 public class Test {
 2     public static void main(String[] args ){    
 3         int var = 1 ;    
 4         f(var) ;    
 5         System.out.println(var) ;    
 6     }
 7     public static void f(int newVar ){    
 8         newVar = 2 ;    
 9     }
10 }

执行结果: 

1

分析:

当执行 int var = 1 时,jvm在栈中开辟一块空间存放值---1,同时var变量指向值1所对应的内存空间,也就是var变量也有自己的内存空间,不过它的空间里存放的是值1所对应的内存地址。

 

当执行到第七行,要将var的值传递进方法f中时,jvm执行的操作是创建一个新的变量newVar,并将var里存放的值(也就是值1的内存地址)复制一份给newVar。

当执行到第八行时,jvm重新开辟值--2所对应的存储空间来存储值2,并修改了newVar里存放的地址值。

方法返回,执行到第五行,输出var所指向的值,当然是值1,因为var中的地址值根本没有变化。

上面示例用的是int,一个基本数据类型,对于引用数据类型同样适用,因为java中没有引用传递,只有值传递。例如自定义的类UserClass:

 1 class MyClass {
 2     int var1 ;
 3 }
 4 public class Test {
 5     public static void main(String[] args ){    
 6         MyClass myClass = new MyClass() ;
 7         myClass.var1 = 1 ;
 8         f(myClass) ;    
 9         System.out.println(myClass.var1) ;    
10     }
11     public static void f(MyClass newMyClass ){
12         myClass.var1 = 100 ;
13     }
14 }

执行结果:

100

分析:

第六行:在栈中创建一个变量指向在堆中创建的对象。关于堆中对象属性的存储可以理解为每创建一个对象就会在堆中分配一块内存空间给改对象,这块内存空间中记录了该对象属于哪个类,剩下就是存储该对象的属性值。

 

第七行修改对象属性值:

 

下面就是关键的第八行值的传递了,jvm会在栈中在开辟一块空间newMyClass,然后把myClass里的内容拷贝进newMyClass,这样在方法f中对newMyClass的修改就是对MyClass所对应内容的修改,因为newMyClass也是指向与myClass同样的一块内存空间。

第十二行中对newMyClass属性的修改同样会影响myClass所指的内容,因为他们俩指的是同一块内存空间。

最后方法返回myClass所指内容同样被修改。

下面说一个比较特殊的类----String,这是java中的一个特殊的引用类型,使用String传递时会发现在方法中修改不会影响到方法外的值,例如下面这段代码:

 1 public class Test {
 2     public static void main(String[] args ){    
 3         String var = "Hello" ;
 4         f(var) ;
 5         System.out.println(var) ;
 6     }
 7     public static void f(String newVar ){
 8         newVar = "World" ;
 9     }
10 }

运行结果:

Hello

在分析这段代码之前需要知道String的底层是怎样实现的,其实String是通过char数组来完成其功能,简单的说String就是对char[]的一个封装。还要明白直接“字符串内容”和使用new String(“字符串内容”)效果是一样的,只不过jvm对这两种创建的字符串存储的地方不同而已。对上面这段代码的分析当然还要使用对引用数据传值方法分析。

第三行jvm在静态存储区存放创建的“Hello”字符串,并在栈中开辟var指向Hello的地址(var中存储的值是Hello字符串的地址)。当将var作为参数传递时,jvm会在栈中新创建一个变量newVar,这时newVar是指向"Hello"内存区的,但是在第八行 newVar = “World”却把newVar中存储的“Hello”地址改为一个新创建的“World”String对象的地址,注意,var内存储的地址仍然是“Hello”,所以在方法返回时输出的仍然是Hello。

终于写完了~~~ 发现自己想和写完全是两码事‘(*>﹏<*)′,其中一定有错误,在内存分配地方没有说清楚,因为我也不太清楚,还有就是关于对象中属性的内存分配,这个我真不知道,哪位知道别忘告诉我~~

http://www.cnblogs.com/caiyao/p/4964176.html

 

相关文章
|
11月前
|
JSON Java 关系型数据库
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
1143 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
|
11月前
|
存储 Java API
Java交换map的key和value值
通过本文介绍的几种方法,可以在Java中实现Map键值对的交换。每种方法都有其优缺点,具体选择哪种方法应根据实际需求和场景决定。对于简单的键值对交换,可以使用简单遍历法或Java 8的Stream API;对于需要处理值不唯一的情况,可以使用集合存储或Guava的Multimap。希望本文对您理解和实现Java中的Map键值对交换有所帮助。
218 1
|
JSON 前端开发 JavaScript
JSON parse error: Cannot deserialize value of type `java.lang.Integer` from Boolean value
这篇文章讨论了前端Vue应用向后端Spring Boot服务传输数据时发生的类型不匹配问题,即后端期望接收的字段类型为`int`,而前端实际传输的类型为`Boolean`,导致无法反序列化的问题,并提供了问题的诊断和解决方案。
JSON parse error: Cannot deserialize value of type `java.lang.Integer` from Boolean value
|
存储 Java
Redis08命令-Hash类型,也叫散列,其中value是一个无序字典,类似于java的HashMap结构,Hash结构可以将对象中的每个字段独立存储,可以针对每字段做CRUD
Redis08命令-Hash类型,也叫散列,其中value是一个无序字典,类似于java的HashMap结构,Hash结构可以将对象中的每个字段独立存储,可以针对每字段做CRUD
### Cause: java.sql.SQLException: Field ‘id‘ doesn‘t have a default value; Field ‘id‘ doesn‘t have
### Cause: java.sql.SQLException: Field ‘id‘ doesn‘t have a default value; Field ‘id‘ doesn‘t have
|
SQL Java 数据库连接
Cause: java.sql.SQLException: Field ‘id‘ doesn‘t have a default value; Field ‘id‘ doesn‘t have a de
Cause: java.sql.SQLException: Field ‘id‘ doesn‘t have a default value; Field ‘id‘ doesn‘t have a de
|
Java
java lab8--------7-2 sdut-JAVA-Insert Integer element into array lists
java lab8--------7-2 sdut-JAVA-Insert Integer element into array lists
92 0
|
存储 Java API
探讨Java中交换Map的Key和Value值的技术
探讨Java中交换Map的Key和Value值的技术
215 2
|
存储 SQL 关系型数据库
【BUG记录】Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\xA6' for column 'name' at row 1
在MySQL中遇到`Incorrect string value`错误通常是因为尝试插入的字符串包含不被数据库字符集支持的字符,如表情符号。错误根源是MySQL默认的utf8不支持4字节的UTF-8字符(如Emoji)。
1617 1
|
存储 缓存 Java
Java交换map的key和value值
在Java中,直接交换`Map`的key和value是不允许的,因为key是唯一的且不可变。不过,可以通过创建新`Map`实现交换:将原`Map`的value作为新key,key作为新value。注意,如果原`Map`有重复value或null,需额外处理。以下是一个代码示例,展示了如何在value唯一且非null的情况下交换`Map`的key和value。对于重复value或null值的情况,可以使用`List`存储多个key或忽略null值。在实际应用中,`Map`常用于缓存、配置管理、数据库结果映射等多种场景。
244 1

热门文章

最新文章