第四课类和对象

面向对象

一、类 对象 面向对象概念

二、如何声明定义创建对象

三、三大特征:封装、继承、多态

四、工具类

类和对象

面向对象编程

<!--面向对象的三大特性:封装性、继承性、多态性-->

一种编程风格

  • 使用对象和对象之间的交互来设计系统

  • 数据和相关的逻辑封装在一起

核心概念

  • 对象(实例)

  • 方法

  • 消息

  • 封装

  • 继承

  • 多态

  • 对事物的抽象

    • 属性(attributes) 颜色、尺寸

    • 行为(methods) 打电话();上网();发消息();

<!--类可以定义为数据和方法的集合-->

对象

  • 类的具体实例

    • 类中的属性,有自己独立的取值(状态)

    • 类中的行为是外部对自己进行操作的接口(方法)

类和对象的关系

类也称为模板,它提供了对象的基本框架

面向对象的基本过程

  • 定义类

  • 创建对象

  • 对象和对象相互交互

    • 方法的调用

创建类的通用格式 P169

包(package)

  • 在Java中,包主要有以下用途

    • 包允许将类组合成较小的单元

    • 有助于避免命名冲突

    • 包允许在更广范围内保护类、数据和方法

  • 包可以是类、接口和子包的集合

  • 包名的命名规范

    • 通常都是小写英文字母

    • 一般为公司网址的反向排列 如:com.company.region.package

包的使用

  • 创建包

    • package mypackage;

  • 访问包中的类

    • mypackage.My_Class

  • 导入包

    • import java.util.*;

  • 导入包中的类

    • import java.util.Arrays;

  • 导入常量

    • import static java.lang.Math.PI;

类的定义

类的成员

  • 变量

    • 静态变量(有static)

    • 实例变量(无static)

  • 方法

    • 静态方法(有static)

    • 实例方法(无static)

  • 构造方法

实例成员

  • 实例变量

  • 实例方法

静态成员(使用static关键字修饰)

  • 静态变量

  • 静态方法

方法重载(Overloading)

  • 规则

    • 方法名相同

    • 参数列表不同——参数类型、个数

  • 意义

    • 对于含义相近的成员方法,使用相同的名字便于理解

  • 方法被调用时,编译器根据参数的类型和数量来确定调用哪个重载方法、

public class Work_22_04 { //方法重载
   public static void main(String[] args) {
       Work_22_04 work = new Work_22_04(); //创建对象
       work.add(1,2);
       work.add(1.1f,2.2f);
  }
   public void add(int a, int b){ //定义成员方法
       int result = a + b;
       System.out.println(result);
  }
   public void add(float a, float b){ //定义成员方法
       float result = a + b;
       System.out.printf("%.3f",result);
  }
}

构造方法

  • 用于创建对象的方法

    new <构造方法>(参数列表)

    class Member{
       private static int counter; //静态变量
       private String name; //实例变量
       public static Menber getInstance(){ //静态方法
           return new Member();
      }
       Member(){ //构造方法
           this.name = "Member" + counter;
           counter++;
      }
    }
    创建对象:Member m = new Membwer();
  • 语法规则

    • 方法名与类名相同

    • 声明中没有返回值类型

    • 可以有参数列表

  • 意义

    • 在对象创建时设置其内部状态

    • 保证对象在创建完成后立即可用,不需要在使用对象之前设定内部状态

缺省构造方法和构造方法重载

  • 如果类中不定义构造方法,编译器会自动为类添加一个默认构造方法

    • 不带任何参数

    • public可见范围

  • 一个类可以定义多个构造方法,通过参数列表不同实现重载

this关键字

  • this是指向当前对象的引用

  • 用法

    • 实例方法或构造方法使用this访问其他实例成员

    • 构造方法重载,在一个构造方法中调用构造方法

      • 必须位于构造方法的第一句

成员变量初始化

  • 声明时初始化

    public static int i = 3;
    private String name = "BMW";
  • 默认初始值

    public static int i;
    public String name;
  • 构造函数中赋初始值

  • 静态代码块/非静态代码块(实例代码块)

默认值

    byte = 0
   short = 0
   int = 0
   long = 0L
   float = 0.0f
   double = 0.0d
   char = '\u0000'
   boolean = false
   object = null
  • 类变量和实例变量具有默认初始值(堆上的内存)

  • 局部变量没有默认的初始值(栈上的内存)

封装与访问控制

<!--高内聚,低耦合-->

封装(Encapsulation)

  • 目的

    • 隐藏类的实现细节

    • 让使用者只能通过事先定制好的方法来访问数据

    • 可方便地加入控制逻辑,限制对属性的不合理操作

    • 便于修改,竲强代码的可维护性

    • 不变(What To Do)与变(How To Do)的分开

  • 实现方法

    • 使用范围修饰符隐藏内部状态

    • 对象间的交互

package com.cqyt.stx.level02.test.test_9_26;

/**
* 1.定义年龄
* 2.获取年龄
*/
public class Student {
   String number;
   private int age;
   private String like;

   public String getLike(String like){
       return like;
  }

   public int getAge(int age){
       return age;
  }

   public void setAge(int age){
       if(age < 0 || age > 120){
           System.err.println("年龄不合法!");
           return;
      }
       this.age = age;
  }
   public void hi(){

  }
   public void study(){

  }

}
package com.cqyt.stx.level02.test.test_9_26;

public class StudentTest {
   public static void main(String[] args) {
       Student student = new Student();
       //student.age = 21;
       student.setAge(-100);

       System.out.println("当前学生的年龄是:"+ student.getAge(21));

       System.out.println("喜欢的是" + student.getLike("足球"));
  }
}

访问控制修饰符

对象的创建和使用

创建对象

类名 声明一个引用变量 链接对象和引用 new关键字 调用构造方法

Dog myDog = new Dog();

对象引用

对象赋值

对象作为参数

  • 对象作为方法参数,在方法中只能改变改对象的状态,不能改变该对象的引用

  • 实参传给形参的过程可理解为对象的引用的赋值

形参:在方法声明中定义的参数,形参可以时Java支持的任何数据类型

实参:方法被调用时传递的参数

创建对象数组

对象数组的使用

垃圾回收

继承和多态

继承

package com.cqyt.stx.level02.test.test_9_27;
/**
* 操作系统
* 内存
* 磁盘
* 存储
* 输入
*/
public class Computer {
private String os;
public int memory;
protected int disk; //磁盘

public void storage(){
System.out.println("存储方法被调用啦!");
}
protected void input(){
System.out.println("输入方法被调用啦!");
}
public Computer(){
System.out.println("父类的构造方法被调用了!");
}
}
package com.cqyt.stx.level02.test.test_9_27;

public class LaptopTest {
public static void main(String[] args) {
Laptop laptop = new Laptop();
laptop.memory = 32;
laptop.disk = 1024;

//父类的私有属性,子类不可访问
//laptop.os = "Android";

laptop.storage();
laptop.show();

// laptop.input();
//父类的私有方法,子类不可访问
}
}
package com.cqyt.stx.level02.test.test_9_27;

public class Laptop extends Computer {

public Laptop(){
System.out.println("子类的构造方法被调用啦!!!");
}

public void show() {
System.out.println("内存:" + memory + "磁盘:" + disk);
}
}

抽象出不同类的共同点

继承和概念和意义

  • 被继承的类称为父类(超类、基类)

  • 继承父类的类为子类(导出类、派生类)

  • 意义

    • 复用代码——子类拥有父类的所有可见成员

    • 不同的类具有某些共同的属性和行为

    • 实现多态

继承的实现

  • 使用extends关键字

  • 每个类只能直接继承

  • 所有的类都直接或间接继承于java.lang.Object

protected关键字

super关键字

package com.cqyt.stx.level02.test.test_9_27;
/**
* 操作系统
* 内存
* 磁盘
* 存储
* 输入
*/
public class Computer {
private String os;
public int memory;
protected int disk; //磁盘

public void storage(){
System.out.println("存储方法被调用啦!");
}
protected void input(){
System.out.println("输入方法被调用啦!");
}
public Computer(){
System.out.println("父类的构造方法被调用了!");
}

public Computer(String os){
this.os = os;
System.out.println("父类带参构造方法被调用啦!");
}
}
package com.cqyt.stx.level02.test.test_9_27;

public class LaptopTest {
public static void main(String[] args) {
Laptop laptop = new Laptop("windows10");
}
}
package com.cqyt.stx.level02.test.test_9_27;

public class Laptop extends Computer {

public Laptop(){
System.out.println("子类的构造方法被调用啦!!!");
}

public Laptop(String os){
super(os);
this.disk = 128;
System.out.println("子类带参数构造方法被调用啦!");
}

public void show() {
System.out.println("内存:" + memory + "磁盘:" + disk);
}
}

子类中新定义的成员

  • 构造方法

    • 子类构造方法需隐式或显式调用父类构造方法

  • 成员变量

    • 子类可重新定义,对父类成员进行隐藏

  • 实例成员方法

    • 子类可重新定义可见的成员方法,对父类成员进行覆盖

方法覆盖语法规则

多态

在同一继承树上的不同对象针对同一行为的不同表现

父类 变量名 = new 子类;

动态绑定/静态绑定

  • 动态绑定

    • 运行时确定执行方法

    • 与运行时的类型

类型转换

instanceof运算符

instanceof运算符用来判断一个实例对象是否属于一个类

public calss Runner{
public static void main(String[] args){
Bill phoneBill = new PhoneBill();
Bill gasBill = new GasBill();
print(phoneBill);
print(gasBill);
}
private static void print(Bill bill){
System.out.println(bill.getName());
System.out.println(bill.getAmount());
if(bill instanceof PhoneBill){
PhoneBill pb = (PhoneBill)bill;
System.out.println(pb.getCallRecord());
}
}
}

object类

object类

  • 构造方法

    • object()

  • 常用操作

    • equals

    • toString

    • hashCode

    • finalize

    • clone

    • wait

    • notify

    • notifyAll

    • getClass

equals()

  • 用于比较两个对象是否相等,相等返回true

    • Object类的默认实现:两个不同的引用是否指向同一对象(使用==判断)

  • 子类可覆盖此方法

  • 覆盖时遵循的原则

    • 自反性

    • 对称性

    • 传递性

    • 一致性

    • 非空

toString()

  • toString用于返回对象的字符串表示

  • 子类可覆盖此方法

  • 使用“+”运算符将对象同一字符串连接,Java编译器会自动调用toString方法,获取对象的字符串表现形式。

异常处理

异常处理基础部分

异常机制

  • 面对对象的错误处理机制

    • 错误被抽象成类(异常类)

    • 错误的具体信息、发生错误的上下文状态被封装在异常类的实例中

如何使用异常

  • 在方法体中创建异常类的实例

  • 使用throw关键字抛出

  • 异常被抛出之后的代码不会被执行

public void hello(String name){
throw new NullPointerException();
System.out.println("Hello" + name);
}

异常的处理

  • 当预期到一段代码中可能会抛出异常时,可使用try捕获异常

try{
//...
}catch(ExceptionType1 ex){

}catch(ExceptionType2 ex){

}catch(ExceptionType3 ex){

}

多个catch块

  • 单个代码片段可能会引起多个错误

  • 可提供多个catch块分别处理各种异常

从异常中获得错误信息

  • 错误的类型(类名)

  • 错误信息

    • getMessage()

  • 方法调用栈

    • printStackTrace();

String name = null;
try{
hello(name);
System.out.println("OK");
}catch(NullPointerException ne){
System.out.println("出错了");
System.out.println(ne.getMessage());
ne.printStackTrace;
}

java语言中的异常类

所有异常类型都是Throwable的子类

错误(Error)

  • 一般表示无法恢复的系统的错误

    • 例如:OutOfMemoryError内存不足

  • 方法调用者可以不处理此类异常,应用程序不应当尝试进行恢复

运行时异常(RuntimeException)

  • 方法调用者可以不处理此类

预期异常(checked exception)

  • 程序必须对此类异常进行处理,否则会出现编译错误

throws关键字

  • 方法可通过throws关键字告诉调用者方法执行过程中可能会抛出的异常

public void throwOne() throws IllegalAccessException{
throw new IllegalAccessException("非法访问异常");
}

throws和catch的语法规则

  • 方法体中可能抛出预期异常

    • 在方法签名中使用throws写明,表示方法中不处理该异常

    • 使用try-catch捕获此异常并进行处理

  • 方法体中可能可能抛出Error和RuntimeException

    • 无需使用throws写明

    • 无需使用try-catch进行捕获处理

高级异常处理部分

异常处理的策略

  • 自行处理

    • 使用try-catch的语法

    • 只有在知道如何处理的情况下才捕获异常!

    • 一旦程序中出现不可恢复的错误,程序应当尽快终止,不要尝试处理异常

  • 回避异常

    • 使用throws

  • 异常转换

    • catch后进行再次throw

//方法h调用d,捕获可能发生的预期异常,将其转换为运行时异常
void h(){
try{
d();
}catch(Eception e){
throw new RuntimeException(e);
}
}

finally

  • 确保出现异常时所有清除工作都将得到处理

  • 与try块一起使用

  • 无论是否出现异常,finally块都将运行

  • finally是防止资源泄露的有效工具

    • 关闭文件

    • 回收资源

try{
//
}catch(ExceptionType1 ex){

}catch(ExceptionType2 ex){

}finally{
...
}

异常和方法覆盖

  • 父类方法中声明抛出异常A

    • 子类方法可以声明抛出异常A及其子类

    • 子类方法可以不抛出任何异常

class Base{
public void a() throws IOException{

}
}
class Child extends Base{
public void a() throws IOEception{

}
}

自定义异常

  • 继承Exception类或者其子类

    • 对于运行时异常需要继承RuntimeException或者其子类

    • 根据需要实现不同的构造方法

class ArraySizeException extends NegativeArraySizeException{
ArraySizeException(){
super("您传递的是非法的数组的大小");
}
}

常见异常及其用途

ArithmeticException 算术错误,如除以0

IllegalArgumentException 参数错误,包含诸多子类

NumberFormatException 数字格式化错误

IndexOfOutboundsException 数组下标出界

NullPointerException 试图访问 null 对象引用

ClassCastException 类型转换错误



posted @ 2021-10-21 11:13  东八区  阅读(23)  评论(0)    收藏  举报