#How to invoke method defined inside anonymous class from outside it

1 messages · Page 1 of 1 (latest)

severe pasture
#

Hello! I'm trying to learn about anonymous inner classes and can't seem to find a way to call a method that I defined inside the anonymous class from outside of it, even though overriding seems to work perfectly fine. Calling the method from inside the anonymous class (through the initializer) als works fine.

Code:


    void print() {
        System.out.println("I'm extended");
    }
}

public class CursedOriginal {

    //Declare and instantiante anonymous class
    static ExtendedByAnonymous object = new ExtendedByAnonymous() {
        //Initialization Block
        {
            System.out.println("anonymous object created");
            anonprint();
        }

        @Override
        void print() {
            System.out.println("overriden print");
        }

        void anonprint() {
            System.out.println("anonymous print");
        }

    };

    public static void main(String[] args) {
        System.out.println("in main");
        object.print();
        object.anonprint(); //Cannot resolve method 'anonprint' in 'ExtendedByAnonymous'
    }
}

/*
OUTPUT (without object.anonprint();)
anonymous object created
anonymous print
in main
overriden print
 */```

It seems like the compiler is trying to find the method by looking in the ExtendedByAnonymous class, even though, as far as I know, the creation of an anonymous inner class is supposed to generate a new class that simply extends ExtendedByAnonymous, and then create an instance of that new class. Instead of realizing that  ```object``` refers to that generated class, it seems to think that it's a reference to an object of ExtendedByAnonymous.

Is my thinking incorrect? If not, why is the compiler not finding the ```anonprint``` method?
tender sparrowBOT
#

<@&987246399047479336> please have a look, thanks.

tender sparrowBOT
#

While you are waiting for getting help, here are some tips to improve your experience:

Code is much easier to read if posted with syntax highlighting and proper formatting.

If nobody is calling back, that usually means that your question was not well asked and hence nobody feels confident enough answering. Try to use your time to elaborate, provide details, context, more code, examples and maybe some screenshots. With enough info, someone knows the answer for sure.

Don't forget to close your thread using the command </help-thread close:1027500463647621170> when your question has been answered, thanks.

severe pasture
#

In case it's relevant, I'm using Intelij IDEA JDK 15

rain citrus
severe pasture
rain citrus
#

Child object
Parent object

#

those codes are not equivalent

severe pasture
# rain citrus those codes are not equivalent

I see. I was under the impression that the compiler would essentially convert the anonymous class declaration into a normal class declaration with the type given as the superclass and then create an object of the newly created class instead of the class I gave it. Since that's not the case, do you know of any way to call the method defined inside the anonymous class without using one of the methods already defined in the parent class and overriding it to call the method I want? Like:

void print() {
  System.out.println("overriden print");
  anonprint();```
tender sparrowBOT
frail panther
#

the actual object is indeed ur subclass

#

the object is technically capable of doing the method. it's just ur variable that doesnt know about it

#

ur options are:

  1. create a non anonymous class
  2. use var
#

for latter, its:
var foo = new Foo() {...}

#

var is able to capture the type of the anonymous class

severe pasture
# frail panther var is able to capture the type of the anonymous class

Thank you! If I may ask another question, would you say its possible to achieve the same effect by changing the generated bytecode to make it so the variable is of the type of the newly created object, which should now be no longer "anonymous", instead of being of the parent class type? Or maybe some other fancy trick to do that, like reflection?

rain citrus
rain citrus
#

though there is indeed a way, in certain cases

severe pasture
rain citrus
#
var o = new Object() {
  int value = 5;
}
System.out.println(o.value);

This should compile

frail panther
#

yeah as said, var captures the type

severe pasture
#

Sadly I have to leave now but I'll try doing it by manually changing the bytecode and I'll share the results later if you're interested.

frail panther
#

lol okay. cheers

severe pasture
#

so i did the thing with the bytecode and it was... surprisingly simple, to the point of being anticlimatic

i just changed this:

  descriptor: ([Ljava/lang/String;)V
  flags: (0x0009) ACC_PUBLIC, ACC_STATIC
  Code:
    stack=2, locals=1, args_size=1
       0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #13                 // String in main
       5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: getstatic     #21                 // Field anonymousObject:Lurlhere/sitename/projectname/packagedenominator/ExtendedByAnonymous;
      11: invokevirtual #27                 // Method urlhere/sitename/projectname/packagedenominator/ExtendedByAnonymous.print:()V
      14: return

static {};
  descriptor: ()V
  flags: (0x0008) ACC_STATIC
  Code:
    stack=2, locals=0, args_size=0
       0: new           #32                 // class urlhere/sitename/projectname/packagedenominator/CursedOriginal$1
       3: dup
       4: invokespecial #34                 // Method urlhere/sitename/projectname/packagedenominator/CursedOriginal$1."<init>":()V
       7: putstatic     #21                 // Field anonymousObject:Lurlhere/sitename/projectname/packagedenominator/ExtendedByAnonymous;
      10: return```
#

to this:

  descriptor: ([Ljava/lang/String;)V
  flags: (0x0009) ACC_PUBLIC, ACC_STATIC
  Code:
    stack=2, locals=1, args_size=1
       0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #13                 // String in main
       5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: getstatic     #21                 // Field anonymousObject:Lurlhere/sitename/projectname/packagedenominator/CursedOriginal$1;
      11: invokevirtual #27                 // Method urlhere/sitename/projectname/packagedenominator/CursedOriginal$1.anonprint:()V
      14: return

static {};
  descriptor: ()V
  flags: (0x0008) ACC_STATIC
  Code:
    stack=2, locals=0, args_size=0
       0: new           #32                 // class urlhere/sitename/projectname/packagedenominator/CursedOriginal$1
       3: dup
       4: invokespecial #34                 // Method urlhere/sitename/projectname/packagedenominator/CursedOriginal$1."<init>":()V
       7: putstatic     #21                 // Field anonymousObject:Lurlhere/sitename/projectname/packagedenominator/CursedOriginal$1;
      10: return```