如何初始化匿名类的对象?

时间:2015-01-15 13:18:09

标签: java constructor inner-classes

我们不能在匿名类中声明构造函数。但是如果我需要使用局部变量的值来初始化匿名类的对象的状态,我该怎么做?

3 个答案:

答案 0 :(得分:5)

您可以执行以下操作:

final int localVar = 5;

new Runnable() {
    int innerVar = localVar;  // <--- initialized here

    public void run() {
        System.out.println(innerVar);
    }
}.run();

如果localVar发生变异(非最终),您可以使用

解决问题
...
final int tmp = localVar;
new Runnable() {
    int innerVar = tmp;
    ...
...

另请注意,如果需要调用方法或进行其他初始化,您可以使用实例初始值设定项,而这通常是在构造函数中执行的操作:

final int localVar = 5;

new Runnable() {
    int innerVar;

    // Initialization block executed upon construction of this class
    {
        System.out.println("Initializing an anonymous Runnable");
        innerVar = localVar;
    }

    public void run() {
        System.out.println(innerVar);
    }
}.run();

例如参见:Why java Instance initializers?

答案 1 :(得分:3)

您不能使用构造函数创建匿名类的假设并不完全正确。仅当从接口(不能具有构造函数)创建匿名类时才会出现这种情况。请参阅下面的示例:

public class Main {

    public static class Razzy {
        private final String name;

        public Razzy(final String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }

    public static void main(final String[] args) {
        final Razzy anonymous = new Razzy("Award") {
            @Override
            public String getName() {
                return "Anonymous " + super.getName();
            }
        };
        System.out.println(anonymous.getName());
    }
}

这里的Razzy类有一个带String的构造函数。在main方法中,使用这个单个参数构造函数创建了Razzy的匿名子类。

输出结果为:

  

匿名奖

通过这种方式,您可以将局部变量传递给匿名类的构造函数。

请注意,匿名类也可以访问其封闭类的字段:

public class Main {

    private static String input = "Award";

    public interface Razzy {           
        public String getName();
    }

    public static void main(final String[] args) {
        final Razzy anonymous = new Razzy() {
            @Override
            public String getName() {
                return "Anonymous " + input ;
            }
        };
        System.out.println(anonymous.getName());
    }
}

具有相同的输出。

答案 2 :(得分:0)

问题是,您实际上并不需要定义构造函数。匿名类隐式访问封闭方法范围内的任何变量。它们只需要被声明为final(在Java 8中,不需要final关键字,但您仍然无法为它们重新赋值)。

public void enclosingMethod() {
    final int localVariable = 42; // final is necessary

    Runnable r = new Runnable() {
        public void run() {
            // look ma, no constructors!
            System.out.println(localVariable);
        }
    };
    r.run(); // prints 42
}