如何从具有多个属性的 class 中获取一个特定属性

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;
}

我有这个对象。我只想在另一个 class 中访问电子邮件属性,因此我可以使用测试目录中的断言检查电子邮件是否有效。如何仅访问另一个 class 中的人员的电子邮件属性以便稍后使用它来验证电子邮件?

这是我要从中访问电子邮件属性的class。

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

}

这是测试 class 以测试电子邮件是否有效:

class PersonRegisterTest {

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

}

最好将您的数据 members/variables 保存在 class Person 内部,并且您可以添加 getter 和 setter 方法,您可以从 class 外部访问并使用您可以在其中访问 class 的数据 members/variables。 你可以这样做:

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;
   }
}

首先将 getters 添加到你的 Person object/class 并使对象的内部状态只能通过 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
}

然后构建一个可以验证电子邮件地址格式的验证器,或者更好地使用库(如 https://commons.apache.org/proper/commons-validator/):

public final class EmailValidator {

    private EmailValidator() { }

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

通过调用 getter 从新人那里获取电子邮件地址来调用验证器。验证器不应该对 Person 对象有任何了解。

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");
    }
}

Java 中的良好做法是创建所有字段 private,并创建 "getters and setters",即获取和设置值的函数。例如:

public class Person {

    private String email;

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

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

这种做事方式有几个优点:

  • 如果您决定要更改字段中允许的值,您可以使用 setter 方法来实现。例如,如果你想对电子邮件施加最小长度,你可以在你的方法中放置 if (email.length() < 10) return; 以防止电子邮件短于 10 个字符

  • 如果您决定要通过 Internet 或其他方式检索电子邮件,则无需更改代码。

  • 许多工具和框架都希望 Java 对象采用这种格式。著名的例子包括用于 JSON 序列化的 Jackson 和用于 Web 应用程序开发的 Spring/Spring Boot,以及更多。

P.S。如果你厌倦了写吸气剂和 setters:

  1. 检查您的 IDE 是否有自动生成它们的方法(大多数都有)
  2. 查看一个名为Lombok 的库,它提供了@Data 注释,可以在编译时自动生成这些方法。 (https://projectlombok.org/)

对于你的情况,我会将 Person.email 作为包私有 - 这样它就可以保持现在的状态,并将 PersonValidator class 放在你拥有 Person [ 的同一个包中=64=].
这将使您能够将整个 Person 对象传递给验证器方法,例如:

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

但这非常孤立,设计不佳。此外,有很多方法可以从一个 class 调用另一个方法。例如。在 Person class 中创建 isEmailValid 方法,调用 PersonValidator.email(email) 时可以直接使用 email 变量。

许多不常见的方法最有可能使 SOLID、干净的代码和一些其他原则无效(例如耦合太紧 classes)。

像其他答案一样,最好将对象字段保持良好封装(即使用 private 访问修饰符),然后使用 get/set 方法访问它们。
然后,无论您是否首先创建 Person 对象(例如,从文件中解析 Person 列表,然后验证他们是否有正确的电子邮件或从 smth 获取请求参数,例如对新人的 HTTP 请求),您都可以调用 PersonValidator.email(personObject.getEmail()PersonValidator.email(emailParam).
保留 PersonValidator class 的包仅取决于项目的约定。

在对象中使用 "getters/setters" 方法,即 getEmail() setEmail(String email) getName() setName(String name) 是保持代码良好设计的常见且良好的约定。
在适用时实施此类做法是一种很好的做法。

仅供进一步阅读:

在 Person class 中对电子邮件字段使用 public getter 方法不应该使任何编码标准无效(甚至 YAGNI-You Ain't Gonna Need It),因为那里可能有很多未来的用途(例如,使用您的程序为 person/client 显示它)。

上面提到的封装术语,简而言之,就是将对象的内部实现保留在其中——即不让其他 classes 看到它。
在某些情况下,对象通过其方法修改其内部字段,而不是 "setters" 方法,但应始终使用 getField() 方法访问当前字段值。

"Don't overdesign, but keep future growth in mind"(我可能没有引用任何人 :P )。
进一步的用例可能是验证 Person 对象的更多字段成员,这可能导致:

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;
    }
}

同样,如其他答案所述,尝试搜索现有的验证器库比编写新的验证器库要好得多 - 真的,真的
phone 数字有不同的长度和格式(主要取决于国家/地区),check this out.
最短的有效电子邮件地址可以是 a@a" "@a,但这些是本地电子邮件地址。检查 this wiki or this github gist 以查看一些奇怪的有效示例。
至于名字,这取决于国家/地区的法律,它们可能会接受 "A" 或 "Ben11" 等名字,而波兰最奇怪的姓氏是 "Cyps Albo Zyps"。