21

考虑以下代码:

public static void main(String[] args) {
    File file = new File("C:\\someFile.txt") {
        public void doStuff() {
            // Do some stuff
        }   
    };

    file.doStuff(); // "Cannot resolve method"
}

当我们尝试调用我们新定义的方法doStuff()时,这是不可能的。原因是它file被声明为类型的对象,File而不是我们新的匿名子类的实例。

所以,我的问题是,是否有任何“好”的方法来实现这种行为?除了显而易见的(即正确地声明类)之外。

4

4 回答 4

16

这是不可能的,因为您试图在超类引用上调用方法子类。并且该方法未在超类本身中定义。匿名类只是File那里的一个子类。

但是,一种解决方法是通过反射:

file.getClass().getMethod("doStuff").invoke(file);

getClass()方法将返回运行时类型file,然后您可以使用方法获取该类的Class#getMethod()方法。

好吧,我自己不是反思的忠实粉丝。如果你要做这些事情,更好的方法当然是通过扩展超类来创建一个类。使用反射来解决问题真的很头疼,因为使用简单的修改就可以轻松完成。

于 2013-09-06T11:02:15.683 回答
7

好的方法不是在您的情况下使用匿名内部类,而是定义您自己的类,该类扩展File并添加您需要的任何方法。

class StuffedFile extends File {
    // implement all needed constructors
    public void doStuff() { /*.....*/}
}

现在您可以按如下方式使用它:

MyFile f = new MyFile("...");
f.doStuff();

然而,整个这种扩展尝试File听起来并不是一个好的设计。创建其他可以接受文件并对其进行处理的类。您将获得更好的封装性和代码可重用性。

编辑显然你可以使用反射来调用你想要的任何方法,但我不能称之为“好的解决方案”。我可以称之为“可能的解决方法”。

于 2013-09-06T11:04:10.283 回答
3

我能达到你的简洁程度的最接近的是:

public static void main(String[] args) {
  abstract class FileThatDoesStuff extends File {
    // Need a constructor that takes a String because File has one.
    public FileThatDoesStuff(String filePath) {
      super(filePath);
    }
    // It also does stuff.
    public abstract void doStuff();
  }
  FileThatDoesStuff file = new FileThatDoesStuff("C:\\someFile.txt") {
    @Override
    public void doStuff() {
      // Do some stuff
    }

  };
  file.doStuff(); // "Can resolve method"
}

我不得不承认我希望我能做到:

abstract class DoesStuff<T> extends T {
  public abstract void doStuff();
}
于 2013-09-06T12:07:32.193 回答
1

可以访问该方法。但我不知道你为什么要这样做。

public static void main(String[] args) {
   new File("C:\\someFile.txt") {
      public void doStuff() {
          // Do some stuff
      }   
   }.doStuff();
}
于 2014-07-03T09:58:44.137 回答