java析构函数
㈠ 谁能讲一下java的析构函数
Java没有析构函数,java是有自动的垃圾回收机制的。这一点不像c++。
其实,若果想在垃圾回收时做一点事情,可以使用finalize()函数,这是在Object类中定义的,只要重载它就可以了。
例如:protected void
finalize()
{
.............................
// add something....................
}
㈡ java语言放弃了c加加语言的资源回收机制对象必须调用析构函
题主是否想询问“java语言放弃了c加加语言的资源回收机制对象必须调用析构函数”?存在状态的变化。一旦C++的对象要被回收了,在回收该对象之前对象的析构函数将被调用,然后释放对象占用的内存;而java中一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法, 并且在下一次垃圾回收动作发生时,才会真正的回收对象占用的内存。可见在java中,调用GC不等于真正地回收内存资源,而且在垃圾回收中对象存在状态的变化。
㈢ 简述构造函数和析构函数的作用
构造函数只是起初始化值的作用,但实例化一个对象的时候,可以通过实例去传递参数,从主函数传递到其他的函数里面,这样就使其他的函数里面有值了。
析构函数与构造函数的作用相反,用于撤销对象的一些特殊任务处理,可以是释放对象分配的内存空间。
把类的声明放在main函数之前,它的作用域是全局的。这样做可以使main函数更简练一些。在main函数中定义了两个对象并且给出了初值,然后输出两个学生的数据。
当主函数结束时调用析构函数,输出stud has been destructe!。值得注意的是,真正实用的析构函数一般是不含有输出信息的。
(3)java析构函数扩展阅读:
当定义一个类的时候,通常情况下都会显示该类的构造函数,并在函数中指定初始化的工作也可省略,不过Java编译器会提供一个默认的构造函数.此默认构造函数是不带参数的。而一般的方法不存在这一特点。
构造函数有回滚的效果,构造函数抛出异常时,构造的是一个不完整对象,会回滚,将此不完整对象的成员释放(c++)。
当一个类只定义了私有的构造函数,将无法通过new关键字来创建其对象,当一个类没有定义任何构造函数,C#编译器会为其自动生成一个默认的无参的构造函数。
㈣ 为什么在Java中不使用finalize方法
Java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize()。
(1).对象不一定会被回收。
(2).垃圾回收不是析构函数。
(3).垃圾回收只与内存有关。
(4).垃圾回收和finalize()都是靠不住的,只要JVM还没有快到耗尽内存的地步,它是不会浪费时间进行垃圾回收的。
有时当撤消一个对象时,需要完成一些操作。例如,如果一个对象正在处理的是非Java 资源,如文件句柄或window 字符字体,这时你要确认在一个对象被撤消以前要保证这些资源被释放。为处理这样的状况,Java 提供了被称为收尾(finalization )的机制。使用该机制你可以定义一些特殊的操作,这些操作在一个对象将要被垃圾回收程序释放时执行。
要给一个类增加收尾(finalizer ),你只要定义finalize ( ) 方法即可。Java 回收该类的一个对象时,就会调用这个方法。在finalize ( )方法中,你要指定在一个对象被撤消前必须执行的操作。垃圾回收周期性地运行,检查对象不再被运行状态引用或间接地通过其他对象引用。就在对象被释放之前,Java 运行系统调用该对象的finalize( ) 方法。
finalize()方法的通用格式如下:
protected void finalize( )
{
// finalization code here
}
其中,关键字protected是防止在该类之外定义的代码访问finalize()标识符。该标识符和其他标识符将在第7章中解释。
理解finalize( ) 正好在垃圾回收以前被调用非常重要。例如当一个对象超出了它的作用域时,finalize( ) 并不被调用。这意味着你不可能知道何时——甚至是否——finalize( ) 被调用。因此,你的程序应该提供其他的方法来释放由对象使用的系统资源,而不能依靠finalize( ) 来完成程序的正常操作。
注意:如果你熟悉C ,那你知道C 允许你为一个类定义一个撤消函数(destructor ),它在对象正好出作用域之前被调用。Java不支持这个想法也不提供撤消函数。finalize() 方法只和撤消函数的功能接近。当你对Java 有丰富经验时,你将看到因为Java使用垃圾回收子系统,几乎没有必要使用撤消函数。
理解finalize()-析构函数的替代者
by Tim Gooch
在许多方面,Java 类似于 C++。Java 的语法非常类似于 C++,Java 有类、方法和数据成员;Java 的类有构造函数; Java 有异常处理。
但是,如果你使用过 C++ 会发现 Java 也丢掉一些可能是你熟悉的特性。这些特性之一就是析构函数。取代使用析构函数,Java 支持finalize() 方法。
在本文中,我们将描述 finalize() 与 C++ 析构函数的区别。另外,我们将创建一个简单的 Applet 来演示 finalize() 是如何工作的。
最终的界限
与 Java 不同,C++ 支持局部对象(基于栈)和全局对象(基于堆)。因为这一双重支持,C++ 也提供了自动构造和析构,这导致了对构造函数和析构函数的调用,(对于堆对象)就是内存的分配和释放。
在 Java 中,所有对象都驻留在堆内存,因此局部对象就不存在。结果,Java 的设计者觉得不需要析构函数(象 C++ 中所实现的)。
取而代之,Java 定义了一个特殊的方法叫做finalize() ,它提供了 C++ 析构函数的一些功能。但是,finalize() 并不完全与 C++ 的析构函数一样,并可以假设它会导致一系列的问题。finalize() 方法作用的一个关键元素是 Java 的垃圾回收器。
垃圾回收器
在 C/C++、Pascal和其他几种多种用途的编程语言中,开发者有责任在内存管理上发挥积极的作用。例如,如果你为一个对象或数据结构分配了内存,那么当你不再使用它时必须释放掉该内存。
在 Java 中,当你创建一个对象时,Java 虚拟机(JVM)为该对象分配内存、调用构造函数并开始跟踪你使用的对象。当你停止使用一个对象(就是说,当没有对该对象有效的引用时),JVM 通过垃圾回收器将该对象标记为释放状态。
当垃圾回收器将要释放一个对象的内存时,它调用该对象的finalize() 方法(如果该对象定义了此方法)。垃圾回收器以独立的低优先级的方式运行,只有当其他线程挂起等待该内存释放的情况出现时,它才开始运行释放对象的内存。(事实上,你可以调用System.gc() 方法强制垃圾回收器来释放这些对象的内存。)
在以上的描述中,有一些重要的事情需要注意。首先,只有当垃圾回收器释放该对象的内存时,才会执行finalize()。如果在 Applet 或应用程序退出之前垃圾回收器没有释放内存,垃圾回收器将不会调用finalize()。
其次,除非垃圾回收器认为你的 Applet 或应用程序需要额外的内存,否则它不会试图释放不再使用的对象的内存。换句话说,这是完全可能的:一个 Applet 给少量的对象分配内存,没有造成严重的内存需求,于是垃圾回收器没有释放这些对象的内存就退出了。
显然,如果你为某个对象定义了finalize() 方法,JVM 可能不会调用它,因为垃圾回收器不曾释放过那些对象的内存。调用System.gc() 也不会起作用,因为它仅仅是给 JVM 一个建议而不是命令。
结论
然而有益的是,Java 的自动垃圾回收器不会失去平衡。作为便利的代价,你不得不放弃对系统资源释放的控制。不象 C++ 中的析构函数,Java Applet 不会自动执行你的类中的finalize() 方法。事实上,如果你正在使用 Java 1.0,即使你试图强制它调用finalize() 方法,也不能确保将调用它。
因此,你不应当依靠finalize() 来执行你的 Applet 和应用程序的资源清除工作。取而代之,你应当明确的清除那些资源或创建一个try...finally 块(或类似的机制)来实现。
finalize方法是与Java编程中的垃圾回收器有关系。即:当一个对象变成一个垃圾对象的时候,如果此对象的内存被回收,那么就可以调用系统中定义的finalize方法来完成
当然,Java的内存回收可以由JVM来自动完成。如果你手动使用,则可以使用上面的方法。
举例说明:
㈤ java什么时候该写.close()释放资源
虽然Java有自动内存回收机制,但是如果是数据库连接、网络连接、文件操作等,不close是不会被回收的,属于不正确的代码。x0dx0a也就是说,有close方法,必须得自己调用一下才行。x0dx0a垃圾回收机蚂清制仅在Java虚拟机所控制的范围内释放资源。x0dx0a对于类似于数据库连接、socket以及文件操作等,x0dx0a如果有close方法,在你完成任务后执行它x0dx0a并且最好在finally块内做close,因为即使发生了例外,这些代码也能被调用。x0dx0a对于使用完了的对象来讲,Java不蚂野推荐使闷物喊用类似于C++的析构函数来释放内存(C++中new完后得delete,Java中new完,使用后,将其置x0dx0a成null比较好),因为GC会调节最适当的时间来释放内存,在程序中滥用delete会降低Java程序的性能(但应该不会引发额外的错误)。
㈥ java中什么是析构方法能不能写个例子
public class Test {
@Override
public void finalize() {
System.out.println("I'm ending.");
}
public static void main(String... args) throws Throwable {
new Test();
System.gc();
}
}
应该能看到输出的。我渗陵指测试可以。这个finalize()就是Java在彻底丛配删除一个对象前汪誉执行的方法,跟你说的析构方法应该是同一个意思。
㈦ java 类中的建构函式和解构函式名都是什么,java需要手动释放资源吗
java 类中的建构函式和解构函式名都是什么,java需要手动释放资源吗?
java中建构函式名与类名相同,java没有解构函式,java不需要手动释放资源,它是有垃圾回收机制的。
不要随便地将建构函式和解构函式的定义体放在类宣告中。
inline不inline,并不会影响建构函式的预设语义,不会因为不是inline的,就不执行基类的构造。并且分析在外的建构函式,仍然可能是inline的。如果建构函式过于复杂,那么就是写在类定义内,仍然是不会被inline的。
我认为原因是这样的:C++提倡实现与接口相分离,宣告中,只给出需要的引数,甚至只是引数型别旅扒,而没有引数名。如果你写在宣告中,不是要给出函式体,那样实现程式码大家都能看到了,也许直接去改写你的.h,然后再重新编译,以达到对private成员的直接控制,这样不利于封装。C++的设计,使得一般的具体编译器实现没镇竖都能做到,把宣告放在.h中,实现放在.cpp中,编译生成.obj,把.cpp档案删除掉(或者就是不发放给使用的使用者),使用者只要这个.obj和.h,就可以将别人实现的程式码库,并到自己的程式中用。如果建构函式是在类定义内直接给出程式码的,这就等于让使用者随便改了。它可能比别的一般函式负面效果还大。
建构函式、解构函式、虚拟函式可否内联,有何意义
在语法上没有错误首先要掌握一点,建构函式、解构函式、虚拟函式可以宣告为行内函数,这在语法上是正确的。
When the object is referenced via a pointer or a reference, a call to a virtual function cannot be inlined, since the call must be resolved dynamically. Reason: the piler can't know which actual code to call until run-time (i.e., dynamically), since the code may be from a derived class that was created after the caller was piled. Therefore the only time an inlinevirtual call can be inlined is when the piler knows the "exact class" of the object which is the target of the virtual function call. This can happen only when the piler has an actual object rather than a pointer or reference to an object. I.e., either with a local object, a global/static object, or a fully contained object inside a posite.
请问:编译器自动生成的合成解构函式做释放资源的工作吗?谢谢!
不会,如果需要释放资源就要自己写解构函式
在建构函式中开启资料库连线,JAVA没有解构函式怎么自动去关闭
子类的构造方法会预设的呼叫父类的无引数够造方法,如在student类中,在构造方法publicStudent(Stringname,intage,Stringschool){super();这是预设的语句,不用显示的呼叫this.name=name;this.age=age;this.school=school;}
java中主函式和建构函式谁先载入
当然是先主函式。
程式的入口就是主函式。
至于建构函式。。只有要用到这个类的时候 。就是new出这个类以后才会载入,
我去。后边的人为什么要说建构函式呢。。。主函式可是static的静态的呀 。。在最刚开始载入的时候就枯大载入了的!
需要一个带注释的c#程式其中最好标明建构函式,解构函式,属性等~~
namespace GXLogic
{
public class GetLogicDisposedList
{
#region 成员变数
public string PeancyTimeL; 违法时间起
public string PeancyTimeH; 违法时间迄
public string DisposeTimeL; 处理时间
public string DisposeTimeH; 处理时间
public string PlateType; 号牌种类
public string PlateNumber; 号牌号码
public string PeancyAdress; 违法地点
public string Derection; 行驶方向
public string PeancyType; 违法行为
public string DisposedPerson; 处理人(当资料为处理型别时候——处理人)
#endregion
public GetLogicDisposedList()
{
PeancyTimeL = "";
PeancyTimeH = "";
DisposeTimeL = "";
DisposeTimeH = "";
PlateType = "";
PlateNumber = "";
PeancyAdress = "";
Derection = "";
PeancyType = "";
DisposedPerson = "";
}
这就是建构函式,解构函式C#很少用.你想了解这些可以看看C++
编写类String 的建构函式、解构函式 已知类String 的原型为: class String { public: String(const char
String的解构函式
String::~String(void)
{
delete [] m_data;
由于m_data是内部资料型别,也可以写成 delete m_data;
}
String的普通建构函式
String::String(const char *str)
{
if(str==NULL)
{
m_data = new char[1]; 若能加 NULL 判断则更好
*m_data = ‘ ’;
}
else
{
int length = strlen(str);
m_data = new char[length+1]; 若能加 NULL 判断则更好
strcpy(m_data, str);
}
}
拷贝建构函式
String::String(const String &other)
{
int length = strlen(other.m_data);
m_data = new char[length+1]; 若能加 NULL 判断则更好
strcpy(m_data, other.m_data);
}
赋值函式
String & String::operate =(const String &other)
{
检查自赋值
if(this == &other)
return *this;
释放原有的记忆体资源
delete [] m_data;
分配新的记忆体资源,并复制内容
int length = strlen(other.m_data);
m_data = new char[length+1]; 若能加 NULL 判断则更好
strcpy(m_data, other.m_data);
返回本物件的引用
return *this;
}
[转载]为什么建构函式不能宣告为虚拟函式,解构函式可以
建构函式不能宣告为虚拟函式,解构函式可以宣告为虚拟函式,而且有时是必须宣告为虚拟函式。
不建议在建构函式和解构函式里面呼叫虚拟函式。
建构函式不能宣告为虚拟函式的原因是:1构造一个物件的时候,必须知道物件的实际型别,而虚拟函式行为是在执行期间确定实际型别的。而在构造一个物件时,由于物件还未构造成功。编译器无法知道物件
的实际型别,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。。。
2 虚拟函式的执行依赖于虚拟函式表。而
虚拟函式表在建构函式中进行初始化工作
,即初始化vptr,让他指向正确的虚拟函式表。而在构造物件期间,虚拟函式表还没有被初
始化,将无法进行。
编译器在呼叫基类的建构函式的时候并不知道你要构造的是一个基类的物件还是一个派生类的物件。
解构函式设为虚拟函式的作用:解释:在类的继承中,如果有基类指标指向派生类,那么用基类指标delete时,如果不定义成虚拟函式,派生类中派生的那部分无法析构。例:#include "stdafx.h"
#include "stdio.h"class A{public:A();virtual~A();};A::A(){}A::~A(){
printf("Delete class APn");}
class B : public A{public:B();~B();};B::B(){ }B::~B(){
printf("Delete class BPn");}
int main(int argc, char* argv[]){
A *b=new B;delete b;return 0;}
输出结果为:Delete class B
Delete class A
如果把A的virtual去掉:那就变成了Deleteclass A也就是说不会删除派生类里的剩余部分内容,也即不呼叫派生类的虚拟函式
因此在类的继承体系中,基类的解构函式不宣告为虚拟函式容易造成记忆体泄漏。所以如果你设计一定类可能是基类的话,必须要宣告其为虚拟函式。正如Symbian中的CBase一样。
Note:1.
如果我们定义了一个建构函式,编译器就不会再为我们生成预设构造函数了。
2. 编译器生成的解构函式是非虚的,除非是一个子类,其父类有个虚析构,此时的函式虚特性来自父类。
3. 有虚拟函式的类,几乎可以确定要有个虚解构函式。
4. 如果一个类不可能是基类就不要申明解构函式为虚拟函式,虚拟函式是要耗费空间的。5.
解构函式的异常退出会导致析构不完全,从而有记忆体泄露。最好是提供一个管理类,在管理类中提供一个方法来析构,呼叫者再根据这个方法的结果决定下一步的操作。6.
在建构函式不要呼叫虚拟函式。在基类构造的时候,虚拟函式是非虚,不会走到派生类中,既是采用的静态系结。显然的是:当我们构造一个子类的物件时,先呼叫基类的建构函式,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中呼叫虚拟函式,如果可以的话就是呼叫一个还没有被初始化的物件,那是很危险的,所以C++中是不可以在构造父类物件部分的时候呼叫子类的虚拟函式实现。但是不是说你不可以那么写程式,
你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你呼叫子类的实现,而是还是呼叫基类的实现。7.在解构函式中也不要呼叫虚拟函式。在析构的时候会首先呼叫子类的解构函式,析构掉物件中的子类部分,然后在呼叫基类的解构函式析构基类部分,如果在基类的解构函式里面呼叫虚拟函式,会导致其呼叫已经析构了的子类物件里面的函式,这是非常危险的。8.
记得在写派生类的拷贝函式时,呼叫基类的拷贝函式拷贝基类的部分,不能忘记了。
写一个复数Complex类,该类有建构函式、解构函式、 、=运算过载函式和打印函式,并在main函式中测试
#include <iostream>
using namespace std;
class Complex{
double real;
double imag;
public:
Complex(double pr=1, double pi=1){
real=pr; imag=pi;
cout <<"构造物件...
";
}
~Complex(){ cout <<"析构物件...
"; }
Complex& operator=(const Complex& c){
if(this==&c)
return *this;
real=c.real;
imag=c.imag;
return *this;
}
void display(){
cout <<real<<(imag>=0 ? "+" : "")<<imag<<"i"<<endl;
}
};
int main(){
Complex c1(3.3,-4.4),c2;
c2=c1;
c1.display();
c2.display();
return 0;
}
㈧ java中怎么没有析构函数
java中有析构函数,但我们一般用不到它贺纤散,因竖者为java有自动内存回收机制,无需程序员来释放,也就不要担心内存泄露,只不过java中析构函数所采用的方式不是C++中的那样前加~号,在java中
对象析构时会调用void finalize()方法,因此你如果禅氏确实需要析构的话就可以为你写的类添加一个void finalize(){}方法,来完成你所需要的工作
㈨ 5. 请讲一讲java析构函数和虚函数的用法和作用。
java没有析构函数和虚函数,析构函数和虚函数是c++中的。
不过,java中的抽像方法,就相当于c++中的虚函数