finalize()是由JVM自动调用的,你可以用System.gc(),但JVM不一定会立刻执行,JVM感觉内存空间有限时,才会开始执行finalize(),至于新的对象创建个数和被收集个数不同是因为收集的对象只和JVM的垃圾收集策略有关。
1.构造函数
要点:
构建器(Constructor)属于一种较特殊的方法类型,因为它没有返回值.这与 void返回值存在着明显的区别。对于void返回值,尽管方法本身不会自动返回什么,但仍然可以让它返回另一些东西。构建器则不同,它不仅什么也不会自动返回,而且根本不能有任何选择.若创建一个没有构件器的类,则编译器会自动创建一个默认构件器.
2.finalize()和gc()
(1)问题:finalize()函数是干嘛的?Java不是有Garbage Collection(以下简称gc)来负责回收内存吗?
回答:
gc 只能清除在堆上分配的内存(纯java语言的所有对象都在堆上使用new分配内存),而不能清除栈上分配的内存(当使用JNI技术时,可能会在栈上分配内存,例如java调用c程序,而该c程序使用malloc分配内存时).因此,如果某些对象被分配了栈上的内存区域,那gc就管不着了,对这样的对象进行内存回收就要靠finalize().
举个例子来说,当java 调用非java方法时(这种方法可能是c或是c++的),在非java代码内部也许调用了c的malloc()函数来分配内存,而且除非调用那个了 free() 否则不会释放内存(因为free()是c的函数),这个时候要进行释放内存的工作,gc是不起作用的,因而需要在finalize()内部的一个固有方法调用它(free()).
finalize的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存.所以如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作.
(2)问题:finalize()在什么时候被调用?
回答:
有三种情况
1.所有对象被Garbage Collection时自动调用,比如运行System.gc()的时候.
2.程序退出时为每个对象调用一次finalize方法。
3.显式的调用finalize方法
除此以外,正常情况下,当某个对象被系统收集为无用信息的时候,finalize()将被自动调用,但是jvm不保证finalize()一定被调用,也就是说,finalize()的调用是不确定的,这也就是为什么sun不提倡使用finalize()的原因.
3. this
要点:
this关键字只能在方法中使用,它能为调用该方法的对象提供相应的句柄,使得同一个类产生的不同对象实例在调用同一方法的时候,系统能判断出是哪一个对象在进行调用.
比如:
MyObject a=new MyObject();
MyObject b=new MyObject();
a.f();// (3)
b.f();// (4)
编译器在编译的时候,实际上是将(3),(4)句解释为
MyObject.f(a);
MyObject.f(b);
的,这样就将调用了该方法的对象的信息传到了方法中,也就是传给了this,就可以通过this表示调用该方法的对象实例.
用this的概念还可以解释为什么在静态方法中不能调用非静态方法和元素,这是因为静态方法中没有this,也就是说我们不能获得调用该方法的对象的句柄.既然找不到这个对象实例,我们又怎么能够在其中调用对象实例的方法和元素呢?
那为什么静态方法没有this呢?用静态方法的概念可以来理解这个问题.静态方法是类方法,是所有对象实例公用的方法.它不属于某一个具体的对象实例,因此也无法用this来体现这个实例.这和非静态方法是不一样的.打个比方,在一个局域网内的几个用户每个人都有一台客户机,但都访问一台公共的服务器.对于每台客户机来说,它的this就是使用它的用户.而对于服务器来说,它没有this,因为它是大家公用的,不针对某一个具体的客户.
4.对象初始化
要点:
1.对象只有在创建的时候,需要使用它的时候才进行初始化,否则永远都不会初始化.
2.对象进行初始化是有一定顺序的,无论在定义的时候各个成员的摆放位置如何.首先是静态成员和对象,然后是非静态成员和对象,最后才运行构造器.
3.静态成员和对象有且只有一次初始化过程,这个过程发生在第一次创建对象或者第一次使用类的静态成员和对象的时候.
以一个名为Dog的类为例,它的对象实例初始化过程如下:
(1) 类型为Dog的一个对象首次创建时,或者Dog类的static方法/static字段首次访问时,Java解释器必须找到Dog.class(在事先设好的类路径里搜索)。
(2) 找到Dog.class后,它的所有static初始化模块都会运行。因此,static初始化仅发生一次?D?D在Class对象首次载入的时候。
(3) 创建一个new Dog()时,Dog对象的构建进程首先会在内存堆(Heap)里为一个Dog对象分配足够多的存储空间。
(4) 这种存储空间会清为零,将Dog中的所有基本类型设为它们的默认值
(5) 进行字段定义时发生的所有初始化都会执行。
(6) 执行构建器。正如第6章将要讲到的那样,这实际可能要求进行相当多的操作,特别是在涉及继承的时候
5.数组的初始化
数组包括基本数据类型数组和对象数组,其中对于对象数组的初始化,经常会出现"Exception"错误.比如下面的程序
问题代码如下:
public userInfo[] getUsersInfo() {
userInfo[] usersInfo=null;
if (users.size()!=0) {
usersInfo=new userInfo[users.size()];
for(int i=0;i< usersInfo.length;i++) {
//+-------------------出问题的地方-----------------
usersInfo[i].name=((User)(users.elementAt(i))).name;
usersInfo[i].type=((User)(users.elementAt(i))).type;
usersInfo[i].userID=((User)(users.elementAt(i))).userID;
//+-------------------出问题的地方-----------------
}
System.out.println("here");
return usersInfo;
}else {
return null;
}
}
其中userInfo的定义为
class userInfo{
userInfo(String name,int type,int userID){
this.name=name;
this.type=type;
this.userID=userID;
}
String name;
int type;
int userID;
}
运行到程序中标出的问题区域时,系统显示NullPointerException,为什么会这样呢?
这是因为,Java在定义数组的时候
usersInfo=new userInfo[users.size()];
并没有给数组元素分配内存,它只是一个句柄数组,数组中的对象还没有初始化.因此数组中的每个对象都需要new之后才可以访问.例如:
A[] a=new A[2];
for(int i=0;i<2;i++)
a[i] = new A();
这样才能a[i].someMethod()
因此上面的程序应该改为
public userInfo[] getUsersInfo() {
userInfo[] usersInfo=null;
if (users.size()!=0) {
usersInfo=new userInfo[users.size()];
for(int i=0;i< usersInfo.length;i++) {
//+-------------------修改的地方-----------------
usersInfo[i]=new userInfo(((User)(users.elementAt(i))).name,
((User)(users.elementAt(i))).type,
((User)(users.elementAt(i))).userID);
}
//+-------------------修改的地方-----------------
return usersInfo;
}else {
return null;
}
}
就没问题了简单来讲,finalize()是在对象被GC回收前会调用的方法,而System.gc()强制GC开始回收工作纠正,不是强制,是建议,具体执行要看GC的意思简单地说,调用了 System.gc() 之后,java 在内存回收过程中就会调用那些要被回收的对象的 finalize() 方法。
分享到:
相关推荐
然后,我们调用了 System.gc() 方法,以便调用垃圾回收器来回收对象。 运行结果如下: ``` Cake Object 1 is created Cake Object 2 is created Cake Object 3 is created Cake Object 3 is disposed Cake Object ...
垃圾回收算法(JVM)..........63 7、垃圾回收机制和调用 System.gc()的区别? .64 8. 类加载过程90 9. 反射..........101 10. 多线程和线程池........112 11.HTTP、HTTPS、TCP/IP、Socket 通信、三次握手四次挥手...
所有对象被 Garbage Collection 时自动调用,例如运行 System.gc() 时;2. 程序退出时为每个对象调用一次 finalize 方法;3. 显式的调用 finalize 方法。 需要注意的是,finalize() 方法的调用是不确定的,JVM 不...
### JAVA中销毁一个对象的方法详解 ...对于一些特殊需求,还可以通过`finalize()`方法和`System.gc()`来辅助管理对象的生命周期。然而,在实际应用中,应当尽量避免依赖这些辅助手段,以减少潜在的问题和性能开销。
调用`System.gc()`会建议JVM执行全局的垃圾回收,包括新生代和老年代。然而,这并不意味着垃圾回收一定会立即进行,因为JVM可能有自己的垃圾回收策略。频繁使用`System.gc()`可能导致应用程序性能下降,因为它会中断...
综上所述,Java中的日期格式化、静态与非静态内部类的区别、字符和数字的判断方法以及`finalize()`与`System.gc()`的区别都是Java编程中非常重要的知识点。掌握这些内容对于编写高效、可靠的Java应用程序至关重要。
【垃圾回收机制简介】 在Java编程中,与C++或C等语言相比,开发者无需...开发者应该避免过度依赖`finalize()`和`System.gc()`,而是充分利用Java的内存管理机制,同时关注JVM参数的优化,以提升应用程序的整体性能。
`System.gc()`仅是请求垃圾回收,不一定会触发`finalize()`,且频繁调用可能导致性能下降。 理解并优化Java的垃圾回收机制对于开发高性能、稳定的应用至关重要。开发者应当避免不必要的内存消耗,合理控制对象生命...
4. 考虑使用`System.gc()`谨慎地触发垃圾回收,但这应被视为最后手段,因为过度使用可能导致性能下降。 5. 了解并使用JVM提供的各种垃圾收集器,如Serial、Parallel、Concurrent Mark Sweep (CMS) 和 Garbage-First ...
本文总结了 Java 程序员面试题中的一些重要知识点,涵盖了异常处理机制、垃圾回收、Error 和 Exception 的区别、final、finally 和 finalize 的区别、 Anonymous Inner Class、Static Nested Class 和 Inner Class ...
- `System.gc()`:触发垃圾收集,虽然不推荐直接使用,但在某些场景下可能需要手动调用。 - `System.runFinalization()`:运行所有已注册的终结器(finalize方法)。 - `System.exit()`:结束JVM,传入的参数决定...
2. finalize机制可能会导致性能问题、死锁和线程挂起。 3. finalize中的错误可能导致内存泄漏。 4. 如果不在需要时,也没有办法取消垃圾回收。 5. 并且没有办法保证finlize的执行时间。 在JDK9中,finalize()方法...
当对象不再被任何引用(活动部分)指向时,GC会判断其为无用,并在适当的时候调用对象的`finalize()`方法(如果定义了该方法)进行清理工作,随后回收内存。然而,垃圾收集器何时运行是不确定的,且无法被强制执行,...
尽管可以调用`System.gc()`来请求垃圾回收,但这只是一个建议,JVM并不保证立即执行,而是根据自身策略和当前系统状态来决定。因此,开发者无法精确预测垃圾回收的时间点。 Java垃圾回收机制允许对象在被回收前执行...
本文将对Java中的异常处理机制、垃圾回收机制、Error与Exception的区别、final、finally、finalize的区别、Anonymous Inner Class、static Nested Class与Inner Class的区别、HashMap与Hashtable的区别、断言、垃圾...
然而,程序员不能直接控制垃圾回收的时间,只能通过System.gc()建议执行,但并不保证立即生效。 在Java中,录入和输出信息是常见的任务。例如,可以使用Scanner类来读取用户输入,如: ```java Scanner scanner = ...
* 可以通过 System.gc() 或 Runtime.getRuntime().gc() 请求垃圾收集。 7. String 对象的创建: * new String("xyz") 创建两个对象,一个是“xyz”,一个是指向“xyz”的引用对象 s。 8. Math.round() 的使用: ...
//为false时肯定是GC调用了对象的Finalize方法,所以没有必要再告诉GC你不要调用我的Finalize方法啦 if (disposing) { GC.SuppressFinalize(this); } } } static void Main(string[] args) { //tmpObj1...
`System.gc()`是一个建议JVM执行垃圾回收的方法,但它的调用并不保证立即执行垃圾回收。垃圾回收的具体动作取决于JVM的实现和当前的系统状态。 Java提供了`finalize()`方法,这是一个在对象即将被垃圾回收时自动...
System.gc(); // 强制执行垃圾回收 System.out.println(phantom.get()); // null FinalReference 是一个特殊的引用类型,它主要用于管理对象的 finalize() 方法的执行。FinalReference 保存对被 finalize() 方法...