每天简单JAVA教学:JVM的内存管理,static的用法

今天的主题是介绍static和final这两个指示器的用法。但是为了说明它们两个的具体作用之前,我觉得还是有必要先说说jvm的内存管理。

关于这部分,网上已经有很多不错的文章了,比如这个:
[url]http://topic.csdn.net/u/20090602/10/bd9d4ba2-dbeb-49b3-8651-67c5de2b228a.html[/url]

官方的白皮书:
[url]https://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf
[/url]

而关于今天的主题,大家只需要关心官方版本的一句话就好,垃圾回收等内容大家可以有兴趣的就读一下:

在JVM里面,内存被划分为3个区间:Young,Old和Permanent。就是新生代,老生代及永生代。大部分的初始化都是在新生代内存进行的,然后存活时间较长的或者一部分大对象被保存到老生代。而那些便于JVM管理的不会去主动回收的对象,都保留在永生代。

而关于最后一个区间,官方的答案是一般关于类和方法的描述对象,以及类和对象本身,都会被保存到永生代里面!

所以。我们写的.java文件里面的每个class到了jvm里面就会变成一个单独的对象。这个我个人习惯叫类模版,因为它的确很像模版。然后我们要用的往往不是这个模版本身,而是基于这个模版产生的一份拷贝,也就是它的一个实例(instance)。所以,在上一个例子里面,我们需要使用new这个关键字,来在JVM的新生代生成一个Modifier对象的实例。()表示调用默认的Modifier的构造函数。构造函数往往会在创建实例的时候进行一些初始化动作,以使得每个创建的实例会代一些我们预期的初始参数。而且一个模版可以带有多个构造函数,构造函数也可以接受各种参数,例如:

[code]
package constructor;

public class ConstructorDemo {
/**
* 重载了默认不带参数的构造函数,初始化实例时会执行里面的命令
*/
public ConstructorDemo()
{
System.out.println("I'm the default constructor!");
}

/**
* 如果调用new ConstructorDemo(name)来构造实例,则控制台显示不同的内容
* @param name
*/
public ConstructorDemo(String name)
{
System.out.println("New instance with name : "+name);
}
}
[/code]

大家可以自己去用这两个构造函数来初始化实例试试有什么不同。

那么,大家就可以理解,其实class的内容,以及里面的方法,在JVM里面都有一段内存保存着其内容,但是其实并没有直接分配一段可执行的内存空间给它们。所以我们不能够直接调用没有加static的方法。而且由于自动内存管理机制,我们也很难保证同一个类模版的新实例固定在某个地址段里面。

但是static字段允许我们直接让类模版里面的某些方法或字段在直接在类模板的内存段里面划分出来。让这些static方法或者字段可以直接被外部直接访问永生代的一个固定地址来访问。因此,访问static的方法时,可以不创建某个类的实例而是直接通过类模版对象来访问:

[code]
package staticnfinal;

public class StaticDemo {
public static void main(String[] args) {
//调用static方法:
StaticDemo.staticMethod();
//调用非static方法
StaticDemo demo = new StaticDemo();
demo.notStaticMethod();
/*
* 通过实例来访问静态方法也是可以的,但是我们不推荐这种做法,
* Eclipse也会有warning
*/
demo.staticMethod();
}

public static void staticMethod()
{
System.out.println("I can be call without creating new instance");
}

public void notStaticMethod()
{
System.out.println("I must be call after creating new instance!");
}
}
[/code]

最后一个例子大家会发现通过实例也可以调用staticMethod,但是我们不推荐这种做法。

大家可能会问,加static和不加static有什么区别?什么时候应该加,什么时候不应该加?其实问题是这样的。static的方法或字段会占用永生代的内存,前面已经说过这段内存是不会主动去清空它的,所以jvm也是默认往里面放最常用的东西,如类模版对象,方法模版对象以及对它们的映射对象等。所以,如果我们要把方法或者字段定义为static,就一定要是那种会被经常访问到的东西,比如系统的全局变量啊,一些常用的工具方法等等。而不能乱用,因为用多了,应用的内存就会高居不下,因为动态内存少了,固定内存太多。

虽然每次要用方法要开个新的实例貌似更加麻烦及占内存,但是如果从长远来看,由于实例一旦没有被进一步调用就会被自动清理,所以这种方式会很省空间。而且在多线程的情况下,这种每个实例自己一个方法调用空间的做法,也会避免了一些同步问题。所以如果不是是非必要的话,大家还是少用static来生命对象为妙。

明天会介绍方法继承,重构及重载,还有final标识符。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值