如何在Java中返回标志和可选消息?
我想用Java编写一个方法,验证某些条件是否适用于某些数据,并确认数据有效,否则会生成相应的错误消息 问题是我们不能从一个方法返回多个内容,所以我想知道最好的解决方案是什么(在可读性和可维护性方面) 第一个解决方案。很简单,但我们无法知道到底是什么导致检查失败:如何在Java中返回标志和可选消息?,java,readability,Java,Readability,我想用Java编写一个方法,验证某些条件是否适用于某些数据,并确认数据有效,否则会生成相应的错误消息 问题是我们不能从一个方法返回多个内容,所以我想知道最好的解决方案是什么(在可读性和可维护性方面) 第一个解决方案。很简单,但我们无法知道到底是什么导致检查失败: boolean verifyLimits1(Set<Integer> values, int maxValue) { for (Integer value : values) { if (value
boolean verifyLimits1(Set<Integer> values, int maxValue) {
for (Integer value : values) {
if (value > maxValue) {
return false; // Out of limits
}
}
return true; // All values are OK
}
boolean verifyLimits1(设置值,int-maxValue){
for(整数值:值){
如果(值>最大值){
返回false;//超出限制
}
}
返回true;//所有值都正常
}
第二个解决方案。我们有这个消息,但我们正在以一种我们不应该使用的方式使用异常(此外,它可能应该是一个特定于域的已检查异常,在我看来开销太大了):
void verifyLimits2(设置值,int maxValue){
for(整数值:值){
如果(值>最大值){
抛出新的IllegalArgumentException(“值“+value+”超过最大值”);
}
}
}
第三个解决方案。我们有一条详细的消息,但合同并不明确:我们让客户机检查字符串是否为空(他需要读取javadoc)
String verifyLimits3(设置值,int-maxValue){
StringBuilder=新的StringBuilder();
for(整数值:值){
如果(值>最大值){
builder.append(“值“+value+”超过最大值/n”);
}
}
返回builder.toString();
}
您会推荐哪种解决方案?还是有更好的(希望如此!)
(注意:我编了一个小例子,我的实际用例涉及异构数据的复杂条件,所以不要把重点放在这个具体的例子上,建议
Collections.max(values)>maxValue?“超出范围。”:“一切正常。”
:-)解决方案很简单:创建一个自定义的验证结果
类。它可以有一个布尔状态
标志和一个字符串消息
字段,以及您可能需要添加的其他内容。不是返回字符串
或布尔值
,而是返回验证结果
此外,根据上下文的不同,抛出异常实际上可能是正确的做法。不过,这必须根据具体情况逐案考虑
替代解决方案:最后一个错误查询 您可以使用的另一个选项是让验证返回一个
布尔值
,并有一个单独的方法,例如字符串whatwentworlasttime()
,用户可以在返回false
时查询该方法。您必须非常小心任何可能会覆盖“最后一次”验证错误的并发性问题等
这是例如所采取的方法,它不会抛出任何
IOException
(构造函数除外)。要查询是否出现“错误”,您可以查询其方法,该方法返回最后一个IOException
,如果没有,则返回null
。创建您自己的自定义未检查异常,该异常扩展自RuntimeException 您可以使用简单的键值,通过使用HashMap,当然还有预定义的键。
返回HashMap以进行进一步处理。如果需要多个值,则应返回一个简单的类实例。以下是我们在某些情况下使用的示例:
public class Validation {
private String text = null;
private ValidationType type = ValidationType.OK;
public Validation(String text, ValidationType type) {
super();
this.text = text;
this.type = type;
}
public String getText() {
return text;
}
public ValidationType getType() {
return type;
}
}
这对类型使用了一个简单的枚举:
public enum ValidationType {
OK, HINT, ERROR;
}
验证器方法可能如下所示:
public Validation validateSomething() {
if (condition) {
return new Validation("msg.key", ValidationType.ERROR);
}
return new Validation(null, ValidationType.OK);
}
就是这样。
IllegalArgumentException
是一种方法,如果它真的意味着:你向方法(契约)的调用者提出一些要求,但它们被忽略了。在这种情况下,IAE是合适的
如果这不能反映您的用例,我将使用其他解决方案之一。在这种情况下,返回“false”的方法看起来像是业务逻辑结果,而不是真正的异常。所以verifyLimits无论如何都应该返回一个结果,而不是在“false”时抛出异常
class VerifyLimitsResult{
//Ignore get, set methods
Integer maxValue;
Integer value;
public VerifyLimitsResult(Integer maxValue, Integer value) {
this.maxValue = maxValue;
this.value = value;
}
public boolean isOK(){
return value==null;
}
public String getValidationInfo(){
if(isOK()){
return "Fine";
}else{
return "The value " + value + " exceeds the maximum value/n"
}
}
}
....
VerifyLimitsResult verifyLimits4(Set<Integer> values, int maxValue) {
for (Integer value : values) {
if (value > maxValue) {
return new VerifyLimitsResult(maxValue, value);
}
}
return new VerifyLimitsResult(maxValue, null);
}
类验证限制结果{
//忽略get、set方法
整数最大值;
整数值;
公共VerifyLimitsResult(整型maxValue,整型值){
this.maxValue=maxValue;
这个值=值;
}
公共布尔isOK(){
返回值==null;
}
公共字符串getValidationInfo(){
if(isOK()){
退回“罚款”;
}否则{
返回“值”+值+“超过最大值/n”
}
}
}
....
VerifyLimitsResult verifyLimits4(设置值,int maxValue){
for(整数值:值){
如果(值>最大值){
返回新的VerifyLimitsResult(maxValue,value);
}
}
返回新的VerifyLimitsResult(maxValue,null);
}
我将投票支持第二种解决方案(使用IllegalArgumentException或定义特定的解决方案)
一般来说,好的做法是确保可以安全地忽略方法的任何返回值(因为总有一天会有人忘记检查它),并且,在忽略返回值不安全的情况下,最好抛出/捕获异常。另一种方法-使用状态对象:
public class Status {
public final static Status OK = new Status("OK");
private String message;
public Status(String message) { this.message = message; }
public String getMessage() { return message; }
}
若要验证,请返回状态。确定输入是否有效,或创建新的状态消息
public Status validate(Integer input, int maxValue){
if (input > maxValue) {
return new Status(
String.format("%s value out of limits (maxValue=%s)", input, maxValue);
}
return Status.OK;
}
使用验证器很简单,如下所示:
Status status = validate(i, 512);
if (status != Status.OK) {
// handle the error
}
我认为最好的解决方案是创建您自己的异常,该异常保存您想要的尽可能多的错误描述信息。它不应该是RuntimeException
子类;您希望调用方必须处理验证失败,因为太多的程序员无法进行错误处理。通过将失败设置为选中的异常,您可以强制他们(您?)至少放入一些内容,代码审查可以
public Status validate(Integer input, int maxValue){
if (input > maxValue) {
return new Status(
String.format("%s value out of limits (maxValue=%s)", input, maxValue);
}
return Status.OK;
}
Status status = validate(i, 512);
if (status != Status.OK) {
// handle the error
}
// A simple listener to be implemented by the calling method.
public interface OutOfLimitListener {
// Called whenever a limit is violated.
public void outOfLimit(int value, int maxValue);
// ... Add additional results as parameters
// ... Add additional states as methods
}
private boolean verifyLimits(Set<Integer> values, int maxValue, OutOfLimitListener listener) {
boolean result = true; // Assume all values are OK
for (Integer value : values) {
if (value > maxValue) {
listener.outOfLimit(value, maxValue);
result = false; // At least one was out of limits
}
}
return result;
}
@Test
public final void test() throws IOException, InterruptedException {
// Make up a test set of random numbers
Set<Integer> testSet = new HashSet<Integer>();
for(int i=0; i<10; i++) testSet.add((int) (Math.random() * 100));
// Implement the interface once with appropriate reaction to an out-of-limit condition
OutOfLimitListener listener = new OutOfLimitListener() {
@Override
public void outOfLimit(int value, int maxValue) {
System.out.printf("The value %d exceeds the maximum value %d\n", value, maxValue);
}
};
// Call verification
verifyLimits(testSet, 50, listener);
}