Java学习-面向对象编程

2021/7/27 9:05:43

本文主要是介绍Java学习-面向对象编程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1.什么是面向对象

面向过程&面向对象

面向过程思想

  • 步骤清晰简单,第一步做什么,第二步做什么……
  • 面向过程适合处理一些较为简单的问题

面向对象思想

  • 物以类聚,分类的思维模式,思考问题首先想解决问题需要哪些分类,然对这些分类进行单独思考。最后才对某个分类下的细节进行面向过程的思索
  • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题

对于描述复杂的事物,为了从宏观是把握,从整体上合理分析,我们需要使用面向对象思想来分析,但是具体到微观操作,仍然需要面向过程的思想处理

什么是面向对象

  • 面向对象编程(Object-Oriented Programming ,OOP)

  • 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据

  • 抽象

  • 三大特性

    • 封装
    • 继承
    • 多态
  • 从认识论角度思考先有对象后有类,对象是具体的事物,类是抽象的,是对对象的抽象

  • 从代码运行的角度考虑是先有类后有对象,类是对象的模板

2.类与对象

类class:是一个数据结构,是对某一类事物整体描述、定义,但是并不能代表某一个具体的事物,其中包括字段和方法,是创建对象的模板

  • 字段(field)是类的属性,是用变量来表示

    • 字段又称为域、域变量、属性、成员变量等
  • 方法(method)是类的功能和操作,是用函数来表示的

对象Object:是类的一个具体的实例,创建类的对象叫类的实例化,对象的要素包括:

  • 状态(数据成员):具有当前值的数据域的集合构成
  • 行为(方法成员):方法的集合定义

创建与初始化对象

  • 使用new关键字创建对象

  • 使用new关键字创建对象是,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以对类中构造器的调用

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的,一个类即使什么都不写,它也会存在一个构造方法(默认方法,不带参数且方法体为空)。并且构成器有两个特点:

    • 必须和类的名字相同
    • 必须没有返回类型,也不能写void
  • 构造器作用:

    • new一个对象本质是在调用构造方法
    • 初始化对象的值
  • 注意:定义有参构造之后,如果想使用无参构造,一定要显示的定义一个无参的构造

3.封装

  • 该露的露,该藏的藏

    • 程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
  • 封装(数据的隐藏)

    • 通常,应该禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
  • 属性私有,get/set

4.继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模

  • extands 的意思是“扩展”。子类是父类的扩展

  • Java中类只有单继承 ,没有多继承

  • 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等

    继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extands

    子类和父类之间,从意义上讲应该具有“is a”的关系

  • Object类:Java中所有的类默认直接间接继承Object类

5.super&this

  • super:指代super所在类的父类,可以用于调用父类中的方法和构造方法

  • 调用父类的构造方法

    • super():调用父类的无参构造方法
    • super(parameters):调用父类的有参构造方法
  • 调用父类的方法

    • super.methodName(parameters);

子类对象构造的时候,如何构造来自父类的成员?——构造方法链

  • 子类构造方法总是先调用,在任何情况下,构造一个类的实例时,将会调用沿着继承链所在的所有父类的构造方法
  • 如果没有使用super显式的调用父类构造方法,编译器会自动在第一行加上super(),去调用父类的无参构造方法

this是Java的一个关键字,表示某个对象(表示当前对象的引用)。this可以出现在实例方法和构造方法中,但不可以出现在类方法中

this关键字用途:

  • 类的实例方法中可以通过 this.成员变量名 访问成员变量,通常this可以省略掉,但是当引用隐藏数据时不可省略
  • 通过this来调用类中的另一个构造方法

注意点:

  1. super调用父类的构造方法,必须在构造方法的第一行
  2. super只能出现在子类的方法或者构造方法中
  3. super和this不能同时调用构造方法

super VS this

代表的对象不同:

​ this:本身调用的这个对象

​ super:代表父类对象的应用

前提:

​ this:没有继承也可以使用

​ super:只能在继承条件才可以使用

构造方法:

​ this():本类的构造

​ super():父类的构造

6.static

静态成员

  • 静态变量:需要让一个类中所有实例共享数据,也称类变量
  • 静态方法:无需创建类的实例就可以调用,也称为类方法
  • 静态常量:类中的常量被所有对象所共享。声明为final static

实例成员:没有用static关键字声明的变量、方法称为实例变量、实例方法,统称为

实例成员和静态成员的区别

  • 实例成员属于实例,只能在对象创建后只能通过对象名调用;而静态成员属于类,可以通过类名调用(推荐),也可以通过对象名调用
  • 静态方法可以访问静态变量和静态方法,实例方法也可以访问静态变量和静态方法
  • 实例方法可以访问实例变量和实例方法,而静态方法不能访问实例变量和实例方法(因为调用静态方法时,可能还没有创建对象实例)

如果变量或方法依赖与类的具体实例,那么声明为实例成员;反之,不依赖于类的具体实例,那么声明为静态成员

static块:会在类被加载时执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法

7.可见性修饰符

  • 可见性修饰符:探讨的是类中的数据或属性能够从类外被访问,而对与类内,任何访问都是没有限制的
  • public:类、方法和数据域在任何类中可访问
  • protected:保护的成员变量,只能被它所在类及其子类和相同包中的其它类访问(不考虑继承时,与友好相同)
  • 友好(不加任何关键字):如果三个修饰字都没有,默认情况下,类、方法和数据可以从同一个包中的任何类访问,有的地方也称为包私有或者包内访问
  • private:使得方法和数据域只能从自身所在的类中访问

public类:类声明时,如果在关键字class前面加上public关键字,就称这样的类是一个public类。可以在任何另外一个类中,使用public类创建对象

友好类:如果一个类不加public修饰,这样的类被称作友好类。在另外一个类中使用友好类创建对象时,要保证它们在同一个包中

8.对象数组

使用对象数组来存放若干个同类型的对象,即数组的元素是对象。例如:

Student[] stu;

stu=new Student[10];

本质:对象数组的本质是引用变量的数组,也就是数组中存放的都是一系列对象的地址,通过数组下标获得对每个对象的访问

创建数组对象,逐一创建数组中的元素对象,之后才能使用该对象数组

Student[] stu=new Student[10];

for(int i=0;i<stu.length;i++){

​ stu[i]=new Student();

}

9.类的组合

一个类可以把对象作为自己的成员变量,如果用这样的类创建对象,那么该对象中就会有其它对象,也就是说该对象将其他对象作为自己的组成部分,或者说该对象是由几个对象组合而成。我们把这种类之间的关系称为组合

  • 关联关系:如果A类中的成员变量是B类声明的对象,那么A和B的关系是关联关系,称A类的对象关联于B类的对象或A类的对象组合了B类的对象
  • 依赖关系:如果A类中的某个方法参数是B类声明的而对象或返回数据类型是B类对象,那么A和B是依赖关系,称A依赖于B

10.方法重写

  • 方法重写(method overriding):子类中将父类的成员方法的名称保留,重写成员方法的实现,或更改成员方法访问权限,或修改重写方法的返回值类型,也称为方法覆盖
  • 子类通过方法重写可以隐藏继承的方法,可以把父类的行为改变为自己的行为
  • 重写父类方法,修改方法的访问权限只能从小的范围变大的范围,修改返回值类型只能是父类中方法的返回值类型的子类,抛出的异常范围可以缩小但不能扩大
  • 建议使用重写注解@Override,表示被标注的方法重写父类的一个方法

11.多态

子类型:子类定义的类型称为子类型

父类型:父类定义的类型称为父类型

  • 继承关系使用一个子类继承父类的特性,并且附加一些新特征
  • 每个子类的实例都是其父类的实例,因此,总可以将子类的实例传递给父类类型的参数,意味着父类型的变量可以引用子类型的对象

声明类型:变量在定义的时候声明的类型

实际类型:变量引用的对象实际类型

  • 对象调用哪个方法由对象的实际类型决定,这称为动态绑定
  • 父类型的变量可以引用子类型的对象,因此,对于需要父类类型的参数,总可以传入子类的实例父类引用变量的对象实例到底调用哪一种实现,有Java虚拟机在运行时动态决定,父类引用变量称为动态绑定多态性

多态性发生的条件

  • 父类型引用变量引用子类对象
  • 子类重写父类方法
  • 父类型引用变量调用重写的方法

12.instanceof

对象转换:对象的引用可以类型转换为另外一种对象的引用

对象转换的目的:为了获得通用程序设计的效果,通常将方法参数、变量定义成父类型,那么它可以接受任何子类型的值

对象转换原则:

  • 总可以将一个子类的实例转换为一个父类的变量(向上转型),向上转换是隐式转换,例如, Person person=new student;
  • 一个父类的实例转换为它的子类变量时,必须使用转换记号“()”进行显式转换(向下转型),例如,Student student=(Student)person;

为了确保对象转换(向下转型)的安全,使用instanceof运算符在转换前确保对象是另一个对象的实例

instanceof运算符:是一个二目运算符,左边的操作元是一个对象右边的是一个,当左边的对象是右边的类或子类创建的对象时,该运算符运算的结果是true,否则是false

13.final

常量:如果成员变量和局部变量被final修饰,那么就不可以再改变该变量的值,由final定义的变量为常量

常量需要在定义的时候赋值,常量标识符一般用大写字母和下划线

final方法:final定义的方法是最终的,可以防止子类重写该方法

final类:final可以放在类声明中,说明该类是终极类,不能做父类,final类中的所有方法被隐式设置为final,但是类中的成员变量可以定义为final或者非final

14.抽象类

抽象类:有的父类设计得非常抽象,以至于它没有任何具体的实例,这样的类称为抽象类

抽象类定义:用关键字abstract修饰的类

抽象方法定义:用关键字abstract 修饰的方法

  • 抽象类可以有抽象方法,也可以没有抽象方法,但是非抽象类一定不能有抽象方法,含有抽象方法的类一定是抽象类

  • 抽象类不能用new运算符创建对象(即无法实例化),但可以定义抽象类的引用变量

  • 抽象类有构造器,给子类用的

  • 抽象类的抽象方法都要由继承它的子类去实现,除非子类也是抽象类

15.接口

接口:是一种与类相似的结构,只包含常量和抽象方法,可以看成是一种特殊的抽象类,一种完全没有实现的类,目的是指明相关或者不相关类的多个对象的共同行为

接口和实现该接口的类之间的关系称为接口继承,本质上,接口继承和类继承一样,因此,如果一个类实现了一个接口,这个接口类似于该类的父类

实现接口:类可以使用关键字implements继承一个或多个接口:

[修饰符] class 类名[implements 接口名1,...,接口名n]{

}

利用extends关键字,接口可以继承(扩展)其他接口,这样的接口称为子接口

接口特点

  • 接口可以看做是一种特殊的类,每个接口都会编译成独立的字节码文件
  • 不能使用new运算符创建接口的实例,但可以声明接口的引用变量
  • 成员变量默认修饰:public static final
  • 成员方法默认为:public abstract
  • 接口中没有构造函数,方法可以抛出异常

UML图

  • 顶层第一层是名字层,接口的名字必须是斜体字,而且需要用《interface》修饰名字,并且修饰和名字分两行
  • 第二层是常量层,列出接口中的常量及类型,格式是”常量名字:类型“
  • 第三层方法层,也称操作层,列出接口中的方法及返回类型,格式是”方法名字(参数列表):类型“

理解接口

  • 接口可以抽象出重要的行为标准,该行为标准用抽象方法来表示
  • 可以把实现接口的类的对象的引用赋值给接口变量,该接口变量可以调用被该类实现的接口方法,即体现该类根据接口里的行为标准给出的具体行为
  • 接口的思想在于它可以要求某些类有相同名称的方法,但方法的具体内容(方法体的内容)可以不同,即要求这些类实现接口,以保证这些类一定有接口中所声明的方法(即所谓的方法绑定)。接口在要求一些类有相同名称的方法的同时,并不强迫这些类具有相同的父类

形式上比较接口与抽象类

  • 接口中的数据必须是常量,抽象类可以有各种类型的数据
  • 接口中的每个方法都是抽象方法,公共的,所以Java不要求在接口中将修饰符放在方法前,抽象类中有抽象方法,所以抽象类中必须将修饰符abstract放在抽象方法前,公共的方法前也必须加修饰符public
  • 接口中无构造方法,无法实例化对象;抽象类的子类通过方法链调用构造方法,抽象类也无法直接实例化对象

内涵上比较接口与抽象类

  • 抽象类:子类继承父类抽象类,代表的是一种强的“is-a”语义关系,子类对象“is-a”父类类型
  • 接口:子类实现接口代表的是一种弱的“is-a”语义关系。不用实现该接口的所有类都是一种类型,表明子类有某种属性,也可称为类属关系

16.内部类

  • Java支持在一个类中声明另一个类,这样的类称为内部类,而包含内部类的类称为内部类的外嵌类(外部类,包装类,宿主类)
  • 内部类是个编译时的概念,一旦编译成功后,它和外部类属于两个完全不同的类(当然还是有联系的)
class OuterClass{
    class InnerClass{...}//成员内部类
    static class StaticNestedClass{...}//静态内部类
    func(){
        class LocalClass{...}//局部内部类
        new ClassNameorInterfaceName(){...};//匿名内部类
    }
}
  • 成员内部类(inner class)

    • 内部类是依附于外部类的,所有只有先创建了外部类对象才能够创建内部类对象,如:

      OuterClass outerClass=new OuterClass();

      OuterClass.InnerClass innerClass=outerClass.new InnerClass();

    • 成员内部类可以对外部类的成员进行任意访问,但是外部类要访问内部类的成员则需要通过内部类实例来访问

    • 成员内部类不能存在static的成员变量和成员方法,但是可以存在静态常量

    • 成员内部类可以被修饰为private、protect、public或包私有,就像外部类的成员一样,而外部类只能修饰为public或包私有

  • 静态内部类(static nested classer)

    • 内部类对象的创建是不需要依赖于外部类,因此无需先创建外部类对象

      OuterClass.StaticNestedClass nestedObject=new OuterClass.StaticNestedClass();

    • 静态内部类可以有静态成员,外部类可以直接访问静态内部类的静态成员

    • 静态内部类和静态方法一样,只能直接访问外部类的静态数据域和静态方法成员,不饿能直接访问外部类的实例数据域和实例方法(即非static成员),只能通过对象访问外部类的实例成员变量和实例成员方法

  • 局部内部类(local class):

    • 在块中的局部内部类就像是方法里面的局部变量一样,是不能有public、protect、private以及static修饰符的,但可以使用final和abstract修饰
    • 不能声明接口,因为接口是静态的
    • 局部内部类中不能定义静态变量和静态方法,但可以定义静态常量
  • 匿名内内部类

    • new ClassOrInterfaceName(){

      ​ //类体

      }

    • 匿名内部类可以继承一个类或实现一个接口

    • 可以在定义类的同时实例化该类的对象

    • 匿名内部类和局部内部类类似,但匿名类没有名字,所以类体中不能定义构造方法

    • 匿名类是表达式,意味着可以在任意表达式的位置定义匿名类

    • 匿名内部类编译后,对应产生“外部类名$序号”为名称的class文件

枚举类型

  • 枚举类型定义了该类型所有可能的值。JavaSE5版本后引入了枚举类型

  • 用关键字enum定义枚举类型,例如

    public enum Day{

    SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIFAY,SATURDAY

    }

  • 枚举名称与类的名称遵循一样的惯例来定义

  • 由于枚举值是常量,推荐全部用大写字母

  • 枚举类型本质:枚举类型声明,实际上是定义一个类,所有的枚举类型隐式继承java.lang.Enum,经过编译器编译之后产生class文件
    学习B站狂神说
    中国大学MOOC



这篇关于Java学习-面向对象编程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程