`

java 传对象和传变量

    博客分类:
  • java
阅读更多
引用

  • 值传递:方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参 数的值。参数是原始类型int,long,float,byte,char,double、boolean、short等等。 
  • 引用传递:也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。

引用
string不是基本类型,但是传递参数时,为什么其原参数值没有发生变化,下面我们来看看new出String对象的那小段代码(String类中),也就是String类的构造函数:
publicString(String original) {

        int size = original.count;

        char[] originalValue = original.value;

        char[] v;

      if (originalValue.length > size) {

             int off = original.offset;

             v = Arrays.copyOfRange(originalValue, off, off+size);

        } else {

            v = originalValue;

        }

        this.offset = 0;

        this.count = size;

        this.value = v;

}


也许你注意到了里面的char[],这说明对String的存储实际上通过char[]来实现的。怎么样?其实就是一层窗户纸。不知道大家还记不记得在Java API中定义的那些基本类型的包装类。比如Integer是int包装类、Float是float的包装类等等。对这些包装类的值操作实际上都是通过对其对应的基本类型操作而实现的。是不是有所感悟了?对,String就相当于是char[]的包装类。包装类的特质之一就是在对其值进行操作时会体现出其对应的基本类型的性质。在参数传递时,包装类就是如此体现的。所以,对于String在这种情况下的展现结果的解释就自然而然得出了。同样的,Integer、Float等这些包装类和String在这种情况下的表现是相同的。
传对象
public class ZhiShu {
	public  void setMapValue(Map maps){
		maps.put("3","3");
		maps.put("4","4");
	}
	public static void main(String[] args) {
		ZhiShu z=new ZhiShu();
		Map map=new HashMap();
		map.put("1","1");
		map.put("2","2");
		z.setMapValue(map);
		System.out.println(map);
	}
}


顺便说一下string对象
引用
String是一个非可变类,非可变类的实例是不能被修改的,每个实例中包含的信息都必须在该实例创建的时候就提供出来,并且在对象的整个生存周期内固定不变,该类对象本质上是线程安全的,不要求同步。建一个Stirng对象,主要就有以下两种方式:
String str1 = new String("abc");     
Stirng str2 = "abc";   

虽然两个语句都是返回一个String对象的引用,但是JVM对两者的处理方式是不一样的。对于第一种,JVM会马上在堆区中创建一个String对象,然后将该对象的引用返回给用户。对于第二种,JVM首先会在内部维护的串池中通过String的 equels 方法查找是对象池中是否存放有该String对象,如果有,则返回已有的String对象给用户,而不会在堆区中重新创建一个新的String对象;如果串池中没有该String对象,JVM则在堆区中创建新的String对象,将其引用返回给用户,同时将该引用添加至串池中。注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到串池里面的,除非程序调用 String的intern方法。

看下面实例:
引用

String str1 = new String("abc");  

  /**此句在执行的时候先在字符串池中寻找是否有"abc"这样的字符串,如果没有,则在字符串池中创建一个,然后再通过new()方法在堆中创建一份"abc"的拷贝。所以以上的语句实际是创建了两个对象,一个是字符串池中的"abc",一个是堆中的"abc"。许多人可能以为s也是一个对象,这是不对的,s是一个变量,只是对对象的引用。如果在此句后面紧接着执行:       
String S1=new String("abc");
则此句只创建一个对象,即通过new()在堆中创建池中对象"abc"的一份拷贝。即如果上面的语句是如下的话:
String S1="abc";
则此句不会创建对象,只会把字符串池中的对象"abc"的地址赋给S1。
知道为什么new String("abc")亦要检查串池吗?那是因为String()的constructor是原因。这是其中一个String的constructor : String(String original).留意当new String("abc")时.其实已经先做了一个动作,String original = "abc".*/

引用
intern()方法:这是一个本地方法。在调用这个方法时,JAVA虚拟机首先检查字符串池中是否已经存在与该对象值相等对象存在,如果有则返回字符串池中对象的引用;如果没有,则先在字符串池中创建一个相同值的String对象,然后再将它的引用返回,看下面实例:

String str1 = new String("abc"); //jvm 在堆上创建一个String对象    
   
str1 = str1.intern();    
//程序显式将str1放到strings pool中,intern运行过程是这样的:首先查看strings pool    
//有没“abc”对象的引用,没有,则在堆中新建一个对象,然后将新对象的引用加入至    
//strings pool中。执行完该语句后,str1原来指向的String对象已经成为垃圾对象了,随时会    
//被GC收集。    
   
//此时,jvm发现strings pool中已有“abc”对象了,因为“abc”equels “abc”    
//因此直接返回str1指向的对象给str2,也就是说str2和str1引用着同一个对象,    
//此时,堆上的有效对象只有一个。    
Stirng str2 = "abc";    
   
 if(str1 == str2){    
         System.out.println("str1 == str2");    
 }else{    
         System.out.println("str1 != str2");    
 }    
  //打印结果是 str1 == str2    

引用
   (1).栈(stack):主要保存基本类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。

   (2).堆(heap):用于存储对象。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics