【问题标题】:Why is this Java code working? compiler doesn't complain about closure为什么这个 Java 代码有效?编译器不会抱怨关闭
【发布时间】:2014-02-05 15:36:25
【问题描述】:

我的 DialogFragment 包含一个 - 最初不可见 - 确定按钮和一个可点击项目的 ListView。当单击任何 ListView 项目时,我将按钮的可见性设置为 VISIBLE。

这是通过匿名 OnItemClickListener 完成的。下面的代码有效,但我不明白为什么。由于 Java 不支持闭包,我希望编译器会抱怨按钮不是最终的。

这不是典型的闭包案例吗?为什么下面的代码不会产生编译错误?

谢谢

public class AlternativeRoomsDialog extends DialogFragment {

private Button okButton;

static AlternativeRoomsDialog newInstance(String name) {
    AlternativeRoomsDialog f = new AlternativeRoomsDialog();
    return f;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_alternative_rooms, container);
    getDialog().setTitle("Change Room");

    ListView lv = (ListView) view.findViewById(R.id.alternative_rooms_list);
    final adapter = /*some initialization*/;
    lv.setAdapter(adapter);
    lv.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View linlay, int position, long id) {
            okButton.setVisibility(View.VISIBLE);
            ListView lv = (ListView) linlay.getParent();
            int total = lv.getChildCount();
            for (int i=0; i< total; i++){
                lv.getChildAt(i).setBackgroundColor(Color.BLUE);
            }
            linlay.setBackgroundColor(Color.GREEN);
        }
    }); 

    // setup OK button
    okButton = (Button) view.findViewById(R.id.btn_ok);
    okButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(AlternativeRoomsDialog.this.getActivity(), "ok button clicked", Toast.LENGTH_SHORT).show();
        }
    });
    return view;
}

}

【问题讨论】:

  • 你正在关闭this,它(实际上)是final
  • 嗨@SLaks,感谢您的回答。我不确定我是否会跟随。所以你是说qualified.this的行为像final,因为它是一个类实例?
  • final 局部变量一样,this 不能改变。

标签: java android closures anonymous-class


【解决方案1】:

将变量声明为 final 的要求仅适用于局部变量,因为它们是方法返回时超出范围的变量。你的按钮被一个成员变量引用,它不需要是最终的:只要对象存在,成员就不会去任何地方。

【讨论】:

    【解决方案2】:

    你不需要创建实例变量final,只有局部变量才会这样。局部变量需要是final,它们被复制到您在方法内部使用的匿名类,作为该类的实例变量。这样做是因为匿名内部类实例可能会在方法返回后保留在堆内存中。因此,即使在方法堆栈帧被释放后,它也可能需要访问变量。

    现在,由于局部变量有 2 个副本,如果局部变量在匿名内部类之外更改,它们可能会不同步。这真的很奇怪,这就是为什么需要将 局部变量 final.

    实例变量一样,它们在封闭类实例和匿名内部类实例之间共享。因此,您无需将它们设为final

    【讨论】:

      猜你喜欢
      • 2016-04-22
      • 2019-06-16
      • 2016-11-01
      • 1970-01-01
      • 2012-09-12
      • 1970-01-01
      • 2013-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多