草庐IT

java - 我应该在构造函数中验证参数吗?

coder 2023-08-28 原文

我正在按照 MVC 模式创建一个 Web 应用程序。

在effective Java中,作者提到在创建新对象时,要在类的构造函数中验证参数。

但是我并没有创建一些将被第三方使用的 API。我的类只接受来自表单输入字段的参数,这些参数在提交到服务器之前经过验证。

那么在这种情况下,我应该按照作者在 Effective java 中提到的方式创建我的类,还是没有用?

最佳答案

它不像阅读一本书并执行它所说的那样清晰。您需要根据自己的具体情况思考和应用知识。

这实际上取决于您如何初始化类中的变量并在对象构造后立即使用它们:

一些提示:

  • 如果变量将被类中的某些方法使用,或者对象将在构造后立即重新使用(在大多数情况下会),您应该验证所需的值不为空或 null,以避免出现讨厌的异常。

  • 第二次验证输入参数是在您希望为特定内部变量设置正确值时。如果您需要将参数限制在特定的值范围内,那么验证就很重要。

例子:

假设我们在对象中有工资帽:

int salary = 0;
int salaryCap = 1000;

在创建过程中,您可以验证传入的工资金额:

public Employee(int salary) {
 if(salary >= this.salaryCap)
  this.salary = salary;
}
  • 类关系还决定了您是否要验证这些值。例如,如果参数将沿继承链向上传递,我会花时间验证它们,尤其是当它们会影响继承链中其他对象的状态时。

例子:

每当我必须调用 super 构造函数时,我很想验证输入:

public Employee(int salary) {
 super(salary); //validate salary against known constraints
}
  • 变量来自哪里?如果您不信任来源(如 sql 参数等),那么您应该验证它们并可能在执行进一步代码之前清理输入。这可以防止安全攻击。

  • 我总是厌倦在构造函数中进行验证和参数检查。我更喜欢使用 getter 和 setter 来验证输入。这样,如果在对象创建时发生某些事情,至少我可以保证半工作对象而不是状态无法轻易确定的完全不一致的对象。当然这取决于您的上下文,如果您的约束很严格,您可以停止对象创建并提示客户端(用户、调用对象等)输入有效的参数。

使用 getters/setters 给我的好处是,对象实际上是通过调用对象提供的外部接口(interface)逐步构建的,而不是在创建期间约束验证,当异常发生时,使对象不可用/不稳定。

所以不是这个:

public Employee(int salary) {
 if(salary >= this.salaryCap)
  this.salary = salary;
}

我更喜欢这个:

public class Employee {
 public void setSalary(int salary) {
  if(salary >= this.salaryCap)
      this.salary = salary;
 }
}

后者使我能够干净地退出并向调用者发出有效异常,这不会影响对象创建(我不喜欢在构造函数中抛出异常)。

简而言之,您的变量是否有约束?如果是,请在将它们设置为内部数据属性之前验证这些约束。

关于java - 我应该在构造函数中验证参数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15186202/

有关java - 我应该在构造函数中验证参数吗?的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  5. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  6. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  7. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  8. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  9. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  10. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

随机推荐