簡體   English   中英

Java:對外部類私有成員的匿名內部類實例初始化程序訪問

[英]Java: Anonymous Inner Class Instance Initializer Access to Outer Class Private Members

我遇到無法更改一組類的主要API的情況,但是我需要從檔案數據構造一個新實例,包括設置大量私有字段。

到目前為止,我的想法是創建一個靜態工廠方法,該方法將從檔案中生成我的實例,如下所示:

版本1:

public class Item {
    private Long id;

    public static Item fromArchived(final ArchivedItem archived) {
        return new Item(){{
            this.id = archived.getId();
        }};
    }
}

IntelliJ IDEA沒有給我任何紅線,在運行Maven生成以下內容之前,我不知道有任何問題:

error: id has private access in Item

相反,這有效:

版本2:

public class Item {
    private Long id;

    public static Item fromArchived(final ArchivedItem archived) {
        Item item = new Item(){{
//            this.id = archived.getId();
        }};

        item.id = archived.getId();

        return item;
    }
}

我一直在回顧我的核心 Java 知識 ,關於版本1為何不起作用的唯一模糊的猜測是實例初始化程序(雙括號初始化)以某種方式出現在靜態上下文中,這實際上沒有任何意義無論是。 思考?

編輯

我認為問題的最初形式含糊。 我正在尋找的答案是一個解釋原因,為什么我可以看到靜態方法主體中父級的私有id字段,但是卻在同一靜態方法內的匿名子類的實例初始化器主體中卻看不到它的可見性。

其他答案很准確,但這是我的看法。

public class Item {
    private Long id;

    public static Item fromArchived(final ArchivedItem archived) {
        return new Item(){{
            this.id = archived.getId();
        }};
    }
}

在這里,靜態方法生成一個擴展Item的匿名類。 Item $ id將在此匿名類中隱藏。

下面的代碼片段與前面的代碼片段等效,但是作為一個命名嵌套類,它公開了一個構造函數方法,而不是一個調用構造函數的方法。

public class Item {
    private Long id;

    class FromArchived extends Item {
        public FromArchived(final ArchivedItem archived) {
            this.id = archived.getId();
        }
    }
}

不管訪問是來自命名類,嵌套類還是匿名類,可見性修飾符都將強制實施。

最后,以下代碼段應在類中正常工作,您可以完全訪問該類的所有私有字段和方法。

public class Item {
    private Long id;

    public static Item fromArchived(final ArchivedItem archived) {
        Item item = new Item();
        item.id = archived.getId();
        return item;
    }
}

無論您是在構造函數,方法還是靜態方法中,都是如此。

您一直在創建擴展Item類的匿名內部類。 private變量可以在聲明的同一個類中訪問。因此,您不能訪問anonymous內部類中的Item類私有變量。

在第一個示例中, this是指匿名(內部) Item而不是外部Item ,這就是為什么您會收到錯誤消息的原因。

使用下面的構造,您可以在內部創建實例初始化塊的Item子類。

return new Item() { // equivalent to: class AnonymousItem extends Item
    {
        this.id = archived.getId();
    }
};

子類無權訪問父類的私有字段,因此編譯器會為您生成錯誤。

代替編寫this.id = ...您可以編寫((Item) this).id = ...super.id = ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM