java,一切都是对象?
?
真的是一切都是对象?
首先得明确java中的对象存储位置:
StringBuffer stringBuffer=new StringBuffer(“hello, world”),见惯不惯的一个代码段。实际java的操作机制:new StringBuffer(“hello, world”)创建了一个对象,该对象被存储到堆中,其实这个对象我们看不见摸不到。为了能够操作该对象,就有了StringBuffer stringBuffer这样一个引用,这个引用存储在堆栈中,”=”将两者联系在了一起。既然stringBuffer是指向newStringBuffer(“hello,world”)这个对象的,再来个StringBuffer stringBuffer1=stringBuffer,这里其实是引用的赋值而非对象本身的赋值,同理若有stringBuffer1==stringBuffer这样一个语句,也是引用的事。以上都好理解,直到看到Bruce Eckel说:java中的任何传递对象的场合,这里的传递实际上是引用,这不是c中的形参实参的关系么。于是立马敲下代码:
?
package com.cedric.thinkingInJava.test;class Person{String name;int age;}public class ReferenceAndArgs {public static void main(String[] args) {Person person=new Person();Person personBeforeChangeAge;setPersonInfo(person);personBeforeChangeAge=person;System.out.println("Before the change:");printPersonInfo(personBeforeChangeAge);System.out.println("After the change:");changeTheAge(person);printPersonInfo(person);printPersonInfo(personBeforeChangeAge);//这里可以认为所有的引用都指向了最初的new Person()这个对象}static void setPersonInfo(Person person) {person.name="nerd";person.age=22;}static void printPersonInfo(Person person) {System.out.println(person.name+" "+person.age);}static void changeTheAge(Person person) {person.age++;printPersonInfo(person);}}
运行结果:
Before the change:
nerd 22
After the change:
nerd 23
nerd 23
nerd 23
从结果上看,的确所有的引用都指向了一个对象。再试一次:
package com.cedric.thinkingInJava.test;public class test {static void numberIncreaseByOne(String number){number=new String("2");printNumber(number);}static void printNumber(String number) {System.out.println(number);}public static void main(String[] args) {String integer=new String("1");numberIncreaseByOne(integer);printNumber(integer); }}
结果是
? ? 2
? ? 1
问题出现:String是个对象,那定义的integer和number应该指向同一个对象才对,实际并非如此,它是值传递。这里就回到了最开始的问题:真的是一切都是对象?其实在java里有基本变量,也就是常见的intchar,long ,float,double等,他们不用new来创建,他们的值存储在堆栈中,这样可以更高效的运行,说白了他们不是对象。既然不是对象,他们在函数的参数传递时就是值的传递,和c中的实参传递一样。再来看String,google后知道它是封装类,看看它的源码:
?
public final class String implements java.io.Serializable, Comparable<String>, CharSequence{ /** The value is used for character storage. */ private final char value[]; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count;……
?里面的finalchar value[]就可以说明一切了:首先它其实是对char的一个封装而已,char就是基本类型,此外又是final类型,final类型网上看来是存储在常量存储区的。常量存储区的数据时永远不会变的,没有像其他对象一样的引用,所以就有了虽然是对象,但是还是值传递。那么Integer,Float等就可以解释为什么也是值传递了。至于StringBuffer,它的源代码继承了AbstractStringBuffer:
?
abstract class AbstractStringBuilder implements Appendable, CharSequence { /** * The value is used for character storage. */ char value[]; /** * The count is the number of characters used. */ int count; /** * This no-arg constructor is necessary for serialization of subclasses. */ AbstractStringBuilder() {}
?这里的char并非final类型,和String的实现方法并不相同。
虽然知道了类似String这种封装类,但是里面真正的实现机制还是模糊的,下次带着这个问题去看final。