目录
在类的关系中,最常见的关系有下面的三种
可以定义自定义类的数组
下面的代码通过创建自定义数组的方式定义了三个自定义类的数组,然后往该数组种存入该自定义类的对象
package java核心技术卷一;
import java.time.LocalDate;
/**
* @author weijiangquan
* @date 2022/9/10 -18:34
* @Description
*/
public class EmployeeTest{
public static void main(String[] args){
Employee[] staff = new Employee[3];
staff[0] = new Employee("dasd",1233,1987,12,10);
staff[0] = new Employee("dasd",1233,1988,11,11);
staff[0] = new Employee("dasd",1233,1989,10,22);
for (Employee e:staff){
e.raiseSalary(5);
}
for (Employee e:staff){
System.out.println("name="+e.getName()+",salary="+e.getSalary()+",hireDay"+e.getHireDay());
}
}
}
class Employee{
private String name;
private double salary;
private LocalDate hireDay;
public Employee(String n,double s,int year,int month,int day){
name = n;
salary = s;
hireDay = LocalDate.of(year,month,day);
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public LocalDate getHireDay() {
return hireDay;
}
public void raiseSalary(double byPercent){
double raise = salary*byPercent/100;
salary+=raise;
}
}


对于下面的这种写法,虽然没有报错,但是确覆盖掉了类的属性中定义的变量。最终或许带来潜在的影响。以及对于后续的代码造成影响,如同一个定时炸弹,随时都会爆发。
private String name;
private double salary;
private LocalDate hireDay;
public Employee(String n,double s,int year,int month,int day){
String name = n;
double salary = s;
hireDay = LocalDate.of(year,month,day);
}
在java10中,如果可以从变量的初始值推导出它们的类型,那么可以用var关键字声明局部变量,而无须指定类型。例如,可以不这样声明:
Employee harry = new Employee("Harry Hacker",50000,1899,10,1);
而只需要写下面的代码:
var Harry = new Employee("Harry Hacker",50000,1898,10,1);
这样就不需要重复书写类型名了
如果不用了解任何java API就能从等号右边明显看出类型,在这种情况下我们都使用var表示法。不过我们不建议对数值类型使用var,如 int , long 或是 double ,使你不用担心 0 , 0L , 00 之间的区别。对于Java API有了更多的使用经验之后,你可能希望更多的使用var关键字。
注意var关键字只能用于方法中的局部变量。参数和字段的类型必须声明
java语言总是按值传递的,也就是说,方法得到的是所有参数值的以恶搞副本。具体来讲,方法不能修改传递给它的任何参数变量的的内容。
对于上面的点,基础数据类型应该不用多说,比较有疑惑的地方可能是引用类型的。

public static void swap(Employee x,Employee y){
Employee temp = x;
x = y;
y = temp;
}
想一下,如果Java对象采用的是按引用调用,那么这个方法就应该能够实现交换。

最后发现其实是白费力气。在方法结束的时候参数变量 x 和 y 被丢弃了。原来的变量a和b仍然引用这个方法调用之前所引用的对象。

这个过程说明: Java程序设计语言对对象采用的不是按引用调用,实际上,对象引用按值传递的。
下面总结一下在Java中的对方法的参数能够做什么和不能做什么。
最后可以知道,虽然参数 x 和 参数 y 的的值交换了,但是 a 和 b 的没有受到任何影响。



我们不会面面俱到,也不希望过于沉闷,所以在这一章结束之前先简单地介绍几点技巧。应用这些技巧可以使你设计的类更能得到专业OOP圈子的认可。
一定要保证数据私有。
这是最重要的;绝对不要破坏封装性。有时候,可能需要编写一个访问器方法或更改器方法,但是最好还是保持实例字段的私有性。很多惨痛的教训告诉我们,数据的表示形式很可能会改变,但它们的使用方式却不会经变化。当数据保持私有时,表示形式的变化不会对类的使用者产生影响,而且也更容易检测 bug。
一定要对数据进行初始化。
Java不会为你初始化局部变量,但是会对对象的实例字段进行初始化。最好不要依赖于系统的默认值,而是应该显式地初始化所有的数据,可以提供默认值,也可以在所有构造器中设置默认值。
不要在类中使用过多的基本类型。
这个想法是要用其他的类替换使用多个相关的基本类型。这样会使类更易于理解,也更易于修改。例如,用 一个名为Address的新类替换一个Customer类中以下的实例字段:
private String street;
private String city;
private String state;
这样一来,可以很容易地处理地址的变化,例如,可能需要处理国际地址。
不是所有的字段都需要单独的字段访问器和字段更改器。
你可能需要获得或设置员工的工资。而一旦构造了员工对象,肯定不需要更改雇用日期。另外,在对象中,常常包含一些不希望别人获得或设置的实例字段,例如,Address类中的州缩写数组。
分解有过多职责的类。
这样说似乎有点含糊,究竟多少算是“过多”?每个人的看法都不同。但是,如果明显地可以将一个复杂的类分解成两个更为简单的类,就应该将其分解(但另一方面,也不要走极端。如果设计10个类,每个类只有一个方法,显然就有些矫枉过正了)
类名和方法名要能够体现它们的职责。
与变量应该有一个能够反映其含义的名字一样,类也应该如此(在标准类库中,也存在着一些含义不明确的例子,如 Date类实际上是一个用于描述时间的类)。
对此有一个很好的惯例:类名应当是一个名词( Order),或者是前面有形容词修饰的名词( RushOrder),或者是有动名词(有“-ing”后缀)修饰的名词(例如,BillingAddress)。对于方法来说,要遵循标准惯例:访问器方法用小写get开头 ( getSalary),更改器方法用小写的set开头(setSalary)。
优先使用不可变的类
LocalDate类以及java.time包中的其他类是不可变的——没有方法能修改对象的状态。类似plusDays的方法并不是更改对象,而是返回状态已修改的新对象。
更改对象的问题在于,如果多个线程试图同时更新一个对象,就会发生并发更改。其结果是不可预料的。如果类是不可变的,就可以安全地在多个线程间共享其对象。
因此,要尽可能让类是不可变的,这是一个很好的想法。对于表示值的类,如一个字符串或一个时间点,这尤其容易。计算会生成新值,而不是更新原来的值。
当然,并不是所有类都应当是不可变的。如果员工加薪时让raiseSalary方法返回一个新的 Employee对象,这会很奇怪。
本章介绍了有关对象和类的基础知识,这使得Java可以作为一种“基于对象”的语言。要真正做到面向对象,程序设计语言还必须支持继承和多态。Java提供了对这些特性的支持,具体内容将在下一章中介绍。
对于最后一点或许你会有一定的疑惑,或许等到有一定的开发经历之后就发现吧。
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir
假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。