当前位置: 首页 > 面试题库 >

为什么方法引用可以使用非最终变量?

韦睿
2023-03-14
问题内容

我对内部类和lambda表达式有些困惑,我试图问一个问题,但随后又产生了一个疑问,发布另一个问题可能比评论前一个问题更好。

直截了当:我知道这样的东西不会编译

public class Main {
    public static void main(String[] args) {
        One one = new One();

        F f = new F(){      //1
            public void foo(){one.bar();}   //compilation error
        };

        one = new One();
    }
}

class One { void bar() {} }
interface F { void foo(); }

由于Java如何管理闭包,因为one它不是 [有效地]最终的 ,依此类推。

但是,这怎么允许呢?

public class Main {
    public static void main(String[] args) {
        One one = new One();

        F f = one::bar; //2

        one = new One();
    }
}

class One { void bar() {} }
interface F { void foo(); }

//2等于//1?在第二种情况下,我是否不会面临“使用过时的变量”的风险?

我的意思是,在后一种情况下,one = new One();执行后f仍然具有过期的副本one(即引用旧对象)。这不是我们要避免的歧义吗?


问题答案:

尽管方法可以以相同的方式使用,但方法引用不是lambda表达式。我认为这就是造成混乱的原因。下面是Java的工作方式的简化,它不是真正的工作方式,但是足够接近。

假设我们有一个lambda表达式:

Runnable f = () -> one.bar();

这等效于实现的匿名类Runnable

Runnable f = new Runnable() {
    public void run() {
       one.bar();
    }
}

这里的规则与匿名类(或方法本地类)的规则相同。这意味着one需要有效地完成工作。

另一方面,方法句柄:

Runnable f = one::bar;

更像是:

Runnable f = new MethodHandle(one, one.getClass().getMethod("bar"));

MethodHandle

public class MethodHandle implements Runnable {
    private final Object object;
    private final Method method;

    public MethodHandle(Object object, java.lang.reflect.Method method) {
        this.object = Object;
        this.method = method;
    }

    @Override
    public void run() {
        method.invoke(object);
    }
}

在这种情况下,分配给的对象将one作为创建的方法句柄的一部分进行分配,因此one它本身不一定要有效地最终运行。



 类似资料:
  • 问题内容: 我有按钮单击侦听器,并且在方法中我有一个局部变量,例如 为什么Java要求让我最终决定? 问题答案: 当onCreate()方法返回时,您的局部变量将从堆栈中清除,因此它们将不再存在。但是匿名类对象new View.OnClickListener()引用了这些变量。当然,这是错误的行为,因此Java不允许您执行此操作。 最终确定后,它将成为一个常数。因此它存储在堆中,可以在匿名类中安全

  • 问题内容: 关于编译器错误,有一些关于Stack Overflow的主题,解决方案是“将其声明为最终的,您就完成了”,但是对于这个 理论性的 问题,我想检查一下该代码无法编译的逻辑原因是什么: (解决方案:声明为final),而这一点却做到了: 我真的很困惑 不是最终值,它可以多次更改,而的可怜参数只能在其方法体内更改,而是由编译器负责;) 甚至编译器错误也误导了我。: 与什么不同?与内部类不是在

  • 在《生锈的一生》一章中,有一个例子: 为什么他们使用

  • 问题内容: 编辑:我需要更改几个变量的值,因为它们在计时器中运行了几次。我需要在每次迭代中通过计时器不断更新值。我无法将值设置为,因为这将阻止我更新值,但是我遇到了在下面的第一个问题中描述的错误: 我以前写过下面的内容: 我收到错误消息“无法引用用其他方法定义的内部类内部的非最终变量”。 对于名为的价格和名为的,这种情况正在发生。你知道我为什么会遇到这个问题吗?我不明白为什么我需要作最后声明。另外

  • 问题内容: 我在查看有关最终变量的另一个问题,并注意到您可以声明最终变量而无需初始化它们(空白的最终变量)。是否有理由这样做,何时才是有利的? 问题答案: 这对于创建不可变对象很有用: Bla是不可变的(一旦创建,就无法更改,因为颜色是最终的)。但是您仍然可以通过用各种颜色构造它们来创建各种Blas。 例如,另请参阅此问题。 编辑 也许值得一提的是,“空白最终”在Java中具有非常特殊的含义,这似

  • 问题内容: 我读了这个问题不可变对象,并留下了关于不可变对象,并最终场一个问题: 为什么我们需要不可变类中的实例变量为最终变量? 例如,考虑以下不可变的类: 如果在上面的代码中没有set方法,而实例变量仅在构造函数中设置,为什么要求将实例变量声明为final? 问题答案: 有没有 要求 这样做的变量。但是,当您确实明确打算永远不更改变量时,通常这样做是一种好习惯,因为这不仅可以使变量避免错别字或其