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