面向对象程序设计概述
面向对象程序设计简称OOP,Java是完全面向对象的。
面向对象的程序是由对象组成,每个对象包含了对用户公开的特定功能部分和隐藏的实现部分。Java中有很多对象来自于标准库,还有一些事自定义的。
传统的结构化程序设计通过一系列的过程(即算法)来求解问题,所以有人说程序=算法+数据结构,其中算法是第一位,而数据是第二位,这样的方式就是首先要确定如何操作数据,然后再决定如何组织数据,以便于操作。而OOP则是将数据放在第一位,然后再考虑操作数据的算法。
(一)类
类(class)是构造对象的模板或蓝图,由类构造(construct)对象的过程称为创建类的实例。
封装(encapsulation,有时称为数据隐藏)是与对象有关的一个重要概念。封装是将数据和行为组合在一个包中,并对对象的使用者隐藏了数据的实现方式。对象中的数据称为实例域(instance field),操纵数据的过程称为方法(method)。对于每个特定的类实例(对象)都有一组特定的实例域值。这些值得集合就是这个对象的当前状态(state)。无论何时,只要想对象发送消息,它的状态就会改变。
继承:OOP的另一个原则会让用户自定义Java类变得轻而易举,就是:可以通过扩展一个类来建立一个新的类。事实上,在Java中所有的类都源自于一个“神通广大的超类”,它就是Object。在扩展一个已有的类时,这个扩展后的新类具有所扩展的类的全部属性和方法。在新类中,只需提供适用于这个新类的新方法和数据域就可以了。
(二)对象
要想使用OOP,一定要清楚对象的三个主要特征:
①对象的行为(behavior):可以对对象施加哪些操作,或可以对对象施加哪些方法?
②对象的状态(state):当施加那些方法时,对象如何响应?
③对象标识(identity):如何辨别具有相同行为但状态不同的对象?
同一个类的所有对象实例,由于支持相同的行为而具有相似性,即可以调用相同的方法。对象的改变通常必须通过调用方法实现,如果不是则说明,对象的封装遭到了破坏。作为一个类的实例,每个对象的标识永远都是不同的。
(三)识别类
OOP首先是从设计类开始,然后再往每个类中添加方法。识别类的简单规则是在分析问题的过程中寻找名词,而方法就对应着动词。例如:订单,商品,账户,付款等。在这之中,商品被添加到订单中,订单被发送或取消,订单货款被支付。。。其中的动词:添加,发送,取消,支付都可以作为方法,而商品,订单这样的名词就是类的对象。
(四)类之间的关系
在类之间,最常见得关系有:
①依赖(“use-a”)
②聚合(“has-a”)
③继承(“is-a”)
依赖(dependence)如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类,就好比我们找银行贷款,而银行要去找中国人民银行查该用户的征信。
聚合(aggregation)聚合关系表示类A的对象包含类B的对象。
继承(inheritance)用于表示特殊与一般的关系。如果类A扩展类B,类A不但包含从类B继承的方法,还拥有一些额外的功能。
使用预定义类
(一)对象与对象变量
要想使用对象,就必须先构造对象,并指定其初始状态(就好比我们对基本类型数据初始化一样)。然后才能使用对象中的方法。在Java中,我们使用构造器(constructor)构造新实例。构造器是一种特殊的方法,用来构造并初始化对象。构造器的名字应该与类名相同。例如:Date类的构造器名为Date。要想构造一个Date类的对象,需要在构造器前加上new关键字。
new Date()
这个表达式构造了一个新的对象,这个对象被初始化为当前的日期和时间。如果我们希望这个对象被多次使用,则可以将这个对象放入一个变量中:
Date now = new Date();
在对象和对象变量之间存在着一个重要的区别:
Date deadline;//这里定义了一个Date类型的变量deadline,但是还没有引用对象。此时还不能使用deadline调用任何方法。
要想使用必须对这个变量进行初始化,有两种方法:①可以用新构造的对象来初始化这个变量,②让这个变量引用另一个已经存在的对象。
在Java中,任何对象变量的值都是对存储在另一地方的一个对象的引用。new操作符的返回值也是一个引用。
Date deadline = new Date();
我们仔细分析上面的代码,对于new Date()这个表达式,它的意义在于构造了一个Date类的对象,但是它的返回值是这个新创建的对象的引用,然后再把这个引用存储在变量deadline中。
如果将一个方法应用于一个值为null的对象上那么就会产生运行时错误。
birthday = null;
String s = birthday.toString();//runtime error
(二)Java类库中的LocalDate类
Java中的Date类的实例有一个状态即特定的时间点。这个点就是所谓的纪元,他是格林威治时间1970年1月1日00:00:00。Java标准库分别包含了两个类,一个是表示时间点的Date类,一个是日历表示法的LocalDate类。
注意:不要使用构造器来构造LocalDate类的对象,实际上,应当使用静态工厂方法代表你调用构造器。
LocalDate now = LocalDate.now();//会构造一个新的对象来表示构造这个对象时的日期。2018-3-25
也通过提供年月日来构造一个特定日期的对象:
package CoreJava;
import java.time.DayOfWeek;
import java.time.LocalDate;
public class LocalDateTest {
public static void main(String[] args) {
LocalDate now = LocalDate.now();
System.out.println("今天是"+now.toString());
LocalDate marryDay = LocalDate.of(2018,1,13);
//还可以通过getYear,getMonthValue,getDayOfMoth得到年,月,日
int year = marryDay.getYear();
System.out.println(year+"年");
int month = marryDay.getMonthValue();
System.out.println(month+"月");
int day = marryDay.getDayOfMonth();
System.out.println(day+"日");
DayOfWeek week = marryDay.getDayOfWeek();
System.out.println("这天是星期"+week.toString());
}
}
(三)更改器方法和访问器方法
更改器方法就是在某个对象调用更改器方法后,原来的对象被改变,例如GregorianCalendar.add方法是一个更改器方法。
访问器方法就是只访问对象而不修改对的的方法。
package CoreJava;
import java.time.DayOfWeek;
import java.time.LocalDate;
public class CalendarTest {
public static void main(String[] args) {
LocalDate now = LocalDate.now();
int month = now.getMonthValue();//获得当前的月
int today = now.getDayOfMonth();//获得当前的日
now = now.minusDays(today-1);//将now设置为这个月的第一天,并得到这一天为星期几。
DayOfWeek weekday = now.getDayOfWeek();
int value = weekday.getValue();
System.out.println("Mon Tue Wed Thu Fri Sat Sun");
for(int i=1;i<value;i++) {
System.out.print(" ");
}
while(now.getMonthValue()==month) {
System.out.printf("%3d", now.getDayOfMonth());
if(now.getDayOfMonth()==today) {
System.out.print("*");
}else {
System.out.print(" ");
}
now = now.plusDays(1);
if(now.getDayOfWeek().getValue()==1) {
System.out.println();
}
}
if(now.getDayOfWeek().getValue()!=1) {
System.out.println();
}
}
}