Java 是否有方法访问对象中的对象?

Java 是否有方法访问对象中的对象?,java,hashmap,composition,Java,Hashmap,Composition,我通过构建一个简单的目录来练习java。我有四节课。这些是: 人 地址 接触 测试类 person.get(1).setStreet("place"); 我已经完成了这个系统的创建,它按照我想要的方式工作。为此,我为人员、地址和联系人制作了3个不同的数组。为了将人员、地址和联系人链接在一起,我将它们分别放在具有相同索引号的数组中。(不是字面上把它们联系在一起,只是一种在编辑一个人时知道要访问哪个地址或联系人的方法) 但是现在,我想优化它。我想创建一个HashMap来容纳一个地址和联系人在其中的

我通过构建一个简单的目录来练习java。我有四节课。这些是:

  • 地址

  • 接触

  • 测试类

  • person.get(1).setStreet("place");
    
    我已经完成了这个系统的创建,它按照我想要的方式工作。为此,我为人员、地址和联系人制作了3个不同的数组。为了将人员、地址和联系人链接在一起,我将它们分别放在具有相同索引号的数组中。(不是字面上把它们联系在一起,只是一种在编辑一个人时知道要访问哪个地址或联系人的方法)

    但是现在,我想优化它。我想创建一个HashMap来容纳一个地址和联系人在其中的人。有关更多信息,请参阅下面的代码

    个人类

    public class Person {
    private long Id;
    private firtName;
    private Address address;
    private Contact contact;
    
    //some setter and getter methods
    
    public Person(Address address, Contact contact) {
    this.address = address;
    this.contact = contact;
    }
    }
    
    地址类

    public class Address {
    
    private String street;
    private String city;
    private String province;
    
    
    //some setter and getter methods
    }
    
    联系方式

    public class Contact {
    
    private long Phone;
    private String Email;
    
    //some setter and getter methods
    }
    
    testClass.class

    public class testClass {
    
    public static void main(String[] args) {
    HashMap<Integer, Person> person = new HashMap<Integer, Person>();
    
    person.put(1, new Person(new Address(), new Contact)));
    person.get(1).setStreet("place");
    
    }
    
    }
    
    有没有一种方法可以直接访问/编辑此人的地址或联系人,而无需创建单独的数组或方法

    private Address address;
    private Contact contact;
    
    如果您将这些
    公开
    而不是
    私有
    ,您将能够像这样直接访问它们:

    Person person = new Person(new Address(), new Contact());
    
    Person p = person.get(1);
    String city = p.address.getCity();
    String email = p.contact.getEmail();
    
    但是,这违反了封装原则(应该隐藏内部字段,并且只允许通过方法进行访问)

    相反,您应该创建person类,如下所示:

    public class Person {
        private long Id;
        private firtName;
        private Address address;
        private Contact contact;
    
    //some setter and getter methods
    
        public Person(Address address, Contact contact) {
            this.address = address;
            this.contact = contact;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public Contact getContact() {
            return contact;
        }
    }
    
    并通过

    Person p = person.get(1);
    String city = p.getAddress().getCity();
    String email = p.getContact().getEmail();
    

    当一个人是地址、联系信息等的集合时,您应该为其设置getter和setter。然后你会写下这句话,把街道对准一个人:

    person.getAddress().setStreet("this and that")
    
    您还可以分配一个新地址:

    person.setAddress(new Address("streeetname", "cityname"))
    

    这是Java中的一个常见习惯用法,也是一条发展之路。拥有公共访问对象会产生新的问题,因为在使用它们的所有类中,如果没有副作用,就无法更改这种访问。

    我在这里看到的是依赖项反转问题。您的班级
    人员
    取决于
    地址
    联系人
    。在最纯粹的意义上,地址和联系人应该是接口,因此它们的实现可以在运行时交换

    public class Person {
      private long Id;
      private firstName;
      private Address address;
      private Contact contact;
    
      public Person(Address address, Contact contact) {
        this.address = address;
        this.contact = contact;
      }
    
      public Address getAddress() {
        return this.address;
      }
    
      public setAddress(Address address) {
        this.address = address;
      }
    
      public Contact getContact() {
        return this.contact;
      }
    
      public setContact(Contact contact) {
        this.contact = contact;
      }
    
    }
    
    然后您可以通过以下方式访问
    地址

    person.get(1).getAddress().setStreet("place");
    

    我不明白这里有什么问题。什么是“直接访问”,你说的是什么数组/方法?有地址和联系人的getter方法,并对它们进行修改。对你的命名稍加补充。联系人可能会被误认为是个人,而您的意思是联系信息。用单数称呼一组人也是令人困惑的。作为indexedPeople或peopleMap或至少是people更容易理解。通过创建方法getAddress()和getContact()意味着我正在创建这两个类的实例,对吗?但是,如果我必须提供100人,我还必须为每个getAddress和getContact提供100个参考资料吗?我不知道这是否是一个好的设计。当您使用“new”关键字时,您只创建这些类的一个实例。之后,Person类在内存中保存对其位置的引用,getAddress只返回同一个对象。除此之外,还有一个小小的补充:您不必在构造函数中传递地址和联系信息。您还可以为这些设置创建setter。但这在很大程度上取决于您的业务逻辑。我终于理解了背后的逻辑。谢谢你的帮助!我终于能够按照我想要的方式运行它了。这种方法的问题是,我需要为每个人的getAddress创建多少个引用。我想不出一个解决方案,如何使用前缀自动创建一个对象,以使这些引用不同。对不起,我不太明白这里的问题,现在我明白了。这是关于我使用person而不是person。得到(x),对吗?在我的示例中,person对象是person的一个实例。请参阅我对有关命名约定的问题的评论。