JTree D&D DataFlavor 问题(在某些情况下为 NotSerializableException)
JTree D&D DataFlavor issue (NotSerializableException in some cases)
我正在为 JTree
实施 D&D。我写了一个自定义 TransferHandler
并创建了一个新的 Transferable
class。这个class很简单:
public class TreePathTransferable implements Transferable{
private static final DataFlavor[] flavors = new DataFlavor[] {
new DataFlavor(TreePath[].class,"TreePaths")};
private TreePath[] data;
public TreePathTransferable(TreePath[] data) {
super();
this.data = data;
}
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavors[0].equals(flavor);
}
public TreePath[] getTransferData(DataFlavor flavor) throws
UnsupportedFlavorException, IOException{
return data;
}
}
如果"on drop"我叫
dtde.getTransferable().getTransferData(dtde.getTransferable().getTransferDataFlavors()[0])
我得到一个 java.io.NotSerializableException
。如果我按以下方式将 TreePathTransferable
中数据对象的 class 更改为 Object
:
public class TreePathTransferable implements Transferable{
private static final DataFlavor[] flavors = new DataFlavor[] {
new DataFlavor(Object.class,"Object")};
private Object data;
public TreePathTransferable(Object data) {
super();
this.data = data;
}
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavors[0].equals(flavor);
}
public Object getTransferData(DataFlavor flavor) throws
UnsupportedFlavorException, IOException{
return data;
}
}
一切正常。这对我来说毫无意义,因为传输的数据是相同的 - TreePath[]
。为什么不同?
堆栈跟踪
注意:我已将不可序列化的 class 替换为 XXX。这是 DefaultMutableTreeNode 的子 class 的 属性。这个subclass是不可序列化的,所以这个Exception是有意义的,但是为什么第二种情况下她没有出现呢?
java.io.NotSerializableException: XXX
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at java.util.HashMap.internalWriteEntries(HashMap.java:1777)
at java.util.HashMap.writeObject(HashMap.java:1354)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1287)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.access0(ObjectOutputStream.java:162)
at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1707)
at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:482)
at java.util.Vector.writeObject(Vector.java:1077)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1278)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1278)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1278)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1278)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:83)
at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:376)
TransferHandler
public class MyTreeTransferHandler extends TransferHandler {
public MyTreeTransferHandler() {
super();
}
protected Transferable createTransferable(JComponent c) {
Transferable t = null;
if(c instanceof JTree) {
JTree tree = (JTree) c;
t = new TreePathTransferable(tree.getSelectionPaths());
return t;
}
return t;
}
public int getSourceActions(JComponent c) {
return TransferHandler.MOVE;
}
public boolean canImport(JComponent c, DataFlavor[] flavors){
return true;
}
}
你的情况是由三件事造成的:
- 您使用了 DataFlavor 构造函数,但未直接指定不序列化传输的数据。无论如何它都是间接的(参见 DataFlavor.javaJVMLocalObjectMimeType or this question)
- D&D 机制会尝试序列化传输的数据(如果可以的话)。原因是:"This insulates applications sharing DnD and Clipboard data from each other".
- D&D 机制通过检查您在 DataFlavor 构造函数中提供的 class 而不是传输对象的运行时 class 来检查它是否可以序列化数据。
根据您的堆栈跟踪,可以在 TransferableProxy source code:
中看到
public Object getTransferData(DataFlavor df)
throws UnsupportedFlavorException, IOException
{
Object data = transferable.getTransferData(df);
// If the data is a Serializable object, then create a new instance
// before returning it. This insulates applications sharing DnD and
// Clipboard data from each other.
if (data != null && isLocal && df.isFlavorSerializedObjectType()) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ClassLoaderObjectOutputStream oos =
new ClassLoaderObjectOutputStream(baos);
oos.writeObject(data);
ByteArrayInputStream bais =
new ByteArrayInputStream(baos.toByteArray());
try {
ClassLoaderObjectInputStream ois =
new ClassLoaderObjectInputStream(bais,
oos.getClassLoaderMap());
data = ois.readObject();
} catch (ClassNotFoundException cnfe) {
throw (IOException)new IOException().initCause(cnfe);
}
}
return data;
}
重要的部分是df.isFlavorSerializedObjectType()
。 This calls isRepresentationClassSerializable
方法实现为 return java.io.Serializable.class.isAssignableFrom(representationClass);
.
所以这会将您在 DataFlavor
构造函数中提供的 Class 与 Serializable
接口进行比较。由于 TreePath[].class
implements Serializable and Object 没有,因此不会为 Object
class 执行序列化(使用 new DataFlavor(Object.class,"Object")
构造函数调用)。
我正在为 JTree
实施 D&D。我写了一个自定义 TransferHandler
并创建了一个新的 Transferable
class。这个class很简单:
public class TreePathTransferable implements Transferable{
private static final DataFlavor[] flavors = new DataFlavor[] {
new DataFlavor(TreePath[].class,"TreePaths")};
private TreePath[] data;
public TreePathTransferable(TreePath[] data) {
super();
this.data = data;
}
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavors[0].equals(flavor);
}
public TreePath[] getTransferData(DataFlavor flavor) throws
UnsupportedFlavorException, IOException{
return data;
}
}
如果"on drop"我叫
dtde.getTransferable().getTransferData(dtde.getTransferable().getTransferDataFlavors()[0])
我得到一个 java.io.NotSerializableException
。如果我按以下方式将 TreePathTransferable
中数据对象的 class 更改为 Object
:
public class TreePathTransferable implements Transferable{
private static final DataFlavor[] flavors = new DataFlavor[] {
new DataFlavor(Object.class,"Object")};
private Object data;
public TreePathTransferable(Object data) {
super();
this.data = data;
}
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavors[0].equals(flavor);
}
public Object getTransferData(DataFlavor flavor) throws
UnsupportedFlavorException, IOException{
return data;
}
}
一切正常。这对我来说毫无意义,因为传输的数据是相同的 - TreePath[]
。为什么不同?
堆栈跟踪
注意:我已将不可序列化的 class 替换为 XXX。这是 DefaultMutableTreeNode 的子 class 的 属性。这个subclass是不可序列化的,所以这个Exception是有意义的,但是为什么第二种情况下她没有出现呢?
java.io.NotSerializableException: XXX
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at java.util.HashMap.internalWriteEntries(HashMap.java:1777)
at java.util.HashMap.writeObject(HashMap.java:1354)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1287)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.access0(ObjectOutputStream.java:162)
at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1707)
at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:482)
at java.util.Vector.writeObject(Vector.java:1077)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1278)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1278)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1278)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:441)
at javax.swing.tree.DefaultMutableTreeNode.writeObject(DefaultMutableTreeNode.java:1278)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1378)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:83)
at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:376)
TransferHandler
public class MyTreeTransferHandler extends TransferHandler {
public MyTreeTransferHandler() {
super();
}
protected Transferable createTransferable(JComponent c) {
Transferable t = null;
if(c instanceof JTree) {
JTree tree = (JTree) c;
t = new TreePathTransferable(tree.getSelectionPaths());
return t;
}
return t;
}
public int getSourceActions(JComponent c) {
return TransferHandler.MOVE;
}
public boolean canImport(JComponent c, DataFlavor[] flavors){
return true;
}
}
你的情况是由三件事造成的:
- 您使用了 DataFlavor 构造函数,但未直接指定不序列化传输的数据。无论如何它都是间接的(参见 DataFlavor.javaJVMLocalObjectMimeType or this question)
- D&D 机制会尝试序列化传输的数据(如果可以的话)。原因是:"This insulates applications sharing DnD and Clipboard data from each other".
- D&D 机制通过检查您在 DataFlavor 构造函数中提供的 class 而不是传输对象的运行时 class 来检查它是否可以序列化数据。
根据您的堆栈跟踪,可以在 TransferableProxy source code:
中看到public Object getTransferData(DataFlavor df)
throws UnsupportedFlavorException, IOException
{
Object data = transferable.getTransferData(df);
// If the data is a Serializable object, then create a new instance
// before returning it. This insulates applications sharing DnD and
// Clipboard data from each other.
if (data != null && isLocal && df.isFlavorSerializedObjectType()) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ClassLoaderObjectOutputStream oos =
new ClassLoaderObjectOutputStream(baos);
oos.writeObject(data);
ByteArrayInputStream bais =
new ByteArrayInputStream(baos.toByteArray());
try {
ClassLoaderObjectInputStream ois =
new ClassLoaderObjectInputStream(bais,
oos.getClassLoaderMap());
data = ois.readObject();
} catch (ClassNotFoundException cnfe) {
throw (IOException)new IOException().initCause(cnfe);
}
}
return data;
}
重要的部分是df.isFlavorSerializedObjectType()
。 This calls isRepresentationClassSerializable
方法实现为 return java.io.Serializable.class.isAssignableFrom(representationClass);
.
所以这会将您在 DataFlavor
构造函数中提供的 Class 与 Serializable
接口进行比较。由于 TreePath[].class
implements Serializable and Object 没有,因此不会为 Object
class 执行序列化(使用 new DataFlavor(Object.class,"Object")
构造函数调用)。