我們知道ComboBoxModel
接口用於創建一個女巫類,我們可以指定如何將對象集合(模型)與組合框相關聯,基本上通過提供必要的「信息」檢索項目並設置當前項目。 通常我寫這些類聲明爲成員Collection <of a concrete type>
,只是將一些功能委託給實現方法中的集合對象。 當所有包含對象的實際類都是Not-Proxied對象時,一切都很好(當然,我們有90%的時間會出現這種情況),但這次面對引用Proxied Objects和事情的事實會出現奇怪的錯誤。 JComboBox行爲出錯,因爲它無法更改當前選擇。帶有動態代理對象的ComboBoxModel
我想獲得一些更多的信息,但現在我只知道,當週圍有代理對象的方法ComboBoxModel
接口setSelectedItem
,任何具體的類實現不調用。這是我的問題:發生了什麼,更重要的是它是否可以修復?
我留下一個例子,準備好自己看看。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
/**
*
* @author Administrador
*/
public class AComboBoxWithProxyProblem extends JFrame implements ActionListener
{
ComboBoxModel modelWithProxies = new ItemComboBoxModelWithProxies();
ComboBoxModel modelWithoutProxies = new ItemComboBoxModelWithoutProxies();
public AComboBoxWithProxyProblem()
{
final JComboBox comboBox = new JComboBox();
comboBox.addActionListener(this);
getContentPane().setLayout(new BoxLayout(this.getContentPane(),BoxLayout.LINE_AXIS));
getContentPane().add(comboBox);
JRadioButton btnProxy = new JRadioButton("Proxy model");
btnProxy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
comboBox.setModel(modelWithProxies);
comboBox.setSelectedIndex(0);
}
});
getContentPane().add(btnProxy);
JRadioButton btnNoProxy = new JRadioButton("Non Proxy model");
btnNoProxy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
comboBox.setModel(modelWithoutProxies);
comboBox.setSelectedIndex(0);
}
});
getContentPane().add(btnNoProxy);
ButtonGroup group = new ButtonGroup();
group.add(btnProxy);
group.add(btnNoProxy);
setTitle("Mmmm...");
}
@Override
public void actionPerformed(ActionEvent e)
{
JComboBox comboBox = (JComboBox)e.getSource();
Item item = (Item)comboBox.getSelectedItem();
System.out.println("[actionPerformed] - " + item.getId() + " : " + item.getDescription());
}
interface ItemInterface
{
String getDescription();
int getId();
@Override
String toString();
}
class Item implements AComboBoxWithProxyProblem.ItemInterface
{
private int id;
private String description;
public Item(int id, String description)
{
this.id = id;
this.description = description;
}
@Override
public int getId()
{
return id;
}
@Override
public String getDescription()
{
return description;
}
@Override
public String toString()
{
return description;
}
}
private class ItemComboBoxModelWithoutProxies extends AbstractListModel implements ComboBoxModel
{
List<ItemInterface> foos;
ItemInterface selected;
public ItemComboBoxModelWithoutProxies()
{
foos = new ArrayList<>();
foos.add(new Item(1,"One"));
foos.add(new Item(2,"Two"));
foos.add(new Item(3,"Three"));
}
@Override
public Object getSelectedItem()
{
return selected;
}
@Override
public void setSelectedItem(Object tournament)
{
System.out.println("[setSelectedItem] " + tournament);
selected = (ItemInterface) tournament;
}
@Override
public int getSize()
{
return this.foos.size();
}
@Override
public Object getElementAt(int i)
{
return this.foos.get(i);
}
}
private class ItemComboBoxModelWithProxies extends AbstractListModel implements ComboBoxModel
{
List<ItemInterface> foos;
Object selected;
public ItemComboBoxModelWithProxies()
{
foos = new ArrayList<>();
ItemInterface item;
item = (ItemInterface) Proxy.newProxyInstance(Item.class.getClassLoader(),
Item.class.getInterfaces(),
new ItemInvocationHandler (new Item(1,"One")));
foos.add(item);
item = (ItemInterface) Proxy.newProxyInstance(Item.class.getClassLoader(),
Item.class.getInterfaces(),
new ItemInvocationHandler (new Item(2,"Two")));
foos.add(item);
item = (ItemInterface) Proxy.newProxyInstance(Item.class.getClassLoader(),
Item.class.getInterfaces(),
new ItemInvocationHandler (new Item(3,"Three")));
foos.add(item);
}
@Override
public Object getSelectedItem()
{
return selected;
}
@Override
public void setSelectedItem(Object tournament)
{
System.out.println("[setSelectedItem] " + tournament);
selected = (ItemInterface) tournament;
}
@Override
public int getSize()
{
return this.foos.size();
}
@Override
public Object getElementAt(int i)
{
return this.foos.get(i);
}
private class ItemInvocationHandler implements InvocationHandler {
Item item;
public ItemInvocationHandler(Item item)
{
this.item = item;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
return method.invoke(this.item, args);
}
}
}
public static void main(String[] args)
{
JFrame frame = new AComboBoxWithProxyProblem();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
那麼,這就是全部!
謝謝!
Victor。
非常完成答案。所以,讓我清楚的事情...我們在這裏面臨的事實是JComboBox的代碼可以將代理「A」與代理對象「B」進行比較,此外,代理「A」實際上代表對象「B」,等於到它們屬於不同類別的事實(任何合理的等價實現都應該返回false)。順便說一句,我設法做一些變通.. returing被代理的對象(在getSelectedItem和getElementAt),並有一個對象 - >代理的映射(爲了檢索代理,將對象傳遞爲鍵) – Victor
是的,這是基本的。如果你嘗試並執行'proxyA.equals(proxyB)',它實際上並沒有比較兩個代理對象,比較'proxyA.objectBeginProxied'和'proxyB',它永遠不能返回'true'。這是一個有趣的工作,你可能想要更新你的問題與周圍的工作,爲任何其他人有同樣的問題 – MadProgrammer