[英]Is there a way to pass a method reference in Java?
首先,盡管它們具有相同的標題,但這不是該問題的重復。 這個問題指的是與C函數本質上相同的傳遞方法:它們不必屬於特定的對象。 在這種情況下,您可以傳遞Runnable
或Callable
對象。
相反,我在問以下問題:是否可以將引用傳遞給類中的特定方法,並讓該方法調用特定對象?
舉例來說,我在Swing中查看FlowLayout
的代碼,並注意到preferredLayoutSize
和minimumLayoutSize
實現完全相同,只是一行不同:
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
boolean firstVisibleComponent = true;
boolean useBaseline = getAlignOnBaseline();
int maxAscent = 0;
int maxDescent = 0;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.width += hgap;
}
dim.width += d.width;
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
maxAscent = Math.max(maxAscent, baseline);
maxDescent = Math.max(maxDescent, d.height - baseline);
}
}
}
}
if (useBaseline) {
dim.height = Math.max(maxAscent + maxDescent, dim.height);
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
boolean useBaseline = getAlignOnBaseline();
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
int maxAscent = 0;
int maxDescent = 0;
boolean firstVisibleComponent = true;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.visible) {
Dimension d = m.getMinimumSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.width += hgap;
}
dim.width += d.width;
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
maxAscent = Math.max(maxAscent, baseline);
maxDescent = Math.max(maxDescent,
dim.height - baseline);
}
}
}
}
if (useBaseline) {
dim.height = Math.max(maxAscent + maxDescent, dim.height);
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
preferredLayoutSize
方法調用m
的preferredLayoutSize
方法(第i
個組件),而minimumLayoutSize
調用m
的minimumLayoutSize
方法。 據我所知,這兩種方法在其他方面是相同的。
正如任何程序員都會告訴您的那樣,代碼重復是一件壞事。 但是,在這種情況下,如何消除重復的代碼並不明顯。 顯然,應該有一個私有方法,其中包含兩個公共方法都調用的代碼,並傳遞對Component
類的preferredLayoutSize
和minimumLayoutSize
方法的引用。 在CI中,可以使用函數指針來做到這一點,因此在Java中應該有某種方式可以做到這一點。 傳遞Runnable
或Callable
幾乎可行,但都不返回值。 編輯:這是錯誤的。 Callable
中的重寫方法確實返回一個值,並且對其作用的對象可以作為參數傳遞。
現在,我已經輸入了所有內容,我想到了一個解決方案:您可以使用名為Dimension layoutSize(Component comp)
的方法編寫一個interface
,並編寫兩個實現,其中一個返回comp.preferredLayoutSize()
,而另一個返回comp.minimumLayoutSize()
。 然后,您可以編寫一個私有方法,將該接口的實例作為參數,然后使用該私有方法在代碼的正確位置運行單獨的方法。 您甚至可以使用匿名內部類,因此不必為每種類型的布局大小編寫新的類。 但是,對於一個相當簡單的問題,似乎仍然有很多麻煩。 有更容易的方法嗎?
您可以將一個方法包裝在LayoutSizing
類(可能是一個本地類)中,並使用一個抽象方法在m
上進行計算(以m
為參數),然后在這兩個方法中使用以下方法實例化new LayoutSizing() { @Override ... }
實現的方法。
希望在Java 8中看起來會更好。
您可以使用一個接口:
interface DimensionReturningThingy {
public Dimension getDim (Component c);
}
public Dimension preferredLayoutSize(Container target) {
commonCode (target, new DimensionReturningThingy () {
public Dimension getDim (Component m) {
return m.getPreferredSize ();
});
}
// and similarly for minimumLayoutSize
public Dimension commonCode (Container target, DimensionReturningThingy drt) {
// now repeat code above, except that replace
Dimension d = m.getPreferredSize();
// with
Dimension d = drt.getDim (m);
我不太擅長命名,所以我敢肯定您可以為其中的一些名字起更好的名字。
編輯:在您編輯原始文章以提及界面解決方案之前,我想我正在回答這個問題。
對於這種特殊情況,最簡單的解決方案是將這兩種方法重構為三種:
private Dimension layoutSize(Container target, boolean prederred) {
...
Dimension d = prederred?m.getPreferredSize():m.minimumLayoutSize();
...
}
public Dimension preferredLayoutSize(Container target) {
return layoutSize(target, true);
}
public Dimension minimumLayoutSize(Container target) {
return layoutSize(target, false);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.