`
chenyanchaoyc
  • 浏览: 3971 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java 值传递和对象引用传递

    博客分类:
  • java
 
阅读更多
  一.值传递和对象引用传递概念
   值传递:方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参 数的值。
   引用传递:也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。
  1.java中分类两种类型:引用类型和基本类型
    基本类型都是属于值传递。引用类型只是引用对象的值,其实也可以说是属于值传递,我们是把引用对象值的地址传给方法参数中,而不是传递引用对象本身。下面来举例说明。
  
   public final class ParamTest {
	// 初始值为0
	protected int num = 0;

	// 为方法参数重新赋值
	public void change(int i) {
		i = 5;
	}

	// 为方法参数重新赋值
	public void change(ParamTest t) {
		ParamTest tmp = new ParamTest();
		tmp.num = 9;
		t = tmp;
	}

	// 改变方法参数的值
	public void add(int i) {
		i += 10;
	}

	// 改变方法参数属性的值
	public void add(ParamTest pt) {
		pt.num += 20;
	}

	public static void main(String[] args) {
		ParamTest t = new ParamTest();

		// 为基本类型参数重新赋值
		t.change(t.num);
		System.out.println(t.num);
		// 为引用型参数重新赋值
		t.change(t);
		System.out.println(t.num);

		// 改变基本类型参数的值
		t.add(t.num);
		System.out.println(t.num);
		// 改变引用类型参数所指向对象的属性值
		t.add(t);
		System.out.println(t.num);
	}
}
 
   

   输出结果为:
               0
               0
               0
               20
  你算对了吗?
  接下来我们一一分析
  首先第一个输出零我们是属于基本类型传递,这里不多说了,两个i是不一样的对象,在stack中是有两个对象存在的,分别是指向不同的值。
  第二个输出零分析:  

  
   这是我们在执行t = tmp;之前的对象指向情况

  
    这是我们执行t = tmp;之后的对象指向情况
    通过这两个图我们能明显的看出我们main函数中对象只是做了传递了一个对象值的引用路径作用,所以他的值不会做出改变。
   
    接下来第三个零分析
    基本上跟第一个是一个道理。
  
    第四个值分析
    我们继续用图来说明问题
   
  


    到这里相信你已经明白了差不多了,我们两个对象指向的值地址没有发生改变,所以在方法中改变num的值,就改变了引用对象地址中num的值,而我们main函数中用的值地址也是这个,所以值发生了改变。
  
  2.我们来探讨一下String类的引用
   string对象是个最终类,在创建String对象时jvm在heap中给它分配了一个对象池,如果你创建的对象存在在这个对象池,那么jvm就不会再给你分配空间创建新的值地址。但是这种方式只是要String s = "abc";这样创建,如果是String s = new String("abc");就不能使用了,他创建了一个值对象地址,跟之前的abc地址不是一个。
   举例来说明:
  
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s2.equals(s3));
System.out.println(s1==s2);
System.out.println(s1==s3);
System.out.println(s2==s3);

    输出结果是:
                true
                true
                true
                true
                false
                false
   当程序执行该代码的时候,JVM会像普通对象一样生成这个String对象,在heap里面保存,直接返回引用,并不会与String Pool交互,这样一来,String Pool的优势就没有被发挥了,怎么办呢?难道我们就不去使用new的方法创建String了吗?答案是JVM还提供了一个方法:String.intern();来让String Pool管理这种String对象。

intern方法的工作原理是这样的:首先在heap里面创建一个完全一样的String对象,并且将该对象的引用放入String Pool中,最后返回给调用方,看代码:
String s1 = new String("abc");
String s2 = "abc";
String s3 = s1.intern();
System.out.println(s1==s2);
System.out.println(s1==s3);
System.out.println(s2==s3);

    输出结果:
              false
              false
              true
  结论:我们在写JAVA代码的时候要尽量避免使用String s = new String("abc");这种方式,因为这样产生的对象并没有“注册”到String Pool中,无法被重复使用,如果已经存在这种对象了,我们可以通过使用s = s.intern();的方式重新创建对象并“注册”到String Pool中,方便后面的重复使用。

  3.深入JVM内存的划分

由于JVM对与heap和stack内存的使用有其特殊的规则,深入了解JVM是如何使用内存的,非常有助于我们在写程序的时候搞清楚自己的对象到底在什么地方,从而可以帮助我们在多线程程序和性能要求较高的程序中优化自己代码,有兴趣的同学可以参考sun的官方文档(http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#1732),下面仅就部分知识做简单描述。

    a. 每个线程都有自己独占的stack,里面存放的是当前线程执行的method及其局部变量

    b. heap中有部分是公共区域,存放的是类实例(class instance)和已分配内存的数组(array)

    c. heap中对于每个线程都有各自独立的内存区域,存放以下内容:

        运行时常量池(runtime constant pool),上面提到的String Pool就属于其中的一部分

        方法代码(method code),即线程要执行的方法代码

        静态变量和方法(static variables and method),我们定义的static类型的变量和方法都存放在这里

更详细的描述可以参考图片:
 
  • 大小: 27.9 KB
  • 大小: 28.4 KB
  • 大小: 23.4 KB
  • 大小: 23.9 KB
  • 大小: 59.1 KB
分享到:
评论

相关推荐

    Java:按值传递还是按引用传递详细解说

    综上所述,在Java中,对于基本数据类型的参数传递实际上是按值传递,而对于对象类型的参数传递则是按引用传递的一种特殊形式——传递的是对象引用的副本,但由于这些副本指向同一个对象,因此对对象的修改会影响到...

    java 值传递和引用传递的比较

    在Java编程语言中,了解值传递和引用传递的概念至关重要,因为它们直接影响到函数参数的处理方式。下面将详细探讨这两个概念及其区别。 首先,我们来理解什么是值传递。在Java中,基本数据类型(如int、double、...

    java值传递与引用传递

    在Java编程语言中,函数参数的传递方式有两种:值传递和引用传递。理解这两种机制对于编写高效、无误的代码至关重要。以下是对这两种传递方式的详细解析。 首先,值传递是指函数调用时,实际参数的值被复制一份传给...

    Java面向对象值传递和引用传递

    Java 面向对象值传递和引用传递 Java 面向对象编程中,参数传递是非常重要的一个概念。参数传递有两种方式:值传递和引用传递。了解这两种方式的区别是非常重要的,因为它们对程序的执行结果产生了很大的影响。 值...

    Java是值传递,传对象引用也是通过值

    总的来说,理解Java中的值传递和对象引用传递对于编写高效、无误的代码至关重要。无论是基本类型还是对象类型,参数传递都是以值的形式进行,但对象类型的值是其引用,允许我们在方法内修改对象的状态,而不影响方法...

    java值传递和引用传递详解

    所以,尽管看起来像是引用传递,但实际上是值传递的一种特例,即传递对象引用的值。 理解值传递和引用传递对于优化代码和避免意外的副作用至关重要。在编程时,需要根据实际需求选择合适的参数传递方式,确保代码的...

    值传递和引用传递

    本文将详细介绍值传递和引用传递的概念、用法以及它们之间的区别,并通过Java语言中的具体示例来加深理解。 #### 二、值传递 **值传递**是指在函数或方法调用时,传递给函数的实际参数的值被复制一份到形参,即形参...

    Java的按值传递和按引用传递分析.rar

    Java编程语言中有两种参数传递方式:按值传递和按引用传递。理解这两种方式对于编写高效、无误的代码至关重要。 1. **按值传递(Pass by Value)** - Java中的基本类型(如int, double, char等)是按值传递的。这...

    面向对象语言中的值传递与引用传递

    面向对象编程语言中,参数传递主要有两种方式:值传递和引用传递。这两种方式在Java这样的语言中有着明显的区别,理解它们对于编写高效、无误的代码至关重要。 **值传递**: 值传递是Java中处理基本数据类型(如int...

    java中对象和对象引用的区别!

    在Java中正确地区分对象与对象引用是非常重要的,这不仅关系到程序的正确性,也影响到资源管理和性能优化。理解了这些基本概念之后,开发者能够更加灵活地运用Java进行开发工作,避免常见的错误和陷阱。

    java参数传递时到底是值传递还是引用传递分享.pdf

    Java中参数传递的方式有两种理解:值传递和引用传递,但这两种说法实际上是对同一种机制的不同角度的描述。下面将详细解释这两种理解方式。 首先,我们来看值传递的理解。在Java中,当一个对象作为参数传递给方法时...

    值引用与对象引用

    在编程中,变量的引用方式分为两大类:值引用(Value Reference)和对象引用(Object Reference)。这两种引用方式决定了程序如何处理数据以及数据的存储方式。理解这些概念对于编写高效、安全的代码至关重要。 ###...

    Java 值传递Visio资源

    在Java中,参数传递有两种方式:值传递和引用传递。这个“Java 值传递Visio资源”包含了几个Visio图形文件,帮助我们直观地理解这两种传递方式。 1. **值传递**: 当方法调用时,对于基本类型(如int, double, char...

    java客户端服务器传递对象

    在Java编程中,客户端与服务器之间...总结起来,"java客户端服务器传递对象"涉及到的关键技术有Java RMI、对象序列化、网络通信,以及客户端和服务器端的编程实践。理解并熟练掌握这些技术对于构建分布式系统至关重要。

    java参数传递时到底是值传递还是引用传递[归类].pdf

    Java的参数传递方式实际上是一种特殊的"值传递",通常被称为"按引用传递对象的引用",这与C++等语言中的引用传递有所不同。以下是对这个主题的详细解释。 在Java中,所有的参数传递都是基于值的,但这涉及到一个...

    java中的值传递和引用传递[汇编].pdf

    Java编程语言中,参数传递的方式主要有两种:值传递和引用传递。然而,由于Java不支持指针,所以严格意义上的引用传递并不存在。但是,通过对象的传递,Java实现了类似引用传递的效果。 值传递是Java中基本类型的...

    java对象和对象的引用之间的关系

    Java中的参数传递有两种方式:基本类型的值传递和引用类型的引用传递。对于基本类型(如`int`),传递的是值的副本;而对于引用类型(如`StringBuffer`),传递的是引用的副本。这意味着对于引用类型的参数,如果在...

Global site tag (gtag.js) - Google Analytics