3

我可以做这个:

new Object(){
    public void hi(){}
}.hi();

我(或我可以)如何做到这一点:

IWouldRatherStayAnonymous t = new IWouldRatherStayAnonymous extends Thread(){
    public void NoNoYouCantCallMe(String s){}
};
t.NoNoYouCantCallMe("some useful data that i will need later, but don't want to save this anonymous class");

如果我不能在语法上做到这一点,谁能解释为什么这永远行不通的逻辑/实现设计?

===========================================

编辑:澄清 - 我想创建一个匿名类而不保存它,然后实例化该匿名类的实例。我只需要 1 个引用,因为我不打算经常使用这个引用(即使在同一个外部类中我也不想要其他任何东西来使用它)。但是,我只想将一些数据只传递给这个匿名类一次(理想情况下是构造函数,但您会注意到您实际上无法覆盖 Thread() 中的构造函数)。

这真的不是一笔大买卖,我只是好奇这是否可行,但从一些答案看来,它是可行的,但不是很漂亮。

4

7 回答 7

4

您的问题有点令人困惑,但听起来您想要一个既扩展Thread又实现某些接口的类,但在它所使用的方法之外无法访问该类(这甚至会排除私有嵌套类)。在这种情况下,使用本地类

void myMethod() {
    class Impl extends Thread implements SomeInterface {
        @Override
        public void someInterfaceMethod(String s){ }
    }
    new Impl().someInterfaceMethod("data");
}

编辑:为了响应您的更新,您自然可以给本地类一个构造函数并传入数据,或者只是让它关闭final外部方法中的变量。

于 2013-08-27T03:11:08.697 回答
2

如果我不能在语法上做到这一点,谁能解释为什么这永远行不通的逻辑/实现设计?

我可以解释。如果您有 Java 中的表达式foo.bar(...),编译器必须确保表达式的静态(编译时)类型foo支持 method bar()。在您的第一种情况下,左侧的表达式是匿名类创建表达式,因此它的静态类型是具有该方法的匿名类。

但是,在第二种情况下,左侧的表达式是一个变量。变量的静态类型是声明变量的类型。在 Java 中,变量必须用显式类型声明(不是varauto像其他一些语言一样)。因此,它的静态类型必须是命名类型。Thread并且没有其他命名类型支持该方法NoNoYouCantCallMe();只有匿名类支持这种方法,不能声明匿名类类型的变量。这就是为什么它在语法上是不可能的。

但是,我只想将一些数据只传递给这个匿名类一次(理想情况下是构造函数,但您会注意到您实际上无法覆盖 Thread() 中的构造函数)。

这很简单。您不需要显式地将数据传递给匿名类,因为在匿名类和本地类中,您自动可以访问final周围范围内的变量。因此,您无需传入数据,而是直接使用来自外部的数据。

final String someData = "blah";

Thread t = new Thread() {
    public void run() { doStuffWith(someData); }
};
于 2013-08-27T21:53:24.863 回答
1

访问匿名类的方法有两种方式:

  • 通过实现接口或扩展类,然后调用您在匿名类中实现的方法,或者
  • 通过使用反射(我假设您知道它是如何完成的,但不想这样做)。

Java 不提供静态捕获匿名类类型的方法,例如以类似于C#var关键字的方式。

在您的情况下,您可以使用该方法创建一个抽象类型void NoNoYouCantCallMe(String),并将该类用作匿名类的基础,如下所示:

abstract class MyThreadBase extends Thread {
    public abstract void YesICanCallYou(String s);
}
...
MyThreadBase t = new MyThreadBase() {
    public void YesICanCallYou(String s){}
};
...
t.YesICanCallYou();
于 2013-08-27T02:18:13.893 回答
1

You can create an inner class, just don't make it anonymous. Anonymous means that you don't have a type for it.

I'd suggest either a named inner-class or a second class in the same file. I use the second quite often, it just can't be public.

于 2013-08-27T02:23:12.923 回答
1

如果你真的想在不使用接口或抽象类的情况下做这样的事情,你可以通过反射调用它:

@Test
public void testCrazyStuff() throws IllegalArgumentException, SecurityException,
    IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
    Object object = new Thread()
    {
        public void ICanBeCalled( String s )
        {
            System.out.println( s );
        }
    };
    object.getClass()
      .getMethod( "ICanBeCalled", String.class )
      .invoke( object, "Whatever string!" );
}

但这是没有意义的......最好使用像其他人建议的那样具有接口或抽象类的简单解决方案。

于 2013-08-27T02:29:06.467 回答
1

您可以使用自由变量捕获将数据传递给匿名内部类,将要捕获其值的任何变量声明为final

public void myFunction(final int magicNumber) {
  new Thread() {
    @Override public void run() {
      System.out.println("I can access the magic number: " + magicNumber);
    }
  }.start();
}
于 2013-08-27T03:51:00.733 回答
0

One option is to declare a single, abstract class that anonymous classes can implement:

public interface IDontWorkForSomeReasonThread {
    public void NoNoYouCantCallMe(String s);
}

public static abstract class MyAbstractThread 
extends Thread 
implements IDontWorkForSomeReasonThread { }

public static void main (String[] args) throws java.lang.Exception {
    IDontWorkForSomeReasonThread t = new MyAbstractThread() {
      public void NoNoYouCantCallMe(String s){}
    };

    t.NoNoYouCantCallMe( "foo" );
}
于 2013-08-27T02:21:39.277 回答