- 浏览: 794152 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (651)
- Java (39)
- Java 初学者小问题 (66)
- 设计模式 (7)
- 项目管理 (3)
- 数据库 (1)
- 算法 (2)
- Java practices (6)
- Effective Java2读书笔记 (78)
- Linux (2)
- programming ruby 读书笔记 (5)
- Core Java Ninth Edition Volume I 读书笔记 (15)
- Pro Git 读书笔记 (12)
- Git (3)
- Maven in Action 读书笔记 (20)
- Web (12)
- 非技术类书籍 (11)
- 电影 (40)
- Web Cache (1)
- jquery (0)
- 历史 (4)
- Dive Into HTML5 读书笔记 (13)
- 三国演义小学毕业考 (79)
- 高效能人士的7个习惯 读书笔记 (12)
- Java Performance 读书笔记 (3)
- Protocol Buffer 学习笔记 (6)
- Mongo DB 学习笔记 (7)
- Morphia 学习笔记 (7)
- Algorithms -- Princeton 学习笔记 (13)
- String研究 (10)
- Hadoop: The Definitive Guide 读书笔记 (3)
- Java与模式读书笔记 (5)
- Date研究 (3)
- The Roman Empire 听课笔记 (4)
- Algorithms -- Standford 学习笔记 (16)
- Core Java Ninth Edition Volume II 读书笔记 (9)
- Thinking in Java 4th Edition 读书笔记 (21)
- Node : Up and Running 学习笔记 (5)
- Eloquent Javascript (8)
- Smashing Node.js 读书笔记 (1)
- Algorithms II -- Standford 学习笔记 (19)
- Algorithm II -- Princeton 学习笔记 (14)
- 网络安全 (2)
- Javascript (4)
- 正则表达式 (1)
- JAVA 7/8 (15)
- JVM (10)
- NodeJS (1)
- 鸟哥的linux私房菜读书笔记 (14)
- Web Service (1)
- The art of programming (9)
- Introduction to Algorithm 读书笔记 (4)
- Java 源码阅读 (0)
- Spring in Action 读书笔记 (2)
- Java Network Programming 读书笔记 (2)
最新评论
-
心存高远:
谢谢作者分享,刚好看到这里不太明白,现在茅塞顿开。不过runt ...
关于 Maven的传递依赖的理解 -
sxlkk:
851228082 写道甚至在某次技术会议现场遇到《Maven ...
关于 Maven的传递依赖的理解 -
851228082:
851228082 写道a----compile----b-- ...
第五章 坐标和依赖 -
851228082:
a----compile----b-----provided- ...
第五章 坐标和依赖 -
851228082:
甚至在某次技术会议现场遇到《Maven in action》的 ...
关于 Maven的传递依赖的理解
Class invariants are methods which check the validity of an object's state (its data). The idea is to define validation methods for fields, and to perform these validations whenever the fields change. As usual, this should be done without repeating any code.
An object's state may become invalid for various reasons :
An invalid argument is passed by the caller.
To ensure that the caller fulfills the requirements of a method or constructor, all arguments to non-private methods should be explicitly checked. An Exception should be thrown if a problem is detected. A special case is deserialization, which should treat readObject like a constructor. (Assertions should not be used for these types of checks.)
The implementation of the class is defective.
As a defensive measure, a method which changes the state of an object can include an assertion at its end, to check that the object has indeed remained in a valid state. Here, such assertions verify correctness of internal implementation details - they do not check arguments.
Example 1
Resto is an immutable Model Object (MO). Its class invariant is defined by the validateState method. In this particular case, if validation fails a checked exception is thrown, and the end user is presented with their original input, along with associated error messages.
Such immutable classes represent the simplest case, since validation is performed only once, during construction (and deserialization, if necessary). By definition, an immutable object cannot change state after construction, so performing validations at other times in the object's life is never necessary.
package hirondelle.fish.main.resto; import hirondelle.web4j.model.ModelCtorException; import hirondelle.web4j.model.ModelUtil; import hirondelle.web4j.model.Id; import hirondelle.web4j.security.SafeText; import hirondelle.web4j.model.Decimal; import static hirondelle.web4j.model.Decimal.ZERO; import hirondelle.web4j.model.Check; import hirondelle.web4j.model.Validator; import static hirondelle.web4j.util.Consts.FAILS; /** Model Object for a Restaurant. */ public final class Resto { /** Full constructor. @param aId underlying database internal identifier (optional) 1..50 characters @param aName of the restaurant (required), 2..50 characters @param aLocation street address of the restaurant (optional), 2..50 characters @param aPrice of the fish and chips meal (optional) $0.00..$100.00 @param aComment on the restaurant in general (optional) 2..50 characters */ public Resto( Id aId, SafeText aName, SafeText aLocation, Decimal aPrice, SafeText aComment ) throws ModelCtorException { fId = aId; fName = aName; fLocation = aLocation; fPrice = aPrice; fComment = aComment; validateState(); } public Id getId() { return fId; } public SafeText getName() { return fName; } public SafeText getLocation() { return fLocation; } public Decimal getPrice() { return fPrice; } public SafeText getComment() { return fComment; } @Override public String toString(){ return ModelUtil.toStringFor(this); } @Override public boolean equals(Object aThat){ Boolean result = ModelUtil.quickEquals(this, aThat); if ( result == null ) { Resto that = (Resto) aThat; result = ModelUtil.equalsFor( this.getSignificantFields(), that.getSignificantFields() ); } return result; } @Override public int hashCode(){ if ( fHashCode == 0 ){ fHashCode = ModelUtil.hashCodeFor(getSignificantFields()); } return fHashCode; } // PRIVATE // private final Id fId; private final SafeText fName; private final SafeText fLocation; private final Decimal fPrice; private final SafeText fComment; private int fHashCode; private static final Decimal HUNDRED = Decimal.from("100"); private void validateState() throws ModelCtorException { ModelCtorException ex = new ModelCtorException(); if ( FAILS == Check.optional(fId, Check.range(1,50)) ) { ex.add("Id is optional, 1..50 chars."); } if ( FAILS == Check.required(fName, Check.range(2,50)) ) { ex.add("Restaurant Name is required, 2..50 chars."); } if ( FAILS == Check.optional(fLocation, Check.range(2,50)) ) { ex.add("Location is optional, 2..50 chars."); } Validator[] priceChecks = {Check.range(ZERO, HUNDRED), Check.numDecimalsAlways(2)}; if ( FAILS == Check.optional(fPrice, priceChecks)) { ex.add("Price is optional, 0.00 to 100.00."); } if ( FAILS == Check.optional(fComment, Check.range(2,50))) { ex.add("Comment is optional, 2..50 chars."); } if ( ! ex.isEmpty() ) throw ex; } private Object[] getSignificantFields(){ return new Object[] {fName, fLocation, fPrice, fComment}; } }
Example 2
Here is an example of a mutable, Serializable class which defines class invariants.
Items to note :
- the assertion at the end of the close method
- the call to validateState at the end of the readObject method
- the implementation is significantly more complex, since the class is mutable
import java.text.StringCharacterIterator; import java.util.*; import java.io.*; /** * In this style of implementation, both the entire state of the object * and its individual fields are validated without duplicating any code. * * Argument validation usually has if's and thrown exceptions at the * start of a method. Here, these are replaced with a simple * call to validateXXX. Validation is separated cleanly from the * regular path of execution, improving legibility. */ public final class BankAccount implements Serializable { /** * @param aFirstName contains only letters, spaces, and apostrophes. * @param aLastName contains only letters, spaces, and apostrophes. * @param aAccountNumber is non-negative. * * @throws IllegalArgumentException if any param does not comply. */ public BankAccount( String aFirstName, String aLastName, int aAccountNumber) { //don't call an overridable method in a constructor setFirstName(aFirstName); setLastName(aLastName); setAccountNumber(aAccountNumber); } /** * All "secondary" constructors call the "primary" constructor, such that * validations are always performed. */ public BankAccount() { this ("FirstName", "LastName", 0); } public String getFirstName() { return fFirstName; } public String getLastName(){ return fLastName; } public int getAccountNumber() { return fAccountNumber; } /** * This method changes state internally, and may use an assert to * implement a post-condition on the object's state. */ public void close(){ //valid: fAccountNumber = 0; //this invalid value will fire the assertion: //fAccountNumber = -2; assert hasValidState(): this; } /** * Names must contain only letters, spaces, and apostrophes. * * @throws IllegalArgumentException if any param does not comply. */ public void setFirstName( String aNewFirstName ) { validateName(aNewFirstName); fFirstName = aNewFirstName; } /** * Names must contain only letters, spaces, and apostrophes. * * @throws IllegalArgumentException if any param does not comply. */ public void setLastName ( String aNewLastName ) { validateName(aNewLastName); fLastName = aNewLastName; } /** * AccountNumber must be non-negative. * * @throws IllegalArgumentException if any param does not comply. */ public void setAccountNumber( int aNewAccountNumber ) { validateAccountNumber(aNewAccountNumber); fAccountNumber = aNewAccountNumber; } /** * Can be used to easily pass object description to an assertion, * using a "this" reference. */ public String toString(){ final StringBuilder result = new StringBuilder(); final String SPACE = " "; result.append(fFirstName); result.append(SPACE); result.append(fLastName); result.append(SPACE); result.append(fAccountNumber); return result.toString(); } /// PRIVATE ///// private String fFirstName; private String fLastName; private int fAccountNumber; /** * Verify that all fields of this object take permissible values; that is, * this method defines the class invariant. * * Call after deserialization. * @throws IllegalArgumentException if any field takes an unpermitted value. */ private void validateState() { validateAccountNumber(fAccountNumber); validateName(fFirstName); validateName(fLastName); } /** * Return true if <code>validateState</code> does not throw * an IllegalArgumentException, otherwise return false. * * Call at the end of any public method which has changed * state (any "mutator" method). This is usually done in * an assertion, since it corresponds to a post-condition. * For example, * <pre> * assert hasValidState() : this; * </pre> * This method is provided since <code>validateState</code> cannot be used * in an assertion. */ private boolean hasValidState() { boolean result = true; try { validateState(); } catch (IllegalArgumentException ex){ result = false; } return result; } /** * Ensure names contain only letters, spaces, and apostrophes. * * @throws IllegalArgumentException if argument does not comply. */ private void validateName(String aName){ boolean nameHasContent = (aName != null) && (!aName.equals("")); if (!nameHasContent){ throw new IllegalArgumentException("Names must be non-null and non-empty."); } StringCharacterIterator iterator = new StringCharacterIterator(aName); char character = iterator.current(); while (character != StringCharacterIterator.DONE ){ boolean isValidChar = (Character.isLetter(character) || Character.isSpaceChar(character) || character =='\''); if ( isValidChar ) { //do nothing } else { String message = "Names can contain only letters, spaces, and apostrophes."; throw new IllegalArgumentException(message); } character = iterator.next(); } } /** * AccountNumber must be non-negative. * * @throws IllegalArgumentException if argument does not comply. */ private void validateAccountNumber(int aAccountNumber){ if (aAccountNumber < 0) { String message = "Account Number must be greater than or equal to 0."; throw new IllegalArgumentException(message); } } private static final long serialVersionUID = 7526472295622776147L; /** * Always treat de-serialization as a full-blown constructor, by * validating the final state of the de-serialized object. */ private void readObject(ObjectInputStream aInputStream) throws ClassNotFoundException, IOException { //always perform the default de-serialization first aInputStream.defaultReadObject(); //ensure that object state has not been corrupted or //tampered with maliciously validateState(); } /** * Test harness. */ public static void main (String[] aArguments) { BankAccount account = new BankAccount("Joe", "Strummer", 532); //exercise specific validations. account.setFirstName("John"); account.setAccountNumber(987); //exercise the post-condition assertion //requires enabled assertions: "java -ea" account.close(); //exercise the serialization ObjectOutput output = null; try{ OutputStream file = new FileOutputStream( "account.ser" ); OutputStream buffer = new BufferedOutputStream( file ); output = new ObjectOutputStream( buffer ); output.writeObject(account); } catch(IOException exception){ System.err.println(exception); } finally{ try { if (output != null) output.close(); } catch (IOException exception ){ System.err.println(exception); } } //exercise the deserialization ObjectInput input = null; try{ InputStream file = new FileInputStream( "account.ser" ); InputStream buffer = new BufferedInputStream( file ); input = new ObjectInputStream ( buffer ); BankAccount recoveredAccount = (BankAccount)input.readObject(); System.out.println( "Recovered account: " + recoveredAccount ); } catch(IOException exception){ System.err.println(exception); } catch (ClassNotFoundException exception){ System.err.println(exception); } finally{ try { if ( input != null ) input.close(); } catch (IOException exception){ System.err.println(exception); } } } }
This article originates from http://www.javapractices.com/topic/TopicAction.do?Id=6
发表评论
-
Avoid clone
2010-10-31 12:07 991Avoid implementing clone. c ... -
Implementing Serializable
2010-10-28 11:40 970Do not implement Serializable l ... -
Immutable objects
2010-10-21 22:46 1016Immutable objects are simply ob ... -
Lazy initialization
2010-10-21 12:03 1102Lazy initialization is a perfor ... -
Copy constructors
2010-10-20 23:57 904Copy constructors : provide ...
相关推荐
在网页开发中,jQuery Validate 是一个非常常用的验证插件,用于对用户输入的数据进行校验,确保数据的有效性和完整性。这个插件可以帮助开发者创建复杂的表单验证规则,提高用户体验,减少服务器端的压力。结合 ...
jquery.validate.1.9.0.min.js jquery.validate.1.12.0.min.js jquery.validate.1.13.1.min.js jquery.validate.1.16.0.min.js jquery.validate.1.14.0.min.js jquery.validate.1.15.1.min.js jquery.validate....
标题中的"validate方法"通常指的是在编程中用于验证数据或对象的方法。这可能是为了确保输入的数据符合特定的格式、规则或者限制,以防止错误、安全问题或者数据不一致。在不同的编程语言和框架中,validate方法可能...
在使用jQuery Validate时,我们需要对目标表单元素添加特定的class或者data属性来指定验证规则。例如,我们可以使用`required`标志来表明某个字段是必填的,或者使用`minlength`和`maxlength`来限制输入的字符长度。...
jquery.validate.js jquery.validate.js
以下是安装validate_password插件的详细步骤,以及相关的配置和使用方法。 1. **修改配置文件** 首先,你需要编辑MySQL的配置文件,通常位于`/etc/my.cnf`(根据你的操作系统和安装路径可能有所不同)。使用命令`...
《jQuery.validate实例详解》 在Web开发中,表单验证是不可或缺的一部分,它能确保用户输入的数据符合我们设定的规则,提高数据的准确性和安全性。jQuery库中的validate插件为开发者提供了一种简单、高效的表单验证...
- **错误元素**:默认情况下,错误消息会显示在输入元素之后,但可以通过 `errorElement` 和 `errorClass` 设置自定义元素和类名。 - **错误定位**:使用 `errorPlacement` 回调函数控制错误消息的位置。 - **错误...
jQuery Validate 是一个强大的客户端验证插件,用于在用户提交表单前进行实时验证。这个框架大大简化了HTML表单的验证过程,提供了丰富的内置验证规则和可扩展的自定义验证功能,使得表单验证更加人性化和高效。 1....
jQuery Validate 是一个强大的JavaScript库,专门用于前端表单验证,由jQuery团队开发并维护。它极大地简化了在网页上创建高效、用户友好的验证规则的过程,避免了开发者编写大量重复的验证代码。jQuery Validate ...
jQuery Validate是jQuery的一个重要插件,它专门用于进行表单验证。表单验证是前端开发中一个重要的环节,可以确保用户提交的信息是完整和正确的。通过在class属性中添加校验规则,可以使表单校验的实现更为简便。 ...
classNames: { touched: 'touched', untouched: 'untouched', valid: 'valid', invalid: 'invalid', pristine: 'pristine', dirty: 'dirty', }, events: 'blur', inject: true, }; Vue.use(VeeValidate...
在本文中,我们将深入探讨如何使用 jQuery Validate,包括基本的使用方法、可选参数以及常见的验证规则。 首先,要使用 jQuery Validate,你需要在页面中引入 jQuery 库和 jQuery Validate 的脚本文件。如以下代码...
《jQuery.validate.js API 中文详解》 jQuery.validate.js 是一个非常流行的JavaScript库,它为HTML表单提供了强大的验证功能。这个库是基于jQuery构建的,因此可以无缝集成到任何使用jQuery的项目中,大大简化了...
《jQuery Validate插件详解与实例应用》 在Web开发中,表单验证是不可或缺的一环,它能够确保用户输入的数据符合预设的规则,提高数据的准确性和安全性。jQuery Validate是一个强大的JavaScript库,专为jQuery设计...
这是一个关于jquery_validate插件学习的总结,内容不多,但是都是干货,有兴趣的可以看一下。
在本文中,我们将深入探讨如何利用jQuery Validate来创建自定义验证样式。 首先,我们从标题"jquery validate 验证自定义样式"开始。jQuery Validate插件默认提供了一些基本的样式,但这些样式可能不能满足所有设计...
《jQuery.validate 用法详解及源码解析》 在网页开发中,表单验证是必不可少的一环,确保用户输入的数据符合预设的规则,避免无效数据的提交。jQuery.validate插件是一个强大的、易于使用的JavaScript库,它使得在...
jquery.validate.min.js jquery jquery验证插件 validate
标题中的“比较好用的 FormValidate”指的是一个用于表单验证的工具或库,它可能是一个JavaScript框架,旨在帮助开发者更方便、高效地实现前端或后端的表单数据验证。在网页开发中,表单验证是必不可少的部分,它...