Thinking in java_2_3

第二章:一切都是对象

真的是一切都是对象?

首先得明确java中的对象存储位置:

1)  寄存器:最快的存储区,在处理器内部,暂时忽略。

2)  堆栈:速度仅次于寄存器,但是得明确规定数据的大小和生命周期,对象的引用存储于其中(java对象不存在此)。

3)  堆:java对象的存储区,无需知道数据大小,生命周期。

4)  静态存储:static来标识的对象存储区。

5)  常量存储:常量值通常直接存放在程序代码内部,他们永远不会被改变。

6)  非RAM,忽略。

StringBuffer stringBuffer=newStringBuffer(“hello, world”),见惯不惯的一个代码段。实际java的操作机制:newStringBuffer(“hello, world”)创建了一个对象,该对象被存储到堆中,其实这个对象我们看不见摸不到。为了能够操作该对象,就有了StringBuffer stringBuffer这样一个引用,这个引用存储在堆栈中,”=”将两者联系在了一起。既然stringBuffer是指向new StringBuffer(“hello,world”)这个对象的,再来个StringBuffer stringBuffer1=stringBuffer,这里其实是引用的赋值而非对象本身的赋值,同理若有stringBuffer1==stringBuffer这样一个语句,也是引用的事。以上都好理解,直到看到Bruce Eckel说:java中的任何传递对象的场合,这里的传递实际上是引用,这不是c中的形参实参的关系么。于是立马敲下代码:

packagecom.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 thechange:");

       printPersonInfo(personBeforeChangeAge);

      

       System.out.println("After thechange:");

       changeTheAge(person);

       printPersonInfo(person);

       printPersonInfo(personBeforeChangeAge);

       //这里可以认为所有的引用都指向了最初的new Person()这个对象

    }

   

    static void setPersonInfo(Personperson) {

       person.name="nerd";

       person.age=22;

    }

   

    static void printPersonInfo(Personperson) {

       System.out.println(person.name+" "+person.age);

    }

   

    static void changeTheAge(Personperson) {

       person.age++;

       printPersonInfo(person);

    }

}

运行结果:

Before the change:

nerd 22

After the change:

nerd 23

nerd 23

nerd 23

从结果上看,的确所有的引用都指向了一个对象。再试一次:

packagecom.cedric.thinkingInJava.test;

public class test {

 

    static voidnumberIncreaseByOne(String number){

       number=new String("2");

       printNumber(number);

    }

   

    static void printNumber(Stringnumber) {

       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 usedfor character storage. */

    private final char value[];

 

    /** The offset is thefirst index of the storage that is used. */

    private final int offset;

 

    /** The count is thenumber of characters in the String. */

    private final int count;

……

里面的final char value[]就可以说明一切了:首先它其实是对char的一个封装而已,char就是基本类型,此外又是final类型,final类型网上看来是存储在常量存储区的。常量存储区的数据时永远不会变的,没有像其他对象一样的引用,所以就有了虽然是对象,但是还是值传递。那么Integer,Float等就可以解释为什么也是值传递了。至于StringBuffer,它的源代码继承了AbstractStringBuffer:

abstract class AbstractStringBuilder implements Appendable,CharSequence {

    /**

     * The value isused for character storage.

     */

    char value[];

 

    /**

     * The count isthe number of characters used.

     */

    int count;

 

    /**

     * This no-arg constructor isnecessary for serialization of subclasses.

     */

    AbstractStringBuilder() {

}

这里的char并非final类型,和String的实现方法并不相同。

虽然知道了类似String这种封装类,但是里面真正的实现机制还是模糊的,下次带着这个问题去看final。

总结:了解了引用,第一次特意去了解StringBuffer stringBuffer=new StringBuffer(“hello, world”)的运行机制,知道了封转类。

第三章:控制程序流程

这章在c里面基本学过,没有太多花时间:

package com.cedric.thinkingInJava.test;

 

class Person{

    Stringname;

}

 

public classChapter3Test {

 

    public static void main(String[] args) {

      

       //等号的测试

       testEquals();

      

       //按位运算的测试(只适用于int)

       testBitwiseOperation();

      

       //floatint测试

       testFloatToInt();

    }

   

    private static void testFloatToInt() {

       int i=(int)9.8;

      

       System.out.print(i);//--舍去了小数部分

      

    }

 

    static void testEquals() {

       Integern1=newInteger(10);

       Integern2=newInteger(10);

       Personp1=newPerson();

       Personp2=newPerson();

      

       p1.name=p2.name="nerd";

      

       //因为n1n2是独立的引用,两者不相同

       System.out.println(n1==n2);//--false

      

       //java中基本的类库都实现了equals的封装,使得两者比较的是对象的内容

       System.out.println(n1.equals(n2));//--true

      

       //自己创建的类对于equals没有进行覆盖

       System.out.println(p1.equals(p2));//--false

    }

 

    static void testBitwiseOperation(){

       int i=-1;

      

       //左移几位相当于乘以几个2

       System.out.println(i<<2);//--(-4)

      

       //右移则是除以2

       System.out.println(i>>1);//--(-2)

      

       //无符号右移则是在最左边添加0

       //-2-->1111111111111110无符号转移后011111111111111

       System.out.println(i>>>1);//2147483647

    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值