【问题标题】:How to get one particular atribute from a class with several atributes如何从具有多个属性的类中获取一个特定属性
【发布时间】:2020-05-08 01:06:04
【问题描述】:
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;
}

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

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

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

}

这是测试电子邮件是否有效的测试类:

class PersonRegisterTest {

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

}

【问题讨论】:

    标签: java unit-testing junit assert


    【解决方案1】:

    Java 中的良好做法是将所有字段设为private,并创建“getter 和 setter”,即获取和设置值的函数。例如:

    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 等等。

    附:如果您厌倦了编写 getter 和 setter:

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

    【讨论】:

      【解决方案2】:

      最好将类 Person 中的数据成员/变量保持为私有,并且您可以添加 getter 和 setter 方法,您可以从类外部访问它们,并使用它们可以访问类的数据成员/变量. 您可以执行以下操作:

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

      【讨论】:

        【解决方案3】:

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

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

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

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

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

        在对象中包含“getters/setters”方法,即getEmail() setEmail(String email) getName() setName(String name) 是保持代码设计良好的常见且良好的约定。
        在适用时实施这样的做法是一个很好的做法。

        仅供进一步阅读:

        在 Person 类中为电子邮件字段提供公共 getter 方法不应使任何编码标准无效(甚至 YAGNI-You Ain't Gonna Need It 也不应该),因为将来可能会有很多用途(例如,为个人/客户显示它使用您的程序)。

        所提到的封装术语简而言之,它是关于将对象的内部实现保留在其中 - 即不使其对其他类可见。
        在某些情况下,对象通过其方法修改其内部字段,这些方法不是“setter”方法,但应始终使用getField() 方法访问当前字段值。

        “不要过度设计,但要牢记未来的增长”(我可能没有引用任何人: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;
            }
        }
        

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

        【讨论】:

          【解决方案4】:

          首先将 getter 添加到您的 Person 对象/类,并使对象的内部状态只能通过 getter 访问:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-09-28
            • 2013-11-15
            • 1970-01-01
            • 1970-01-01
            • 2021-05-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多