java关于类方法返回值是对象以及空返回的区别

返回值为void时,基本类型定义和对象类型定义的区别

在这里先给大家看一段代码

package cn.man.sqltest.controller;
import java.util.ArrayList;
import java.util.List;

public class Test {
public static void main(String[] args) {

Test test = new Test();

StringBuffer strBuf = new StringBuffer();
test.changeStr(strBuf);
System.out.println(strBuf.toString());

String str = new String();
test.changeStr1(str);
System.out.println(str);

}
private void changeStr1(String str) {
str = "abcd";
}
private void changeStr(StringBuffer strBuf) {
strBuf = strBuf.append("1234");
}


}


在这段代码中string类型的方法和StringBuffer的方法都是void无返回类型的方法,那么我们看一下他们的输出结果是什么样的呢。

在上面的输出结果中,只输出了StringBuffer参数类型,那么是什么原因导致StringBuffer无需返回参数也能改变值呢。

这里就要说到的知识点就涉及到了java的内存原理以及String的不变性。我们先就讨论java中String基本类型的不变性。在下面对String基本类型写了一段代码

String s = "ABCabc";  
System.out.println("s = " + s);  
  
s = "123456";  
System.out.println("s = " + s);

打印结果为:
s = ABCabc
s = 123456
首先创建一个String对象s,然后让s的值为“ABCabc”, 然后又让s的值为“123456”。 从打印结果可以看出,s的值确实改变了。那么怎么还说String对象是不可变的呢? 其实这里存在一个误区: s只是一个String对象的引用,并不是对象本身。对象在内存中是一块内存区,成员变量越多,这块内存区占的空间越大。引用只是一个4字节的数据,里面存放了它所指向的对象的地址,通过这个地址可以访问对象。
也就是说,s只是一个引用,它指向了一个具体的对象,当s=“123456”; 这句代码执行过之后,又创建了一个新的对象“123456”, 而引用s重新指向了这个心的对象,原来的对象“ABCabc”还在内存中存在,并没有改变。内存结构如下图所示:


Java和C++的一个不同点是, 在Java中不可能直接操作对象本身,所有的对象都由一个引用指向,必须通过这个引用才能访问对象本身,包括获取成员变量的值,改变对象的成员变量,调用对象的方法等。而在C++中存在引用,对象和指针三个东西,这三个东西都可以访问对象。其实,Java中的引用和C++中的指针在概念上是相似的,他们都是存放的对象在内存中的地址值,只是在Java中,引用丧失了部分灵活性,比如Java中的引用不能像C++中的指针那样进行加减运算。

从上面的事例中我们可以发现对于java的基本类型包括int,char等,当使用到其返回参数时候,必须要有一个返回值,缺少返回值则该方法无效。而对于StringBuffer,List这类面向于对象的定义类型时候,可以采用void返回空。采用void返回的好处是减少了java的内存消耗,在以后的项目中可能会涉及到更多的对象方法调用。

返回值为对象方法时

这种情况涉及到了java虚拟机对于内存的分配规则,同样这里我们先看一段代码,通过代码进行解读。
StringBuffer strBuf = new StringBuffer();
		test.changeStr(strBuf);
		System.out.println(strBuf.toString());

		List list = new ArrayList();
		test.changeList(list);
		System.out.println(list);
		
		List list2 = new ArrayList();
		list2 = test.changeList2(list2);
		System.out.println(list2);
	}
	private void changeList(List list) {
		list.add("a");
		list.add("b");

	}
	private List changeList2(List list2) {
		list2.add("a");
		list2.add("b");
		return list2;
	}
	private void changeStr(StringBuffer strBuf) {
		strBuf = strBuf.append("1234");
	}

代码的运行结果很出乎意料,在java程序运行当中,虽然同样是王list集合里面添加元素,但是第一个方法是void类型的空方法,第二个方法是返回型的List方法,结果都一样!java将内存划分为堆栈两部分,简单的说“堆”是用来new出新的对象的,假如你在程序中String s = “123”;这个意思就是在“堆”里创建一个内存用来存放这个对象。那么“栈”又是什么呢,可以剪短的说是java用于映射“堆”地址,学过C语言的同学可以想象“堆”是实际占有内存的空间地址,而“栈”是指向该地址的一个指针。
在上面List方法中,void类型的方法往list集合里面添加了两个元素后,实际是修改了内存中list集合的内容,所以在实际输出中可以直接用System.out.println(list)进行输出。
在list返回类型的方法中,return list的返回作用是重新在“栈”中创立了一个引用,即可以不通过原来的引用就可以访问到内存地址,就像C语言中指向同个对象有不同的指针,实际内存并没有变化。list2 = test.changeList2(list2);就刚好充当了提供不同引用访问内存的作用。在这里一定要注意到一点,java中只要是非基本类型的定义都是通过引用进行指定修改新的内存,而不是直接进行修改。

总结几点:

1、java中的基本类型是不可变的,只会在新的内存生成一个对象,旧的没有被引用的对象会被java的虚拟机在后续事件回收利用,这也是java占用内存的一个原因。
2. 对象返回时,也需要将函数处理的结果进行一次对象拷贝,不过被拷贝的返回值对象内存已经在函数调用之前已经开辟出来了,函数只需要记录它的地址即可,然后调用拷贝构造函数初始化它。










  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值