Thinking in java,必须由你创建所有对象!!

一旦创建了一个引用,就希望它能与一个新的对象相关联。通常用new操作符来实现,new关键字的意思是“给我一个新对象”

String s=new String("asdf")

它不仅表示“给我一个新的字符串”,而且通过提供一个初始字符串,给出了怎样产生这个String的信息。

存储到什么地方

程序运行时,对象时怎么放置安排的?特别时内存是怎样分配的?有五个不同的地方可以存储数据

  1. 寄存器:这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部。但是寄存器的数量是极其有限的,所以寄存器根据需求进行分配。你不能直接控制,也不能再程序中感受到寄存器存在的任何迹象
  2. 堆栈:位于通用RAM(随机访问存储器)中,但通过堆栈指针可以从处理器那里获得直接支持。堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建程序时,java系统必须知道存储再堆栈内所有项的确切生命周期,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些java数据存储于堆栈中——特别是对象引用,但是Java对象并不存储于其中。存的是局部变量,引用,方法的调用关系(调用关系)
  3. 。一种通用的内存池(也位于RAM区),用于存放所有java对象,堆不同于堆栈的好处是:编译器不需要知道存储的数据在堆中存活多长时间。因此,在堆里分配存储有很大的灵活性。当需要一个对象时,只需要用new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。当然,为这种灵活性必须要付出相应的代价:用堆进行存储分配和清理可能比用堆栈进行存储分配需要更多的时间**(new出来的东西都在堆里)**
  4. 常量存储:常量值通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变。有时候,在嵌入式系统中,常量本身会和其他部分分隔离开,所以在这种情况下,可以选择将其存放在ROM(只读存储器)种。
  5. 非RAM存储器:如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。其中两个基本的例子就是流对象和持久化对象。在流对象种,对象转化成字节流,通常被发送给另一台机器。在“持久化对象中”,对象被存放于磁盘上,因此,即使程序终止,它们仍可以保持自己的状态
    Heap对于一个JVM来说,只有一份。
    JVM stack 可能有多少份,每个thread(线程(汤的小99))有一份。

static关键字

通常来说,当创建类时,就是在描述哪个类的对象的外观与行为。除非用new创建那个类的对象,否则,实际上并未获得任何对象。执行new来创建对象时,数据存储空间才被分配,其方法才供外界调用。
有两种情形用上述方法时无法解决的。一种情形时,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建任何对象。另一种情形是,希望某个方法不与包含它的类的任何对象关联在一起。也就是说,即使没有创建对象,也能够调用这个方法
通过static关键字可以满足这两方面的需要。**当声明一个事物是static时,就意味这个域或方法不会与包含它的那个类的任何对象实例关联在一起。**所以,即使从未创建某个类的任何对象,也可以调用其static方法或访问其static域。通常,你必须创建一个对象,并用它来访问数据或方法。因为非static域和方法必须知道它们一起运作的特定对象。
只须将static关键字放在定义之前,就可以将字段或方法设定为static。
例如,下面代码,生成了一个static字段,并对其进行了初始化

Class StaticTest{
    static int i=47;
}

现在,即使你创建了两个StaticTest对象,Static.Test.i也只有一份存储空间,这两个对象共享一个i,看看下面代码

StaticTest str1=new StaticTest();
StaticTest str2=new StaticTest();

这里 str1.i和str2.i指向同一存储空间。因此具有相同的值,47
引用static变量有两种方法。如前例所示,可以通过一个对象去定位它,如st2.i;也可以通过其类名直接引用。

StaticTest.i++;

其中,++运算符对变量进行递加操作,此时,str1.i和str2.i仍具有相同的值48.

class StaticTest {
    static int i=47;
}
public class Static {

    public static void main(String[] args) {
        StaticTest str1=new StaticTest();
        StaticTest str2=new StaticTest();
        System.out.println("str1.i="+str1.i+"\t"+"str2.i="+str2.i);
    }
}

在这里插入图片描述

        StaticTest str1=new StaticTest();
        StaticTest str2=new StaticTest();
        StaticTest.i++;
        System.out.println("str1.i="+str1.i+"\t"+"str2.i="+str2.i);

在这里插入图片描述
尽管当static作用于某个字段时,肯定会改变数据创建的方式(因为一个static字段对每个类来说都只有一份存储空间,而非static字段则是对每个对象都有一个存储空间),但是如果static作用于某个方法,差别却没有那么大,static方法的一个重要用法就是在不创建任何对象的前提下就可以调用它。正如我们将会看到的那样,这一点对定义main()方法很重要,这个方法时运行一个应用时的入口点。
和其他方法一样,static方法可以创建或使用与其类型相同的被命名对象,因此,static方法常常拿来做“牧羊人”的角色,负责看护与其隶属同一类型的实例群。

java中的数组

几乎所有的程序设计语言都支持数组。在c和c++使用数组是很危险的,因为C和C++中的数组就是内存块。如果一个程序要访问其自身内存块之外的数组,或在数组初始化前使用数组内存,都会产生难以预料的后果。
java确保数组会被初始化,而且不能再它的范围之外被访问。这种范围检查,时以每个数组上少量的内存开销及运行时的下标检查为代价的。但由此换来的时安全性和效率的提高。
当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值拥有自己的关键字null,一旦java看到null,就知道这个引用还没有指向某个对象,如果试图使用一个还是null的引用,再运行时将会报错。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值