第七章 面向对象

基本介绍 面向对象编程有三大特征:封装、继承和多态

7.1 封装

封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作[方法],才能对数据进行操作。

封装的实现步骤(三步)

1)将属性进行私有化private【不能直接修改属性】

2)提供一个公共的(public)set方法,用于对属性判断并赋值

public void setXxx(类型参数名)//Xxx表示某个属性

//加入数据验证的业务逻辑

属性=参数名;

3)提供一个公共的(public)get方法,用于获取属性的值

public数据类型getXxx({//权限判断,Xxx某个属性

return xx;}

7.2  常量

含义:

      就是固定的,不能改变的量。只能用,不能修改, 如final String gender ="Male";

注意:

  1. final修饰的基本数据类型,值不能改变,修饰引用数据类型,不能重新new对象
  2. final和static关键字连用,叫静态常量,属性命名必须是大写 ,下划线分隔,如 static  final String FEMALE_SEX= "Female";
  1. static 修饰类中属性,叫静态属性或类属性、类成员,类名.属性名(推荐)或对象名.属性名
 public static void main(String[] args) {
			Constant cons = new Constant();
			System.out.println(cons.FEMALE_SEX); //对象名.属性
			System.out.println(Constant.FEMALE_SEX);//类名.属性   推荐使用
		}

7.3 继承

7.3.1继承基本介绍

继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来 声明继承父类即可。

7.3.2继承的基本语法

class子类extends 父类{

1)子类就会自动拥有父类定义的属性和方法

2)父类又叫超类,基类

3)子类又叫派生类

}

7.3.3继承的深入讨论/细节问题

1) 子类继承了所有的属性方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问

2)子类必须调用父类的构造器, 完成父类的初始化

3) 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无 参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译 不会通过 。

4) 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)

5) super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)

6) super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

7) java 所有类都是 Object 类的子类, Object 是所有类的基类.

8) 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)

9) 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制

如何让 A 类继承 B 类和 C 类? //【A 继承 B, B 继承 C】

10) 不能滥用继承,子类和父类之间必须满足 is-a (什么是什么)的逻辑关系

7.4 super 关键字

7.4.1基本介绍

super 代表父类的引用,用于访问父类的属性、方法、构造器

7.4.2 基本语法

  1. 访问父类的属性,但不能访问父类的private属性[案例]super.属性名;
  2. 访问父类的方法,不能访问父类的private方法

super.方法名(参数列表);

  1. 访问父类的构造器(这点前面用过):

super(参数列表);只能放在构造器的第一句,只能出现一句!

7.4.3调用父类的构造器的好处

  1. 分工明确,父类属性由父类初始化,子类的属性由子类初始化
  2. 当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super.this、直接访问是一样的效果!
  1. super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类(上级类)中都有同名的成员,使用super访问遵循就近原则。当然也需要遵守访问权限的相关规则

7.4.4 super 和 this 的区别

7.5 方法重写/覆盖(override)

7.5.1 基本介绍

简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法。

7.5.2注意事项和使用细节

方法重写也叫方法覆盖,需要满足下面的条件:

  1. 子类的方法的形参列表,方法名称,要和父类方法的形参列表方法名称完全一样。
  2. 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类,比如父类返回类型是 Object,子类方法返回类型是String。

7.5.3 重载 和 重写 的区别

7.6 抽象类和抽象方法

当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类。

7.6.1抽象类的介绍

  1. 用abstract 关键字来修饰一个类时,这个类就叫抽象类

访问修饰符abstract类名{

}

  1. 用abstract关键字来修饰一个方法时,这个方法就是抽象方法

访问修饰符 abstract 返回类型方法名 (参数列表); //没有方法体

  1. 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类

7.6.2抽象类使用的注意事项和细节

1) 抽象类不能被实例化

2) 抽象类不一定要包含abstract方法。也就是说.抽象类可以没有abstract方法。

3) 一旦类包含了abstract方法,则这个类必须声明为abstract 。

4) abstract只能修饰类和方法,不能修饰属性和其它的。

5) 抽象类可以有任意成员【抽象类本质还是类】,比如:非抽象方法.构造器、静态属性等等[举例]

6) 抽象方法不能有主体,即不能实现。

7) 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类。

8 抽象方法不能使用private、final和static来修饰,因为这些关键字都是和重写相违背的。

7.7 多态

7.7.1多态基本介绍

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

7.7.2多态的具体体现

  1. 一个对象的编译类型和运行类型可以不一致
  2. 编译类型在定义对象时,就确定了,不能改变
  1. 运行类型是可以变化的.
  2. 编译类型看定义时=号的左边,运行类型看=号的右边

7.7.3多态注意事项和细节讨论

多态的前提是:两个对象(类)存在继承关系

多态的向上转型

  1. 本质:父类的引用指向了子类的对象
  2. 语法: 父类类型 引用名 = new 子类类型();
  1. 特点:编译类型看左边,运行类型看右边。

可以调用父类中的所有成员(需遵守访问权限),

不能调用子类中特有成员;

最终运行效果看子类的具体实现!

多态向下转型

  1. 语法: 子类类型 引用名 = (子类类型)) 父类引用;
  2. 只能强转父类的引用,不能强转父类的对象
  1. 要求父类的引用必须指向的是当前目标类型的对象。
  2. 当向下转型后,可以调用子类类型中所有的成员。

7.8 Object 类

== 和equals 的对比

== 是一个比较运算符

  1. ==: 既可以判断基本类型,又可以判断引用类型;
  2. ==: 如果判断基本类型,判断的是值是否相等。示例:int i=10;double d=10.0;
  1. ==: 如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象;
  2. equals:是Object类中的方法,只能判断引用类型:
  1. 默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。

instanceof

instanceof 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型

System.out.println( aa instanceof AA);

7.9 接口

7.9.1 基本介绍

接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来。

语法:

interface接口名{

//属性

//抽象方法

}

class类名 implements 接口{

自己属性;

自己方法;

必须实现的接口的抽象方法

}

小结:接口是更加抽象的抽象的类,抽象类里的方法可以有方法体,接口里的所有方法都没有,方法体【jdk7.0】。接口体现了程序设计的多态和高内聚低偶合的设计思想。

特别说明:Jdk8.0后接口类可以有静态方法,默认方法,也就是说接口中司以有方法的具体实现

7.9.2特征

  1. 接口中的属性默认是public static final型(静态常量)
  2. 接口中的方法通常是public abstract型抽象方法
  1. 接口中可以有具体方法,但要添加default关键字(jdk 1.8以后支持)
  2. 接口中可以有静态方法(jdk1.8以后)
  1. 接口中支持多继承
  2. 接口中没有构造方法,不能产生对象
  1. 类在继承同时,可以实现多个接口
    • 类与类之间:单继承
    • 类和接口之间:实现  多个接口
    • 接口与接口之间:多继承
  1. 接口中的属性,只能是final的,而且是 public static final修饰符。比如:int a=1;实际上是 public static final int a=1;(必须初始化)
  2. 接口中属性的访问形式:接口名.属性名

7.9.3 接口和抽象类的区别

  1. 接口之间是多继承,抽象类是单继承
  2. 接口中属性是静态常量,而抽象类不需要
  1. 接口中没有构造方法,而抽象类有(但不能创建对象)
  2. 接口中的可以是抽象方法或default修饰的具体方法(jdk1.8新增),而抽象类中可以有任意类型的方法

7.10内部类

如果定义类在局部位置(方法中/代码块) : (1) 局部内部类 (2) 匿名内部类

定义在成员位置 : (1) 成员内部类 (2) 静态内部类

7.10.1基本介绍

一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。是我们类的第五大成 【 类的五大成员是哪些? 属性、方法、构造器、代码块,内部类

内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系,注意:内部类是学习的难点,同时也是重点,后面看底层源码时,有大量的内部类.

语法:

class outer{ //外部类

class Inner{ //内部类

}

}

class Other{ //外部其他类

}

7.10.2 内部类的分类

定义在外部类局部位置上(比如方法内):

1)局部内部类(有类名)

2)匿名内部类(没有类名,重点!!!!!!!!)

定义在外部类的成员位置上:

1)成员内部类(没用static修饰)

2)静态内部类(使用static修饰)

7.10.3 局部内部类的使用

说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。

  1. 可以直接访问外部类的所有成员,包含私有的
  2. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
  1. 作用域:仅仅在定义它的方法或代码块中。
  2. 局部内部类---访问---->外部类的成员[访问方式:直接访问]
  1. 外部类---访问---->局部内部类的成员

访问方式:创建对象,再访问(注意:必须在作用域内)

记住:(1) 局部内部类定义在方法中/代码块

(2) 作用域在方法体或者代码块中

(3) 本质仍然是一个类

  1. 外部其他类---不能访问----->局部内部类(因为局部内部类地位是一个局部变量)
  2. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问。

7.10.4 匿名内部类的使用

(1)本质是类 (2)内部类 (3)该类没有名字 (4)同时还是一个对象

说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

  1. 匿名内部类的基本语法

new 类或接口(参数列表){

类体

}

  1. 匿名内部类的语法比较奇特,请往意,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法。
  2. 可以直接访问外部类的所有成员,包含私有的。
  1. 不能添加访问修饰符,因为它的地位就是一个局部变量。
  2. 作用域:仅仅在定义它的方法或代码块中。
  1. 匿名内部类---访问---->外部类成员[访问方式: 直接访问]
  2. 外部其他类---不能访问--->匿名内部类(因为匿名内部类地位是一个局部变量)
  1. 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则m如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问。

7.10.5 成员内部类的使用

说明:成员内部类是定义在外部类的成员位置,并且没有static修饰。

1.可以直接访问外部类的所有成员,包含私有的

2.可以添加任意访问修饰符(public.protected、默认、private),因为它的地位就是一个成员。

3.作用域和外部类的其他成员一样,为整个类体,在外部类的成员方法中创建成员内部类对象,再调用方法.

4.成员内部类---访问---->外部类成员(比如:属性) 访问方式: 直接访问

5.外部类---访问------>成员内部类 访问方式:创建对象,再访问

6.外部其他类---访问---->成员内部类

7.如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问.

7.11枚举

枚举是一组常量的集合。

枚举属于一种特殊的类,里面只包含一组有限的特定的对象。

7.11.1 自定义枚举

  1. 不需要提供setXxx方法,因为枚举对象值通常为只读.
  2. 对枚举对象/属性使用final+ static共同修饰,实现底层优化.
  1. 枚举对象名通常使用全部大写,常量的命名规范.
  2. 枚举对象根据需要,也可以有多个属性//Enumeration02.java

7.11.2 enum 关键字实现枚举注意事项

1) 当我们使用 enum 关键字开发一个枚举类时,默认会继承 Enum 类, 而且是一个 final 类[如何证明],老师使用 javap 工 具来演示

2) 传统的 public static final Season2 SPRING = new Season2("春天", "温暖"); 简化成 SPRING("春天", "温暖"), 这里必须知道,它调用的是哪个构造器.

3) 如果使用无参构造器 创建 枚举对象,则实参列表和小括号都可以省略

4) 当有多个枚举对象时,使用,间隔,最后有一个分号结尾

5) 枚举对象必须放在枚举类的行首.

7.12 克隆对象

步骤:

  1. 重写Object对象中clone()方法
  2. 实现Cloneable标识型接口

7.13 异常-Exception

7.13.1 基本概念

Java语言中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常)

执行过程中所发生的异常事件可分为两大类

1)Error(错误):Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如: StackOverflowError[栈溢出]和OOM(out ofmemory).Error是严重错误,程序会崩溃。

2)Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception 分为两大类:运行时异常[程序运行时,发生的异常]和编译时异常[编程时,编译器检查出的异常]。

7.13.2 异常体系图

异常体系图的小结 :

  1. 异常分为两大类,运行时异常和编译时异常.
  2. 运行时异常,编译器检查不出来。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常
  1. 对于运行时异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响
  2. 编详时异常,是编译器要求必须处置的异常。

7.13.3 常见的运行时异常

常见的运行时异常包括

1) NullPointerException 空指针异常

2) ArithmeticException 数学运算异常

3) ArrayIndexOutOfBoundsException 数组下标越界异常

4) ClassCastException 类型转换异常

5) NumberFormatException 数字格式不正确异常

7.13.4 编译异常

编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译。

常见的编译异常:

sQLException //操作数据库时,查询表可能发生异常

IOException //操作文件时,发生的异常

FileNotFoundException //当操作一个不存在的文件时,发生异常

ClassNotFoundException //加载类,而该类不存在时,异常

EOFException //操作文件,到文件未尾,发生异常

lllegalArguementException //参数异常

7.13.5 try-catch异常处理

try-catch方式处理异常说明

1)Java提供try和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有多个try...catch块。

2)基本语法

try {

//可疑代码

//将异常生成对应的异常对象,传递给catch块

}catch(异常){

//对异常的处理

}

//如果没有finally,语法是可以通过

7.13.6 try-catch方式处理异常

-注意事项

1)如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块.

2)如果异常没有发生,则顺序执行try的代码块,不会进入到catch.

3)如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用如下代码- finally {}

4)可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,

(Exception在后,NullPointerException在前),如果发生异常,只会匹配一个catch。

5)可以进行try-finally 配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉/退出。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑

7.13.7 throws 异常处理

一、基本介绍

1) 如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。

2) 在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。

二、注意事项和使用细节

1) 对于编译异常,程序中必须处理,比如try-catch或者 throws2)对于运行时异常,程序中如果没有处理,默认就是throws的方式处理。

3)子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型。

4)在throws过程中,如果有方法 try-catch,就相当于处理异常,就可以不必throws。

7.13.8自定义异常

一、基本概念

当程序中出现了某些“错误”,但该错误信息并没有在Throwable子类中描

述处理,这个时候可以首己设计异常类,用于描述该错误信息。

二、自定义异常的步骤

1)定义类:自定义异常类名(程序员自己写)继承Exception或RuntimeException

2)如果继承Exception,属于编译异常

3)如果继承RuntimeException,属于运行异常(一般来说,继承RuntimeException)

三、 throw 和 throws 的区别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值