Java 基础 --- Java变量储存机制及参数传递

JVM内存机制

在这里插入图片描述

在这里插入图片描述

Primitive type的储存和值传递

primitive type的储存

  • primitive type的局部变量是储存在JVM stack上, 首先JVM创建一个名为A的变量, 存在于局部变量表中,然后去栈中查找是否存有字面量值为10的内容,如果有就直接把A指向这个地址. 如果没有,JVM会在栈中开辟一块空间来存储10这个内容.
  • 当写下 int A = 10 时:
    在这里插入图片描述
  • 当写下 int A = 10, int B = 10 时:
    在这里插入图片描述
  • int A = 10, int B = 10, B = 20;
    在这里插入图片描述

primitive type的值传递

  • 如下图,在执行main方法时,JVM会在栈顶加进一个栈帧,此栈帧包括一个A=10的变量。在执行passPrimitive方法时,JAM会再加入一个新的栈帧,此栈帧包括一个B=10的变量,当执行B=100时,在passPrimitive栈帧中的B值会被改变,但在main栈帧中的A值不会被改
    在这里插入图片描述
  • Before: A is 10
  • B is 100
  • After: A is 10

Reference Type的储存和值传递

Reference Type的储存

  • reference包括除基础类型之外的其他所有类型,变量中储存的时一个引用(在栈中存一个可以指向heap的引用),具体过程如下
    在这里插入图片描述

Reference Type的传递

  • 会改变实参
    在这里插入图片描述
  • Before: S1’ID is 100
  • In The method: S1’ID is 200
  • After: S1’ID is 200
  • 当执行第21行(Student s1 = new Student())时
    在这里插入图片描述
  • 当执行第24行时(进入Test方法)
    在这里插入图片描述

总结:

  • 在Java中没有引用传递,只有值传递。在Java中“值”的概念分为两种,一个是基础类型的实际数值,一个是引用,但是对于任何一种变量Java都拿不到地址(引用变量只是储存的是引用, 但是变量本身的地址是拿不到的, 也就是说Java中对对象的引用本身做不了任何操作,比如替换成另外一个引用)所以不存在引用传递。反之,在C++/C中对于任何一个变量(基础变量,类,指针变量等)除了可以拿到变量里的值以外还可以拿到变量的地址,所以有值传递,引用传递,指针传递之分

关于包装类的参数传递问题: Integer as example

  • 虽然所有的包装类都是引用传递,但是在函数中传递包装类并不能改变实参
  • 因为所有的包装类都是不可变类, 也就是用final修饰, 比如final int value. 所以当对象被重新赋值时,会生成新的对象
  • 根据Integer的缓存机制,如果在-128-127之间 就从常量池中获取一个Integer对象返回;如果不在范围内 会new Integer(value)返回
public class ValuePassing {
	
	public static void fun1(Integer i) {
		System.out.println("在fun1中赋值前i的地址是: " + System.identityHashCode(i));
		i = 10; //从常量池中获取一个Integer对象,或者new Integer(value)
		//赋值之后,地址发生改变
		System.out.println("在fun1中赋值后i的地址是: " + System.identityHashCode(i));
	}
	
	public static void main(String[] args) {
        Integer i = 5;
        System.out.println("在main中i的地址是: " + System.identityHashCode(i));
        fun1(i);
        
        i = 20;
        //赋值之后,地址发生改变
        System.out.println("在main中i重新赋值之后的地址是: " + System.identityHashCode(i));
    }
}

output:
在main中i的地址是: 1072591677
在fun1中赋值前i的地址是: 1072591677
在fun1中赋值后i的地址是: 1523554304
在main中i重新赋值之后的地址是: 1175962212

关于缓存:

public class ValuePassing {
	
	public static void fun1(Integer i, Integer j) {
		System.out.println("在fun1中赋值前i的地址是: " + System.identityHashCode(i));
		System.out.println("在fun1中赋值后j的地址是: " + System.identityHashCode(j));
		//对i和j同时赋予一样的值后(在-128-127之间),地址一样
		i = 10; 
		j = 10;
		System.out.println("-----------------------------------------------");
		System.out.println("在fun1中赋值后i的地址是: " + System.identityHashCode(i));
		System.out.println("在fun1中赋值后j的地址是: " + System.identityHashCode(j));
	}
	
	public static void main(String[] args) {
        Integer i = 5;
        Integer j = 20;
        System.out.println("在main中i的地址是: " + System.identityHashCode(i));
        System.out.println("在main中j的地址是: " + System.identityHashCode(j));
        System.out.println("-----------------------------------------------");
        fun1(i, j);
    }
}

output:
在main中i的地址是: 1072591677
在main中j的地址是: 1523554304
-----------------------------------------------
在fun1中赋值前i的地址是: 1072591677
在fun1中赋值后j的地址是: 1523554304
-----------------------------------------------
在fun1中赋值后i的地址是: 1175962212
在fun1中赋值后j的地址是: 1175962212
public class ValuePassing {
	
	public static void fun1(Integer i, Integer j) {
		System.out.println("在fun1中赋值前i的地址是: " + System.identityHashCode(i));
		System.out.println("在fun1中赋值后j的地址是: " + System.identityHashCode(j));
		
		//不在-128-127之间地址则不一样
		i = 1000; 
		j = 1000;
		System.out.println("-----------------------------------------------");
		System.out.println("在fun1中赋值后i的地址是: " + System.identityHashCode(i));
		System.out.println("在fun1中赋值后j的地址是: " + System.identityHashCode(j));
	}
	
	public static void main(String[] args) {
        Integer i = 5;
        Integer j = 20;
        System.out.println("在main中i的地址是: " + System.identityHashCode(i));
        System.out.println("在main中j的地址是: " + System.identityHashCode(j));
        System.out.println("-----------------------------------------------");
        fun1(i, j);
    }
}

output:
在main中i的地址是: 1072591677
在main中j的地址是: 1523554304
-----------------------------------------------
在fun1中赋值前i的地址是: 1072591677
在fun1中赋值后j的地址是: 1523554304
-----------------------------------------------
在fun1中赋值后i的地址是: 1175962212
在fun1中赋值后j的地址是: 918221580
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值