Aşağıdaki gibi çalışan bir Swing eylem sınıfım var:
package org.trypticon.hex.gui.datatransfer;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorListener;
import java.awt.event.ActionEvent;
import javax.annotation.Nonnull;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.TransferHandler;
import org.trypticon.hex.gui.Resources;
import org.trypticon.hex.gui.util.FinalizeGuardian;
import org.trypticon.hex.gui.util.FocusedComponentAction;
public class PasteAction extends FocusedComponentAction {
private final FlavorListener listener = (event) -> {
// this method in the superclass calls back `shouldBeEnabled`
updateEnabled();
};
@SuppressWarnings({"UnusedDeclaration"})
private final Object finalizeGuardian = new FinalizeGuardian(() -> {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.removeFlavorListener(listener);
});
public PasteAction() {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.addFlavorListener(listener);
}
@Override
protected boolean shouldBeEnabled(@Nonnull JComponent focusOwner) {
TransferHandler transferHandler = focusOwner.getTransferHandler();
if (transferHandler == null) {
return false;
}
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
DataFlavor[] flavorsInClipboard = clipboard.getAvailableDataFlavors();
return transferHandler.canImport(focusOwner, flavorsInClipboard);
}
@Override
protected void doAction(@Nonnull JComponent focusOwner) throws Exception {
Action action = TransferHandler.getPasteAction();
action.actionPerformed(new ActionEvent(
focusOwner, ActionEvent.ACTION_PERFORMED, (String) action.getValue(Action.NAME)));
}
}
Bu FinalizeGuardian
burada belirtilen şu anda kullanılarak uygulanmaktadır finalize()
:
package org.trypticon.hex.gui.util;
public final class FinalizeGuardian {
private final Runnable cleanupLogic;
public FinalizeGuardian(Runnable cleanupLogic) {
this.cleanupLogic = cleanupLogic;
}
@Override
protected final void finalize() throws Throwable {
try {
cleanupLogic.run();
} finally {
super.finalize();
}
}
}
Bu yüzden, bariz nedenlerden dolayı, kullanmaya geçmek istiyorum Cleaner
bunun için.
İlk deneme böyle bir şeydi:
package org.trypticon.hex.gui.util;
import java.lang.ref.Cleaner;
public final class FinalizeGuardian {
private static final Cleaner cleaner = Cleaner.create();
public FinalizeGuardian(Runnable cleanupLogic) {
cleaner.register(this, cleanupLogic);
}
}
Sorun şu ki, nesne hiçbir zaman hayalete ulaşılamaz hale gelmiyor, çünkü:
Cleaner
kendisi güçlü bir referansa sahiptircleanupLogic
cleanupLogic
bir başvuru tutarlistener
dinleyiciyi kaldırmak içinlistener
çağırmak için action sınıfına bir başvuru tutarupdateEnabled
üzerine- action sınıfı aşağıdakilere bir başvuru içerir:
FinalizeGuardian
böylece erken toplanmaz.
Çünkü FinalizeGuardian
hiç hayalet erişilebilir olur kendisi, temiz hiç denecek.
Yani bilmek istediğim, bunu yapmak için gereken kurallara uyacak şekilde yeniden yapılandırmanın bir yolu var mı Cleaner
dinleyiciyi eylem sınıfımın dışına taşıyarak kapsüllemeyi kırmayı içermeyen doğru çalışma mı?