无法调用匿名类方法

时间:2015-01-13 19:04:46

标签: java anonymous-class

我试图调用一个方法,setPostal(String post)我是从一个匿名类创建的,但由于某种原因,编译器甚至没有在main中识别它。这是什么原因?我的部分代码(地址是学生的内部类):

学生

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'
    }
}

地址

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();
    }
}

4 个答案:

答案 0 :(得分:2)

据推测,无论Address是什么,它都没有setPostal(String)方法。

在编译时,实例方法将根据调用它们的值的类型进行解析。

你正在调用它

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

在类型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;
        }
    }
}.setPostal("whatever");

答案 1 :(得分:1)

表达式test3.getAddress()的类型是Address,这意味着您只能调用Address类(或其超类型)中声明的方法。

编译器没有弄清楚在运行时,此表达式将评估为您的特殊匿名类的对象。编译器的工作不是为您运行程序,因此它可以计算出您可能使用的每个对象的类。因此,新方法setPostal(似乎只存在于您的匿名类中)无法在此处使用。

答案 2 :(得分:1)

匿名课程是一个坏主意。尝试创建一个具体的类,然后实例化它。

您可以在课堂内声明这一点,以便将其隐藏在外面。

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;
        }
    }
    // ...
}

然后使用它

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();
    }
}

然后您只需要在test中投射地址。

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

注意:如果option.length > 0只有option[0] <= 0,则address对象将为null

答案 3 :(得分:0)

对于那些得到的人:

“找不到符号” 。FUNCTION_NAME_HERE。

尝试动态使用匿名内部类时:



错误:错误:找不到符号“ myMethod”

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

由于

尽管存在方法,但您的匿名用户 对象向下转换为对象 没有方法。


错误:错误:找不到符号“ myMethod”

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

原因:

与以前相同的原因。 (但是我们走在正确的轨道上。)



正确:

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

祝贺

您正在动态创建一个类,其中只能有一个实例。

用法:函数中的小助手功能。