2

I'm trying to call a method, setPostal(String post) I made from an anonymous class, but for some reason the compiler doesnt even recognize it in main. Any reason why this is? Part of my code (address is an inner class of Student):

Student

public class Student implements Gradeable, Cloneable {
    String name;
    int id;
    Address address;

    public Student() {
        name = "unknown";
        address = new Address();
    }

    public Student(String name, int id, Integer... option) {
        this.name = name;
        this.id = id;
        if (option.length > 0) {
            if (option[0] > 0) {
                address = new Address() {
                    String postal;

                    public void setPostal(String post) {
                        postal = post;
                    }

                    @Override
                    public String toString() {
                        return "Street: " + street + " | number: " + number
                                + " | town: " + town + " | province: " + province
                                + " | Postal Code: " + postal;
                    }
                };
            }
        } else {
            address = new Address();
        }
    }

    Address getAddress() {
        return address;
    }

    void setAddress(Address address) {
        this.address = address;
    }

    public static void main(String[] args) throws CloneNotSupportedException, InterruptedException {
        Student test = new Student("ryan", 41254, 1);
        test.getAddress().setPostal("L1G 6h9") // Compiler: Cannot resolve symbol 'setPostal'
    }
}

Address

public class Address implements Cloneable {
    String street;
    int number;
    String town;
    String province;
    String zip;

    public Address() {

    }

    public Address(String street, int number, String town,
                   String province, String zip) {
        this.street = street;
        this.number = number;
        this.town = town;
        this.province = province;
        this.zip = zip;
    }

    String getStreet() {
        return street;
    }

    int getNumber() {
        return number;
    }

    String getTown() {
        return town;
    }

    String getProvince() {
        return province;
    }

    String getZip() {
        return zip;
    }

    @Override
    public String toString() {
        return "Street: " + street + " | number: " + number
                + " | town: " + town + " | province: " + province
                + " | ZIP: " + zip;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Address)
            if (((Address) obj).getStreet().equals(street)
                    && ((Address) obj).getNumber() == number
                    && ((Address) obj).getTown().equals(town)
                    && ((Address) obj).getProvince().equals(province)
                    && ((Address) obj).getZip().equals(zip)){
                System.out.println("Address equal");
                return true;
            }
        System.out.println("Address not equal");
        return false;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
5
  • You need to post your Address class, or at least an interface for it, which includes setPostal(String):void. Commented Jan 13, 2015 at 19:08
  • Can you show the Address class? Commented Jan 13, 2015 at 19:08
  • possible duplicate of call anonymous class method in java Commented Jan 13, 2015 at 19:10
  • Is Address nested inside Student? Please fix your code. Also, why is Address not public? I moved Address out of Student, looks like you just pasted it wherever. Commented Jan 13, 2015 at 19:36
  • Yes, it's the inner class of Student. I stated it in the OP. My mistake if it wasn't clear enough. Commented Jan 13, 2015 at 20:07

4 Answers 4

2

Presumably, whatever Address is, it doesn't have a setPostal(String) method.

Instance methods, at compile time, are resolved based on the type of the value on which they are invoked.

You're invoking it

test3.getAddress().setPostal("L1G 6h9") //Compiler: Cannot resolve symbol 'setPostal'

on an expression of type Address, which doesn't have such a method, regardless of the fact that a subtype (the anonymous subclass) does.


The only way (minus reflection) to invoke a method that is declared only in an anonymous class is to invoke the method on the value returned by the anonymous class instance creation expression.

new Address() {
    String postal;
    public void setPostal(String post) {
        postal = post;
    }

    @Override
    public String toString() {
        return "Street: " + street + " | number: " + number
                        + " | town: " + town + " | province: " + province
                        + " | Postal Code: " + postal;
        }
    }
}.setPostal("whatever");
Sign up to request clarification or add additional context in comments.

4 Comments

I really don't get if test3 instance not present how can we call method on that? please can you assist me
@atish It might be a typo. It might just not be shown. Either way, they would get a completely different error.
ya, that's my mistake. Im only posting part of my code, so I accidentally erased the instantiation of test3. I changed test3 to test so that it makes sense now.
You could also return this from the setPostal() if you wanted to chain multiple.
1

The type of the expression test3.getAddress() is Address, which means you can only call methods that are declared in the Address class (or a supertype of it).

The compiler doesn't figure out that at run time, this expression is going to evaluate to be an object of your special anonymous class. It's not the compiler's job to run your program for you, so it can work out the class of every object you might use. So the new method setPostal (which appears to only exist in your anonymous class) can't be used here.

Comments

1

Anonymous classes are a bad idea. Try to create a concrete class, then instantiate that.

You can declare this inside your class to hide it from the outside.

public class Student implements Gradeable, Cloneable {
    // ...
    private static class PostalAddress extends Address {
        String postal;

        public PostalAddress {
            super();
        }        

        public void setPostal(String post) {
            postal = post;
        }

        @Override
        public String toString() {
            return "Street: " + street + " | number: " + number
                + " | town: " + town + " | province: " + province
                + " | Postal Code: " + postal;
        }
    }
    // ...
}

Then use it

public Student(String name, int id, Integer... option) {
    this.name = name;
    this.id = id;
    if (option.length > 0) {
        if (option[0] > 0) {
            address = new PostalAddress();
        }
    } else {
        address = new Address();
    }
}

Then all you have to do is cast the address in test.

public static void main(String[] args) throws CloneNotSupportedException, InterruptedException{
   Student test = new Student("ryan", 41254, 1);
   ((PostalAddress) test.getAddress()).setPostal("L1G 6h9");
}

Note: if option.length > 0 but option[0] <= 0, your address object will be null.

6 Comments

This won't make the slightest bit of difference, because the return type of getAddress() is still Address, not PostalAddress.
Well, that just means that the architecture of the code will need to be re-thought.
Maybe. But the point is, using a named class instead of an anonymous class is not going to fix OP's issue.
The Student call can accept a generic argument which is of type Address. Student<T extends Address> then set the return type of getAddress() to T.
Well this will... ((PostalAddress)test3.getAddress()).setPostal("L1G 6h9");
|
0

For those getting:

"Cannot find symbol" FUNCTION_NAME_HERE.

When trying to use an anonymous inner class on the fly:



WRONG: error: cannot find symbol "myMethod"

Object t = new Object(){ 
    public void myMethod(){
        System.out.println("[METHOD]");
    };;
};;
t.myMethod();

BECAUSE:

Though method exists, your anonymous object is downcasted to Object, which does NOT have method.


WRONG: error: cannot find symbol "myMethod"

class Test{};
Test t = new Test(){
    public void myMethod(){
        System.out.println("[METHOD]");
    };;
};;
t.myMethod();

BECAUSE:

Same reason as previous. (But we are on the right track.)



CORRECT:

abstract class Test{ abstract public void myMethod(); }
Test t = new Test(){
    public void myMethod(){
        System.out.println("[METHOD]");
    };;
};;
t.myMethod();

Congratulations:

You've created a class on the fly in which there can only be one instance.

Usage: Small helper functions in a function.

Comments

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.