首页>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

最新回答
  • 2021-1-11
    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文档