Java中的参数传值方式
本文转载自 https://blog.csdn.net/SEU_Calvin/article/details/70089977
1. 你觉得下面程序会输出什么
- public static void change(String s) {
- s = “123”;
- }
- public static void main(String args[]) {
- String s = “abc”;
- change(s);
- System.out.println(s);
- }
面试官写下了这段代码,问我s会输出什么。
我想起了各种排序算法直接把一个int数组array,通过参数传递给一个方法,在方法里完成数据的移动后,直接在main()函数中输出array[]中的值就是修改过的。所以我回答说,那应该输出123吧。
然后面试官说,不对,是输出abc,你觉得原因是什么。
我想了想回答说,String是final的,所以值是不变的。
接着面试官写下了如下代码:
- public static void main(String[] args) {
- MyClass myClass = new MyClass();
- change(myClass);
- System.out.println(myClass.val);
- }
- private static void change(MyClass myClass) {
- myClass = new MyClass();
- myClass.val = 2;
- }
- public static class MyClass{
- int val = 1;
- }
问我MyClass类不是final的,但为什么这里还是会输出1。我有点被问懵了,其实后来面试结果又仔细看一下,是自己忽略掉了第八行代码,其实把第八行代码注释掉,肯定就输出2了。
2. Java参数传值
2.1 值传递
先从一个例子说起:
- public static void change(int i, int j) {
- inttemp = i;
- i =j;
- j =temp;
- }
- public static void main(String[] args) {
- inta = 3;
- intb = 4;
- change(a,b);
- System.out.println(a);
- System.out.println(b);
- }
输出为:
- 3
- 4
值传递是指方法调用时,实际参数把它的值传递给对应方法的形参,如change()方法中i和j,也在内存空间中分配了存储单元,这样形参在change()方法中的改变不会影响实际参数的值。
值传递的数据类型包括,八种基本数据类型和String。
2.2 引用传递
值传递的数据类型包括,八种基本数据类型和String,八种数据类型还比较好理解,比如2.1中的int,但是String并不是基本数据类型,这要怎么理解呢。比如下面这个例子。
- public class Example {
- String str = new String("abc");
- char[] ch = { 'a', 'b', 'c' };
- public static void main(String args[]) {
- Example ex = new Example();
- ex.change(ex.str, ex.ch);
- System.out.println(ex.str);
- System.out.println(ex.ch);
- }
- public void change(String str, char ch[]) {
- //ch = new char[]{'a','b','c'};
- str = "change";
- ch[0] = 'c';
- }
- }
这个例子的输出为:
- abc
- cbc
要知道String和char数组都是引用类型,不是基本类型。
当我们把str作为参数传入方法后,会新建另一个变量,已经不是原来的变量了,但是他们指向的数据区域都一样,所以如果你在方法中改变了str指向的数据区域,即执行str = "change",那也只是改变新建的另一个变量所指向的数据区域,即指向一个新对象"change",str仍然指向原来的数据区域。所以会输出abc。
但是对于char数组的例子呢,即对象类型,也就是Object的子类(除了String),是把ch的引用传递进来,即引用传递。这样里面和外面的ch都指向了相同的数据区域,执行ch[0] = 'c',就会把这个数据区域里的第一个字符改成c,并没有改变内部ch的数据地址,所以这个修改也会反映到外部的ch。所以会输出cbc。如果你改变了内部ch所指向的数据区域,即把上面代码中注释的那一行打开,即执行ch = new char[]{'a','b','c'},这样ch已经指向一个新的数据区域。输出的结果肯定也就是abc了。
这样在1中面试官给的两段代码也就很容易解释了。
3 两种数据传递总结
值传递和引用传递的本质区别在于是否在传递的时候进行对象的内存拷贝。
基本类型是由于在JVM中存储区域不同于普通对象所以传递前会拷贝,传递的是拷贝后的值,但是对象在传递的时候不拷贝,直接传“引用值”,指向同一片对象堆内存区域,当然要注意String这种特殊情况。
Java中的参数传值方式的更多相关文章
- 2016/10/21 java中的参数传方式
参考:http://blog.sina.com.cn/s/blog_59ca2c2a0100qhjx.html http://www.cnblogs.com/caiyao/p/4964176.html
- JS 和 Java 中URL特殊字符编码方式
前几天遇到url特殊字符编码的问题,在这里整理一下: JavaScript 1. 编码 escape(String) 其中某些字符被替换成了十六进制的转义序列. 解码 unescape(String ...
- 如何理解Java中参数传递只能传值?
以前学习C#的时候,是完全在工作岗位上学习,一些底层较为深入的道理都不是很清楚.如今学习了Java,对于Java参数传递只能传值,不能传引用(指针)感到很困惑,在C#中不是常常说把某个引用传递到函数中 ...
- Java中的参数验证(非Spring版)
1. Java中的参数验证(非Spring版) 1.1. 前言 为什么我总遇到这种非正常问题,我们知道很多时候我们的参数校验都是放在controller层的传入参数进行校验,我们常用的校验方式就是引入 ...
- Java中数组的初始化方式
Java中数组的初始化方式 初始化方式有两种: 1.静态初始化:初始化时由程序猿显式指定每一个数组元素的初始值,由系统指定数组长度 2.动态初始化:初始化时由程序猿仅仅指定数组长度,由系统为数组 ...
- 原码,补码,反码的概念及Java中使用那种存储方式
原码,补码,反码的概念及Java中使用那种存储方式: 原码:原码表示法是机器数的一种简单的表示法.其符号位用0表示正号,用:表示负号,数值一般用二进制形式表示 补码:机器数的补码可由原码得到.如果机器 ...
- Java 中可变参数
可变参数 Java 中可变参数 现在需要编写一个求和的功能,但是不知道有几个参数,在调用的时候才知道有几个参数,请问这如何实现呢? Java 给我们提供了一个 JDK 1.5 的新特性---可变参数 ...
- Java中实现线程的方式
Java中实现线程的方式 Java中实现多线程的方式的方式中最核心的就是 run()方法,不管何种方式其最终都是通过run()来运行. Java刚发布时也就是JDK 1.0版本提供了两种实现方式,一个 ...
- java参数传值方式
java参数有值类型和引用类型两种.所以java参数的传值也就从这两个方面分析. 从内存模型来说参数传递更为直观一些,这里涉及到两种类型的内存:栈内存(stack)和堆内存(heap). 基本类 ...
随机推荐
- 将PHP 5.3.3 (cli)升级到PHP 5.6.31 (cli)
centos默认系统安装的是php5.3 [root@sz-local1 scripts]# rpm -qa |grep phpphp-pdo-5.3.3-47.el6.x86_64php-mysql ...
- 【php】global的使用与php的全局变量
php的全局变量和其余编程语言是不同的,在大多数的编程语言中,全局变量在其下的函数.类中自己主动生效.除非被局部变量覆盖,或者根本就不同意再声明同样名称与类型的局部变量.可是php中的全局变量不是默认 ...
- Android 适配(一)
一.Android适配基础参数 1.常见分辨率(px) oppx 2340x1080 oppR15 2280x1080 oppor11sp 2160*1080 ...
- lua注册函数
#include <stdio.h> #include <math.h> #define MAX_COLOR 255 extern "C" { #inclu ...
- Manager模块 队列 管道 进程池
Manager模块 作用: 多进程共享变量. Manager的字典类型: 如果value是简单类型,比如int,可以直接赋值给共享变量,并可以后续直接修改 如果value是复杂类型 ,比如list, ...
- Dire Wolf(区间DP)
Dire Wolf Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)Total ...
- GCD多线程在swift中的变化
1.异步线程加载主线程刷新 DispatchQueue.global().async { // TODO:执行异步线程网络请求 DispatchQueue.main.async(execute: { ...
- DNN自适应
- 【译】Java语言速览:StackOverflow
Java (请不要与 JavaScript 搞混) 是一种设计为与 Java 虚拟机 (JVM) 一起使用的多用途编程语言.一般称呼安装了相关工具使其可以开发并运行 Java 程序的电脑系统为 &qu ...
- react create app ,nginx服务器配置
server{ listen 80; server_name www.domain.com domain.com; location ~* \.js$ { root /home/hard/Projec ...