外部访问内部私有类字段的Java最佳实践

时间:2017-07-28 14:21:18

标签: java access inner-classes

我搜索了很多我的问题的答案并找到了几个选项,想知道你最好的做法是什么。

用例: 所以我有一个单例类AccontManager,它有一个只与它相关的内部类,它是一个User类。

public class AccountManger {

private static final AccountManger ourInstance = new AccountManger();
private User user;

public static AccountManger getInstance()
{
    return ourInstance;
}

private AccountManger(){}

public User getUser(){
    return this.user;
}

private class User{
    private String id;

    private User (String id){
        this.id = id;
    }
}
}

现在,情况是User字段必须访问外部包类,但用户类仅对此单例类是唯一的,因此内部类必须是私有的。

最理想的是,在内部类中创建公共getter方法以获取用户字段是最好的,但由于内部类是私有的,所以这是不可能的。

可能的做法:

  1. 练习:在AccountManager字段的外部User类中创建相应的getter方法。

    缺点:用户字段与User相关,因此外部类不应该在其字段中使用getter方法。

    代码示例

    public class AccountManger {
    
        private static final AccountManger ourInstance = new AccountManger();
        private User user;
    
        public static AccountManger getInstance()
        {
            return ourInstance;
        }
    
        private AccountManger(){}
    
        public User getUser(){
            return this.user;
        }
    
        public String getUserId() // <-- get User id
        {
            return user.id;
        }
    
        private class User{
            private String id;
    
            private User (String id){
                this.id = id;  
         }  
    }
    }
    
  2. 练习:将User修饰符更改为public,但保持构造函数为私有,因此无法实例化。

    缺点:内部User类将作为AccountManager单例类的成员显示,它不应该是。{1}}。

    代码示例

    public class AccountManager {
    
        private static final AccountManger ourInstance = new AccountManager();
        private User user;
    
        public static AccountManager getInstance()
        {
            return ourInstance;
        }
    
        private AccountManger(){}
    
        public User getUser(){
            return this.user;
        }
    
        public String getUserId() // <-- get User id
        {
            return user.id;
        }
    
        private class User{
            private String id;
    
            private User (String id){
                this.id = id;
            }
        }
        }  
    
  3. 实践

    • 创建公共界面,例如IUser
    • 让内部类User实现该接口
    • 添加到外部类,在本例中为AccountManager添加到User实例的getter方法

    缺点:需要使用接口才能从User获取数据。

    代码示例

    public class AccountManager {
    
    private static final AccountManager ourInstance = new AccountManager();
    private User user;
    
    public interface IUser{
        String getName();
    }
    
    private AccountManager(){}
    
    public static AccountManager getInstance(){
        return ourInstance;
    }
    
    public User getUser(){
        return this.user;
    }
    
    private class User implements IUser{
        private String id;
    
        private User(String id){
            this.id = id;
        }
    
        @Override
        public String getName() { // <-- get user id
            return id;
        }
    }
    }
    


    那么你怎么看? 列出的任何一个选项?
    还有其他方法吗?

  4. 感谢您的输入

3 个答案:

答案 0 :(得分:3)

我会说User类需要private,并且AccountManager应该对其属性getterssetters实施。< / p>

您不必知道什么是User,因为AccountManager会告诉您能够知道什么。作为一个加号,你可以服从Law of Demeter,这总是好事。

IMO,内部类应该用作使外层类中的代码更清晰的方法,并且它们不应该在其他地方使用。

但我想让User私有的构造函数比什么都好。

答案 1 :(得分:0)

我看到了三种替代方法:

  • 使User类成为独立和公共(如果需要,给它一个AccountManager字段)。然后用户成为您的公共API的一部分 - 可能不是您想要的。

  • 在AccountManager类中,为公共相关的用户属性创建getter和setter。这使用户实体成为客户经理的不可见组件。 (打个比方:如果你谈论你的汽车的马力,你隐藏的事实是它不是汽车本身的属性,而是它的引擎,这很好)。

  • 如果您希望用户的概念成为API的一部分,但仍希望保持内部User类的私有性,请使用公开相关的方法创建一个接口IUser,并让User实现IUser。然后,您可以在AccountManager中公开public IUser getUser()方法,外部世界只能看到界面中声明的功能。

答案 2 :(得分:0)

看作AccountManager(你拼写错误&#34;经理&#34;在你的代码示例中)是一个单身人士课程,它不会真正有效地发挥作用,但你自己也说过#&# 34;用户类仅对此单例&#34;是唯一的,因此User类的目的可能会更好地表示static。< / p>

无论如何,在原始代码示例中,您添加了一个方法public User getUser()。由于课程Userprivate,我真的没有注意到这一点,因为在课程AccountManager之外,对User对象的任何引用都将没用,因为你将永远无法访问其任何成员或声明一个User变量,以便为其分配如此获得的User引用。我可以设想的唯一可能的用例是AccountManager声明public(或任何高于User的访问修饰符)接受User参数的方法。但即便如此,我也会质疑这样的设计是否真的是你想要的。

所以你可能想要考虑一下你是否真的需要public User getUser()方法,只要User保留private。这已经引导我们解决您的原始问题。我认为你提出的第一个解决方案更好。对我而言,这似乎正是允许超类访问“私人”的原因。子类的成员。引自stackoverflow上的this answer

  

内部类(为了访问控制的目的)被认为是包含类的一部分。这意味着可以完全访问所有私人。

因此,如果您认为UserAccountManager的一部分,那么您不必为从private内访问其AccountManager字段感到内疚但是从外部User,因为显然,Java的设计者也会这样想。

最后,如果您不想在id存在期间更改字段User,则可以id final