Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-我应该在setter中读取值吗?_Java - Fatal编程技术网

Java-我应该在setter中读取值吗?

Java-我应该在setter中读取值吗?,java,Java,我有一个setter,我希望它在设置值之前检查电子邮件地址是否包含字符“@”和“.”。如果电子邮件地址不包含这些字符,我希望用户再次输入电子邮件地址。我应该在setter中读取新值,还是不实用,应该只在main中读取,还是使用其他方法读取 import java.util.Scanner; public class Person { private String emailAddress; Scanner input = new Scanner( System.in);

我有一个setter,我希望它在设置值之前检查电子邮件地址是否包含字符“@”和“.”。如果电子邮件地址不包含这些字符,我希望用户再次输入电子邮件地址。我应该在setter中读取新值,还是不实用,应该只在main中读取,还是使用其他方法读取

import java.util.Scanner;
public class Person {
    private String emailAddress;
    Scanner input = new Scanner( System.in);

    public void setEmail(String email)
    {
         while(email.indexOf('@')<0 || email.indexOf('.')<0)
         {
                System.out.println("The email address must contain the characters \"@\" and \".\" ");
                System.out.println("Enter email address again:
                email = input.nextLine();
         }
    }
}
import java.util.Scanner;
公共阶层人士{
私有字符串电子邮件地址;
扫描仪输入=新扫描仪(System.in);
公用电子邮件(字符串电子邮件)
{

而(email.indexOf('@')No,这是一种不好的做法

问题是,如果您在没有交互控制台的上下文中调用该方法,例如在单元测试中,您将陷入困境

抛出一个
IllegalArgumentException
,让调用方实现重试(或不重试)

在您的setter中:

void setEmail(String email) {
  if (!email.contains("@") || !email.contains(".")) {
    throw new IllegalArgumentException("Invalid email: " + email);
  }
  this.emailAddress = email;
}
在您的来电者中:

while (true) {
  try {
    setEmail(emailAddress);
    break;
  } catch (IllegalArgumentException e) {
    // Show a message, or whatever.
  }

你把功能和责任混为一谈的方式很糟糕

是的,setter应该绝对验证输入,这是使用访问器方法而不是公开变量本身的最常见原因之一

不,设定者不应使用
System.in
System.out
向用户请求新的输入。将其留给
main
或其他人。这不在设定者的职责范围内(和
Person
class的职责范围内)

这里最好的方法是使用
IllegalArgumentException
,并让调用代码按照自己的意愿处理

public void setEmail(String email)
{
     if(email.indexOf('@')<0 || email.indexOf('.')<0)
     {
            throw new IllegalArgumentException("Invalid email address.");
     }
     this.email = email;
}

一般来说,如果一个方法做的不是它的名字所暗示的事情,这是一个坏主意。

如果该方法名为
setFoo()
,人们希望它更新名为
foo
的字段,而不做其他任何事情。当然,您可以(实际上您应该)验证您的输入并抛出
IllegalArgumentException
,如果它不是您想要的,但不做其他任何事情

这通常被称为“最小惊喜原则”,这是编写代码时非常有用的设计原则

另一个普遍的经验法则是,方法应尽可能只负责一件事。

当然,什么是“东西”会有所不同,它可能是非常具体的东西(例如:“这个方法乘以两个参数”),也可能更一般(“这个方法处理我所有的输入”),但如果你不能用简单的句子解释这个方法做了什么,它可能做得太多了

(作为练习,考虑一下如何向朋友解释
setEmail()
的作用。大声说出来。它确实有效。)


当您在执行I/O时,这一点更为重要,就像您在示例中所做的那样:应该非常清楚谁从
扫描器中读取数据,以及何时读取数据,否则在程序的哪个阶段就几乎无法跟踪预期的输入。在这种情况下,即使是
人员
类也不应该对
Scanner
。在其他地方处理输入,并将
Person
类保留为仅表示一个人。

我将验证它,与您正在执行的操作类似,但如果参数无效,我将抛出异常。感谢您的回答!
boolean goodEmail = false;
while (!goodEmail) {
  String inputEmail = getTheEmailAddressFromTheUserSomehow();

  try {
    person.setEmail(inputEmail);
    goodEmail = true;
  } catch (IllegalArugmentException e) {
    //try again!
    //or don't, depends on the workflow of the application
  }
}