说到面向对象,我们先来看看和面向对象相对的面向过程的概念。
什么是面向过程?面向过程,顾名思义“过程”是重点,可以理解为当我们要解决某个问题时,会把这个问题里的步骤进行拆分细化,然后按照指定的顺序来执行这些步骤。举例说明我想吃米饭,那么在面向过程中,我需要进行插秧,施肥,收获,放入电饭锅,最后才可以吃饭。假如在水稻种植过程中出现了病虫害,说不定都撑不到收获的季节,那么最后的米饭是不是就吃不上了。这样为了吃一口米饭是不是就显得很繁琐,那我宁愿饿死也不吃了。再假如第二天我又想吃面条了,那我就又得先去播种小麦,施肥,收割,制成面粉,制成面条,煮面,最后才吃上面条。从吃米饭和吃面条来看,支撑我生命活动的非常重要的进食过程是不是非常的麻烦,没有办法,这就是面向过程的着重“过程”之所在。
void 吃米饭(){
插秧();
施肥();
收获();
放入电饭锅();
吃饭();
}
void 吃面条(){
播种();
施肥();
收割();
制成面粉();
制成面条();
开水煮面();
吃饭();
}
再来看看面向对象,何为面向对象?面向对象即所有的事物都可以抽象成对象来表示。
还是以支撑生命活动的进食操作为例,在面向对象中,可以抽象出以下几个对象,①将我抽象为对象,我有吃饭的能力。②将饭馆抽象为对象,他提供点餐的能力。③将粮油公司抽象为对象,他提供收购和销售的能力。④将农民抽象为对象,他提供种植和销售的能力。那么对于我而言,我想吃米饭还是想吃面条,就不需要我再去从水稻小麦的种植开始,亲力亲为。我只需要来到饭馆,使用饭馆提供的点餐功能,即可吃到我想吃的东西。虽然我是向饭馆点餐,但是饭馆也不需要关心水稻小麦是怎么种植的,他只需要从粮油公司手中购买所需的原材料即可。粮油公司也不需要知道水稻小麦的种植过程怎样,他只需要调取农民的销售功能即可获得收获来的水稻和小麦。
我{
吃饭(){
饭馆.点餐(米饭);
}
}
饭馆{
点餐(食物){
粮油公司.销售();
制作食物(食物);
}
制作食物(食物);
}
粮油公司{
收购(){
农民.销售();
};
销售();
}
农民{
种植(){
播种();
施肥();
收割();
}
销售();
}
面向对象实现后,乍一看来似乎比面向过程更加复杂,加入了我以外的其他角色。但是仔细看下,其实面向对象比面向过程有优点的:
将数据或方法隐藏到对象的内部,对外只提供公共的接口供调取所用。具体来说就是可以使用private关键字将对象的属性私有化,然后对外提供public修饰的getter,setter方法。
下面是访问修饰符的作用范围:
访问修饰符 | 本类 | 同一个包 | 子类 | 其他包 |
---|---|---|---|---|
private | √ | × | × | × |
default | √ | √ | × | × |
protect | √ | √ | √ | × |
public | √ | √ | √ | √ |
继承可以理解为父辈的资源传承给后代。例如父类是鸟类,他有羽毛,有飞翔的能力,那么继承了鸟类的后代如老鹰,它也就有了羽毛和飞翔的能力。同时子类自己还可以有其自己的属性,例如老鹰有超凡的视力。
继承有以下几点需要注意的地方:
多态是继承的一种体现,父类可以有很多的子类,因此父类的引用指向不同的子类实现。
以下图的刺激战场中的载具对象来说:
不管是跑车还是蹦蹦还会摩托,它们都有一个共同的父类–载具,载具有轮子的属性以及载人运输的能力。因此上图中的所有的车都有轮子,都可以载人跑毒。子类可以提供多种父类功能及属性的形态,这就称之为多态。
方法名相同,方法参数不同称之为重载。与方法返回类型没有关系。
子类继承了父类,在子类中对继承自父类的方法进行覆盖,重新进行了实现,这一过程称之为重写。方法的名称,参数列表,返回类型必须和父类的一模一样,否则就不可以称之为重写。最常见的是抽象到极致的接口,当我们实现一个接口时,需要对它里面定义的所有的方法进行实现。
内部类主要是用于描述在类内部的事物。这样定义可以减少外部类属性的对外暴露,并且在创建外部类时会自动创建内部类,因此只需要在需要时直接调用内部类即可。
匿名内部类可以理解为在类内部创建的,没有具体名称的类的实现。以创建线程(ps.只是一种表述方式,实际开发中不推荐)为例,可以在类中创建一个匿名的线程类,这样写是不是感觉非常的省事,不需要创建对象继承Thread类,然后再编写调用线程的方法。
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("before java 8");
}
}).start();
Java8以后,对于匿名类的编写有了改变,通过引入lambda表达式,简化了匿名类的编写,如下:
new Thread(() -> {
System.out.println("after java 8");
}).start();
在java类中存在构造代码块,静态代码块,构造方法等,我们先看看下面代码的执行:
class A {
public A() {
System.out.println("Constructor A");
}
{
System.out.println("This is A");
}
static {
System.out.println("This is static block A");
}
}
class B extends A {
public B() {
System.out.println("Constructor B");
}
{
System.out.println("This is B");
}
static {
System.out.println("This is static block B");
}
public static void main(String[] args) {
new B();
}
}
执行结果是:
This is static block A
This is static block B
This is A
Constructor A
This is B
Constructor B
由此可以看出,各代码块的执行顺序:静态代码块>构造代码块>构造方法
以下是关于代码块执行的总结: