类(class)是构造对象的模板或蓝图。 由类构造(construct)对象的过程称为创建类的实例(instance)。
类是名词,方法是动词。
封装( encapsulation, 有时称为数据隐藏) 是与对象有关的一个重要概念。 从形式上看, 封装不过是将数据和行为组合在一个包中, 并对对象的使用者隐藏了数据的实现方式。 对象中的数据称为实例域( instance field) , 操纵数据的过程称为方法( method) 。 对于每个特定的类实例( 对象) 都有一组特定的实例域值。 这些值的集合就是这个对象的当前状态( state) 。 无论何时, 只要向对象发送一个消息, 它的状态就有可能发生改变。
实现封装的关键在于绝对不能让类中的方法直接地访问其他类的实例域。 程序仅通过对象的方法与对象数据进行交互。 封装给对象赋予了“黑盒” 特征, 这是提高重用性和可靠性的关键。 这意味着一个类可以全面地改变存储数据的方式, 只要仍旧使用同样的方法操作数据, 其他对象就不会知道或介意所发生的变化。

继承(inheritance):可以通过扩展一个类来建立另外一个新的类。 事实上, 在Java中, 所有的类都源自于一个“神通广大的超类” , 它就是Object。在扩展一个已有的类时, 这个扩展后的新类具有所扩展的类的全部属性和方法。 在新类中, 只需提供适用于这个新类的新方法和数据域就可以了。

类与类之间的关系

  • 依赖(uses-a):如果一个类的方法操纵另一个类的对象, 我们就说一个类依赖于另一个类。
  • 聚合(has-a):聚合关系意味着类A的对象包含类B的对象。 减少聚合(耦合)
  • 组合(contains-a):
  • 继承(is-a):是一种用于表示特殊与一般关系的。

    聚合与组合的区别

    (1)聚合与组合都是一种结合关系,只是额外具有整体-部分的意涵。
    (2)部件的生命周期不同

    • 聚合关系中,整件不会拥有部件的生命周期,所以整件删除时,部件不会被删除。再者,多个整件可以共享同一个部件。
    • 组合关系中,整件拥有部件的生命周期,所以整件删除时,部件一定会跟着删除。而且,多个整件不可以同时间共享同一个部件。

(3)聚合关系是”has-a”关系,组合关系是”contains-a”关系

通常,当希望构造的对象可以多次使用时,需要将对象放在一个对象变量里:

  1. Date birthday = new Date();

对象变量和对象的关系:
image.png
对象变量并没有实际包含一个对象,它只是引用一个对象。在Java中,任何对象变量的值都是对存储在另一个地方(堆)的某个对象的引用。用 new 操作福的返回值也是一个引用。
可以显式的将对象变量设置为null,指示这个对象变量目前没有引用任何变量。

Java中的对象变量并不相当于C++中的引用。因为C++中没有null引用,而且C++引用不能复制。可以把Java中的对象变量看作类似于C++的对象指针。

Java中的LocalDate类

标准Java类库分别包含了两个类: 一个是用来表示时间点的Date类; 另一个是用来表示大家熟悉的日历表示法的LocalDate类。
将时间与日历分开是一种很好的面向对象设计。 通常, 最好使用不同的类表示不同的概念。
不要使用构造器来构造LocalDate类的对象。 实际上, 应当使用静态工厂方法( factory method) 代表你调用构造器。 下面的表达式 :

  1. LocalDate.now()

会构造一个新对象, 表示构造这个对象时的日期。
可以提供年、 月和日来构造对应一个特定日期的对象:

  1. LocalDate.of(1999,12,31);

当然, 通常都希望将构造的对象保存在一个对象变量中:

  1. LocalDate newYearEve = LocalDate.of(1999,12,31);


一旦有了一个LocalDate对象, 可以用方法getYear、 getMonthValue和
getDayOfMonth得到年、 月和日:

  1. int year = newYearEve.getYear();
  2. int month = newYearEve.getMonthValue();
  3. int day = newYearEve.getDayOfMonth();

更改器和访问器

LocalDate aThousandDaysLater = LocalDate.plusDays(1000);
这个调用之后newYearsEve会有什么变化? 它会改为1000天之后的日期吗? 事实上, 并没有。 plusDays方法会生成一个新的LocalDate对象, 然后把这个新对象赋给aThousandDaysLater变量。 原来的对象不做任何改动。 我们说plusDays方法没有更改调用这个方法的对象。
与LocalDate.plusDays方法不同, GregorianCalendar.add方法是一个更改器方法( mutator method) 。 调用这个方法后, someDay对象的状态会改变。
只访问对象而不修改对象的方法有时称为访问器方法( accessormethod) 。 例如, LocalDate.getYear和GregorianCalendar.get就是访问器方法 。

完成一个日历程序:

  1. package core;
  2. import java.time.*;
  3. public class CalendeTest {
  4. public static void main(String [] argv){
  5. LocalDate date = LocalDate.now();
  6. int month = date.getMonthValue();
  7. int today = date.getDayOfMonth();
  8. date = date.minusDays(today-1);
  9. DayOfWeek weekday = date.getDayOfWeek();
  10. int value = weekday.getValue();
  11. System.out.println(" Mon Tue Wed Thu Fri Sat Sun");
  12. for(int i=1;i<value;i++)
  13. System.out.print(" ");
  14. while (date.getMonthValue()==month){
  15. System.out.printf("%3d",date.getDayOfMonth());
  16. if(date.getDayOfMonth()==today)
  17. System.out.print("*");
  18. else
  19. System.out.print(" ");
  20. date = date.plusDays(1);
  21. if(date.getDayOfWeek().getValue()==1)
  22. System.out.println();
  23. }
  24. if(date.getDayOfWeek().getValue()!=1)
  25. System.out.println();
  26. }
  27. }

LocalDate的方法

image.png
image.png

用户自定义类

一个源文件中只能有一个公共类,但可以有任意数目的非公共类。
当编译源代码时,源文件中有多少个类就生成多少个源代码文件。

多个源文件的使用

使用通配符调用Java编译器

  1. javac Employee*.java //匹配调用所有前缀带Employee,后缀为java的文件

当Java编译器发现EmploeeTest.java使用(调用)Emploee类时,它会自动查找Emploee.class文件,如果没有找到,就会自动搜索Emploee.class,然后对它进行编译。如果Emploee.class版本较已有的Emploee.class文件版本更新,Java编译器就会自动的重新编译这个文件。