面向对象三大特性
封装
封装就是在定义类时,对属性进行私有,提供对应的公开get、set方法。
1、属性私有 private
语法:private 数据类型 变量名;
private 数据类型 变量名 = 值;
private 关键字:私有 私有化,代表该属性只能在本类中使用。
2、提供共开的get/set方法
public 关键字:公开 公有,代表所有类都可以使用。
get方法:获取/读取 属性值
public 返回值类型 getXxx(){
return 属性名;
}
注意:(1)方法的返回值类型必须与return的属性类型相同。
(2)方法名的命名规则必须是get后加属性名首字符大写例如:getName getAge
(3)没有参数
set方法:设置/修改属性值
public void setXxx(数据类型 变量名){
//添加 权限检查,检查通过 则让你改密码
this.属性名 = 变量名;
}
注意:(1)方法的返回值类型,必须是void
(2)方法名的命名归咋必须是set后加属性名首字符大写例如:setName()
(3)set方法形参列表中,必须只有一个参数,且数据类型与属性类型必须一致。
3、封装的使用
封装前:对象名.属性名 = 值 System.out.println(对象名.属性名)
封装后:对象名.setXxx(实参); System.out.println(对象名.getXxx());
get/set方法是外界访问/设置对象私有属性的唯一通道,方法内部可对数据进行检查过滤。
继承
1、概念和语法
继承:是类和类的一种关系。"is a"的关系。
语法:class 子类 extends 父类{ //extends关键字 继承
//属性
//方法
//构造方法
}
好处:1>子类可以直接使用父类中的属性和方法(可复用性)
2>子类还可以定义自己独有的属性和方法(可扩展性)
2、方法覆盖(重写)Override【重点】
-
Override:在子类中定义和父类相同的方法。
-
语法要求:
1>方法名称、形参列表、返回值类型必须和父类中的一致。
2>访问修饰符可以相同或者权限更大。
3>不能抛出比父类更多更广的异常。
-
使用:对象名.方法名(实参列表)
-
执行:优先执行子类中的方法
-
使用场景:父类中方法的实现部分,不满足子类的需求时,在子类中重写实现
3、父类提取的原则
- 所有子类的共性可以提取到父类中,被所有子类复用。
- 父类中定义一般性的信息,代表范围更广。
- 子类中定义更具体的信息,代表的范围更加具体。
4、Java中类与类的继承关系
- 在Java中,类和类的继承关系为单继承。
- 一个子类只能有一个直接父类,同时支持多级继承。
5、访问修饰符【重点】
访问修饰符:Java中的一组关键字,用于限制访问权限。
本类 | 同包 | 不同包子类 | 不同包 | |
---|---|---|---|---|
private | 可 | |||
缺省 | 可 | 可 | ||
protected | 可 | 可 | 可 | |
public | 可 | 可 | 可 | 可 |
6、子类能使用父类的哪些成员/元素
父类中有属性、成员方法、构造方法
子类能使用父类的哪些成员/元素?
-
构造方法不能使用
-
属性、成员方法子类中能否使用,取决于访问修饰符
private不能使用!!
缺省 本包内可以使用
protected 本包+不同包子类可以使用
public 都可以使用
7、super关键字【重点】
super是引用,代表直接父类对象。
有两种用法:
-
super. 的用法
位置:用在子类的构造方法或成员方法中
作用:访问父类的属性或方法
语法:super.属性名 //访问父类的属性
super.方法名 //访问父类的方法
-
super() 的用法
位置:用在子类构造方法的第一行【重】
作用:调用父类的构造方法
语法:super() //调用父类的无参构造方法
super() //调用父类的带参构造方法
注意:
(1)在子类的构造方法中,如果没有写super(),系统默认子类构造器第一行访问父类无参构造器。
(2)在子类的构造方法中this()和super()不能同时存在,因为二者都必须在第一行。
8、子类对象的创建过程【理解】
子类对象的创建过程:
- 分配内存空间(父类加子类),属性赋默认值。
- 递归的构建父类对象
- 初始化父类属性
- 执行父类构造方法
- 初始化本类的属性
- 执行本类构造方法
public class Test{
public static void main(String[] args){
C c = new C();
}
}
/*
1、分配内存(父加子)
2、初始化A的属性
3、调用A的构造方法A()
4、初始化B的属性
5、调用B的构造方法B()
6、初始化C的属性
7、调用C的构造方法C()
*/
class A{
public A(){
System.out.println("a");
}
}
class B extends A{
public B(){
System.out.println("b");
}
}
class C extends B{
public C(){
System.out.println("c");
}
}
------------------------------------------------------------------
a
b
c
【重点】
@Override
public void eat(){
super.eat();
System.out.println(“吃骨头”);
}
可以在重写的方法中调用父类的方法
public class Test{
public static void main(String[] args){
C c = new C();
}
}
class A{
D d = new D();
public A(){
System.out.println("A()...");
}
}
class B extends A{
D d;
public B(){
System.out.println("B()...");
}
}
class C extends B{
D d = new D();
public C(){
System.out.println("C()...");
}
}
class D{
public D(){
System.out.println("D()...");
}
}
---------------------------------------------------------------
D()...
A()...
B()...
D()...
C()...
分析:
1、分配内存
2、初始化爷爷属性
3、构造爷爷
4、初始化爸爸属性
5、构造爸爸
6、初始化本人属性
7、构造本人
多态
多态的概念和理解
1、多态(多种形态)概念
不同的子类对象可以赋值给同一种父类型引用。
父类型的引用可以指向不同的子类对象。
同类型的对象,执行同一个行为,会表现出不同的行为特征。
Animal a = new Dog(); //父类型的引用a指向子类Dog的对象
2、语法
父类名 变量名 = new 子类名(实参);
3、编译看左,运行看右
编译时,通过引用,只能调用引用类型中有的方法。
执行时,如果子类覆盖了父类中的方法,则执行子类的方法。
4、多态的前提
- 有继承/实现关系
- 有父类引用指向子类对象
- 有方法重写
引用类型间的转换【开发重点】
1、回顾:基本类型间的转换
double d = 5; //ok 大类型<–小类型(小转大自动转)
double d = 12.5; int m = (int) d; //大类型–>小类型 强制转换
2、引用类型间的转换
1、小转大 自动转【子类类型 赋值给父类类型】
Animal a = new Dog(); //ok
子类对象赋值给父类对象 自动转
2、大转小 强制转【父类类型赋值给子类类型】
Animal a = new Dog();
Dog d = (Dog) a;
引用类型强制类型转换的语法:
小类型 变量 = (小类型)大类型变量;
3、强转类型的两种情况
注意:强制类型转换后再执行时,有两种情况
1、大类型中的对象的类型和强转的类型不兼容,则ClasscastException
Animal a = new Dog();
Cat c = (Cat) a; //编译ok 运行报错 类型转换异常
2、大类型中的对象的类型和强转的类型兼容则执行成功
Animal a = new Dog();
Dog d = (Dog) a; //编译ok运行ok
3、不存在继承关系不允许相互转换
Animal a = new Dog();
Person p = (Person) a; //不存在继承关系 编译报错 运行报错
instanceof运算符
语法:引用名 instanceof 类名
作用:判断引用中存储的实际类型和instanceof后的类型是否兼容或匹配。
注意:进行判断的二者需要有继承关系,不然会编译报错。
多态的应用
1.多态应用在数组上。
本类型 + 所有子类的对象都可以作为数组元素进行存储
2.多态应用在方法的参数上。
3.多态应用在方法的返回值上。
4.多态应用在集合的泛型上。