看了也不会系列-函数参数传递方式

196 阅读3分钟

在开始学习数据结构之前,先对java的变量的特性做一个了解

Java内存管理

名称 特征 作用 配置参数 异常
程序计数器 占用内存小,线程私有,生命周期与线程相同 大致为字节码行号指示器
虚拟机栈 线程私有,生命周期与线程相同,使用连续的内存空间 Java 方法执行的内存模型,存储局部变量表、操作栈、动态链接、方法出口等信息 -Xss StackOverflowErrorOutOfMemoryError
java堆 线程共享,生命周期与虚拟机相同,可以不使用连续的内存地址 保存对象实例,所有对象实例(包括数组)都要在堆上分配 -Xms-Xsx-Xmn OutOfMemoryError
方法区 线程共享,生命周期与虚拟机相同,可以不使用连续的内存地址 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据 -XX:PermSize:16M-XX:MaxPermSize64M OutOfMemoryError
运行时常量池 方法区的一部分,具有动态性 存放字面量及符号引用

这是java最常见内存管理模型,在这篇文章中重点讨论的是虚拟机栈和java堆,具体的特征和作用在表中可见。

Java基本数据类型

java的基本数据类型共有8种,即int,short,long,byte,float,double,boolean,char。通过常见的变量声明方式,比如a=2;来定义。

当java编译器运行时,遇到a=2;这一行,它会首先在栈中创建一个变量为a的引用,然后查找有没有字面值为2的地址,有的话则让a指向2,没有则开辟一个内存地址存储2,然后让a指向这个地址。

以上所有操作涉及到底内存区域都是在栈中完成的

Java对象类型

当java编译器运行时,遇到声明对象的时候,比如 Object a=new Object();,它会在栈区为a分配内存空间。此时的a是一个引用变量。然后会在堆区分配内存,里面保存对象的相关数据。最后让a指向堆区的地址

Java函数值传递方式

  • 基本数据类型和包装类型: 方法的入参对于基本数据类型和字符串常量来说,传递的其实只是这个值本身的一个拷贝而已,对于外面的变量来说,并没有改变什么,入参的作用域也仅限函数内部,属于局部变量(对于包装类型和String,依然如此)
  • 对象类型: 传递进去的都是对象的引用的拷贝,而不是值的拷贝(包装类型传入的虽然也是引用,但是传递进去的仍然是值的拷贝)。拷贝跟原对象指定的是同一块内存区域,所以在函数里面改变该内存区域的内容对外面会有同样的影响和效果。

示例

public class test {
    public static void main(String[] args) {
        int a = 1;
        test(a);
        System.out.println("a的值是:"+a);
        Integer c=2;
        test(c);
        System.out.println("c的值是:"+c);
    }

    public static void test(int b) {
        b = 3;
    }
}

这里使用基本数据类型和包装类,可以看到值并没有被更改

public class Test {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        test1.number = 0;
        test(test1);
        System.out.println("test1的number:" + test1.number);
    }

    public static void test(Test1 test1) {
        test1.number = 100;
    }
}

class Test1 {
    int number;
}

这里使用的是对象,可以看到属性被修改了。

总结

以后的数据结构的学习就基于以上的特点。因为java是面向对象的语言,所以后面不论是哪种数据结构,都是通过对象和对象嵌套实现的。