匿名内部 class 示例有效性问题

Anonymous inner class example validity concern

我试图使用我曾经购买过的星图复习一些 Java 语言。关于匿名内部 classes 的使用,他们给出了这个例子:

Dice rollDice() {
    return new Dice() {
        int number = (int)( Math.random() * 6 ) + 1;
    };
}

问题是,我看不出这是如何工作的,也无法让编译器接受它作为另一个 class 中的方法。编译器抱怨每次引用 Dice "symbol can not be found."

我是不是没有正确理解他们的例子,还是这个代码完全无效?提前致谢!

p.s。如果这是工作代码,有人可以向我提供一个如何使用它的示例吗?

编辑:我终于找到了有意义的东西 匿名内部 class 的语法如下所示

new SuperClassName/InterfaceName() {
// Implement or override methods in superclass or interface
// Other methods if necessary
}

上面的代码被传递给一个采用 Superclass 实例或完全实现接口的方法。例如,一个方法有一个 EventHandler 参数,而我们还没有定义一个 class 来实现 handle(ActionEvent e) 方法。

enlargeButton.setOnAction(
    new EventHandler<ActionEvent>() {
        public void handle(ActionEvent e) {
            circlePane.enlarge();
        }
    });

这样就真正做到了匿名。我认为 Java 自己的教程中给出的示例非常糟糕。

因为我不知道 'Dice' class 我不能写相同的方法,但我尝试了一些类似的东西。它编译和工作可以通过使用反射访问 'number' 变量。我的意见是它不是很有用。以下是我的代码:

  public class TestClass {

    public static void main(String a[]){
      TestClass aClass = rollDice();
      try {
        System.out.println("value of number : " + aClass.getClass().getDeclaredField("number").getInt(aClass));
      }
      catch (NoSuchFieldException e) {
        e.printStackTrace();
      }
      catch (IllegalAccessException e) {
        e.printStackTrace();
      }
    }

     static TestClass rollDice() {
      return new TestClass() {
        int number = (int) (Math.random() * 6) + 1;
      };
    }
  }

看起来您已经基本回答了您自己的问题,您可能希望通过一些完整的教程或文档来全面理解事情,但这里有一些您的直接问题的答案。

您的第一个示例代码只有在您拥有可以扩展的 Dice class 或接口后才能编译。因此,作为示例,您可以编译此代码:

class Dicey {
    interface Dice {
    }
    Dice rollDice() {
        return new Dice() {
            int number = (int) (Math.random() * 6) + 1;
        };
    }
    public static void main(String... none) {
        Dice dice = new Dicey().rollDice();
        // dice.number; <-- not available
    }
}

现在你可以做到这一点,但你怀疑这不是一件很有用的事情(出于一些原因),但最大的问题是在你创建这个匿名实例之后并没有真正的方法来获取 .number 成员。

更常见的情况是,您会让一个匿名子class 在接口上实现一些方法,这样您就可以实际使用它做一些事情。例如

class HelloAnonymous {
    interface Hello {
        String say();
    }

    Hello hello(String world) {
        return new Hello() {
            public String say() {
                return world;
            }
        };
    }

    public static void main(String... none) {
        System.out.println(new HelloAnonymous().hello("world").say());
        // prints 'world'
    }
}

为您提供了一种制作非常有用的 Hello 对象的方法,它可以说些什么。说了这么多,编写匿名内部 classes 是相当老套的做法,因为功能接口现在在很大程度上取代了对它们的需求。所以在这个例子中你可以有:

class HelloAnonymous {
    @FunctionalInterface
    interface Hello {
        String say();
    }

    // old school
    Hello hello(String world) {
        return new Hello() {
            public String say() {
                return world;
            }
        };
    }

    // with lambda notation
    Hello alsoHello(String world) {
        return () -> {
            return world;
        };
    }

    public static void main(String... none) {
        System.out.println(new HelloAnonymous().hello("world").say());
        System.out.println(new HelloAnonymous().alsoHello("world").say());
    }
}

那个例子非常糟糕。把那个来源扔掉。试试这个:

import java.util.Random;

public class DieFactory {
  interface Die { int roll(); }

  static Die create(long seed) {
    Random random = new Random(seed);
    return new Die() {
      @Override
      public int roll() {
        return random.nextInt(6) + 1;
      }    
    };
  }

  // Now you can roll 2 dice pretty easily.
  public static void main(String [] args) {
    DieFactory.Die die1 = DieFactory.create(42);    
    DieFactory.Die die2 = DieFactory.create(24);    
    for (int i = 0; i < 40; i++) {
      System.out.println(die1.roll() + die2.roll());
    }
  }
}

顺便说一下,单词 "dice" 是单数形式的复数形式 "die."