首頁>Program>source

我想轉換一个 anonymous classlambda expression .但是這个匿名類我用 this 關鍵字。

例如,我寫了這个簡單的 Observer/Observable 模式:

import java.util.ArrayList;
import java.util.Collection;
public static class Observable {
    private final Collection<Observer> notifiables = new ArrayList<>();
    public Observable() { }
    public void addObserver(Observer notifiable) { notifiables.add(notifiable); }
    public void removeObserver(Observer notifiable) { notifiables.add(notifiable); }
    public void change() {
        notifiables.forEach(notifiable -> notifiable.changed(this));
    }
}
public interface Observer {
    void changed(Observable notifier);
}

和帶有匿名類的此示例代碼(使用this關鍵字):

public class Main {
    public static void main(String[] args) {
        Observable observable = new Observable();
        observable.addObserver(new Observer() {
            @Override
            public void changed(Observable notifier) {
                notifier.removeObserver(this);
            }
        });
        observable.change();
    }
}

但是当我將其轉換為lambda表達式時:

public class Main {
    public static void main(String[] args) {
        Observable observable = new Observable();
        observable.addObserver(notifier -> { notifier.removeObserver(this); });
        observable.change();
    }
}

我收到此編譯錯誤:

Cannot use this in a static context and in a non `static` context

public class Main {
    public void main(String[] args) {
        method();
    }
    private void method() {
        Observable observable = new Observable();
        observable.addObserver(notifier -> {
                notifier.removeObserver(this);
        });
        observable.change();
    }
}

編譯錯誤為:

The method removeObserver(Main.Observer) in the type Main.Observable is not applicable for the arguments (Main)

所以我的問题是: Is there a way to reference the "lambda object" with this

最新回復
  • 5月前
    1 #

    您不能引用 this 在lambda表達式中. this的語義 已更改為仅从lambda內部引用週圍類的例項.没有办法引用lambda表達式的 this 从lambda內部。

    問题是您使用 thismain() 方法.主要方法是靜態的,没有引用代表 this的物件

    使用 this時 在內部類的例項內部,您引用的是內部類的例項。 Lambda表達式不是內部類, this 未引用lambda表達式的例項.它引用的是您在其中定義lambda表達式的類的例項。在您的情况下,它將是Main的例項.但是,由於您使用的是靜態方法,因此没有例項。

    這是第二个編譯錯誤告诉您的內容.您將Main例項移交给您的方法.但是您的方法簽名需要一个Observer例項。

    Update:

    Java語言規範15.27.2說:

    Unlike code appearing in anonymous class declarations, the meaning of names and the this and super keywords appearing in a lambda body, along with the accessibility of referenced declarations, are the same as in the surrounding context (except that lambda parameters introduce new names).

    The transparency ofthis(both explicit and implicit) in the body of a lambda expression - that is, treating it the same as in the surrounding context - allows more flexibility for implementations, and prevents the meaning of unqualified names in the body from being dependent on overload resolution.

    Practically speaking, it is unusual for a lambda expression to need to talk about itself (either to call itself recursively or to invoke its other methods), while it is more common to want to use names to refer to things in the enclosing class that would otherwise be shadowed (this, toString()). If it is necessary for a lambda expression to refer to itself (as if viathis), a method reference or an anonymous inner class should be used instead.

    h 解決方法1

    您的 change() 方法丟擲 ConcurrentModificationException 無論如何。

    public class Main {
        public static void main(String[] args) {
            Observable observable = new Observable();
            final Observer[] a = new Observer[1];
            final Observer o = er -> er.removeObserver(a[0]); // !!
            a[0] = o;
            observable.addObserver(o);
            observable.change();
        }
    }
    public class Observable {
        private final java.util.Collection<Observer> n
            = java.util.new ArrayList<>();
        public void addObserver(Observer notifiable) {
            n.add(notifiable);
        }
        public void removeObserver(Observer notifiable) {
            n.add(notifiable);
        }
        public void change() {
            for (final Observer o : n.toArray(new Observer[n.size()])) {
                o.changed(this);
            }
        }
    }
    public interface Observer {
        void changed(Observable notifier);
    }
    
    解決方法2

    我改變了 changed(Observable)changed(Observable, Observer) 這樣观察者就可以處理自己。

    public class Main {
        public static void main(String[] args) {
            Observable observable = new Observable();
            final Observer o = (er, ee) -> er.removeObserver(ee); // !!
            observable.addObserver(o);
            observable.change();
        }
    }
    public class Observable {
        private final java.util.Collection<Observer> n
            = new java.util.ArrayList<>();
        public void addObserver(Observer notifiable) {
            n.add(notifiable);
        }
        public void removeObserver(Observer notifiable) {
            n.add(notifiable);
        }
        public void change() {
            for (final Observer o : n.toArray(new Observer[n.size()])) {
                o.changed(this, o);
            }
        }
    }
    public interface Observer {
        void changed(Observable notifier, Observer notifiee);
    }
    

  • html:在<img>或<br>標記等的末尾是否需要" /"?
  • jquery:在JavaScript中將字元串轉換為XML文件