1.面向对象与面向过程

一、编程思想不同

1、面向过程:是一种以过程为中心的编程思想。都是以什么正在发生为主要目标进行编程。

2、面向对象语言:是一类以对象作为基本程序结构单位的程序设计语言,指用于描述的设计是以对象为核心,而对象是程序运行时刻的基本成分。

二、特点不同

1、面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

2、面向对象语言:识认性,系统中的基本构件可识认为一组可识别的离散对象,对象具有唯一的静态类型和多个可能的动态类型,在基本层次关系的不同类***享数据和操作。

三、优势不同

1、面向过程:不支持丰富的“面向对象”特性(比如继承、多态),并且不允许混合持久化状态和域逻辑。

2、面向对象语言:在内部被表示为一个指向一组属性的指针。任何对这个对象的操作都会经过这个指针操作对象的属性和方法。

面向对象编程语言三大特征:

隐藏/封装(encapsulation, capsul胶囊)

需要让用户知道的暴露出来,不需要让用户了解的全部隐藏起来。这就是封装。“该露的露,该藏的藏。”

继承(extend)

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

继承的另一个好处是:代码重用,让我们不再重新发明轮子(don’t reinvent wheels)

多态(polymorphism)

为了处理问题的灵活性。 就是在做之前,不要把话说死,说的模糊一点想象空间大一点,真做的时候再具体化。

2.类

类的定义:

class 类名{

}

类名需要满足命名规则和规范,类的命名应该使用大驼峰命名原则

对于一个类来说,一般有三种常见的成员:属性 field 、方法 method 、构造器 constructor 。这三种成员都可以定义零个或多个。

3.对象的创建和使用

必须使用 new 关键字创建对象。

Person person= new Person ();

使用 对象(引用) . 成员变量 来引用对象的成员变量。

person.age;

使用 对象(引用) . 方法名(参数列表) 来调用对象的方法。

person. setAge(23);

同一类的每个对象有不同的成员变量存储空间。

同一类的每个对象共享该类的方法。

构造器用于构造该类的实例。Java通过new关键字来调用构造器,从而返回该类的实例。

  • 构造器没有返回值 方法名必须要与类名相同。
  • 构造器虽然有返回值,但是不能定义返回类型(返回值的类型肯定是本类),不能在构造器里使用带数据的return语句。
  • 如果没有自己写构造器,系统编译时会自动定义一个空构造数。如果已经定义构造器,系统不会自己定义!

4.this关键字

基本含义:当前对象 ->this当前哪个对象持有this就指代谁

普通方法中,this总是指向调用该方法的对象。

构造方法中,this总是指向正要初始化的对象。

this最常的用法:

  • 让类中的一个方法,访问该类的另一个方法(this.方法名())或属性(this.属性名)。访问属性更常用,用来区分同名的形参和属性。
  • 使用this关键字调用重载构造方法。避免写相同的初始化代码,只能在构造方法中用,并且必须位于构造方法的第一句。
public class TestThis { 

int a; 

int b; 

int c; 

TestThis(){ 

System.out.println("正要new一个Hello对象"); 

}

TestThis(int a,int b){ 

//Hello(); // //这样是无法调用构造方法的! 

this(); //调用无参的构造方法,并且必须位于第一行! 

a = a;//这里都是指的局部变量而不是成员变量 

this.a = a;//这样就区分了成员变量和局部变量. 这种情况占了this使用情况的大多数!

this.b = b; 

}

TestThis(int a,int b,int c){ 

this(a,b); //调用无参的构造方法,并且必须位于第一行!

this.c = c; 

}

void sing(){} 

void chifan(){ 

this.sing(); //sing(); 

System.out.println("你妈妈喊你回家吃饭!"); 

}

public static void main(String[] args){ 

TestThis hi = new TestThis(2,3); 

hi.chifan(); 

} 

}

还有一点,this是不能与static关键字一起用的。因为被static修饰的方法或变量是先于对象存在的。程序运行的时候,会先加载静态方法和静态变量。而此时对象都还没开始创建,哪来的当前对象去调用。所以说this关键字不能与static一起用

5.static关键字

static属性: 属性被所有对象共享;这个属性先于对象存在的

static方法: 这个方法先于对象存在

static 表示静态的, 所有对象共用的(所有对象都看到一份,而且只要其中任何一个对象对其进行修改,其他所有对象都会看到这个变化),所有的静态内容都是跟随类存在,在对象还没有的时候就已经存在。

可以通过对象引用或类名(不需要实例化)访问静态成员。

在static方法中不可访问非static的成员。也不可以出现this关键字

6.块的执行顺序

静态代码块>匿名普通代码块>构造代码块

如果有继承关系,加载顺序为:

父类静态代码块->子类静态代码块->父类普通代码块->父类构造函数->子类普通代码块->子类构造函数

7.JDK中主要包

  • java.lang -包含一些Java语言的核心类,如String、Math、Integer、System 和Thread,提供常用功能。
  • java.net -包含执行与网络相关的操作的类。
  • java.io -包含能提供多种输入/输出功能的类。
  • java.util -包含一些实用工具类,如定义系统特性、使用与日期日历相关的
  • 函数。

import:通过import可以导入其他包下面的类,从而可以在本类中直接通过类名来调用。

java会默认导入 java.lang 包下所有的类,因此这些类我们可以直接使用。

import java.util.Date; 

import java.util.*; //导入该包下所有的类。会降低编译速度,但不会降低运行速度。

8.访问控制符

权限:public>protected>default>private

9.封装->使用访问控制符

需要让用户知道的暴露出来,不需要让用户了解的全部隐藏起来。这就是封装

编程中封装的具体意义:

  • 便于调用者调用。
  • 良好的封装,便于修改内部代码,提高可维护性。
  • 良好的封装,可进行数据完整性检测,保证数据的有效性。

类的属性的处理:

一般使用 private 。 (除非本属性确定会让子类继承)

提供相应的 get/set 方法来访问相关属性. 这些方法通常是 public ,从而提供对属性的读取操作。(注意:boolean变量的get方法是用:is开头!)

一些只用于本类的辅助性方法可以用 private ,希望其他类调用的方法用public 。

10.继承

为什么需要继承?继承的作用?

第一好处:继承的本质在于抽象。类是对对象的抽象,继承是对某一批类的抽象。

第二好处:为了提高代码的复用性。(事实上,利用组合可以更好的实现代码复用!)

子类继承父类,可以得到父类的全部属性和方法 (除了父类的构造方法)。

java中只有单继承,一个子类只能继承一个父类

并且,被final修饰的类不能被继承

如果没有使用extends关键字,默认该类继承的是Object类

11.super关键字

super 是直接父类对象的引用。可以通过 super 来访问父类中被子类覆盖的方法或属性。

普通方法:

没有顺序限制。可以随便调用。

super

访问父类的属性: super.属性名; 前提是有访问权限

方法父类的方法: super.方法名(); 前提是有访问权限

访问父类的构造器: suepr(); 前提是有访问权限

在没有显示通过super调用父类构造器时,一定会在子类构造器的入口默认调用一个无参构造 suepr() 。

如果父类中没有提供无参构造,子类必须手动调用父类的带参构造 suepr(实参列表);

在子类构造器中,this与super关键字不能通过使用。因为这两个关键字都必须在第一行,作为构造器的入口。

12.重载与重写

重载是发生在同一个类里面的,重写是发生在父类与子类之间的。

重载->方法名字相同,而参数不同。返回类型可以相同也可以不同

注意点:

  • 被重载的方法必须改变参数列表(参数个数或类型不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。

重写->方法体,返回值和形参都不能改变。即外壳不变,核心重写!

注意点:

  • 访问权限不能比父类中被重写的方法的访问权限更低 如父类为public 子类只能为public
  • 声明为 final 的方法不能被重写。
  • 声明为 static 的方法不能被重写,但是能够被再次声明。
  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
  • 构造方法不能被重写。

13.final关键字

修饰变量

被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。

修饰成员变量

成员变量必须要赋值

修饰局部变量

常量要进行初始化,如果采用系统默认值的话,就失去了存在的意义。

因此必须显式初始化,可以直接赋值或初始化块中或构造函数中。

但只能赋值一次!

final修饰的是引用变量时只是引用值不能改变。对应的对象内部的属性仍然可变。

修饰方法

该方法不可被子类重写。但是可以被重载!

如果父类方法是 private final ,那么对子类完全不可见;子类也就可以定义自己的同名的方法。这个不是重写了,而是子类自己新定义的方法。

修饰类

修饰的类不能有子类,不能被继承。比如:Math、String。

14.多态:方法的多态,属性没有多态。

方法绑定:

静态绑定:

在编译期完成,可以提高代码执行速度。静态绑定的方法包括

  1. 静态方法
  2. 构造器
  3. private方法
  4. 用关键字super调用的方法

动态绑定:

动态绑定是指在 执行期间(非编译期) 判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。程序运行过程中,把函数(或过程)调用与响应调用所需要的代码相结合的过程称为动态绑定。

如何去实现多态

编译时类型和运行时类型不一致,就可能会造成多态。

多态的存在要有3个必要条件:要有继承,要有方法重写,父类引用指向子类对象

15.抽象类与接口

抽象类:

abstract class 类名{

abstract public void test();

}

类中必须要有抽象方法(被abstract关键字修饰的方法),有抽象方法的类只能定义能抽象类或者接口

抽象类不能实例化,即不能用new来实例化抽象类。

抽象类可以包含属性、方法、构造方法。但是构造方法不能用来new实例,只能用来被子类调用。

抽象类只能用来继承。

抽象方法必须被子类实现。

抽象类和普通父类的区别,就在于包含抽象方法,抽象方法必须被子类实现,从而可以对子类的设计进行规范。

接口:

接口可被多继承,子类通过关键字implements实现接口

[权限修饰符] interface 接口名 [extends 父接口1,父接口2…] { 

常量定义; 

抽象方法定义; 

}

继承写在前,实现接口写在后

public class test extends tests implements 接口1,接口2{

}

有抽象类了为什么还要接口

抽象类提供了空模板,子类可以继承去实现父类不能实现的功能。继承的是抽象类的属性和方法。

如果单纯想要使用方法,那可以去实现接口,因为接口只提供抽象方法。

  1. 访问修饰符:只能是public或默认。
  2. 接口名:和类名采用相同的命名机制
  3. extends:接口可以多继承
  4. 常量:接口中的属性只能是常量,总是:public static final 修饰。不写也是。
  5. 方法:接口中的方法只能是:public abstract。 省略的话,也是public abstract.如果改成其他的修饰符,就会影响类去重写方法。

接口中只能包含 静态常量、抽象方法 ,不能有普通属性、构造方法、普通方法、静态块。

接口和抽象类的区别

抽象类和接口均包含抽象方法,类必须实现所有的抽象方法,否则是抽象类

抽象类和接口都不能实例化,他们位于继承树的顶端,用来被其他类继承和实现

两者的区别主要体现在两方面:语法方面和设计理念方面

语法方面的区别是比较低层次的,非本质的,主要表现在:

接口中只能定义全局静态常量,不能定义变量。抽象类中可以定义常量和变量。

接口中所有的方法都是全局抽象方法。抽象类中可以有0个、1个或多个,甚至全部都是抽象方法。

抽象类中可以有构造方法,但不能用来实例化,而在子类实例化是执行,完成属于抽象类的初始化操作。接口中不能定义构造方法。

一个类只能有一个直接父类(可以是抽象类),但可以充实实现多个接口。一个类使用extends来继承抽象类,使用implements来实现接口。

抽象类体现了一种继承关系,目的是复用代码,抽象类中定义了各个子类的相同代码,可以认为父类是一个实现了部分功能的“中间产品”,而子类是“最终产品”。父类和子类之间必须存在“is-a”的关系,即父类和子类在概念本质上应该是相同的。

接口并不要求实现类和接口在概念本质上一致的,仅仅是实现了接口定义的约定或者能力而已。接口定义了“做什么”,而实现类负责完成“怎么做”,体现了功能(规范)和实现分离的原则。接口和实现之间可以认为是一种“has-a的关系”

16.面向对象设计原则

16.1. 单一职责原则·

一个类应该有且只有一个变化的原因。单一职责原则将不同的职责分离到单独的类,每一个职责都是一个变化的中心。需求变化时,将通过更改职责相关的类来体现。如果一个类拥有多于一个的职责,则多个职责耦合在一起,会有多于一个原因来导致这个类发生变化。一个职责的变化可能会影响到其他的职责,另外,把多个职责耦合在一起,影响复用性。

16.2. 里氏代换原则

这就是要求继承是严格的is-a关系。所有引用基类的地方必须能透明地使用其子类的对象。在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。

例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类;但是我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物。

16.3. 依赖倒置原则

依赖倒置原则的核心就是要我们面向接口编程,理解了面向接口编程,也就理解了依赖倒置。

低层模块尽量都要有抽象类或接口,或者两者都有。

变量的声明类型尽量是抽象类或接口。根据标准写实现

16.4. 接口隔离原则

客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上,通俗的讲就是需要什么就提供什么,不需要的就不要提供。

16.5. 迪米特法则

迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简 写LKP),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。

也就是说,一个类应该对自己需要耦合或调用的类知道的最少,类与类之间的关系越密切,耦合度越大,那么类的变化对其耦合的类的影响也会越大,这也是我们面向设计的核心原则:低耦合,高内聚。

16.6. 开闭原则

对修改关闭,对扩展开放。在软件的生命周期内,因为变化,升级和维护等原因需要对软件原有代码进行修改,可能会给旧代码引入错误,也有可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现。不过这要求,我们要对需求的变更有前瞻性和预见性。其实只要遵循前面5中

设计模式,设计出来的软件就是符合开闭原则的。

17.类与类之间的关系

17.1. 继承关系

继承指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力。在Java中继承关系通过关键字extends明确标识,在设计时一般没有争议性。在UML类图设计中,继承用一条带空心三角箭头的实线表示,从子类指向父类,或者子接口指向父接口。

17.2. 实现关系

实现指的是一个class类实现interface接口(可以是多个)的功能,实现是类与接口之间最常见的关系。在Java中此类关系通过关键字implements明确标识,在设计时一般没有争议性。在UML类图设计中,实现用一条带空心三角箭头的虚线表示,从类指向实现的接口。

17.3. 依赖关系

简单的理解,依赖就是一个类A使用到了2,而这种使用关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。比如某人要过河,需要借用一条船,此时人与船之间的关系就是依赖。表现在代码层面,为类B作为参数被类A在某个method方法中使用。在UML类图设计中,依赖关系用由类A指向类B的带箭头虚线表示。

17.4. 关联关系

关联体现的是两个类之间语义级别的一种强依赖关系,比如我和我的朋友,这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,一般是长期性的,而且双方的关系一般是平等的。关联可以是单向、双向的。表现在代码层面,为被关联类B以类的属性形式出现在关联类A中,也可能是关联类A引用了一个类型为被关联类B的全局变量。在UML类图设计中,关联关系用由关联类A指向被关联类B的带箭头实线表示,在关联的两端可以标注关联双方的角色和多重性标记。

17.5. 聚合关系

聚合是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系。此时整体与部分之间是可分离的,它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享。比如计算机与CPU、公司与员工的关系等,比如一个航母编队包括海空母舰、驱护舰艇、舰载飞机及核动力攻击潜艇等。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。在UML类图设计中,聚合关系以空心菱形加实线箭头表示。

17.6. 组合关系

组合也是关联关系的一种特例,它体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合。它同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束,比如人和人的大脑。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。在UML类图

设计中,组合关系以实心菱形加实线箭头表示。