枚举常量值添加匿名类

问题描述 投票:2回答:1

在枚举的常量值声明中在类体中添加onymous(非匿名)类方法有什么用法?

public enum Status {
    SUCCESS("SUCCESS"){},FAILED("FAILED"){  
         class Test { 
               public void test() {
                  System.out.println("test");
               }
         }
    };
    private String code;

    Status(String code) {
        this.code = code;
    }

如何访问/执行此类方法?我发现anonymous class的例子,不推荐

作为建议,让你的枚举实现你的界面,使代码更具可读性

我没有在JLS的Enum Constants部分找到用法

枚举常量的可选类体隐式定义了一个匿名类声明(第15.9.5节),该声明扩展了直接封闭的枚举类型。班级团体由匿名班级的通常规则管理;特别是它不能包含任何构造函数。

只有当它们覆盖封闭枚举类型中的可访问方法时,才可以在封闭枚举类型之外调用在这些类主体中声明的实例方法。

java enums anonymous-class
1个回答
1
投票

TL; DR很难想象在枚举常量内部定义内部类是有意义的真实情况。

让我们从您的代码示例开始......

public enum Status {
    SUCCESS("SUCCESS") {

    },
    FAILED("FAILED") {  
        class Test { 
            public void test() {
                System.out.println("test");
            }
        }
    };
    private String code;

    Status(String code) {
        this.code = code;
    }
}

由于FAILED是带有body的枚举值,因此它成为Status枚举类的匿名子类。 Test在这个匿名类中定义。由于其封闭类的匿名性,没有办法在FAILED之外表达它的名字。肯定不是Status.FAILED.Test

所以Test主要在FAILED内部使用(如果FAILED的实现足够复杂以保证内部类)。一般来说,我更喜欢枚举常量不会变得如此复杂,但这是一种风格问题。

Test外部访问FAILED只能通过Test扩展/实现的超类或接口,并且只能通过该超类或接口公开的方法。

一个(设计的)示例显示FAILED内部和外部的用法,可能是:

public class StatusTest {

    enum Status {
        FAILED{  
            class Test implements Runnable { 
                private String text = "Test " + System.currentTimeMillis();
                @Override
                public void run() {
                    System.out.println(text);
                }
            }
            @Override
            public Runnable getRunner() {
                return new Test();
            }
            @Override
            public void message() {
                getRunner().run();
            }
        };
        public abstract void message();
        public abstract Runnable getRunner();
    }

    public static void main(String[] args) {
        Status status = Status.FAILED;
        status.message();
        Runnable runner = status.getRunner();
        runner.run();
    }
}

(后来添加)

当然,在这个例子中,Runnable没有理由得到一个类名。我通常只使用命名的内部类而不是匿名的内部类

  • 用于多个地方或
  • 如此复杂,以至于它会使封闭方法变得不可读。

在引入匿名内容与命名内部类时,这一直是一样的决定。使用枚举,更不用说给内部类命名,因为这个名称在外面不可用。所以,如果我要查看上面的代码,我会重构它以使用匿名类:

public class StatusTest {

    enum Status {
        FAILED { 
            @Override
            public Runnable getRunner() {
                return new Runnable() { 
                    private String text = "Test " + System.currentTimeMillis();
                    @Override
                    public void run() {
                        System.out.println(text);
                    }
                };
            }
            @Override
            public void message() {
                getRunner().run();
            }
        };
        public abstract void message();
        public abstract Runnable getRunner();
    }

    public static void main(String[] args) {
        Status status = Status.FAILED;
        status.message();
        Runnable runner = status.getRunner();
        runner.run();
    }
}

在这两种情况下,内部类本身对于外部代码是不可见的,仅在枚举常量内部,并且如果枚举常量的实现变得如此复杂以至于它保证了命名的内部类,我肯定会重构它,例如,通过将复杂性委托给一些普通的顶级课程。

© www.soinside.com 2019 - 2024. All rights reserved.