簡體   English   中英

如何將參數傳遞給匿名類?

[英]How to pass parameters to anonymous class?

是否可以向匿名類傳遞參數或訪問外部參數? 例如:

int myVariable = 1;

myButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // How would one access myVariable here?
    }
});

有沒有辦法讓偵聽器訪問 myVariable 或傳遞 myVariable 而不將偵聽器創建為實際的命名類?

是的,通過添加一個返回'this'的初始化方法,並立即調用該方法:

int myVariable = 1;

myButton.addActionListener(new ActionListener() {
    private int anonVar;
    public void actionPerformed(ActionEvent e) {
        // How would one access myVariable here?
        // It's now here:
        System.out.println("Initialized with value: " + anonVar);
    }
    private ActionListener init(int var){
        anonVar = var;
        return this;
    }
}.init(myVariable)  );

不需要“最終”聲明。

從技術上講,不,因為匿名類不能有構造函數。

但是,類可以引用包含范圍的變量。 對於匿名類,這些可以是包含類的實例變量或標記為final的局部變量。

編輯 :正如Peter所指出的,您還可以將參數傳遞給匿名類的超類的構造函數。

是。 你可以捕獲變量,對內部類可見。 唯一的限制是它必須是最終的

像這樣:

final int myVariable = 1;

myButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // Now you can access it alright.
    }
});

這將是神奇的

int myVariable = 1;

myButton.addActionListener(new ActionListener() {

    int myVariable;

    public void actionPerformed(ActionEvent e) {
        // myVariable ...
    }

    public ActionListener setParams(int myVariable) {

        this.myVariable = myVariable;

        return this;
    }
}.setParams(myVariable));

http://www.coderanch.com/t/567294/java/java/declare-constructor-anonymous-class所示,您可以添加實例初始化程序。 它是一個沒有名稱並首先執行的塊(就像構造函數一樣)。

看起來他們也在為什么java實例初始化器討論過 實例初始化程序如何與構造函數不同? 討論了與構造函數的差異。

我的解決方案是使用一個返回已實現的匿名類的方法。 常規參數可以傳遞給方法,並且可以在匿名類中使用。

例如:(從某些GWT代碼處理文本框更改):

/* Regular method. Returns the required interface/abstract/class
   Arguments are defined as final */
private ChangeHandler newNameChangeHandler(final String axisId, final Logger logger) {

    // Return a new anonymous class
    return new ChangeHandler() {
        public void onChange(ChangeEvent event) {
            // Access method scope variables           
            logger.fine(axisId)
        }
     };
}

對於此示例,將使用以下引用新的匿名類方法:

textBox.addChangeHandler(newNameChangeHandler(myAxisName, myLogger))

或者 ,使用OP的要求:

private ActionListener newActionListener(final int aVariable) {
    return new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("Your variable is: " + aVariable);
        }
    };
}
...
int myVariable = 1;
newActionListener(myVariable);

其他人已經回答說匿名類只能訪問最終變量。 但他們留下了如何保持原始變量非最終的問題。 Adam Mlodzinski給出了一個解決方案但是非常臃腫。 這個問題有一個更簡單的解決方案:

如果你不希望myVariable成為最終版,你必須將它包裝在一個無關緊要的新范圍內,如果它是最終的。

int myVariable = 1;

{
    final int anonVar = myVariable;

    myButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // How would one access myVariable here?
            // Use anonVar instead of myVariable
        }
    });
}

Adam Mlodzinski在他的回答中沒有做任何其他事情,但有更多的代碼。

你可以使用普通的lambdas (“lambda表達式可以捕獲變量”)

int myVariable = 1;
ActionListener al = ae->System.out.println(myVariable);
myButton.addActionListener( al );

甚至是一個功能

Function<Integer,ActionListener> printInt = 
    intvar -> ae -> System.out.println(intvar);

int myVariable = 1;
myButton.addActionListener( printInt.apply(myVariable) );

使用Function是重構裝飾器和適配器的好方法, 請參見此處

我剛開始學習lambdas,所以如果發現錯誤,請隨意寫評論。

將一些值放入外部變量(不屬於anonymus類)的簡單方法是如何實現的!

以同樣的方式,如果你想獲得外部變量的值,你可以創建一個返回你想要的方法!

public class Example{

    private TypeParameter parameter;

    private void setMethod(TypeParameter parameter){

        this.parameter = parameter;

    }

    //...
    //into the anonymus class
    new AnonymusClass(){

        final TypeParameter parameterFinal = something;
        //you can call setMethod(TypeParameter parameter) here and pass the
        //parameterFinal
        setMethod(parameterFinal); 

        //now the variable out the class anonymus has the value of
        //of parameterFinal

    });

 }

你可以使用一個合格的:

public class Foo {
    int myVariable = 1;

    new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Foo.this.myVariable = 8;
        }
    });
}

我認為匿名類基本上就像lambdas但語法更差......結果證明這是真的,但語法更糟,導致(應該是)本地變量滲透到包含類中。

您可以通過將它們放入父類的字段來訪問任何最終變量。

例如

接口:

public interface TextProcessor
{
    public String Process(String text);
}

類:

private String _key;

public String toJson()
{
    TextProcessor textProcessor = new TextProcessor() {
        @Override
        public String Process(String text)
        {
            return _key + ":" + text;
        }
    };

    JSONTypeProcessor typeProcessor = new JSONTypeProcessor(textProcessor);

    foreach(String key : keys)
    {
        _key = key;

        typeProcessor.doStuffThatUsesLambda();
    }

我不知道他們是否已經在java 8中對此進行了排序(我已經陷入了EE世界而且還沒有得到8)但是在C#中它看起來像這樣:

    public string ToJson()
    {
        string key = null;
        var typeProcessor = new JSONTypeProcessor(text => key + ":" + text);

        foreach (var theKey in keys)
        {
            key = theKey;

            typeProcessor.doStuffThatUsesLambda();
        }
    }

在c#中你不需要一個單獨的界面......我想念它! 我發現自己在java中做了更糟糕的設計,並重復自己更多,因為你需要在java中添加的代碼量+復雜性來重用某些東西比復制和粘貼很多時候更糟糕。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM