исправленный код ниже
abstract class Employee {
public abstract void names();
public abstract void offices();
}
class Banani extends Employee {
@Override
public void names() {
System.out.println("I am at Banani.");
}
@Override
public void offices() {
// TODO Auto-generated method stub
}
}
class Shyamoli extends Employee {
@Override
public void names() {
System.out.println("I am at Shyamoli");
}
@Override
public void offices() {
// TODO Auto-generated method stub
}
}
public class javatest {
public static void main(String[] args) {
Employee south = new Banani();
Employee north = new Shyamoli();
north.names();
south.names();
}
}
Я всегда использую этот шаблон проектирования для реализации интерфейса IDisposable. (что предлагает Microsoft), и для меня GC.SuppressFinalize всегда имеет гарантию!
using System;
using System.ComponentModel;
//The following example demonstrates how to use the GC.SuppressFinalize method in a resource class to prevent the clean-up code for the object from being called twice.
public class DisposeExample
{
// A class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class MyResource : IDisposable
{
// Pointer to an external unmanaged resource.
private IntPtr handle;
// Other managed resource this class uses.
private readonly Component component = new Component();
// Track whether Dispose has been called.
private bool disposed;
// The class constructor.
public MyResource(IntPtr handle)
{
this.handle = handle;
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
private void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose managed resources.
component.Dispose();
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
CloseHandle(handle);
handle = IntPtr.Zero;
}
disposed = true;
}
// Use interop to call the method necessary
// to clean up the unmanaged resource.
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
}
public static void Main()
{
// Insert code here to create
// and use a MyResource object.
}
}
Источник: MSDN: метод GC.SuppressFinalize
Одна странность, которую вы можете заметить , заключается в том, что финализатор все еще может работать, даже когда метод экземпляра все еще работает, если этот метод экземпляра не работает используйте любые переменные позже. Итак, в вашем примере кода метод Dispose
не использует никаких переменных экземпляра после первой строки. Затем экземпляр может быть завершен, даже если Dispose
все еще выполняется.
Если вы вставите вызов GC.KeepAlive (this)
в конце Dispose
метод, вы можете найти проблема исчезнет.
Я много раз использовал один и тот же шаблон, и GC.SupressFinalize всегда работал.
Имейте в виду, что вызов GC.ReRegisterForFinalize приведет к повторной регистрации объектов для завершения.
Всякий раз, когда я использую описанную выше технику, я всегда гарантирую, что при построении объекта включаю полную трассировку стека, чтобы можно было отследить метод, который выделил неразмещенный объект. [+1266] Например. в конструкторе используйте
StackFrame frame = new StackFrame(1);
и сообщите об этом в вашем отладочном сообщении во время финализатора.
Также я заметил, что ваш GC.SupressFinalize не входит в предложение finally; если во время удаления выбрасывается исключение, ваш финализатор объектов не будет подавлено.
Я бросаю InvalidOperationException в финализатор, что упрощает поиск типов, которые не были удалены должным образом. Когда вызывается Dispose (), где вызывается GC.SuppressFinalize, я никогда не получаю исключения.
Когда создается объект с определяемым пользователем финализатором, среда выполнения должна сохранять внутреннюю ссылку на него, чтобы, когда он становится недоступным в пользовательском коде, финализатор все еще может быть вызван в поток финализации среды выполнения. Учитывая, что время имеет существенное значение при вызове финализаторов, нет смысла держать объекты в очереди, если пользователь запросил их подавление. В моей тестовой реализации CLI я сохраняю флаг SuppressFinalizer в заголовках объектов, которые имеют определенные пользователем финализаторы. Если флаг истинен, когда поток финализатора достигает этого объекта в очереди, вызов финализатора пропускается. Я не удаляю объект из очереди, поэтому могу оставить вызов GC.SuppressFinalize ()
O (1) вместо O ( N ),