4

It's possible to make anonymous classes have new fields in Java:

class A {
   public static void main(String[] args) {
       Object o = new Object() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }
       };
       System.out.println(o.x);
   }
}

But they can't be accessed in this example, because o is of type Object:

$ javac A.java && java A
A.java:10: cannot find symbol
symbol  : variable x
location: class java.lang.Object
       System.out.println(o.x);
                           ^
1 error

Note that o is actually not an Object, it's an instance of a different class extending Object. This class has one public field x. Does this class have a name? How can I make o be the proper type so I can get access to o.x? (Note that it's possible to do this with reflection, but I want to do it statically).

12
  • I don't think you can without using an interface. Commented May 10, 2013 at 21:26
  • 1
    Have you considered declaring the class within the method? At that point you could get at it... Commented May 15, 2013 at 18:17
  • 1
    @Dog: Why do you think it should be possible? The only way of expressing a variable of that type is by giving the type a name. It doesn't surprise me at all that this can't be done, to be honest. Commented May 15, 2013 at 21:04
  • 1
    @Dog: No, there's no "surely" about it. newacct's answer isn't just limited to a field - it's also limited to an instance that you don't want to do anything else with. This is simply not something anonymous inner classes were designed for. Commented May 16, 2013 at 5:49
  • 1
    @Dog: Not at all. That's relying on a compiler implementation detail and it requires recompilation. It's horribly brittle. Just don't do it. Give it up - create a named type instead. You still haven't said anything about why you want to work against the language in this way. Commented May 16, 2013 at 15:30

4 Answers 4

3

This class does have a name. It's A$1. However, you can't access this at compile time (the compiler creates A$1 for you). Thus, you can't access the field without reflection.

If you're in Eclipse, you can use Source menu (AltShiftS) → Convert Anonymous Class to Nested to convert it to a "real" class automatically.

Alternatively, you could have:

class A {
   public static void main(String[] args) {
       I o = new I() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }
           public int getX() { return x; }
       };
       System.out.println(o.getX());
   }
   interface I {
       public int getX();
   }
}

EDIT: Here's a really evil way to accomplish this that you should not do:

class A {
   public static void main(String[] args) {
       Object o = new Object() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }

           public Object clone() {
               // BAD BAD BAD
               return x;
           }
       };
       try {
           System.out.println(o.clone());
       } catch (CloneNotSupportedException cnse) {
           assert false;
       }
   }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yup. There really isn't a way to do it without changing the question.
3

You could access it directly on the anonymous class creation expression:

class A {
   public static void main(String[] args) {
       System.out.println(new Object() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }
       }.x);
   }
}

But then, you can't otherwise use the object created anymore, so it's kinda useless.

Comments

1

Java is not a C#, if I'am not mistaken such syntax sugar is allowed there. You can have a look at sun.reflect.MagicAccessorImpl. But this class is not a common practice. Used only for auto generated code. If you extend MagicAccessorImpl JVM will not perform field access level check. So you can do thing like this:

// ----- A.java -----
class A {
    private int privateField = 5;
}

// ----- B.java -----
class B extends sun.reflect.MagicAccessorBridge {
    public static void main(String[] args) {
        A a = new A();
        a.privateField = 10;
        System.out.println(a.privateField);
    }
}

// ----- MagicAccessorBridge.java -----
package sun.reflect;

public class MagicAccessorBridge extends MagicAccessorImpl {
    // Since MagicAccessorImpl is package-private, we'll make a public bridge
}

Taken from here

Comments

0
+50

like this

class A {
   public static void main(String[] args) {
       Object o = new Object() {
           public int x = 0;
           {
               System.out.println("x: " + x++);
               System.out.println("x: " + x++);
           }
       };
       //System.out.println(((A$1)o).x);
   }
}

compile once

$ java A.java

uncomment print line

recompile & run

$ java A.java && java A
x: 0
x: 1
2

3 Comments

howcome it needs to be compiled twice?
@Dog: Because the first time it will create an A$1.class file, and then second time it will consume it, while also recreating it. This is really brittle, and I'd strongly suggest you don't do it.
Don't try this at home!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.