String 如何处理具有结构的字符串?

String 如何处理具有结构的字符串?,string,validation,String,Validation,假设我有一个表示一个人的对象,该对象的电子邮件地址使用getter和setter方法。setter方法定义可能如下所示: setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } 调用person.setEmailAddress(0),则会生成类型错误,但调用person.setEmailAddress(“asdf”)则不会,即使“asdf”根本不是有效的电子邮件地址 根据我的经

假设我有一个表示一个人的对象,该对象的电子邮件地址使用getter和setter方法。setter方法定义可能如下所示:

setEmailAddress(String emailAddress)
    {
    this.emailAddress = emailAddress;
    }
调用
person.setEmailAddress(0)
,则会生成类型错误,但调用
person.setEmailAddress(“asdf”)
则不会,即使“asdf”根本不是有效的电子邮件地址

根据我的经验,所谓的字符串几乎从来都不是任意的字符序列,对长度或格式没有限制。URI浮现在脑海中——街道地址、电话号码和名字也是如此。。。你明白了。然而,这些数据类型通常存储为“字符串”

回到我的person对象,假设我这样修改
setEmailAddress()

setEmailAddress(EmailAddress emailAddress)
    // ...
其中,
EmailAddress
是一个类。。。其构造函数采用电子邮件地址的字符串表示形式。我有什么收获吗

好的,电子邮件地址是一个不好的例子。如果URI类将URI的字符串表示形式作为构造函数参数,并提供管理该URI的方法(设置路径、获取查询参数等),那么该类又如何呢?源字符串的有效性变得非常重要

所以我问你们大家,如何处理有结构的字符串?您如何在界面中明确您的结构期望


谢谢。

这是一个非常常见的问题,属于标题“”-验证文本用户输入的方法有很多,其中最常见的是


您也可以考虑使用内置类,因为它提供了对电子邮件地址的验证。

字符串是字符串。如果您需要字符串比普通字符串更智能,那么将它们解析为您描述的结构对象将是一个好主意。我会使用正则表达式来实现这一点。

好吧,如果您想对EmailAddress对象执行几种不同的操作,那么这些其他操作不必检查它是否是有效的电子邮件地址,因为EmailAddress对象保证具有有效的字符串。您可以在构造函数中抛出异常,或者使用工厂方法,或者使用任何您正在使用的“一种真正的方法学”方法。

“具有结构的字符串”是常见代码气味的症状


补救办法是密切关注验证或操纵这些结构部分的代码中的重复。在第一次提示重复时(但不是之前),提取一个封装结构的类,并在那里定位验证和查询。

就我个人而言,我喜欢强类型的想法,因此如果我仍然使用这种语言,我会采用第二个示例的风格。我唯一要改变的可能是使用一个更“cast-like”的结构,比如
EmailAddressFromString(String)
,它生成了一个新的
EmailAddress
对象(或者如果字符串不正确的话,则调整),因为我有点喜欢应用匈牙利符号


顺便说一句,Joel在《如果你感兴趣的话》一书中很好地阐述了整个问题。

在格式化字符串方面,正则表达式是你的朋友。您还可以将每个部分分别存储在一个结构中,以避免每次使用正则表达式时遇到麻烦。e、 g

struct EMail
{
    String BeforeAt = "johndoe123";
    String AfterAt = "gmail.com";
}

Struct URL
{
    String Protocol = "http";
    String Domain = "sub.example.com";
    String Path = "stuff/example.html";
}

我同意调用强类型对象,但对于从字符串解析为对象的情况,答案很简单:错误处理

有两种处理错误的一般方法:异常和返回条件。通常,如果希望接收格式错误的数据,则应返回错误消息。对于不需要输入的情况,我会抛出一个异常。例如,您可能会传入格式错误的电子邮件地址,例如“bob”而不是“bob”bob@gmail.com'. 但是,对于null值,您可能会抛出一个异常,因为您不应该尝试使用null来生成电子邮件


回到你的问题,我确实认为你通过把一个结构编码成一个对象获得了一些东西。具体地说,您只需要验证字符串是否代表一个特定位置(如构造函数)的有效电子邮件地址。在其他地方,您的代码可以自由地假设EmailAddress对象是有效的,并且您不必依赖名为“EmailHelper”或类似名称的狡猾类。

我个人认为,在这种情况下,将EmailAddress字符串强式键入为EmailAddress是不必要的

要创建您的电子邮件地址,您迟早要执行以下操作:

EmailAddress(String email)
还是二传手

SetEmailAddress(String email)
在这两种情况下,您都必须验证电子邮件字符串输入,这将使您回到初始验证问题

正如其他人指出的那样,我会使用正则表达式


如果您计划以后必须对存储的信息执行特定操作(比如仅获取域名之类的),那么拥有EmailAddress类将非常有用

欢迎来到编程世界

我不认为你的问题是你犯错误的征兆。相反,它是一个基本问题,在编程世界中以多种形式出现。具有某种结构和意义的字符串在应用程序的不同子系统之间传递,每个子系统只能进行大量的解析和验证

例如,验证电子邮件地址的问题相当棘手。例如,各种人提供的接受电子邮件地址的正则表达式通常要么“太紧”(不要全部接受),要么“太松”(接受非法的东西)。例如,对于“regex”电子邮件地址,表示:

我收到的正则表达式 大多数反馈,更不用说“bug” 关于的报告,就是你能找到的 在本网站的主页上: \b[A-Z0-9.Z%+-]+@[A-Z0-9.-]+[A-Z]{2,4}\b使用 雷格斯巴迪。Th