5

I can do this:

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

how do i (or can i) do this:

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");

and if i can't syntactically do this, can anyone explain the logic/implementation design that of why this would never work?

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

Edit: clarifications - I would like to create an anonymous class without saving it, and then instantiate an instance of that anonymous class. I only need 1 reference, since i don't plan on using this reference often (nor do i want anything else even in the same outer class to use it). However, I would like simply like to pass some data to this anonymous class only once (ideally the constructor, but you will notice that you can't actually override the constructor in Thread()).

It's really not a HUGE deal, I was just curious if this was doable, but it seems from some of the answers that it is feasible, but just not very pretty.

David T.
  • 22,301
  • 23
  • 71
  • 123
  • Remove the words `MyThread extends` and this will work. Of course, it won't do anything yet. – Dawood ibn Kareem Aug 27 '13 at 02:15
  • More importantly, WHY don't you want to "save" the class? – Strelok Aug 27 '13 at 02:22
  • @Strelok saving it means that it can be accidentally used elsewhere, by someone else, who might mess things up, for a particular anonymous class that I know for a fact will only be used once, by me only. (which is not that big of a deal, i agree, but i was just curious) – David T. Aug 27 '13 at 03:02
  • Wait so do you need to also implement an interface or not? Based on your latest edit your actual issue is how to have custom data in your anonymous class. Or is it both issues? – Paul Bellora Aug 27 '13 at 03:57
  • no need for interface implementation, although it may be necessary later on to be able to do something in addition to just save the data. – David T. Aug 28 '13 at 19:39

7 Answers7

5

Your question is a little confusing, but it sounds like you want a class that both extends Thread and implements some interface, but which can't be accessible outside of the method it's being used by (which would rule out even private nested classes). In that case use a local class:

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

EDIT: In response to your update, you can naturally give the local class a constructor and pass in data, or just let it close over final variables in the outer method.

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
3

if i can't syntactically do this, can anyone explain the logic/implementation design that of why this would never work?

I can explain. If you have an expression foo.bar(...) in Java, the compiler must make sure that the static (compile-time) type of the expression foo supports the method bar(). In your first case, the expression on the left is the anonymous class creation expression, so its static type is the anonymous class which has the method.

However, in your second case, the expression on the left is a variable. The static type of a variable is the type that the variable was declared with. In Java, variables must be declared with an explicit type (no var or auto like some other languages). Therefore, its static type must be a named type. Thread and no other named type supports the method NoNoYouCantCallMe(); only the anonymous class supports this method, and you can't declare a variable of anonymous class type. That's why it is not syntactically possible.

However, I would like simply like to pass some data to this anonymous class only once (ideally the constructor, but you will notice that you can't actually override the constructor in Thread()).

This is simple. You don't need to explicitly pass data into the anonymous class, because inside anonymous classes and local classes you automatically have access to final variables from the surrounding scope. So instead of passing data in, you just directly use data from the outside.

final String someData = "blah";

Thread t = new Thread() {
    public void run() { doStuffWith(someData); }
};
newacct
  • 119,665
  • 29
  • 163
  • 224
2

If you really wanted to do something obscene like that without using an interface or an abstract class, you can call it via reflection:

@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!" );
}

But this is pointless... It's much better to go with a simple solution of having an interface or an abstract class like others suggested.

Strelok
  • 50,229
  • 9
  • 102
  • 115
1

There are two ways of accessing method of anonymous classes:

  • By implementing an interface or extending a class, and later calling methods that you implemented in your anonymous class, or
  • By using reflection (I assume you know how it's done, but do not want to do it).

Java does not provide a way of capturing the type of the anonymous class statically, e.g. in a way similar to C#'s var keyword.

In your case, you can create an abstract type with the void NoNoYouCantCallMe(String) method, and use that class as the base of your anonymous class, like this:

abstract class MyThreadBase extends Thread {
    public abstract void YesICanCallYou(String s);
}
...
MyThreadBase t = new MyThreadBase() {
    public void YesICanCallYou(String s){}
};
...
t.YesICanCallYou();
Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
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.

Bill K
  • 62,186
  • 18
  • 105
  • 157
1

You can pass data to an anonymous inner class using free variable capture, declaring any variables whose values you want to capture as final:

public void myFunction(final int magicNumber) {
  new Thread() {
    @Override public void run() {
      System.out.println("I can access the magic number: " + magicNumber);
    }
  }.start();
}
jacobm
  • 13,790
  • 1
  • 25
  • 27
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" );
}
Andy Thomas
  • 84,978
  • 11
  • 107
  • 151