001    package ps6;
002    
003    /** An Address is an immutable record type defining a location.
004     *   @specfield num     : integer // number of the building along the street
005     *   @specfield name    : String  // name of the street
006     *   @specfield zipcode : String  // US ZIP code
007     */
008    public class Address {
009    
010        // AF(x):
011        //    num = x.streetNum
012        //    name = x.streetName
013        //    zipcode = x.zipcode
014        // RI:
015        //    num >= 0
016        //    streetName != null &&
017        //    zipcode != null
018    
019        private final int streetNum;
020        private final String streetName;
021        private final String zipcode;
022    
023        /**
024         * Address Constructor
025         *
026         * @requires num > 0 && name != null && zipcode != null
027         * @effects returns an Address with the given field values
028         * */
029        public Address (int num, String name, String zipcode) {
030            if (num < 0) {
031                throw new IllegalArgumentException("Negative street number");
032            } else if (name == null) {
033                throw new NullPointerException("Street name is null");
034            } else if (zipcode == null) {
035                throw new NullPointerException("Zip code is null");
036            }
037            this.streetNum = num;
038            this.streetName = name.intern();
039            this.zipcode = zipcode.intern();
040        }
041    
042        /**
043         * Get the street number
044         * @returns this.num
045         */
046        public int getNum () {
047            return streetNum;
048        }
049    
050        /**
051         * Get the name of the street
052         * @returns this.name
053         */
054        public String getName () {
055            return streetName;
056        }
057    
058        /**
059         * Get the zipcode for the street
060         * @returns this.zipcode
061         */
062        public String getZipcode () {
063            return zipcode;
064        }
065    
066        public boolean equals (Object other) {
067            return (other instanceof Address) && equals((Address) other);
068        }
069    
070        public boolean equals (Address other) {
071            //can use referential equality because strings are interned
072            return (other != null) &&
073                zipcode == other.zipcode &&
074                streetName == other.streetName &&
075                (streetNum == other.streetNum);
076        }
077    
078        public int hashCode () {
079            return streetName.hashCode() + zipcode.hashCode() * 7 + streetNum * 17;
080        }
081    
082        /**
083         * @return a String representation of this address in the format:
084         * "num name zipcode"
085         **/
086        public String toString () {
087            return new String (streetNum + " " + streetName + " " + zipcode);
088        }
089    }