一、封装
定义:
将类的某些信息隐藏在类的内部,不允许外部程序直接访问,
而是通过该类提供的方法来对隐藏的信息进行操作和访问。
封装的表现
- 方法就是一个最基本的封装体
- 类也是一个封装体
封装的好处:
- 提高代码的复用性
- 隐藏了代码的实现细节,还要对外提供可以访问的方式,便于调用者的使用
- 提高了安全性
封装举例:用机箱封装电脑的硬件,只留一些接口
私有private
防止类中的数据成员,在类的定义之外被修改
私有的变量访问的方式可以提供对应的 setXxx或者getXxx的方法。
- 防止类中的数据成员,在类的定义之外被修改
- 私有的变量访问的方式可以提供对应的 setXxx或者getXxx的方法。
- 类中不需要对外提供的内容都私有化,包括属性和方法
this关键字
- 可以在成员变量名前面加上this.来区别成员变量和局部变量
- this代表的是对象,具体代表哪个对象呢?哪个对象调用了this所在的方法,this就代表哪个对象。
二、继承
子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例
域和方法,或子类从父类继承方法,使得子类具有父类相同的行为
格式
格式:class 子类 extends 父类 {}
优势
- 继承的出现提高了代码的复用性,提高软件开发效率
- 继承的出现让类与类之间产生了关系,提供了多态的前提
注意
- 类只支持单继承,不允许多继承,也就是说一个类只能有一个直接父类
- 多个类可以继承一个父类
- 在Java中,多层继承是可以的,即一个类的父类可以再去继承另外的父类
继承-子父类中成员变量的特点
- Fu类中的成员变量是非私有的,子类中可以直接访问,若Fu类中的成员变量私有了,子类是不能直接访问的。
- 当子父类中出现了同名成员变量时,在子类中若要访问父类中的成员变量,必须使用关键字super来完成
- 在子类中,访问父类中的成员变量格式:super.父类中的成员变量
继承-子父类中成员方法特点-重写
1、子父类中成员方法的特点
通过对象调用方法时,会先在子类中查找有没有对应的方法,
若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法
2、成员方法特殊情况——覆盖
子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为override重写或者覆盖。
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法
3、覆盖注意事项
- 子类方法覆盖父类方法,必须要保证权限大于等于父类权限
- 写法上稍微注意:必须一模一样:方法的返回值类型 方法名 参数列表都要一样
三、多态
同一操作作用于不同的对象,可以有不同的解释,
产生不同的执行结果,这就是多态性。
格式:父类的引用变量指向子类对象
父类类型 变量名 = new 子类类型();
变量名.方法名();
-
普通类多态定义的格式
父类 变量名 = new 子类(); 如: class Father {} class Son extends Fu {} //类的多态使用 Father f = new Son();
-
抽象类多态定义的格式
抽象类 变量名 = new 抽象类子类(); 如: abstract class Father { public abstract void method(); } class Son extends Father { public void method(){ System.out.println(“重写父类抽象方法”); } } //类的多态使用 Father fu= new Son();
-
接口多态定义的格式
接口 变量名 = new 接口实现类();
如: interface Father {
public abstract void method();
}
class Son implements Father {
public void method(){
System.out.println(“重写接口抽象方法”);
}
}
//接口的多态使用
Father fu = new Son(); -
多态-调用成员的特点
成员变量是看左边的数据类型 方法是父子都有优先子,子类没有找父类
class Father {
int num = 4;
}
class Son extends Father {
int num = 5;
}
class Demo {
public static void main(String[] args) {
Father f = new Son();
System.out.println(f.num);
Son z = new Son();
System.out.println(z.num);
}
}
instanceof关键字
判断某个对象是否属于某种数据类型
格式:boolean b = 对象 instanceof 数据类型;
例:
Person p1 = new Student(); // 前提条件,学生类已经继承了人类
boolean flag = p1 instanceof Student; //flag结果为true
boolean flag2 = p2 instanceof Teacher; //flag结果为false
多态-转型
-
向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。
使用格式: 父类类型 变量名 = new 子类类型(); 如:Person p = new Student();
-
向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的!
使用格式: 子类类型 变量名 = (子类类型) 父类类型的变量; 如:Student stu = (Student) p; //变量p 实际上指向Student对象
多态优势:
隐藏了子类类型,
提高了代码的扩展性。
多态的弊端:
只能使用父类共性的内容,
而无法使用子类特有功能,功能有限制
抽象类
抽象类的产生
某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。
比如一个图形类应该有一个求周长的方法,但是不同的图形求周长的算法不一样。那该怎么办呢?
方法功能声明相同,但方法功能主体不同。那么这时也可以抽取,
但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
当定义了抽象函数的类也必须被abstract关键字修饰,被abstract关键字修饰的类是抽象类。
抽象类和抽象方法的定义
抽象方法定义格式:public abstract 返回值类型 方法名(参数);
抽象类定义的格式:abstract class 类名 {}
例:
//研发部员工
abstract class Developer {
public abstract void work();//抽象函数。需要abstract修饰,并分号;结束
}
//JavaEE工程师
class JavaEE extends Developer{
public void work() {
System.out.println("正在研发淘宝网站");
}
}
//Android工程师
class Android extends Developer {
public void work() {
System.out.println("正在研发淘宝手机客户端软件");
}
}
抽象类特点:
- 抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。
- 抽象类不可以直接创建对象,原因:调用抽象方法没有意义。
- 只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类。
注意:
- 抽象类一定是个父类?
是的,因为不断抽取而来的 - 抽象类中是否可以不定义抽象方法?
是可以的,那这个抽象类的存在到底有什么意义呢?不让该类创建对象,方法可以直接让子类去使用 - 抽象关键字abstract不可以和哪些关键字共存?
private,final ,static
接口
接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”。
接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类
(相当于接口的子类)来完成。这样将功能的定义与实现分离。
接口的定义
与定义类的class不同,接口定义时需要使用interface关键字。
定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。
格式:
- 使用interface代替了原来的class,其他步骤与定义类相同
- 接口中的方法均为公共访问的抽象方法
- 接口中无法定义普通的成员变量
public interface 接口名 {
抽象方法1;
抽象方法2;
抽象方法3;
}
类实现与接口
- 用implements关键字在实现类获得接口
- 实现类仍然需要重写方法以实现具体的功能。
格式:
class 类 implements 接口 {
重写接口中方法
}
接口中成员的特点
- 接口中可以定义变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称之为常量,其值不能改变
- 接口中可以定义方法,方法也有固定的修饰符,public abstract
- 接口不可以创建对象
- 子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。否则子类是一个抽象类。
接口和抽象的区别
1、相同点:
- 都位于继承的顶端,用于被其他类实现或继承;
- 都不能直接实例化对象;
- 都包含抽象方法,其子类都必须覆写这些抽象方法;
2、区别:
- 抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口包含抽象、静态、默认方法;
- 一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)
二者的选用:
优先选用接口,尽量少用抽象类;
需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
interface 打猎{
public abstract void 打猎();
}
//定义狗的提取的共性功能
abstract class 狗{
public abstract void 吃饭();
public abstract void 吼叫();
}
// 猎狗属于狗一种,让其继承狗,获取的狗的特性,
//由于猎狗具有打猎功能,那么它只要实现打猎接口即可,这样即保证猎狗具备狗的特性,也拥有了打猎的功能
class 猎狗 extends 狗 implements 打猎{
public void 打猎() {
}
void 吃饭() {
}
void 吼叫() {
}
}
class 猎猪 implements 打猎{
public void 打猎() {
}
}