简体   繁体   中英

How to get one particular atribute from a class with several atributes

public  class Person {
String name;
int year;
int month;
int day;
String email;
String phonenr;

public Person(String name, int year, int month, int day, String email, String phonenr) {
    this.name = name;
    this.year = year;
    this.month = month;
    this.day = day;
    this.email = email;
    this.phonenr = phonenr;
}

I have this object. I want to access email atribute only in another class so i could check if the email is valid using assert in test directory. How do I access only email atribute from Person in another class to use it later to validate the email?

This is the class i want to access email atribute from.

public class PersonValidator {
public static boolean email(String email){
    Person onePerson = new Person();
    return false;
}

}

This is test class to test if email is valid:

class PersonRegisterTest {

@Test
void checkValidEmail() {
 assertTrue(PersonValidator.email("adrianJames@oslomet.no"));
 assertTrue(PersonValidator.email("example@example.com"));
 assertTrue(PersonValidator.email("example.example@yahoo.com"));

}

Good practice in Java is to make all fields private , and create "getters and setters", ie functions to get and set values. For example:

public class Person {

    private String email;

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEmail() {
        return this.email;
    }
}

This way of doing things has several advantages:

  • If you you decide you want to change what values are allowed in a field, you can do that using the setter method. For example, if you want to impose a minimum length on emails, you can put if (email.length() < 10) return; in your method to prevent emails shorter than 10 characters

  • If you decide you want to retrieve emails over the internet or some other way, you do not have to change your code.

  • Many tools and frameworks expect Java objects to be in this format. Notable examples include Jackson for JSON serialization, and Spring/Spring Boot, for web application development, as well as many many more.

PS if you are sick of writing getters and setters:

  1. Check if your IDE has a way of automatically generating them (most of them do)
  2. Look into a library called Lombok, it provides the @Data annotation which can generate these methods automatically at compile time. ( https://projectlombok.org/ )

Its better to keep your data members/variables inside the class Person as private, and you can add getters and setters method, which you can access from outside the class and using which you can access the data members/variables of your class. You can do something like:

public  class Person {
String name;
int year;
int month;
int day;
String email;
String phonenr;

public Person(String name, int year, int month, int day, String email, String phonenr) {
    this.name = name;
    this.year = year;
    this.month = month;
    this.day = day;
    this.email = email;
    this.phonenr = phonenr;
}

   public String getEmail()
   {
      return this.email;
   }
}

First add getters to you Person object/class and make the internal state of the object only accessible via the getters:

public class Person {
    private final long id;
    private final String name;
    private final String email;

    public Person(long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public String getEmail() {
        return email;
    }

    // Other 2 getters
}

Then build a validator that can validate email address format, or better use a library (like https://commons.apache.org/proper/commons-validator/ ) for that:

public final class EmailValidator {

    private EmailValidator() { }

    public static boolean isValidEmail(String email) {
        // check if valid email and return true or fale
    }
}

Call the validator by getting the email address from new person by calling the getter. The validator shouldn't have any knowlegde of the Person object.

public static void main(String[] args) {
    Person newPerson = new Person(1L, "test user", "valid@hotmail.com");

    if (EmailValidator.isValidEmail(newPerson.getEmail())) {
        System.out.println("Valid email address");
    } else {
        System.out.println("Invalid email address");
    }
}

For your case I'd make the the Person.email as package private - so it can stay as it is now, and put the PersonValidator class in the same package where you have Person class.
That would make you able to pass whole Person object to validator method like:

public static boolean email(Person person) {
    String email = person.email;
    return false;
}

But this is very isolated and not well designed. Also, there are plenty of ways being able to call methods from one class in another. Eg create isEmailValid method in Person class and where you could directly use the email variable when calling PersonValidator.email(email) .

Many of those uncommon approaches are most likely to invalidate SOLID, clean code and some other principles (like too tight coupled classes).

Like other answers stated it's much better to keep object fields well encapsulated (ie using private access modifier) and later access them with get/set methods.
Then regardless if you first create Person object (eg parse the Person list from file and then validate if they have correct email or get request params from smth like HTTP request for new person) you could call PersonValidator.email(personObject.getEmail() or PersonValidator.email(emailParam) .
The package of keeping the PersonValidator class depends only on the convention of your project.

Having the "getters/setters" methods in an object, ie getEmail() setEmail(String email) getName() setName(String name) is common and good convention to keep your code well designed.
It's a good practice to implement such when applicable.

Just for further reading:

Having public getter method for email field in Person class shouldn't invalidate any coding standards (not even YAGNI-You Ain't Gonna Need It), because there could be plenty of future usages (eg displaying it for person/client using your program).

The mentioned encapsulation term in short words, it's about keeping inner implementation of an object inside it - ie not making it visible by other classes.
There're situations where an object modifies its inner fields by its methods, which are not the "setters" ones, but the current field value should always be accessed with getField() method.

"Don't overdesign, but keep future growth in mind" (i'm probably not citing anyone:P ).
The further use case could be to validate more field members of a Person object, which could result in having:

class PersonValidator {
    public static boolean validatePerson(Person person) {
        return validEmail(person.getEmail()) &&
                //other validators when needed &&
                validPhone(person.getPhonenr());
    }
    //very hard to validate
    //most likely if has just a numbers (replacing "-" before)
    //and only a length check (at least 3 without country code)
    public static boolean validPhone(String phone) {
        return false; //
    }
    public static boolean validEmail(String email) {
        return false;
    }
}

Again, as stated in other answers, it's much better to try searching for existing validator libraries, than writing new one - REALLY, REALLY .
There're different lenths and formats of phone numbers (mostly dependend on country), check this out .
The shortest valid email address could be a@a , or " "@a , but those are local email addresses. Check this wiki or this github gist to see some strange valid examples.
And the name, it depends on country laws and they are some which probably could accept the first names such as "A" or "Ben11" and the weirdest surname in Poland is "Cyps Albo Zyps".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM