Java中的值传递和引用传递
2017-11-29 16:04
267 查看
理解Java中的值传递和引用传递,形参和实参
1. 两大数据类型以及特殊的String
8种基本数据类型int char byte boolean long short float double
对象类型
1、8种基本数据类型的包装类型
2、数组等
3、定义的对象
特殊: String
2. 两大引用类型
基本类型对象的引用
这两者是有区别的
基本类型 | 对象的引用 |
---|---|
声明定义的时候就为实际的数据分配了空间 | 声明时只是分配了一个引用的空间,一般是4个字节,实际对象的空间未分配 |
int a; // 已经为存放a分配了内存 a=10;//正确,因为声明a时就分配了空间 Date a; //在内存开辟一个引用空间, 即实际才使用了4个字节 a = new Date();//开辟存储Date对象的数据空间,并把该空间的首地址赋给a String a; //在内存开辟一个引用空间
3. 值传递和引用传递
1.形参:形式参数,用来接收调用该方法时传递的参数, 相当于一个实际参数的副本,只有在被调用的时候才分配内存空间,一旦调用结束,就释放内存空间。因此仅仅在方法内有效
2.实参:
传递给被调用方法的值,预先创建并赋予确定值。
值传递:
方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是 原始值的一个copy,此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是 对形参这个值的修改,不影响实际参数的值。
引用传递
也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址;
在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。
具体例子说明一下:
public class A { public static void main(String[] args) { A t = new A(); int a = 99; t.test1(a);//这里传递的参数a就是按值传递 System.out.println(a); MyObj obj=new MyObj(); obj.b = 10; t.test2(obj);//这里传递的参数obj就是引用传递 System.out.println(obj.b); } public void test1(int a){ a = a + 1; System.out.println(a); } public void test2(MyObj obj){ obj.b = 100; System.out.println(obj.b); } } // 输出结果 100 99 100 100
特殊的:对于String 类型, 以及8中基本类型的包装类型等immutable不可变的Java类型,其传递方式为值传递
4. 总结
1.java的基本数据类型是值传递,对象引用类型是引用传递,但是特殊的:String, Integer, Double等immutable的不可变类型可以理解为值传递。2.当传值调用时,改变的是形参的值,并没有改变实参的值,实参的值可以传递给形参,但是,这个传递是单向的,形参不能传递回实参。
3.当引用调用时,传递的是地址,指向的是同一个对象,方法中的操作会改变实参对象的内容。
本文参考了博客: http://www.cnblogs.com/binyue/p/3862276.html
https://www.cnblogs.com/jaylon/p/5721571.html
这里面牵扯到了 不可变类,简单介绍一下:
不可变类
所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值。如JDK内部自带的很多不可变类(String+ 8种基本数据类型):Interger、Long 和 String等。
String类型如何设计成不可变类
- 1、类使用final修饰符,设计成不可被继承的
- 2、成员变量,使用final修饰符,设计成不可以被修改的
- 3、成员变量设计成私有的private,而且不设置setter方法
- 4、通过构造器初始化所有成员,进行深拷贝(deep copy) 在getter方法中,不要直接返回对象本身,而是克隆对象,并返回对象的拷贝, String(char value[])
- 5、获取,在getter方法中,不要直接返回对象本身,而是克隆对象,并返回对象的拷贝,toCharArray()方法
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; //存储字符串 /** Cache the hash code for the string */ private int hash; // Default to 0 字符串的hash值 // 构造函数,使用深克隆 public String(char value[]) { this.value = Arrays.copyOf(value, value.length); } // 获取时,不直接返回对象的引用,而是返回复制后的副本,防止外界进行修改 public char[] toCharArray() { // Cannot use Arrays.copyOf because of class initialization order issues char result[] = new char[value.length]; System.arraycopy(value, 0, result, 0, value.length); return result; } }
String 设计成不可变类的好处
- 1、设计成不可变的,方便 线程安全,可以被多个线程共享
- 2、字符串常量池 可以将一些字符常量放在常量池中重复使用,避免每次都重新创建相同的对象、节省存储空间。但如果字符串是可变的,此时相同内容的String还指向常量池的同一个内存空间,当某个变量改变了该内存的值时,其他遍历的值也会发生改变。所以不符合常量池设计的初衷
- 3、类加载器要用到字符串,不可变性提供了安全性,以便正确的类被加载。譬如你想加载java.sql.Connection类,而这个值被改成了myhacked.Connection,那么会对你的数据库造成不可知的破坏。
- 4、支持hash映射和缓存。
因为字符串是不可变的,所以在它创建的时候hashcode就被缓存了,不需要重新计算。这就使得字符串很适合作为Map中的键,字符串的处理速度要快过其它的键对象。这就是HashMap中的键往往都使用字符串
String 的intern方法的作用:
如果常量池中存在字符,则返回常量池中字符的引用,
如果常量池中不存在字符,则将字符串添加到常量池中(在新的jdk1.7以上,在常量池中创建的字符串存储的是堆中字符串的引用),返回该对象的引用。
更加详细的请查看这篇博客
http://blog.csdn.net/seu_calvin/article/details/52291082
特殊的是,可以通过反射机制改变这一不可变的特性,通过反射,我们可以改变String类型的值的内容
相关文章推荐
- java中的值传递和引用传递
- java中什么是引用传递和值传递
- java基本数据类型和引用数据类型的调用传递的区别
- Java中值传递和引用传递
- Java中按值传递与按引用传递的区别
- Java中只有值传递没有引用传递
- JAVA中方法参数的引用传递
- java中的值传递和引用传递
- java中的参数传递-值传递、引用传递
- Java中的值传递和引用传递
- 请注意:java中没有引用传递
- 详解java的值传递、地址传递、引用传递
- 面试之路(18)-java的函数参数传递类型之值传递还是引用传递
- JAVA值传递or引用传递
- java 值传递 引用传递(又叫地址传递,对象传递)
- java的参数是值传递而非引用传递
- Java值传递和引用传递基础分析
- java语言值传递与引用传递
- 【Java基础】Java:按值传递还是按引用传递详细解说
- Java值传递和引用传递详解