【Java面向对象总结】详细!

Java面向对象

文章目录

第一章 类和对象

开发方法

  1. 结构化开发
    • 面向功能划分软件结构
    • 自顶而下
    • 最小的子系统是方法
    • 制约了软件的可维护性和可扩展性
  2. 面向对象开发
    • 把软件系统看成各种对象的集合
    • 系统结构较稳定
    • 子系统相对独立
    • 软件可重用性、可维护性和可扩展性强

1. 类

具有相同属性和方法的一组对象的集合

2. 对象

用来描述客观事物的一个实体,由一组属性和方法构成

万物皆对象

属性——对象具有的各种特征

​ 每个对象的每个属性都拥有特定值
在这里插入图片描述

方法——对象执行的操作
在这里插入图片描述

3. 类和对象的关系 类是对象的抽象,对象是类的具体

在这里插入图片描述

​ 类是抽象的概念,仅仅是模板;对象是一个你能够看得到、摸得着的具体实体

4.创建类

使用class关键字,类中有成员变量和成员方法

Java是面向对象的语言

所有Java程序都以类class为组织单元

关键字class定义自定义的数据类型

类将现实世界中的概念模拟到计算机程序中

public class  类名 {//类名首字母大写(大骆驼)
        //定义属性部分
        属性1的类型 属性1;
 	     …
        属性n的类型 属性n;     //成员变量
    
        //定义方法部分
        方法1;
        …
        方法m;               //成员方法
}

定义类的步骤:
(1)定义类名
(2)编写类的属性
(3)编写类的方法

类图

使用类图描述类

用于分析和设计“类”

直观、容易理解

在这里插入图片描述

5. 创建和使用对象

创建对象 使用new关键字

类名 对象名 = new  类名();
School center = new School();

调用对象成员:使用“.”进行操作
调用对象下的属性和方法:使用 对象名.属性名||对象名.方法名
center.name = "课工场";    //给name属性赋值
center.showCenter();	  //调用showCenter()方法

6.类的方法

方法是个“黑匣子”,完成某个特定的应用程序功能,并返回结果

类的方法定义类的某种行为(或功能)

定义方法
语法:
访问修饰符 返回值类型 方法名([参数列表]){//(1)驼峰命名规则(小骆驼)(2)有意义
    [return 返回值]
}

注意:
    访问修饰符目前使用public公共的
    没用返回值时使用voidreturn 可以省咯
    方法名一般使用小骆驼命名
方法的返回值

两种情况

1.如果方法具有返回值,方法中必须使用关键字return返回该值,返回值类型为该值的类型;返回值只能有一个

public class Student{
    String name = "张三";
    public String  getName(){
        return name;//作用: 跳出方法、返回结果
    }
}

2.如果方法没有返回值,返回值类型为void

方法调用

方法之间允许相互调用,不需要知道方法的具体实现,实现重用,提高效率

在这里插入图片描述

方法调用时,原方法有参数,调用时要传参,参数个数和参数类型要一致

观察之前编写过的方法,都是无参方法

7.成员变量(全局变量)和局部变量

成员变量(全局变量)与局部变量区别

成员变量有默认值,局部变量没有

作用域不同

以{ }为准

变量声明的位置决定变量作用域

变量作用域确定可在程序中按变量名访问该变量的区域

在同一个方法中,不允许有同名局部变量
在不同的方法中,可以有同名局部变量
在同一个类中,成员变量和局部变量同名时,局部变量具有更高的优先级

第二章 方法与方法重载

1. 方法

语法:
<访问修饰符>  返回类型  <方法名>(<形式参数列表>) {
        //方法的主体
    [return 返回值]
}
//调用方法
对象名.方法名(实参列表)
注意:
    调用方法时不能指定实参类型!
    形参和实参数据类型要一致!数量也要一致!
public class Test {
    public void calc1(int num){
        num=num+1;
    }
    public void calc2(Student student){
        student.age=student.age+1;
    }
}

//测试类
Test test=new Test();
int n=8;
test.calc1(n);
Student stu=new Student();
stu.age=18;
test.calc2(stu);
System.out.println(n+"---"+stu.age);
// 8---19
基本数据类型和引用数据类型数据在传参时区别
基本数据类型 值传递(浅拷贝)

操作传递的是变量的值,改变一个变量的值不会影响另一个变量的值。

引用数据类型 地址传递(深拷贝)

赋值是把原对象的引用(可理解为内存地址)传递给另一个引用

数组,对象参数传递

3. 构造方法

无参的构造方法,与类同名,不含返回类型。

作用:初始化对象属性

访问修饰符   构造方法名 ( ) { 
       //初始化代码
}
/*
1.方法名与类名相同
2.无返回值
3.系统会自带无参构造方法,当有其他构造方法,会自动覆盖无参构造
*/
自定义构造方法

当类有了带参构造方法之后,系统不再自动生成默认的无参构造方法,若使用需重新定义

public Student(){}
public Student(String name,int age){
//构造方法一般都是public的,才能被系统调用。
	 this.name=name;
     this.age=age;
}

自定义构造方法
> 方法名相同
> 参数项不同
> 与返回值、访问修饰符无关

带参构造方法this关键字
是对一个对象的默认引用这里用以区分同名成员变量

构造方法只能用于创建对象时,不能在程序中像调用其他方法一样调用它,但是可以用this()的形式在其他构造方法中调用它

注意this()必须在第一行

this关键字的用法
  1. 调用属性 this.属性名
this.health = 100; 
this.name = "大黄";
  1. 调用方法 this.方法名
this.print(); 
  1. 调用构造方法 this() 必须在第一行
this();
this("小黑",100,100,"雄");
//如果使用,必须是构造方法中的第一条语句 

4. 方法重载

  1. 同一个类中
  2. 方法名相同
  3. 参数个数或类型不同
  4. 与返回值、访问修饰符无关

第三章 封装与继承

1. 封装 隐藏类的内部实现细节,对外提供一个可访问的接口

面向对象三大特征之一 ——封装

将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问

封装的两个大致原则

把尽可能多的东西藏起来,对外提供便捷的接口

把所有的属性藏起来
在这里插入图片描述

步骤
  1. 设置属性为private
  2. 创建get和set方法
  3. 可以在方法中添加判断等代码

封装的好处

​ 1.便于使用者正确使用系统,防止错误修改属性

​ 2.有助于系统之间的松耦合,提高系统独立性

​ 3.提高软件的可重用性

​ 4.降低了构建大型系统的风险

2. 包

文档分门别类,易于查找和管理

使用目录解决文件同名冲突问题

包的作用
在这里插入图片描述

1. 包命名规范
  1. 包名由小写字母组成,不能以圆点开头或结尾

    package mypackage;

  2. 包名之前最好加上唯一的前缀,通常使用组织倒置的网络域名

    package net.javagroup.mypackage;

  3. 包名后续部分依不同机构内部的规范不同而不同

    package net.javagroup.research.powerproject;

规范:
网络项目.公司名.项目.模块名
com.hz.oop03.test01
		    .test02
net
cn
2. 导入包

为了使用不在同一包中的类,需要在Java程序中使用import关键字导入这个类

package 当前类位于那个包下(package 必须在代码的第一行)

import 引入类(包名.类名)
import java.util.*;      //导入java.util包中所有类
import cn.jtest.classandobject.School;    //导入指定包中指定类

1. 系统包:java.util
2. 自定义包:cn.jtest.classandobject
    
    *: 指包中的所有类,可以使用*但是不推荐
School :指包中的School
3. 注意
  1. 一个类同时引用了两个来自不同包的同名类

    必须通过完整类名来区分 com.hz.oop03.test01

  2. 每个包都是独立的,顶层包不会包含子包的类

  3. package和import的顺序是固定的

    package必须位于第一行(忽略注释行)

    只允许有一个package语句

    其次是import

    接着是类的声明

3. 访问权限控制

在这里插入图片描述

4. static修饰符

static可以修饰
  1. 成员变量

    静态变量,可以直接通过类名访问

class User {
	//静态变量
	public static final int ID = 1111l;
}

User.ID
  1. 成员方法

静态方法,可以直接通过类名访问

public static void show(){
    System.out.printIn("这是静态方法”);
}

User.show();     不需要new
  1. 代码块

静态代码块:只加载一次(当Java虚拟机加载类时,就会执行该代码块)

static {
    代码逻辑
    一般用于程序初始化信息
}

JVM加载类时,加载静态代码块如果有多个静态块,按顺序加载每个静态代码块只会被执行一次

public class StaticTest {
         static int num=100;
         static{
                num+=100;
               System.out.println(num);
         }
         static{
                num+=100;
               System.out.println(num); 
        }
}

StaticTest st1=new StaticTest();
StaticTest st2=new StaticTest();
System.out.println(StaticTest.num);

static变量

一、类的成员变量包括

  1. 类变量(静态变量)

    • 被static修饰的变量

    • 在内存中只有一个拷贝

    • 类内部,可在任何方法内直接访问静态变量

    • 其他类中,可以直接通过类名访问

  2. 实例变量

    • 没有被static修饰的变量

    • 每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响

二、static变量的作用:

  1. 能被类的所有实例共享,可作为实例之间进行交流的共享数据
  2. 如果类的所有实例都包含一个相同的常量属性,可把这个属性定义为静态常量类型,从而节省内存空间

static方法

  1. 静态方法:可直接通过类名访问

    • 静态方法中不能使用this和super
    • 不能直接访问所属类的实例变量和实例方法
    • 可直接访问类的静态变量和静态方法
  2. 实例方法:通过实例访问

    • 可直接访问所属类的静态变量、静态方法、实例变量和实例方法
  3. 静态方法必须被实现

main()就是最常用的静态方法

常见错误
class Dog {
	private String name = "旺财"; // 昵称
       ……	
	public void play(int n) {
    	static int localv=5;             //在实例方法里不可以定义static变量 
        health = health - n;		
        System.out.println(name+" "+localv+" "+health+" "+love);
       }	
    public static void main(String[] args) {
        Dog d=new Dog();
        d.play(5); 
    }
} 

5. 继承

继承是Java中实现代码重用的重要手段之一。

Java中只支持单根继承,即一个类只能有一个直接父类
在这里插入图片描述

使用继承优化设计:将重复代码抽取到父类中

在这里插入图片描述

修改后:子类与父类是is-a关系(继承关系)

  • 方便修改代码
  • 减少代码量
使用继承

编写父类

[访问修饰符] class Pet { 
    //公共的属性和方法
}

编写子类,继承父类

[访问修饰符] class Dog extends Pet { 
    //子类特有的属性和方法
}
extends 继承关键字
单根继承
  • 子类可以调用父类属性和方法
  • 父类调用不到子类独有的属性和方法
  • 子类构造方法默认调用父类无参构造方法

6. super关键字

子类访问父类成员
调用父类构造方法:
super();    
super(name);

调用父类属性:
super.name;

调用父类方法:
super.print();
super关键字来访问父类的成员
  • 使用super关键字,super代表父类对象
  • super只能出现在子类的方法和构造方法中
  • super调用构造方法时,只能是第一句
  • super不能访问父类的private属性和方法
继承条件下的构造方法

继承条件下构造方法的调用规则

  • 子类构造方法没有通过super显式调用父类的有参构造方法,也没通过this显式调用自身其他构造方法

    系统默认调用父类的无参构造方法

  • 子类构造方法通过super显式调用父类的有参构造方法

    执行父类相应构造方法,而不执行父类无参构造方法

  • 子类构造方法通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规则

理解继承
  1. 子类继承父类的什么?

    • 继承public和protected修饰的属性和方法,不管子类和父类是否在同一个包里
    • 继承默认权限修饰符修饰的属性和方法,但子类和父类必须在同一个包里
  2. 子类可以继承父类的所有资源吗?

    不可以,不能被继承的父类成员有:

    • private成员
    • 子类与父类不在同包,使用默认访问权限的成员
    • 构造方法

访问修饰符protected可以修饰属性和方法,本类、同包、子类可以访问

使用继承
  1. 继承与真实世界类似

    • 符合is-a关系的设计使用继承
  2. 继承是代码重用的一种方式

    • 将子类共有的属性和行为放到父类中

总结

实现封装的步骤是什么?

  1. 修改属性可见性。设为private,防止错误的修改
  2. 创建公有的getter/setter方法。用于属性的读写
  3. 在getter/setter方法中加入属性控制语句。对属性值的合法性进行判断

常用的访问权限控制符有哪些?

public、protected、default(默认,不加修饰符)、private。

访问权限分别为:

  1. public:所有类可访问
  2. protected:同包类及不同包的子类可访问
  3. default:同包类可访问
  4. private:仅本类可访问

继承有何好处?

  • 方便修改代码
  • 减少代码量,提高代码重用性

如何实现继承?

创建父类,写公共的属性和方法

创建子类extends继承父类,写子类特有的属性和方法

第四章 方法重写与多态

1. 方法重写

方法的重写或方法的覆盖(overriding)

  • 子类根据需求对从父类继承的方法进行重新编写
  • 重写时,可以用super.方法的方式来保留父类的方法
  • 构造方法不能被重写
方法重写规则
  • 方法名相同
  • 参数列表相同
  • 返回值类型相同或者是其子类
  • 访问权限不能严于父类
  • 父类的静态方法不能被子类覆盖为非静态方法,父类的非静态方法不能被子类覆盖为静态方法
  • 子类可以定义与父类同名的静态方法,以便在子类中隐藏父类的静态方法(注:静态方法中无法使用super)
  • 父类的私有方法不能被子类覆盖
  • 不能抛出比父类方法更多的异常
方法重写vs方法重载

在这里插入图片描述

2. Object类

Object类是所有类的父类

public class  Pet  extends Object {
          ……
}

在这里插入图片描述

Object类被子类经常重写的方法

在这里插入图片描述

Object类的equals()方法
  1. 比较两个对象是否是同一个对象,是则返回true
  2. 操作符==

简单数据类型,直接比较值。如1==2

引用类型,比较两者是否为同一对象

(1)Object类的equals()方法与==没区别

(2)当有特殊需求,如认为属性相同即为同一对象时,需要重写equals()

(3)Java.lang.String重写了equals()方法,把equals()方法的判断变为了判断其值

3. 多态

什么是多态

频繁修改代码,代码可扩展性、可维护性差

使用多态优化

同一种事物,由于条件不同,产生的结果也不同

多态:同一个引用类型,使用不同的实例而执行不同操作

多态的使用

1
在这里插入图片描述

2

又要给XXX看病时,只需

  • 编写XXX类继承Pet类(旧方案也需要)
  • 创建XXX类对象(旧方案也需要)
  • 其他代码不变(不用修改Master类)

方法重写是实现多态的基础

3

Pet类的toHospital()如何实现呢?

  • toHospital()不需要有具体的实现
  • 抽象方法
  • Pet类声明为抽象类
  • 实例化Pet毫无意义
public abstract class Pet {		
} 
向上转型

向上转型:父类的引用指向子类对象,自动进行类型转换

//测试方法
Pet pet = new Dog();
//<父类型> <引用变量名> = new <子类型>();
pet.setHealth(20);
Master master = new Master();
master.cure(pet);
  • 此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法,不是父类的方法
  • 此时通过父类引用变量无法调用子类特有的方法
向下转型

向下转型:将一个指向子类对象的父类引用赋给一个子类的引用,即:父类类型转换为子类类型。需强制类型转换

如果需要调用子类特有的方法则:
Dog dog=(Dog)pet;//将pet 转换为Dog类型
//<子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;
dog. catchingFlyDisc();//执行Dog特有的方法
  • 在向下转型的过程中,如果没有转换为真实子类类型,会出现类型转换异常
instanceof

Java中提供了instanceof运算符来进行类型的判断

  • 使用instanceof时,对象的类型必须和instanceof后面的参数所指定的类在继承上有上下级关系
多态的应用
  • 使用父类作为方法的形参,是Java中实现和使用多态的主要方式
  • 使用父类作为方法的返回值,也是Java中实现和使用多态的主要方式

4. 抽象

abstract抽象类

**abstract抽象类:**不能被实例化,等待被继承
public abstract class Pet

abstract抽象方法
  1. 抽象方法使用abstract修饰public abstract void show();

  2. 抽象方法没有方法体

  3. 抽象方法必须被重写

  4. 抽象方法必须在抽象类中,而抽象类中可以没用抽象方法

public abstract void print();

  • 抽象方法没有方法体
  • 抽象方法必须在抽象类里
  • 抽象方法必须在子类中被实现,除非子类是抽象类

第六章 抽象类和接口

1. 抽象类与抽象方法

public abstract class Pet { //抽象类
    public abstract void toHospital() ;//抽象方法
}
抽象类VS普通类
  • 抽象类不能被实例化

    但可以创建一个引用变量,其类型是一个抽象类,指向非抽象的子类实例

  • 普通类可以被实例化

抽象方法VS普通方法

有无方法体

抽象类与抽象方法的使用
  • 抽象类中可以没有抽象方法,但包含了抽象方法的类必须被定义为抽象类
  • 如果子类没有实现父类的所有抽象方法,子类必须被定义为抽象类
  • 没有抽象构造方法,也没有抽象静态方法
  • 抽象类中可以有非抽象的构造方法,创建子类的实例时可能调用

2. 接口

接口是一种能力,接口是一种约束。

接口特性
  • 接口不可以被实例化

  • 实现类必须实现接口的所有方法

  • 实现类可以实现多个接口

    • implements、多个接口使用逗号隔开

      Java中的多继承

  • 接口中的变量都是静态常量(public static final)

面向接口编程
关心实现类有何能力,而不关心实现细节

面向接口的约定而不考虑接口的具体实现

接口定义 interface关键字
public interface MyInterface {
    public void foo()//其他方法
}
所有方法默认都是:
public abstract
接口使用 implements关键字 多个接口使用逗号隔开
public class FdDoor extends Door implements Lock{
    @override
	public void open(){
		System.out.println("开门.....");
    }
}
  • 接口中的成员变量

    • 默认都是public static final的,必须显式初始化
  • 接口中的方法

    • 默认都是public abstract的
  • 接口没有构造方法,不能被实例化

  • 一个接口不能实现另一个接口,但可以继承多个其他接口

  • 一个类必须实现接口抽象方法(implements),除非这个类也是抽象类

3. 抽象类vs接口

相同点
  • 代表系统的抽象层
  • 都不能被实例化
  • 都能包含抽象方法
    • 用于描述系统提供的服务,不必提供具体实现
不同点
  • 在抽象类中可以为部分方法提供默认实现,而接口中只能包含抽象方法
    • 抽象类便于复用,接口便于代码维护
  • 一个类只能继承一个直接的父类,但可以实现多个接口
使用原则
  • 接口做系统与外界交互的窗口
    • 接口提供服务
  • 接口本身一旦制定,就不允许随意修改
  • 抽象类可完成部分功能实现,还有部分功能可作为系统的扩展点

面向对象设计原则

多用组合,少用继承
针对接口编程
针对扩展开放,针对改变关闭

总结

  • Java中的接口
    • 属性全都是全局静态常量
    • 方法都是全局抽象方法
    • 无构造方法
  • 一个类可以实现多个接口,非抽象类实现接口时必须实现接口中的全部方法
  • 抽象类利于代码复用,接口利于代码维护

第七章 异常

1. 什么是异常

异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序

  • 异常分为Checked异常和运行时异常
    • Checked异常必须捕获或者声明抛出
    • 运行时异常不要求必须捕获或者声明抛出

2. 如何进行异常处理

Java的异常处理是通过5个关键字来实现的:try、catch、 finally、throw、throws
在这里插入图片描述

1. try-catch块

使用try-catch块捕获异常,分为三种情况:

1.正常 
public void method(){
    try {
        // 代码段(此处不会产生异常)
    } catch (异常类型 ex) {
        // 对异常进行处理的代码段
    }
    // 代码段
}

在这里插入图片描述

2.出现异常 
public void method(){
    try {
        // 代码段 1
        // 产生异常的代码段 2
        // 代码段 3
    } catch (异常类型 ex) {
        // 对异常进行处理的代码段4
    }
    // 代码段5
}

异常是一种特殊的对象,类型为java.lang.Exception或其子类

在这里插入图片描述

3.异常类型不匹配 
public void method(){
    try {
        // 代码段 1
        // 产生异常的代码段 2
        // 代码段 3
    } catch (异常类型 ex) {
        // 对异常进行处理的代码段4
    }
    // 代码段5
}

在这里插入图片描述

  • 在catch块中处理异常
    • 加入用户自定义处理信息
      System.err.println("出现错误:被除数和除数必须是整数 ");

    • 调用方法输出异常信息
      e.printStackTrace();

    • 异常对象常用的方法
      void printStackTrace() 输出异常的堆栈信息
      String getMessage() 返回异常信息描述字符串,是printStackTrace()输出信息的一部分

常见的异常类型

在这里插入图片描述

2. try-catch-finally

在try-catch块后加入finally块 finally块是否发生异常都执行

finally块中语句不执行的情况

不执行的唯一情况

public class ExceptionTest12 {
    public static void main(String[] args) {
        try {
            System.out.println("try...");
            // 退出JVM
            System.exit(1); // 退出JVM之后,finally语句中的代码就不执行了!
        } finally {
            System.out.println("finally...");
        }
    }
}

在这里插入图片描述

try-catch-finally中存在return语句的执行顺序
public void method(){
 	try {
         // 代码段 1
        // 产生异常的代码段 2
      	} catch (异常类型 ex) {
        // 对异常进行处理的代码段3
           	return;
      	}finally{
         // 代码段 4
      	}
}

在这里插入图片描述

3. 多重catch块
  • 引发多种类型的异常
  • 排列catch 语句的顺序:先子类后父类
  • 发生异常时按顺序逐个匹配
  • 只执行第一个与异常类型匹配的catch语句
小结

try-catch-finally结构中try语句块是必须的,catch、finally语句块均可选,但两者至少出现之一

3. 声明异常

如果在一个方法体中抛出了异常,如何通知调用者?

throws声明某个方法可能抛出的各种异常,多个异常用逗号隔开

方式1:调用者处理异常

方式2:调用者继续声明异常

​ main()方法声明的异常由Java虚拟机处理

4. 抛出异常

除了系统自动抛出异常外,有些问题需要程序员自行抛出异常

使用throw抛出异常

throw和throws关键字的区别
throwthrows
生成并抛出异常声明方法内抛出了异常
位于方法体内部,可作为单独语句使用必须跟在方法参数列表后面,不能单独使用
抛出一个异常对象,且只能是一个声明抛出异常类型,可以跟多个异常

5. 异常体系结构

在这里插入图片描述

6. 自定义异常

JDK 中的异常类型不能满足程序的需要时,可以自定义异常类

使用自定义异常的步骤

  1. 定义异常类

    继承Throwable类、继承Excepion 或者RuntimeException

  2. 编写构造方法,继承父类的实现

  3. 实例化自定义的异常对象

  4. 使用throw抛出

7. 异常链

A方法调用B方法时,B方法却抛出了异常。那A方法继续抛出原有的异常还是抛出一个新异常呢?

抛出原有的异常

  • A方法与B方法进行了关联,不便于代码的修改和扩展

抛出新的异常

  • 异常链创建了新的异常但却保留了原有异常的信息

8. 异常处理原则

  1. 异常处理与性能
  2. 异常只能用于非正常情况
  3. 不要将过于庞大的代码块放在try中
  4. 在catch中指定具体的异常类型
  5. 需要对捕获的异常做处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值