一、首先看一个比较容易混淆的例子
package com.example.String;
/**
* Created by 390498 on 2015/10/12.
*/
public class Test2 {
public static void main(String[] args){
String a="原始值";//初始赋值
System.out.println(a);
change(a);//改值
System.out.println(a);
}
/**
* 改变字符串的值
* @param a
*/
private static void change(String a) {
a = "已改变的值";
}
}
输出结果:
原始值
原始值
相信初学者(也不乏部分学了几年JAVA的人)都会认为第十行代码change(a)应该改变了a的值,但实际上change方法并没有改变main方法中的a的值。这点正是本文要讨论的值传递和引用传递。
二、我们再看下何为值传递,何为引用传递。
(1)值传递:在Java中,当基本类型(8大基本数据类型)作为参数传入方法时,无论该参数在方法内怎样改变,外部的变量原形总是不变;
(2)引用传递:方法将非基本类型作为传入参数(对象类型的变量),方法改变参数变量的同时也会改变原型变量;
但是,相信部分读者也注意到,String类型并非基本数据类型,但是为什么按基本数据类型的方式进行处理了呢?其实,这个问题也正是后面我想谈谈的问题。
三、关于String(Integer、Float类似)参数传递问题所在
我们先看一下String类的部分实现:
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
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
/**
* Initializes a newly created {@code String} object so that it represents
* an empty character sequence. Note that use of this constructor is
* unnecessary since Strings are immutable.
*/
public String() {
this.value = new char[0];
}
/**
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param original
* A {@code String}
*/
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
。。。。。。
}
这里我们主要关注带参构造器,我们可以看到,new出来的String的存储形式是不可变的char数组,亦即String是char[]的包装类,而包装类的特征之一就是:在对其值进行操作时,会体现出其对应的基本类型的性质。所以,String类型作为参数类型进行传递的时候,体现出了基本数据类型的值传递的特征。