无法调用匿名 Class 方法

Cannot call an Anonymous Class Method

我正在尝试调用一个方法,setPostal(String post) 我从一个匿名 class 生成的,但出于某种原因,编译器甚至无法在 main 中识别它。这是什么原因?我的部分代码(地址是Student的内部class):

学生

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

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

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

你正在调用它

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

Address 类型的表达式上,它没有这样的方法,不管子类型(匿名子 class)是否有。


调用仅在匿名 class 中声明的方法的唯一方法(减去反射)是在匿名 class 实例创建表达式返回的值上调用该方法。

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

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

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

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

您可以在您的 class 中声明它以从外部隐藏它。

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 > 0option[0] <= 0,您的 address 对象将是 null.

获得者:

"Cannot find symbol" FUNCTION_NAME_HERE.

尝试使用 匿名内部 class 时:



WRONG: 错误: 找不到符号 "myMethod"

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

因为:

虽然方法存在,但是你的匿名 object 被向下转换为 Object,它 没有方法。


WRONG: 错误: 找不到符号 "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();

恭喜:

您即时创建了一个 class,其中只能有一个实例。

用法:函数中的小辅助函数。