無名クラスからローカル変数へのアクセス
こんなクラスがあって
class MyClass{ void doSomething(){ System.out.println("hoge"); } }
こんな感じでアクセスしようとすると
List<Runnable> createTasks(List<MyClass> instances){ List<Runnable> tasks = new ArrayList<Runnable>(); for (MyClass instance : instances) { //←ここのinstanceに Runnable task = new Runnable(){ public void run(){ instance.doSomething();//←ここでアクセス } }; tasks.add(task); } return tasks; }
コンパイルでエラーになります。
AnonymousRunnableSnip.java:42: ローカル変数 instance は内部クラスからアクセス されます。final で宣言される必要があります。 instance.doSomething(); ^ エラー 1 個
そんな場合の対処法。以下の①で何をすればよいでしょうか?
for (MyClass instance : instances) { Runnable task = [①]; tasks.add(task); }
追記 これでいいじゃんということが判明
for (final MyClass instance : instances) {
よって以下は、
無駄無駄文となりました。。。。
↓
↓
↓
1、ローカルクラスで対処
class MyTask implements Runnable{ MyClass mc; MyTask(MyClass mc){ this.mc = mc; } public void run(){ mc.doSomething(); } } Runnable task = new MyTask(instance);
2、無名クラスで対処
Runnable task = new Runnable() { MyClass mc; public Runnable setData(MyClass mc) { this.mc = mc; return this; } public void run() { mc.doSomething(); } }.setData(instance);
Runnable task = ...に代入せずに、tasks.add(...)にわたせば、ローカルクラスよりやや文字数が少ない。
setData()で戻り値を返すのがミソ。
3、メソッドで対処
こんな感じのメソッド作って
private Runnable createTask(final MyClass mc){ return new Runnable(){ public void run(){ mc.doSomething(); } }; }
呼ぶ
Runnable task = createTask(instance);
ローカル変数でもfinalつければアクセスできるので。
ローカルクラスより、こっちの方が素直かな。
4、ジェネリックスなクラスで対処
こんな感じの共通クラス作っといて
abstract class RunnableWith<T> implements Runnable { private T instance; public RunnableWith(T instance){ this.instance = instance; } public void run(){ runWith(instance); } abstract void runWith(T instance); }
それを使う
Runnable task = new RunnableWith<MyClass>(instance){ public void runWith(MyClass mc){ mc.doSomething(); } };
似たような処理がたくさんある場合は、毎回「値を渡す」処理を書く手間は省ける。
他にも対処あるかな?