我有一个包含类似结构的静态嵌套类的父类。嵌套类必须是公共的,因为它应该返回到其内容被执行的其他类。但是,只有父类及其子类应该能够实例化嵌套类,因为它们知道如何定义其内容。下面显示的所有类都在不同的包中。
public abstract class Parent
{
public static class Data
{
public final String data1
...
public Data(String d1, ...)
{
data1 = d1;
...
}
}
public abstract Data getData();
}
public final class Subclass extends Parent
{
@Override
public Data getData()
{
return new Data(.....);
}
}
public class SomeOtherClass
{
public void someMethod()
{
final Data d = new Subclass().getData();
System.out.println(d.data1);
}
}
声明Data
班protected
会阻止getData()
正常工作。减少Data
构造函数上的访问修饰符会阻止Parent
的子类正常工作。我想要的是像protected-by-parent
这样的东西,我猜它在Java中不存在。
是否有合适的解决方法?我可以看到的一种可能性是在protected
中创建Parent
方法,该方法可以有效地镜像,调用和返回Data
的构造函数(将生成private
)。然而这似乎有点凌乱;有人知道更好的方式/设计吗?
答案 0 :(得分:2)
更好的解决方案是创建嵌套类protected
,并使其实现public
接口。只有接口才会暴露给外部类,嵌套类本身仍将是一个实现细节。
public abstract class Parent
{
public interface Data {
public String getData1();
}
protected static class DataImpl implements Data
{
private final String data1;
...
protected DataImpl(String d1, ...)
{
data1 = d1;
...
}
public String getData1(){
return data1;
}
}
public abstract Data getData();
}
public final class Subclass extends Parent
{
@Override
public Data getData()
{
return new DataImpl(.....);
}
}
public class SomeOtherClass
{
public void someMethod()
{
final Data d = new Subclass().getData();
System.out.println(d.getData1());
}
}
答案 1 :(得分:1)
您不能为外部类的子类创建静态成员类import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.ActionEvent;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.tree.*;
public class JTreeTransferHandler2 extends JFrame {
public JTreeTransferHandler2() {
initiate();
}
private void initiate() {
setTitle("Copy from JTree");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,400);
setLocation(200,200);
setVisible(true);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
vegetableNode.add(new DefaultMutableTreeNode("Capsicum"));
vegetableNode.add(new DefaultMutableTreeNode("Carrot"));
DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
fruitNode.add(new DefaultMutableTreeNode("Mango"));
fruitNode.add(new DefaultMutableTreeNode("Apple"));
root.add(vegetableNode);
root.add(fruitNode);
JTree tree = new JTree(root);
TreeTransferHandler treeTransferHandler = new TreeTransferHandler();
tree.setTransferHandler(treeTransferHandler);
Clipboard clipboard = this.getToolkit().getSystemClipboard();
JButton copy = new JButton("Copy");
copy.addActionListener((ActionEvent e) -> {
TransferHandler handler = tree.getTransferHandler();
handler.exportToClipboard(tree, clipboard, TransferHandler.COPY);
});
JButton paste = new JButton("Paste");
paste.addActionListener((ActionEvent e) -> {
Transferable clipData = clipboard.getContents(null);
if (clipData != null) {
if (clipData.isDataFlavorSupported(treeTransferHandler.nodesFlavor)) {
TransferHandler handler = tree.getTransferHandler();
handler.importData(tree, clipData);
}
}
});
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(copy);
buttonsPanel.add(paste);
add(new JScrollPane(tree), BorderLayout.CENTER);
add(buttonsPanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JTreeTransferHandler2 jTreeTransferHandler = new JTreeTransferHandler2();
});
}
}
class TreeTransferHandler extends TransferHandler {
DataFlavor nodesFlavor;
DataFlavor[] flavors = new DataFlavor[1];
DefaultMutableTreeNode[] nodesToRemove;
public TreeTransferHandler() {
try {
String mimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" +
DefaultMutableTreeNode[].class.getName() + "\"";
nodesFlavor = new DataFlavor(mimeType);
flavors[0] = nodesFlavor;
} catch(ClassNotFoundException e) {
System.out.println("ClassNotFound: " + e.getMessage());
}
}
//TransferHandler
@Override public int getSourceActions(JComponent c) {
return TransferHandler.COPY;
}
//TransferHandler
@Override public boolean canImport(JComponent comp, DataFlavor flavor[]) {
for (int i = 0, n = flavor.length; i < n; i++) {
for (int j = 0, m = flavors.length; j < m; j++) {
if (flavor[i].equals(flavors[j])) {
return true;
}
}
}
return false;
}
//TransferHandler
@Override protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree) c;
TreePath[] paths = tree.getSelectionPaths();
if (paths != null) {
List<DefaultMutableTreeNode> copies = new ArrayList<>();
List<DefaultMutableTreeNode> toRemove = new ArrayList<>();
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) paths[0].getLastPathComponent();
DefaultMutableTreeNode copy = copy(node);
copies.add(copy);
toRemove.add(node);
for (int i = 1; i < paths.length; i++) {
DefaultMutableTreeNode next =
(DefaultMutableTreeNode) paths[i].getLastPathComponent();
// Do not allow higher level nodes to be added to list.
if (next.getLevel() < node.getLevel()) {
break;
} else if (next.getLevel() > node.getLevel()) { // child node
copy.add(copy(next));
// node already contains child
} else { // sibling
copies.add(copy(next));
toRemove.add(next);
}
}
DefaultMutableTreeNode[] nodes =
copies.toArray(new DefaultMutableTreeNode[copies.size()]);
nodesToRemove =
toRemove.toArray(new DefaultMutableTreeNode[toRemove.size()]);
return new NodesTransferable(nodes);
}
return null;
}
/** Defensive copy used in createTransferable. */
private DefaultMutableTreeNode copy(TreeNode node) {
return new DefaultMutableTreeNode(node);
}
//TransferHandler
@Override public boolean importData(TransferHandler.TransferSupport support) {
if (!canImport(support)) {
return false;
}
// Extract transfer data.
DefaultMutableTreeNode[] nodes = null;
try {
Transferable t = support.getTransferable();
nodes = (DefaultMutableTreeNode[]) t.getTransferData(nodesFlavor);
} catch (UnsupportedFlavorException ufe) {
System.out.println("UnsupportedFlavor: " + ufe.getMessage());
} catch (java.io.IOException ioe) {
System.out.println("I/O error: " + ioe.getMessage());
}
// Get drop location info.
int childIndex;
TreePath dest;
if (support.isDrop()) {
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
childIndex = dl.getChildIndex();
dest = dl.getPath();
} else {
childIndex = -1;
JTree tree = (JTree) support.getComponent();
dest = tree.getSelectionPath();
}
DefaultMutableTreeNode parent
= (DefaultMutableTreeNode) dest.getLastPathComponent();
JTree tree = (JTree) support.getComponent();
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
// Configure for drop mode.
int index = childIndex; // DropMode.INSERT
if (childIndex == -1) { // DropMode.ON
index = parent.getChildCount();
}
// Add data to model.
for (int i = 0; i < nodes.length; i++) {
// ArrayIndexOutOfBoundsException
model.insertNodeInto(nodes[i], parent, index++);
}
return true;
}
//TransferHandler
@Override public boolean importData(JComponent comp, Transferable t) {
return importData(new TransferHandler.TransferSupport(comp, t));
}
public class NodesTransferable implements Transferable {
DefaultMutableTreeNode[] nodes;
public NodesTransferable(DefaultMutableTreeNode[] nodes) {
this.nodes = nodes;
}
//Transferable
@Override public Object getTransferData(DataFlavor flavor) {
if(!isDataFlavorSupported(flavor)) {
return false;
}
return nodes;
}
//Transferable
@Override public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
//Transferable
@Override public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.equals(nodesFlavor);
}
}
}
的构造函数。表达性并不直接存在于Java语言中。
但是,您可以创建静态成员类protected
Data
的构造函数 - 在这种情况下,外部类仍然可以访问它。外部类可以定义一个受保护的工厂方法来调用private
构造函数 - 通过使它成为Data
,它只能被父本身,子类和同一个包中的所有类访问(总是如此) protected
修饰符的情况)
protected