对象生命周期:如何创建对象和销毁对象(Visual Basic.Net)

     使用 New 关键字创建类的实例(即对象)。 通常,初始化任务必须在使用之前在新对象上执行。 常见的初始化任务包括打开文件、连接到数据库以及读取注册表项的值等等。Visual Basic通过构造函数(允许超初始化的特殊方法)来控制新对象的初始化。

对象离开作用域之后,由公共语言运行时 (CLR) 进行释放。 Visual Basic 通过析构函数来控制使用程序调用的系统资源的释放。 同时,构造函数和析构函数支持多个、可预测的类库的创建。

使用构造函数和析构函数

构造函数和析构函数控制对象的创建和析构。 Sub NewSub Finalize在 Visual Basic 中的过程初始化和销毁对象,它们替换了Visual Basic 6.0 和早期版本中使用的Class_InitializeClass_Terminate方法。

Sub New

创建类时,Sub New 构造函数仅可运行一次。 调用此函数的位置只能是相同类或派生类的另一个构造函数的代码的第一行。 此外,Sub New 方法中的代码始终在类中任何其他代码之前运行。如果不显式定义的构造函数Sub New类的过程,那么 Visual Basic 2005 和更高版本会在程序运行时隐式创建Sub New

若要创建类的构造函数,请在类定义中的任何位置创建一个名为 Sub New 的过程。 若要创建参数化构造函数,请按指定任何其他过程的参数的方式,将参数名称和数据类型指定为 Sub New,如下面代码所示:

Sub New(ByVal s As String)

构造函数常常重载,如下面代码所示:

Sub New(ByVal s As String, i As Integer)

当定义一个从另一个类派生的类时,构造函数的首行必须是对基类的构造函数的调用,除非此基类具有一个无参数且可访问的构造函数。 例如,对包含以上构造函数的基类的调用将为 MyBase.New(s)。 否则 Visual Basic 运行时将隐式调用可选的MyBase.New

当你编写了用于调用父对象构造函数的代码之后,你可以将任何附加初始化代码添加到 Sub New 过程当中。 Sub New在作为参数化构造函数调用时可接受参数。 这些参数是从调用构造函数的过程(例如,Dim AnObject As New ThisClass(X))中传递的。

Sub Finalize

释放对象之前,CLR 为定义 Finalize 过程的对象自动调用 Sub Finalize 方法。 Finalize 方法可包含恰在销毁对象之前需执行的代码,如关闭文件并保存状态消息的代码。 执行 Sub Finalize 会导致性能略微下降,所以只需要强制释放对象的时候才定义 Sub Finalize 方法。

CLR中的垃圾收集器不(也不能)处理非托管对象,即操作系统在CLR环境之外直接执行的对象。这是因为不同的非托管对象必须以不同的方式处理。该信息与非托管对象没有直接关联;必须在使用的对象的相关文档中找到它(比如操作Excel文件,连接其他进程等)。使用非托管对象的类必须在其Finalize方法中处理它们。

Finalize 析构函数是一种仅可从其所属的类或派生类中调用的受保护方法。 系统在对象被销毁时自动调用 Finalize,所以你不应从派生类的 Finalize 实现的外部主动调用 Finalize


不像Class_Terminate,它在对象被设置为空时执行,通常在对象丢失作用域和Visual Basic调用Finalize析构函数之间存在延迟。Visual Basic 2005和后来的版本允许进行第二种析构函数处理,可以在任何时候显式地调用它,以立即释放资源。

Finalize 析构函数不应该抛出异常,因为它们不能由当前应用程序处理,并且可能会导致应用程序终止。

New 和 Finalize 方法如何在类层级中工作

每当创建类的实例时,公共语言运行时 (CLR) 都会尝试执行名为 New 的过程(如果存在于此对象)。 New是一种调用 constructor 的过程,此过程用于在执行对象中任何其他代码之前初始化新对象。

创建派生类的实例时,首先执行基类的 Sub New 构造函数,再执行派生类中的构造函数。 之所以发生此情况,原因在于 Sub New 构造函数中代码的首行使用语法 MyBase.New() 调用类层级中直接位于其上方的类的构造函数。 Sub New构造函数然后调用类层次结构中每个类构造函数之前达到的基类。 此时,先执行基类的构造函数中的代码,再执行所有的派生类中每个构造函数内的代码,最后执行大多数派生类中的代码。



一个对象不再被需要时,CRL 在释放其内存前为该对象调用 Finalize方法。 Finalize方法被称为 destructor,因为它执行清理任务(如保存状态信息、关闭文件、连接到数据库)以及必须在释放对象前完成的其他任务。


IDisposable 接口

类实例经常控制不由 CLR 托管的资源,如窗口句柄和数据库连接。 这些资源必须在类的 Finalize 方法中释放,使其在垃圾回收器销毁对象时释放。 但是,垃圾回收器仅在 CLR 需要更多可用内存时才销毁对象。 这意味着资源可能在对象超出作用域之后很久才释放。

为补充垃圾回收,你的类可以在系统资源实现 IDisposable 接口时提供对其进行有效管理的机制。 IDisposable 具有一种客户端使用对象完成时应调用的方法 Dispose 你可以使用 Dispose 方法立即释放资源和执行关闭文件和数据库连接等任务。 与 Finalize 析构函数不同,Dispose 方法不能自动调用。 要立即释放资源时,类的客户端必须主动调用 Dispose


实现 IDisposable

实现 IDisposable 接口的类应该包含代码的以下部分:

  • 用于跟踪对象是否已释放的字段:

Protected disposed As Boolean = False  

可释放类资源的 Dispose 的重载。 应通过基类的 Dispose 和 Finalize 方法调用此方法:

Protected Overridable Sub Dispose(ByVal disposing As Boolean)  
    If Not Me.disposed Then  
        If disposing Then  
            ' Insert code to free managed resources.  
        End If  
        ' Insert code to free unmanaged resources.  
    End If  
    Me.disposed = True  
End Sub  
  •  仅包含以下代码的Dispose方法的实现
Public Sub Dispose() Implements IDisposable.Dispose  
    Dispose(True)  
    GC.SuppressFinalize(Me)  
End Sub  
  • 仅包含以下代码的 Finalize 方法的重写:
Protected Overrides Sub Finalize()  
    Dispose(False)  
    MyBase.Finalize()  
End Sub

派生类实现 IDisposable 的类

从实现 IDisposable 接口的基类派生出的类无需重写任何基方法,除非它使用需要释放的附加资源。 在这种情况下,派生类应重写基类的 Dispose(disposing) 方法以释放派生类的资源。 因此重写必须调用基类的 Dispose(disposing) 方法。

Protected Overrides Sub Dispose(ByVal disposing As Boolean)  
    If Not Me.disposed Then  
        If disposing Then  
            ' Insert code to free managed resources.  
        End If  
        ' Insert code to free unmanaged resources.  
    End If  
    MyBase.Dispose(disposing)  
End Sub

派生类不应该重写基类的 Dispose 和 Finalize 方法。 从派生类的实例中调用这些方法时,这些方法的基类的实现将调用派生类的重写Dispose(disposing) 方法。

垃圾回收和 Finalize 析构函数

.NET Framework使用参数跟踪垃圾回收 系统定期释放未使用的资源。 Visual Basic 6.0 和早期版本使用不同的系统调用参数计数  来管理资源。 尽管两个系统自动执行同一功能,但还是有一些重要的区别。

当系统确定不再需要这些对象时,CLR 将定期对其进行销毁。 系统资源短缺时对象释放得更快,而非短缺时释放频率更低。 对象失去作用域到 CLR 释放它之间会出现延迟(这跟 Visual Basic 6.0 及更低版本不同) , 这意味着你无法确定销毁对象的确切时间。 在这种情况下,对象被认为具有非确定性生存周期。 在大多数情况下,非确定性生存周期不会更改你编写应用程序的方式,只要你记住Finalize 析构函数可能不会在对象失去作用域时立即执行。

垃圾回收系统间的另一个区别涉及到 Nothing 的使用。 为了在 Visual Basic 6.0 及更低版本中利用引用参数的计数,程序员有时将 Nothing 分配到对象变量以释放这些变量持有的引用。 如果变量持有对对象的最后引用,则会立即释放该对象的资源。 在 Visual Basic Net 的更高版本中,虽然可能存在此过程仍有用的情况,但执行此过程不会使引用的对象立即释放其资源。 若要立即释放资源,请使用对象的 Dispose 方法(如果可用)。 只有当变量的生存期相对于垃圾回收器用于检测孤立对象的时间来说很长时,你才应该将变量设置为 Nothing



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java对象生命周期是指对象从创建到销毁的整个过程。对象生命周期包括以下几个阶段: 1. 创建阶段:通过关键字`new`创建对象,并分配内存空间。在这个阶段,对象的实例变量被赋予默认值,构造方法被调用,对象的状态被初始化。 2. 使用阶段:在对象创建后,可以通过调用对象的方法来使用它。在这个阶段,对象可以执行各种操作,处理数据等。 3. 引用阶段:对象可以被其他变量引用,以便在代码持续使用。对象可以被多个变量引用,或者作为方法的参数传递给其他方法。 4. 终止阶段:当对象不再被引用时,垃圾回收器会自动回收对象所占用的内存空间。在这个阶段,垃圾回收器会调用对象的`finalize()`方法来清理资源和执行一些必要的操作。 类生命周期对象生命周期有一些不同之处。类生命周期是指类从加载到卸载的整个过程。类生命周期包括以下几个阶段: 1. 加载阶段:当程序需要使用某个类时,Java虚拟机会根据类的全限定名(Fully Qualified Name)来查找并加载对应的类文件。在加载阶段,Java虚拟机会执行一些必要的验证和准备工作。 2. 连接阶段:连接阶段分为验证、准备和解析三个步骤。验证阶段用于确保类文件的字节流符合Java虚拟机规范,准备阶段用于为类的静态变量分配内存并给其赋予初始值,解析阶段用于将符号引用转换为直接引用。 3. 初始化阶段:在初始化阶段,类的静态变量会被赋予程序指定的值,静态代码块会被执行。如果类的初始化涉及到其他类,那么这些类也会被先进行初始化。 4. 使用阶段:在类初始化完成后,可以通过类名来访问类的静态成员,并可以创建该类的对象进行实例操作。 5. 卸载阶段:当类不再被使用时,Java虚拟机会卸载该类,并释放相关的资源。 总结起来,对象生命周期是指对象从创建到销毁的过程,而类生命周期是指类从加载到卸载的过程。对象与类的生命周期密切相关,对象的创建需要依赖类的加载和初始化,而对象销毁可能触发类的卸载。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值