面向对象
面相对象(oop)和面向过程(pop)通常一起说,一个是更加关注过程,事力亲为,而面向对象更加注重结果,所以说,面向对象更加是一种思想,它贯穿整个java,以上帝视角来看整个功能需求,简化开发过程,对业务逻辑进行封装,对javabean进行封装,让程序之间解耦,代码之间的调用。
面向对象三大特性:封装,继承,多态
一.封装
封 装(包装零散数据为一个整体; 权限控制)
作用:包装零散的数据为一个不可分割整体;保证数据的安全性(通过四种访问权限)
1.创建对象的过程:
1、 创建 类 Goods
定义类的属性
1、 属性类型 2、 属性值(创建对象时候赋值)
2、创建对象
创建使用: 类名 变量名 = new 类名 ();
特别注意: 创建的时候,一定使用一个相同类型的变量去接受
3、对象的使用 (具体对象 外星人 ,机械革命)
1、 创建好对象
2、 属性的赋值 变量名.属性名称 (对象.属性名)
特别注意: 属性的赋值 ,数据类型一定要相匹配
类 与 对象区别
类是一个抽象概念 ,是对象的模板
对象 是一个具体概念, 代表是一个具体的事物
类 : 都是 属性 + 方法
事物的成员分为两种:成员属性和成员功能。
成员属性在代码中的体现就是成员变量
成员功能在代码中的体现就是成员方法
必须使用 new 关键字创建对象,new 做三件事:
①会在堆中为相应类型分配空间
②会调用相应的构造方法来初始化对象
③将在堆中开辟的空间的地址返回回来
1、栈区(stacksegment)—由编译器自动分配释放,存放局部变量(方法内部变量+形式参数)基本变量值和引用变量地址,具体方法执行结束之后,系统自动释放 JVM 内存资源
2、堆区(heapsegment)—存放 new 出来的东西,jvm 不定时查看这个对象,如果没有引用指向这个对象就回收
3、方法区—存放全局变量,静态变量和字符串常量,程序中方法的二进制代码,而且是多个对象共享一个代码空间区域
2.Static关键字
1、局部变量
生命周期: 从定义开始 到 方法执行结束
2、全局 变量(属性)
1、 静态属性 【当修改静态属性 时, 对所有对象可见】
2、 成员属性 【当修改成员 属性时候, 只对象当前对象可见】
生命周期:
1、 静态属性 : 类加载的时候一直存在 (绑定类)
2、 成员属性: 创建对象到对象被回收 (绑定对象)
全局 变量 在创建 未被定义?
初始化的时候, 提供一个默认值
默认值: 引用类型 ---> null
数字型:
1、整形 0
2、浮点型 0.0
char ---->""
布尔型-----> false
方法
1、静态方法
2、成员方法
方法的使用:
1、静态方法 (绑定类) 类名.方法名 对象.方法名
2、成员方法(绑定对象) 对象.方法名
方法之间的调用
1、静态方法 ---调用---> 静态方法 可行
2、静态方法 (类) ---调用----> 成员方法 (对象) 不可行
解决方案: 在静态方法中 创建对象,然后使用对象调用
3、成员方法(对象) ---调用----> 静态方法 (类) 可行
4、 成员方法(对象) ---调用----> 成员方法(对象) 可行
静态内容是优先于对象存在,只能访问静态,不能使用 this/super。
静态修饰的内容存于静态区。
简单拓展:
JVM 在创建对象,都会默认给对象 检测器
调用 方法区中两种方法时候,
调用成员方法 , 编译后 调用成员方法 将会去检测 this(对象)
调用静态方法, 编译后 将不会去检测 this(对象)
3.成员变量和局部变量区别:
区别一:定义的位置不同
定义在类中的变量是成员变量
定义在方法中或者{}语句里面的变量是局部变量
区别二:在内存中的位置不同
成员变量存储在堆内存的对象中
局部变量存储在栈内存的方法中
区别三:声明周期不同
成员变量随着对象的出现而出现在堆中,随着对象的消失而从堆中消失
局部变量随着方法的运行而出现在栈中,随着方法的弹栈而消失
区别四:初始化不同
成员变量因为在堆内存中,所有默认的初始化值
局部变量没有默认的初始化值,必须手动的给其赋值才可以使用。
4.构造方法:
构造方法和一般方法的区别:
构造方法在对象创建时就执行了,而且只执行一次。
一般方法是在对象创建后,需要使用时才被对象调用,并可以被多次调用。
构造方法的特点:
1) 名称必须和类名一致,与类名相同
2) 没有返回类型|void
3) 构造器可以存在 return,return 有选择的跳出构造器
4) 不能随便调用,和 new 在一起使用,其他时候不能调用
作用:
初始化对象信息,不是用于创建对象的
空构造:
没有参数的构造器、无参构造
1) 一个类中,如果没有显示|手动 加入 任意构造器 javac 编译后 自动加入空构造
2) 一旦加入构造器, javac 不会加入空构造器
5.关键字:this:
可以在成员变量名前面加上 this.来区别成员变量和局部变量
在类的方法定义中使用的 this 关键字代表使用该方法的对象的引用。
this 即”自己”,代表对象本身,谁调用代表谁。在成员方法中或构造器中隐式
的传递。作用如下:
1、this 在构造器中只能放在第一行
2、this.属性避免属性和形参、局部变量同名,发生就近原则
3、this([实参列表]): 构造器的首行调用其他构造器。
4、this 可以看作是一个变量,它的值是当前对象的引用。
5、this 不能出现在被 static 修饰的内容中
6、构造方法不能相互调用(即你调用我、我调用你),会报错,类似死循环
6.语句块:block { }
1、静态块
写法:
static {
}
位置: 类中,方法外
生命周期:在类加载时候加载,只加载一次。
2、构造块
写法: {
}
位置: 类中,方法外
生命周期:在调用构造器的时候,加载并优先构造器执行。
3、普通块
写法: 同构造块
位置: 方法中
生命周期:同方法的生命周期
特别注意:变量的作用域
4、同步块
7.javabaen
java类的属性进行私有化: 实现高内聚,低耦合
一个类:特殊的类:本质:存放数据[数据模型](相互业务class)
提供一个方法去访问属性
书写:
Getter(获取属性值) Setter 方法 (修改 属性值)
命名的时候特点注意:
名称:
例如: age : getAge setAge
注意: Boolean 类型的属性
在生成 getter 方法 ------》 is+属性名称
判断两个字符串是否相等:变量名.eaquals(变量名)
JAVABEAN: 数据传递使用 (数据模型) ---->
javabean { vo bo po (pojo) dto model}
一种类 :属性私有 对外提供方法操作属性
单纯事物bean { 业务bean 感受:UserLogin}
8.关键字.package
package[包的定义] import[包导入] ------》 研究Class存放位置
1、 package
1、类的管理 【分包管理】
1、分包管理: 核心: 便于系统中代码的分类管理
分包【分层】
场景: 电商项目
1、 用户 2、商品 3、购物车 4、 订单 5、支付 -----> 交易主流程 2、package 在类中使用
1、 在页面第一行 写法: package 报名 ----》 表示当前类所在的位置 2、类重命名问题
在不同包下 可以创建相同名称的类
9.关键字.import
import : 指明 引用Class 所在的位置
1、import : 指明class 书写的位置 : 类体外 与 package 之间
2、 在变量上添包名
com.shsxt.demo.Person per = new com.shsxt.demo.Person("", 12);
不需要使用import的类有
1、 语言包 (java.lang)下的类
2、 同包下的类
特殊点 : 导入静态属性 import static java.lang.Math.PI
10. 修饰符.\,访问权限:
置于类的成员定义前,用来限定其他对象对该类对象成员的访问权限。
通过访问权限的控制达到信息隐藏
通过访问权限 public, protected ,default(默认), private 来封装类、方法及属性,达到隐藏细节的目的
1: public: 一览无遗; (同一个类,同一个包,子类,所有类都可以访问);
2: protected:子承父业 (儿子自己使用); (同一个类,同一个包,子类可以访问);
3: default :家庭和睦; (同一个类,同一个包可以访问);
4: private :占为已有(同一个类可以访问);
包 同类 同包 子类 不同
public √ √ √ √
protected √ √ √ X
默认 √ √ X X
private √ X X X
方法的重写: Java权限修饰符
子类在重写父类的方式时候,重写的后的方法权限 >= 父类的权限
1、子类重写父里的public 方法, 重写的方法的权限必须是public
2、父类中方法是 private权限 子类中不可重写也继承
二:继承继承(类与类之间) ----> 父子类之间关系
继承使用一个关键字: extends
继承:子承父业
"父业" : 父类 属性 和 方法
子类可以继承父类 “属性” 方法
待解决的问题?
1、如果子类中出现于父类的中相同属性?
1、单纯的继承关系
Dog dog = new Dog();
System.out.println(dog.name);
调用子类的属性值
2、“多态”现象 当出现 父引用指向子类对象
Animal a = new Dog(); -----> 向上转换 (自动转换)
System.out.println( a.name);
调用父类的属性 { 属性不多态 }
1.属性问题:
1、 父 :有 + 子:有 -------》 { 1、单纯的继承关系 2、“多态”现象 }
2、父 :有 + 子: 没有 -------》 { 属性继承 }
3、父 :没 + 子: 有 -------》 {类的属性问题}
2、如果子类中出现于父类的中相同方法?
子类继承父的方法,但是有时候,子类中修改父类的中继承过方法时候,就会出现方法的重写
方法的重写?Override
研究的范围?{父子类关系(两个类)}
前置条件:
1、父子类 包含相同的方法
1、方法用名 2、方法同参 3、 方法同返回值
检验:在方法上添加一个注解 @Override
目的: 覆盖 父类中的方法 提出先父子类继承方法的差异性
方法问题:
1、 父 :有 子:有 ----> 重写
2、父 :有 子: 没有 ----》方法的继承
3、父 :没 子: 有 -----》 类的方法
2.JAVA中的继承模式:
1、 单继承模式 如果想要继承多个类 ---> 使用多层继承(继承链)
好处:
1、可复用代码
2、 继承关系对于父类没有影响, 但是影响子类
3、 每一个子类都有一个直接父类 ,多个父类
3.构造器的问题:
继承的构造器问题?
当创建子类对象时候, 先创建 父类对象{ 先执行父类构造器 在执行子类构造器 }
在子类对象创建的时候, 我们子类 构造器中,默认在第一行添加一个super()----> 父类空构造;
public Dog() {
super(); // this ()
// TODO Auto-generated constructor stub
}
1、子类构造器中隐含 super();
2、super的使用
3、子类构造器中出现相互调用的时候, [ super 与 this ]
4.关键词super的使用
super的使用方式与this一样的。
区别: this指代当前对象 super指向 父类对象
注意:super 在子类成员方法方式
5.final(最终的)
变量:常量,变量将不能进行第二次赋值
方法: 不能重写
类:不能继承
6:Object
一切类的最终父类
1、boolean equals(Object obj)
指示其他某个对象是否与此对象“相等”。
2、 int hashCode()
返回该对象的哈希码值。
对象地址值
3、 String toString()
回该对象的字符串表示。
注意:
Object obj = new Goods("");
Object类型 可以接受任何 类型的对象 { 适合的类型的 接受 }
三:多态
在编译时,不能确定方法调用者,只有在运行的时候,才能确定
多态(类与类之间, 类与接口之间 )
1:当出现父类引用指向子类对象,发生多态;
2:属性不会发生多态;
3:方法会发生多态(编译看类型,运行看对象)
多态 发生的场景:
两个视角 【继承 和 实现】
1、继承视角 看待多态 【父 子 类关系 】
1、 类继承
1、定义 class 动物类 Animal
2、 定义class 哈士奇(Hsq2) (继承 动物类 )
Animal 2ha = new Hsq2() ;
属性问题:
属性不发生多态现象: 此时调用的属性一定父的属性
方法问题:
方法发生多态
2、抽象类继承 com.shsxt.person
属性问题:
属性不发生多态现象: 此时调用的属性一定父的属性
方法问题:
方法发生多态
2、实现 视角 看待多态 【 实现关系 】
1、接口实现
1、定义一个
public interface Employee {
public void work ();
}
2、定义实现子类
public class CodeMonkey implements Employee {
@Override
public void work() {
System.out.println("码代码。。 修键盘 。。 贴膜 。。。 修鼠标,,, 只有你想不到,没有不会做。。");
}
public void makeMoney () {
System.out.println("挣钱。。。。");
}
}
使用的
Employee emp = new CodeMonkey();
emp.work();
======================================================================================
多态特性触发的前置条件: 继承和实现
多态的弊端:【模糊】
多态 : 隐藏了子类中新增加的方法
类型转换
1)、upcasting 自动|向上
父类型 = 子对象;
2)、downcasting 强制|向下
子类型 = (子类型)父引用;
案例:
Employee emp = new CodeMonkey();// 向上装换 自行
emp.work();
// emp.makeMoney();
CodeMonkey code = (CodeMonkey)emp; // 向下 强制装换 ----》 异常
code.makeMoney();
注意事项:
4、instanceof:
作用: 发生多态时,为了避免转换错误
1:抽象类
由abstract修饰的类 遵循常规类(属性和方法) ----》【特殊点: 抽象方法】
抽象类与类区别: 类定义{属性定义与{方法定义}}
抽象类既可以有抽象方法也可有普通方法
特别注意:
1、抽象类只能定义, 不能实例化。 但是有构造器 但是不能使用
2、 当子类中继承抽象类时候,如果抽象父类中有抽象方法的,子类必须重写
3、抽象方法不能定义为私有的
4:不能使用 final 修饰符
定义:
public abstract class Vehicle {
public String vname;
}
什么是抽象方法?
定义遵循普通方法的定义, 但是(在方法添加 abstract)而且 (没有方法体)
作用: 定义方法的模板 ,但是方法的具体实现
/**
* 抽象方法
*/
public abstract void run();
如果抽象父类 包含 抽象方法 ,那继承的子类是否一定重写抽象方法?
关键: 1、看继承的子类是抽象类---->按需重写
2、看继承的子类是普通类----> 一定重写
包含抽象的方法的不一定是抽象类? 也可有可能是一个接口
抽象类 {
1、抽象方法
2、普通方法
}
2:接口
关键词:interface
作用: 完全规范 {功能类似于抽象类}
定义:
public interface 接口名称 {
}
研究接口:
1、属性
都是常量
2、方法 ----》 {都是抽象方法}
注意: 定义的抽象方法 可以不加 abstract
---> 是否抽象方法都需要 abstract关键词
---> 定义的方法的权限是能是 public 或者是 默认的
接口的使用 【多实现】
1、 普通类 实现接口 implements
实现子类中必须重写 接口的方法
2、接口继承接口
使用的关键词 extends
子接口中 按需实现 父接口的方法
3:适配器模式
适配器模式
重写:
1、接口方法重写
劣势: 需要重写所有的方法 优势:多实现
2、继承方法重写
劣势: 单继承 优势:选择性重写
接口定义规范:
所有的规范
中间适配器:class
重写所有的接口方法
具体实现子类:
按需要重写
4、 instanceof:
对象名instanceof(类)
作用: 发生多态时,为了避免转换错误
关系运算符:
1)、instanceof 用来判断一个引用指向的对象是否为一个类或其子类的实例。只适用在一条继承链上
如果不是返回 false,如果是返回 true.
2)、必须在继承链上,发生多态时使用,否则编译错误