面向对象
OOP(Object Oriented Programming) POP(Procedure Oriented Programming) 面向对象(oop)与面向过程(pop) 二者是一种思想。面向对象相对于面向过程而言的,面向过程强调 功能行为,以函数为最小单位,考虑怎么做。面向对象,强调 具备了功能的对象,以类/对象为最小单位,考虑谁来做。 三大特征
- 封装
- 多态
- 继承
程序员从执行者 转化成了指挥者
面向对象分析问题的思路与步骤: - 根据问题需要,选择现实中的实体
- 从实体中寻找解决问题的属性和功能,形成现实中的类
- 将抽象的实体用计算机语言描述
- 将类实例化为计算机中的对象。
一、类与对象
- 类和对象(类是对象的抽象,对象是类的实体)
- 类:是对一类具有相同属性和行为的事物的抽象(手机)
- 对象:是真实存在的该类事物的物体(华为手机,老年机)
- 类 属性+行为 || 成员变量+成员方法
1. 属性方法
属性 + 行为
||
成员变量Filed + 成员方法Method
2. 类与对象的使用
- 创建类,设计类成员
- 创建类的对象
- 通过 对象.属性 对象.方法
3. 对象的创建使用
类的访问机制:
- 在同一个类中,类中的方法可以直接访问类的成员变量(例外:static方法访问非static,编译不通过)
- 在不同类中,先创建访问类的对象,通过对象来访问类的成员变量
4. 内存解析
5. 匿名对象
不定义对象的句柄,而直接调用这个对象的方法。例如:new person().shout();
- 一个对象只需要进行一次方法调用,就使用匿名对象
- 经常用匿名对象来作为实参传递给一个方法使用
6. 属性(成员变量)与局部变量
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 类中的位置不同 | 类中方法外 | 方法内或方法声明上 |
| 内存位置不同 | 堆内存或静态域 | 栈内存 |
| 生命周期不同 | 随着对象而存在 | 随着方法存在 |
| 初始化值不同 | 有默认初始化值 | 无默认,得先定义赋值后使用 |
| 修饰符 | private、public、static、final | 不能用权限修饰符final |
二、(成员)方法Method
不可以在方法内定义方法 方法是类或对象行为特征的抽象,用来完成某个功能操作。
1. 重载overload
重载:在同一个类中,允许定义一种以上同名方法,只要它们的参数个数或者参数类型不同即可。
特点
与返回值类型无关,只看参数列表,且参数列表必须不同(参数个数或者参数类型)
调用时根据方法参数列表不同来区别
2. 传参
可变形参
- 声明: 方法名(参数的类型名 ...参数名)
- 方法参数指定是0个1个或者多个
- 与同名的方法构成重载
- 方法参数有可变形参的,放在参数最后面
- 最多只能声明一个可变形参 参数传递机制
- java里方法的参数传递方式只有一种:值传递。即将实际参数值的副本传入方法内,而参数本身不受影响。
- 基本类型:将实参的数据值传给形参
- 引用类型:将实参的地址值传给形参
3. 递归
递归:一个方法调用自己本身 注意:要有递归出口 每次调用的返回值,局部变量都会分配栈空间,所以递归次数过多容易导致栈溢出 效率低,不推荐使用
4. 调用过程
三、封装与隐藏
追求高内聚,低耦合
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
- 低耦合:仅对外暴露少量的方法用于使用
设计思想: 隐藏对象内部的复杂性,仅对外公开简单的接口。便于外部调用,从而提高系统的可扩展性、可维护性。"该隐藏的隐藏,该暴露的暴露"封装原则将类的某些信息隐藏在类的内部,不允许外部直接调用,而是通过成员变量private,提供对应的方法。
1. 信息的封装和隐藏
java通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx()和serXxx()实现对该属性的操作。 便于修改,增强代码的可维护性
2. 四种权限修饰符
对于类的权限修饰只能用public、default(缺省)
- private 同一个类
- default(缺省) 同一个包下
- protected 不同包的子类
- public 同一工程下
3. 构造器(构造方法)
不提供构造方法,自动默认无参构造方法;
一旦手动提供构造方法,则不再自动提供无参构造方法。
特征:
- 与类同名
- 不声明返回值类型(与声明void不同)
- 不能被 static、abstract、final、synchronized、native修饰
作用
创建对象,给对象初始化
- 默认构造器的修饰符与类的修饰符一致
- 一个类可以创建多个重载的构造器
- 子类不能继承父类的构造器
4. 属性赋值
四种赋值(顺序1->4): 1.默认赋值 2.显示初始化赋值 3.构造器中初始化 4.通过 对象.属性 对象.方法的方式赋值
5. JavaBean
javabean是一种java语言写成的可重用组件。 javabean指符合下面标准的类:
- 类是公共的
- 有一个无参的公共构造器
- 有属性,且有对应的set、get方法
标准类
- 成员变量: 使用private修饰
- 构造方法: 提供无参、多参构造方法
- 成员方法: 提供setXX、getXX方法、显示信息show
6. UML类图
7. This
解决局部变量隐藏成员变量
this作用
在方法内部使用,即这个方法所属对象的引用
在构造器内部使用,表示该构造器正在初始化的对象
this可以调用类的属性、方法、构造器
使用this
当在方法内需要用到调用该方法的对象时,就用this
比如:用this区分属性与局部变量
- 可以在构造器中使用this(形参列表)的方式,调用本类中重载的其他构造器
- 构造器不能通过this(形参)来调用自身
- 一个类n个构造器,则最多有n-1个构造器使用了this(形参)
- this(形参)必须生声明在类的构造器首行
- 在构造器中,最多只能声明一个this(形参)
8. package
package
包就是文件夹,用来管理类文件的
带包编译:javac–d.类名.java
例如:javac-d. HelloWorld.java
带包运行:java包名+类名
例如:javacom.heima.demo.HelloWorld
包名用小写字母,一般为公司域名的倒置
包的作用
- 管理大型项目,将功能类似的划分同一个包
- 包划分项目层次,便于管理
- 解决类命名冲突的问题
- 控制访问权限
9. MVC设计模式
MVC:常用设计模式之一,降低了耦合性
M:model 视图模型层---主要处理数据
V:view 视图层---view显示数据
C:controller 控制层---处理业务逻辑
10. import
import
使用不同包下的类时,使用的时候要写类的全路径,
写起来太麻烦了为了简化带包的操作,Java就提供了导包的功能
import告诉编译器要去哪里寻找类
import static 组合的使用:调用指定类或接口下的静态的属性或方法
四、继承
1. 继承性
类
父类:基类、超类
子类:派生类
对象在堆内存中,会单独存在一块super区域,用来存放父类的数据
继承好处与弊端
好处:复用性、可维护性
弊端:类的耦合性增强,父变化子不得不变
何时使用继承: A is B 的一种
继承中变量访问特点:
在子类方法中访问一个变量,采用的是就近原则。
-
1.子类局部范围找
-
2.子类成员范围找
-
3.父类成员范围找
-
4.如果都没有就报错(不考虑父亲的父亲... )
继承中构造方法访问特点:
注意:子类中所有的构造方法默认都会访问父类中无参的构造方法
子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认都是:super()
问题:如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢?
通过用super关键字显式的调用父类带参构造方法;或者在父类自己提供无参方法
继承中成员方法访问特点:
-
1.子类成员
-
2.父类成员
-
3.找不到报错。
2. 方法重写
-
子类出现了和父类中一模一样的方法声明, (方法名一样,参数列表也必须一样)
-
override注解:检查是否为重写方法
-
方法重写的注意事项
1.私有方法不能被重写(父类私有成员子类是不能继承的)
2.子类方法访问权限不能更低(public>默认>私有) 3.子类抛出的异常不能大于被重写方法抛出的异常 4.子类方法返回值类型不能更大
3. Super
super:代表父类存储空间的标识(父类对象的引用)
五、多态
1. 多态性
多态:对象不同时刻的不同状态,java中指父类的引用指向子类的对象
前提:
- 有继承/实现关系
- 有方法重写
- 有父类引用指向子类对象
多态中成员变量访问
成员变量:编译看左边,执行看左边
成员方法:编译看左边,执行看右边(因为方法可以重写)
子类可以看做是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型
2. 向下转型
向下转型(强制类型转换)(造型):高级类->低级类 用instanceof来判断是否具有子类与父类关系(继承关系)
3. Object类
- 所有类的根父类是Object类
- 属于java.lang.Object
- equals、hashCode(取得Hash码)、toString
4. ==与equals
面试题:==和equals的区别
1.== 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型 就是比较内存地址(是否同一对象) 2.equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也 是==;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中 用的比较多,久而久之,形成了equals是比较值的错误观点。 3.具体要看自定义类里有没有重写Object的equals方法来判断。 4.通常情况下,重写equals方法,会比较类中的相应属性是否都相等。
5. toString
Object里的方法,返回类名和它的引用地址
6. 包装类
八个基本类型提供了包装类! 一般首字母大写为包装类,除:int ---Integer; char ---Character 装箱:基本类型 --> 包装类 拆箱:包装类 --> 基本类型
包装类->基本:包装类.XxxValue()
字符串->基本类型:包装类.parseXxx()
基本->字符串:String.valueOf()
7. 基本、包装类、string之间转换
六、内部类、抽象类与接口(static、final、代码块、设计模式)
1. static
有些时候,我们希望无论是否产生对象或产生多少对象,某些特定的数据在内存中只有一份,供外部使用
哪些属性不因对象的改变而变,就设置为类属性,形影设置为类方法
- static关键字是静态的意思,可以修饰【成员方法】,【成员变量】 ,【代码块】,【内部类】
- 1.被类的所有对象共享,这也是我们判断是否使用静态关键字的条件
- 2.可以通过类名调用,当然也可以通过对象名调用【推荐使用类名调用】
特点
随着类的加载而加载
优于对象
被所有对象共享
直接类来调用
被static修饰的变量叫做类变量 被static修饰的方法叫类方法
类方法
- 类名.方法()来使用
- 被static修饰的方法内部只能访问被static修饰的属性方法
- 因为不需要实例就可以访问,所以static方法内部不能有this和super
- static修饰的方法不能被重写
类变量的内存

2. 单例设计模式Singleton
设计模式 是在大量的实践中总结和理论化后优选的代码结构、编程风格以及解决问题的思考方式。类似于经典的棋谱==“套路” 饿汉式:
对象预先加载,线程是安全的,在类创建好的同时对象生成,调用获得对象实例的方法反应速度快,代码简练。
public class Singleton {
//私有化构造器
private Singleton(){
}
//提供一个当前类的实例化
//此实例必须静态化
private static Singleton singleton= new Singleton();
//提供公共静态方法,返回当前类对象
public static Singleton getInstance(){
return singleton;
}
}
懒汉式: 对象延迟加载,效率高,只有在使用的时候才实例化对象,但若设计不当线程会不安全,代码相对于饿汉式复杂,第一次加载类对象的时候反应不快。
public class Singleton {
//私有化构造器
private Singleton(){
}
//提供一个当前类的实例
//此实例必须静态化
private static Singleton single;
//提供公共静态方法,返回当前类对象
public static Singleton getInstance(){
if (single==null){
single=new Singleton();
}
return single;
}
}
优点 由于单例模式只生成一个实例,减少了系统性能开销, 当一个对象需要比较多的资源时,如:读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留在内存的方式来解决! 应用场景 举例:java.lang.Runtime
public class Runtime{
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime(){
return currentRuntime;
}
private Runtime(){
}
}
3. main
java虚拟机需要调用类的main方法,所以访问权限是public 不创建对象,所以是static 接收一个string数组参数,保存执行java命令时所运行的类的参数
4. 代码块
代码块作用
对类或对象进行初始化
一个类中的代码块如果被修饰,只能是static,称为静态代码块(static block);不被static修饰,称为非静态代码块
- static 代码块通常为了初始化static的属性。
注意:代码块是从上往下执行静态代码块:只能访问静态属性与方法,优于非静态代码块,随着类的加载而执行,且只执行一次非静态代码块:访问所有,优于构造器,随着对象的创建而执行一次
5. final
- Java中声明类、变量、方法时,可用final修饰,“最终的”
- 1.final标记的类不能被继承。提高安全性,提高程序的可读性。 @String类、System类、StringBuffer类
- 2.final标记的方法不能被子类重写。 @Object类中的getClass()
- 3.final标记的变量称为常量。名称大写,且只能被赋值一次。 static final 为全局常量
6.抽象类与抽象方法
抽象类
是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类
用abstract修饰的类
抽象方法
用abstract修饰的方法;只有方法的声明,没有方法的实现。
public void add(int i);
- 不能用abstract修饰变量、代码块、构造器
- 不能用abstract修饰私有方法、静态方法、final方法、final类
- 含有抽象方法的类必须声明为抽象类
- 抽象类是不能被实例化,是用来被继承的,子类需要重写全部的抽象方法,并提供抽象体,否则子类仍为抽象类 含有抽象方法的类一定是抽象类,抽象类不一定含有抽象方法。
7.模板方法设计模式TemplateMethod
- 多态的应用:TemplateMethod
解决的问题 - 当功能内部一部分实现是确定的,一部分是不确定的。这时可以把不确定的部分暴露出去,让子类实现。
- 也就是说,在软件开发中,整体步骤很固定、通用,这些步骤已经在父类中写好了。但在某些部分易变,易变部分可以抽象出来,供不同子类实现.
代码格式
类似于抽象类写法
应用
各个框架、类库中都有它的影子,比如:
- 数据库访问的封装
- Junit单元测试
- JavaWeb的servlet中关于doGet、doPost方法调用
- Hibernate中模板程序
- Spring中的JDBCTemplate、HibernateTemplate等
8. 接口interface
接口
接口就是规范,定义的一组规则,体现了“如果你是/要...则必须能...”的思想。
继承是一个“是不是”的关系,而接口实现则是“能不能”的关系。
接口的本质是契约,标准,规范。
接口是抽象方法与常量的值定义的集合
1.接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。
Java中的接口更多的体现在对行为的抽象!
2.特点:
-
接口用interface修饰
-
类实现接口用 implements表示
-
接口不能实例化:可以参照多态形式,通过实现类实例化,叫做接口多态。
-
多态的形式:具体类多态、抽象类多态、接口多态
-
接口的子类
要么重写接口的所有抽象方法,要么子类也是抽象类。
3.接口成员特点:
- 成员变量: 只能是常量 public static final
- 构造方法: 没有,接口主要是扩展功能,无具体存在
- 成员方法: 只能是抽象方法 public abstract 《JDK1.7之前》
jdk1.8提出
- 可以为接口添加静态方法和默认方法(用default修饰)
- 当一个接口定义了默认方法,另一个接口也定义了同名同参方法(无论是否默认方法),实现类同时实现两个接口,出现“接口冲突”
- 解决: 实现类必须覆盖接口中的同名同参方法
- 如果接口定义了默认方法,而父类也定义了同名同参非抽象方法,不会出现冲突,因为遵守:类优先原则。接口方法被忽略。
9. 代理模式Proxy
代理对象
是java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。

10. 工厂模式
工厂模式Factory Pattern是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。 意图: 定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。 主要解决: 主要解决接口选择的问题。 何时使用: 我们明确地计划不同条件下创建不同实例时。 如何解决: 让其子类实现工厂接口,返回的也是一个抽象的产品。 关键代码: 创建过程在其子类执行。 优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。 使用场景: 1、日志记录器 2、数据库访问, 3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
11. 接口与抽象类对比
| NO. | 区别 | 抽象类 | 接口 |
|---|---|---|---|
| 1 | 定义 | 包含抽象方法的类 | 包含抽象方法以及常量的集合 |
| 2 | 组成 | 构造方法、抽象方法、普通方法、常量、变量 | 抽象方法、常量(jdk1.8:默认方法、静态方法) |
| 3 | 使用 | 子类Extends | 子类implements |
| 4 | 关系 | 抽象类可以实现多个接口 | 接口不能继承抽象类 |
| 5 | 常见使用模式 | 模板方法 | 简单工厂、工厂方法、代理模式 |
| 6 | 对象 | 都通过对象的多态性产生多态 | |
| 7 | 局限 | 单继承 | 无单继承局限 |
| 8 | 实际 | 模板 | 标准、能力 |
| 9 | 选择 | 优先接口 | 优先接口 |
12. 内部类
1.内部类: 在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类 。
2.内部类访问特点:
- 可以直接访问外部类的成员,包括私有的
- 外部类访问内部类,必须创建内部类的对象
3.成员内部类:
- 在类中方法,跟成员变量是一个位置
- 格式:外部类名.内部类名对象名=外部类对象.内部类对象
- 将一个类,设计为内部类的目的,大多数都是不想让外界去访问,所以内部类的定义应该私有化,私有化之后,再提供一个可以让外界调用的方法,方法内部创建内部类对象并调用
- 编译生成OutClass$InnerClass.class字节码文件 4.局部内部类: - 局部内部类是在方法中定义的类 - 局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用 , 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
5.匿名内部类:
是一个继承了该类或者实现了该接口的子类匿名对象
6.匿名内部类开发中的使用
当发现某个方法需要,接口或抽象类的子类对象,我们就可以传递一个匿名内部类过去,来简化传统的代码
知识图谱
在线阅读:java面向对象
面向对象部分已更新完.......