当前位置:   article > 正文

关于java在成员/全局变量上不同类型赋值遇到的问题(值传递)_java不同数据类型相互赋值

java不同数据类型相互赋值

文件简介

在java中只有值传递,没有引用传递,即使是包装类型,传递了引用,但是依然是通过创建副本进行传递的!

class ss{
    static class Student{
        int id;
        String name;
/*
        public Student(int id, String name) {
            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) {
        int a = 1;
        method1(a);
        System.out.println(a);
        System.out.println("------");

        Integer aa = 1;
        method2(aa);
        System.out.println(aa);
        System.out.println("------");

        String aaa = "1";
        method3(aaa);
        System.out.println(aaa);

        Student student = new Student();
        method4(student);
        System.out.println(student);


    }
    public static void method4(Student input){
        input.setId(3);
    }


    public static void method1(int input){
        input = 2;
    }

    public static void method2(int input){
        input = 2;
    }

    public static void method3(String input){
        input = "2";
    }
}
  • 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
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

结果是什么?

在这里插入图片描述
有返回值的设值才会让String、int改变,而对javabean的直接赋值不需要返回直接变化掉

这是什么导致的?存储位置吗?

回答

值的传递是需要确定 传输的是 存储位置还是一个复制的成员变量

  • 对于javaBeab对象,在栈空间开辟位置,存放引用,传递的是复制的存储位置,但是指向依旧是堆中的旧信息;
  • 对于String、Integer类型,在栈空间开辟位置,存放引用,指向依旧是堆中的旧信息,操作如下两图。

在java中只有值传递,没有引用传递,即使是包装类型,传递了引用,但是依然是通过创建副本进行传递的!

我们创建变量和对象,都是在栈中创建了对象引用,引用指向了堆中的具体值

在上面代码中,String、Integer本来就是finial类型,其引用指向的是一个常量池,如果变化,只是在栈中复制了一个引用,并指向了新的位置

在这里插入图片描述
这里注意对于局部变量:当声明是基本类型的变量的时,其变量名及值(变量名及值是两个概念)是放在方法栈中,
所以copy_a对应值应该在方法栈中,并非堆中

一旦method方法结束,copy_a变量作为一个局部变量就将被清理;
copy_a进行了如下操作:

  1. 在栈中复制引用;
  2. 在堆中复制新的值使copy_a = 1;
  3. 进入方法体内,copy_a修改为2;

而对于Student对象,

在这里插入图片描述
copy_student进行了如下操作:

  1. 在栈中复制引用开辟空间及地址位置;
  2. 在堆中指向对应地址;
  3. 进入方法体内,id修改为2;

数据存放位置

  • 堆 是所有线程共享的内存区域;栈 是每个线程独享的,
  • 如果你将一个实例变量放在栈内,那么就不存在多个线程访问同一个对象资源了,这显然是不对的,所以实例变量要在堆上创建,也不是线程安全的。
  • 但是对于局部变量,是在栈上创建的,每一次方法调用创建一个帧,独享一份内存区域,其他的线程是不会访问到该线程的资源,在 栈上创建也会减轻GC的压力,随着该方法的结束,帧出栈,相对应的内存消除,这种局部变量占用的内存自然就消失了,因此局部变量是线程安全的。

基本数据类型是放在栈中还是放在堆中,这取决于基本类型声明的位置

  • 在方法中声明的变量,即使变量是局部变量,每当程序调用方法时,系统都会为该方法建立一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因。
    在方法中声明的变量可以是基本类型的变量,也可以是引用类型的变量。
    (1)当声明是基本类型的变量的时,其变量名及值(变量名及值是两个概念)是放在方法栈中
    (2)当声明的是引用变量时,所声明的变量(该变量实际上是在方法中存储的是内存地址值)是放在方法的栈中,该变量所指向的对象是放在堆类存中的。

  • 在类中声明的变量是成员变量,也叫全局变量放在堆中的(因为全局变量不会随着某个方法执行结束而销毁)。
    同样在类中声明的变量即可是基本类型的变量 也可是引用类型的变量
    (1)当声明的是基本类型的变量其变量名及其值放在堆内存中的
    (2)引用类型时,其声明的变量仍然会存储一个内存地址值,该内存地址值指向所引用的对象。引用变量名和对应的对象仍然存储在相应的堆中.

参考文献

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/541334
推荐阅读
相关标签
  

闽ICP备14008679号