Java OOP
前言
OOP的全称为Object Oriented Programming,简单来说就是面对对象进行编程,本文我将带领大家简单认识下OOP的世界。
一、OOP简单介绍
why OOP
OOP简单来说就是面对对象进行编程,而在目前的软件的开发领域中有两种主流的开发方法,分别是结构化开发方法和面对对象开发方法,随着软件开发技术的逐渐发展,人们发现面对对象相对于面对过程可以提供更好的重用性、可扩展性和可维护性,于是便催生了许多面对对象的编程语言,今天咱就带大家了解一下java中OOP的相关知识。
OOP中万物皆【对象】(至于【对象】是什么,后面会介绍),更贴近生活,更符合人类的思维习惯,每个【对象】都有其单一职能,面对对象进行编程相比之下会降低复杂度,方便阅读,复用,修改,排错。
面对对象进行编程,更易于扩展,自由添加新的【对象】,易于将复杂的问题,降解为简单的问题。
what’s OOP
OOP作为面对对象的编程,可以实现用程序语言描述事务静态的特征和动态的行为
二、OOP的几个核心概念
类
类的简单介绍
只要是一门面对对象的编程语言,那么就一定会有类这个概念,类是指将相同属性的东西放在一起,类是一个模板,能够描述一类对象的行为和状态。
Java中的每一个源程序中至少都会有一个类,Java是面对对象的程序设计语言,类是面对对象的重要内容。我们可以把类当成一种自定义数据类型,可以使用类来定义变量,这种类型的变量统称为引用型变量,也就是说,所有类都引用数据类型。
类的语法结构:自定义类型
访问修饰符 特殊修饰符 关键字 类名
public class Student{
属性(全局变量,静态特征)
private String name;
... 方法(行为,动态特征)
public void sayHello(){
System.out.println(“hello”);
}
}
类一般是开放的:public,特殊需求时可选:private / 缺省(可以不写) / protected
特殊修饰符:final / abstract / static
类关键字:class
类名命名规则:与变量命名规则相同,但是首字母要大写
对象
对象的简单介绍
对象是实际存在某个类中的每一个个体,因而也被称为实例(instance),对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象。类用来描述一系列对象,类会概述每个对象包括的数据和行为特征。因此,我们可以把类理解成某种概念、定义,它规定了某类对象所共同具有的数据和行为特征。
在面对对象的程序中,首先要将一个对象看做一个类,假设人是对象,任何一个人都是一个对象,类只是一个大概念,而类中的对象是具体的,它们具有自己的【属性】(例如漂亮,身材好)和【方法】(例如会唱歌,会画画),OOP中对象的状态就是属性,行为通过方法实现,在软件开发过程中,方法操作对象内部状态的改变,对象的相互调用也是通过方法来完成的。
对象的创建
变量声明:int age;
变量赋值:age = 18;
变量声明且赋值:int age = 18;
对象的声明:类名 对象名;
Student student;
对象初始化:对象名 = new 构造方法(参数列表...);
student= new Student("小明");
声明且赋值:Student student= new Student("小明");
调用方法:类内直接调用,类外通过对象调用。
类与对象的区别
① 类描述客观世界里某一类事物的共同特征,而对象则是类的具体化,Java程序使用类的构造器来创建该类的对象。
② 类是创建对象的模板和蓝图,是一红类似对象的共同抽象定义。类是一个抽象的概念,不是一个具体的事物。
③ 对象是类的实例化结果,是真实的存在,代表现实世界中的某一事物。
属性
属性的简单介绍
属性有时也称为字段,用于定义该类或该类的实例所包含的数据,在Java程序中,属性通常用来描述某个对象的具体特征,是静态的。例如:小白(对象)的毛发是白色的,小明(对象)的身高为1.8m等,都是属性。
属性的语法结构
访问修饰符 特殊修饰符 数据类型 属性名称;
private String name;
访问修饰符:一般是私有化 private,用于保护数据。
特殊修饰符(可选):final / static / volatile / transient
数据类型:基础类型,引用类型。
属性名命名规则:与变量名命名规则相同。
方法
方法的简单介绍
方法用于定义该类或该类实例的行为特征或功能实现,每个对象都有自己的行为或者是使用他们的方法,比如说人(对象)会吃饭,会睡觉等,我们把这些行为成为方法,它是动态的,可以使用这些方法来操作一个对象。
方法的语法结构
访问修饰符 特殊修饰符 返回类型 方法名称(参数列表...)
public void sayHello(){
Systen.out.println(“Hello”);
}
访问修饰符:一般是开放的,特殊需求时可选:private / 缺省 / protected
特殊修饰符:final / static / 缺省 / abstract
返回类型:void / 基础类型 / 引用类型,调用方法后可以拿到的数据,void为无需数据。
方法命名规则:同变量名的命名规则
参数列表:定义方法时称之为形参,类似于变量声明,参数列表的意思为可以有多个变量,支持动态参数。
方法体:方法的实现逻辑,即:之前面对过程(Process Oriented Programming)的逻辑代码。
方法的分类
入口方法
public class Any{
public static void main(String[] args){
//之前采用的面向过程的编码方式。
}
}
① 一个工程一个入口
② 位于启动类中
③ 语法固定,若错误将导致工程无法启动
④ 启动工程时,jvm调用入口方法,运行工程中的代码。
构造方法
// 类
public class Person{
// 属性
private String name; // 姓名
private String profession; // 职业
private String gender; // 性别
// 构造方法
public Perifox(String name,String profession,String gender){
// 全局变量和参数同名,通过this加以区分
// 若不加this加以区分,按【就近原则】都作为参数处理
this.name = name;
this.profession = profession;
this.gender = gender;
}
}
① 初始化需要赋值类属性
② 每个类至少一个构造方法
③ 默认提供无参构造
④ 若显式声明带参构造,将不再提供无参构造,如需要无参构造必须显式声明
⑤ 支持构造方法重载
⑥ 必须与类同名
⑦ 没有返回值,不同于 void
⑧ 通常开放
⑨ this特指当前对象
构造方法的重载
public class Person{
private String name; // 姓名
private String profession; // 职业
private String gender; // 性别
public Person(){}
public Person(String name){
this.name = name;
}
public Perifox(String name, String profession){
this(name); //必须是构造方法中第一句话
this.profession = profession;
}
public Perifox(String name,String profession,String gender){
this(name, profession); //必须是构造方法中第一句话
this.gender = gender;
}
}
① 方法名相同,都和类名相同
② 参数不同
① 参数的数量不同
② 参数的类型不同
③ 不同类型参数顺序不同
③ this(…) 同类中在一个构造方法内调用另一个重载的构造方法,必须位于该构造方法中的
第一个语句。
自定义方法
public class Person{
...
public int add(int a, int b){ return a+b; } //自定义方法
...
}
① 形参列表:方法体中需要使用,类内没有,需要调用者传入的数据,多个参数之间用英文逗号隔开,作为进行交互的入口。
② 入参规则:参数数量不限,一般三个及以内可以直接入参,三个以上建议封装入参。
③ 动态参数:方便多个类型相同的参数传入,语法:数据类型…参数名,jvm实际处理时将动态参数作为数组处理,每个方法中只能有一个动态参数,且必须是参数列表中的最后一个。
④ 返回类型:只能有一个类型,若返回的数据多或者复杂必须封装作为一个单位返回,作为进行交互的出口。
⑤ return:两个功能,第一结束方法,第二返回一个值。无(如构造方法)或无需(void)返回类型的方法,return可选,若有,return只会发挥第一个功能。有返回类型的方法,return必须有,且必须返回一个和返回类型相同的值。
三、OOP的核心
封装
封装(Encapsulation)
将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。
封装有两个方面的含义:
一是把该隐藏的隐藏起来,
二是把该暴露的暴露出来,这两个含义都需要使用java
提供的访问修饰符来实现。
访问修饰符
java
一共提供了四个访问修饰级别,由小到大分别是 private、默认 、protected、public。
private :如果一个类的成员(包括属性和方法)使用private访问控制修饰时,成员只能在该类的内部访问,适合修饰属性,把属性隐藏在类的内部。
默认:如果类的一个成员(包括属性和方法)不使用任何访问控制修饰符,我们就称它是默认修饰访问控制,它可以被相同包下的其他类访问。
protected :如果一个类的成员(包括属性和方法)使用protected访问控制修饰,那么这个成员既可以被同一包中其他类访问,也可以被不同包中的子类访问。在通常情况下,如果使用protected 来修饰一个方法,通常是希望其子类来重写这个方法。
public :如果一个类的成员(包括属性和方法)使用public访问控制修饰,那么这个成员可以被所有类访问。
继承
继承(Inheritance)
继承是面向对象的特点之一,利用继承可以创建一个公共类,这个类具有多个项目的共同属性,然后一个具体的类继承该类,同时加上自己特有的属性。
在继承体系中,有父子类之分,Java语言是单根继承,所有类都直接或间接继承自Object(祖宗),所有类只能有一个父类,但可以有多个子类,如同人类一父,多子。
例如:
class Father{
private String firstName;
private String lastName;
private String gender;
public Father(String firstName, String lastName, String gender){
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
}
public void teach(){ ...... }
}
class Son extends Father{
public Son(String firstName, String lastName, String gender){
super(firstName, lastName, gender);
}
public void study(){ ...... }
}
调用父类的构造方法
super(参数);
访问父类的属性和方法
super.[方法和全局变量]
类与类的关系
关联:独立生命周期,没有从属关系。
如:学生和老师
上课时:一位老师关联多位学生,一位学生关联多位老师。
下课后:老师是老师,学生是学生,各有各的生命周期。
老师对象回收后不会删除学生,学生对象回收后也不会删除老师。
聚合:独立生命周期,有从属关系。
如:手机和电池,CPU和电脑等,电池从属于手机,手机坏了,电池依然存在,手机电池不能用于笔记本,但可用于其他手机。
组合:没有独立生命周期,有从属关系,且父对象消亡后,子对象伴随一起消亡。
如:问题和答案,问题都不存在了,答案就没有存在的意义。
继承:没有独立生命周期,有从属关系,且父对象消亡后,子对象伴随一起消亡。
如:狗继承了动物,创建狗对象时会自动创建一个动物对象,狗消亡同时动物对象也会消亡。
多态(polymorphism)
Java语言中的多态总是子类型的多态,几乎是机械式的产生了一些多态的行为,使我们不去考虑其中涉及的类型问题,多态表示为多种形式的能力,通用的多态引用有相同结构类型的大量对象,它们有着共同的特征,特定的多态涉及的是小部分没有相同特征的对象。多态有四种不同类型的多态,在面对对象中,通常把多态分为两个大类,四个小类。
强制的
强制多态隐式的将参数按某种方法,转换成编译器认为正确的类型以避免错误。
例如在以下的表达式中,编译器必须决定二元运算符 ‘ + ’ 所应做的工作。
2.0 + 2.0 将两个double相加
2.0 + 2 将double型和int型相加
2.0 + "2" 将double型和String型相加
第一个表达式将两个 double的操作数相加,在Java中特别声明了这种用法。
第二个表达式将double型和int 相加,在Java中没有明确定义这种运算,不过编译器隐式的将第二个操作数转换为double型,并作double型的加法。这对程序员来说十分方便,否则将会抛出一个编译错误,或者强制程序员显式的将int转换为double。
第三个表达式将double与一个String相加,在Java中没有定义这样的操作,所以编译器将double 转换成 String类型,并将它们做串联。
强制多态也会发生在方法调用中。
类型转换
// 自动类型转换(小转大)
Animal a = new Dog;
// 强制类型转换
Dog b = (Dog) a;
Cat c = (Cat) a;
重载的
重载允许用相同的运算符或方法去表示截然不同的意义。
例如:
2.0 + 2.0
2.0 + 2
2.0 + "2"
‘+’在上面的程序中有两个意思,一是表示两个double 型的数相加,二是表示两个串相连。另外还有整型相加、长整型等,这些运算符的重载依赖于编译器根据上下文做出的选择。以往的编译器会把操作数隐式转换为完全符合操作符的类型。虽然Java明确支持重载,但是不支持用户定义的操作符重载。
Java支持用户定义的函数重载,在一个类中可以有相同名字的方法,这些方法可以有不同的意义。在这些重载的方法中必须满足参数数目不同、相同位置上的参数类型不同的条件,这些不同可以帮助编译器区分不同版本的方法。编译器以这种唯一表示的特征来表示不同的方法,比用名字表示更为有效。
强制和重载的多态都被分类为特定的多态,因为这些多态都是在特定的意义上的,强制多态排除了麻烦的类型和编译错误,重载的多态像一块糖,允许程序员用相同的名字表示不同的方法,这个程序员带来了极大的方便。
参数的
参数多态允许把许多类型抽象成单一的表示。例如在一个名为List的抽象类中,描述了一组具有同样特征的对象,提供了一个通用的模板。我们可以通过指定一种类型以重用这个抽象类,这些参数可以是任何用户定义的类型,很多用户都可以使用这个抽象类,因此参数多态毫无疑问成为最强大的多态。
Java实际上并不支持真正的安全类型风格的参数多态,Java的单根继承方式解决了部分问题,但没有发挥出参数多态的全部功能。
包含的
包含多态通过值的类型和集合的包含关系实现了多态的行为,在包括Java在内的众多面向对象的语言中,包含关系是子类型的。所以Java的包含多态是子类型的多态,在早期,Java开发者们所提及的多态就特指子类型的多态,通过一种面向类型的观点,我们可以看到子类型多态的强大功能。
总结
以上就是今天要讲的内容,本文简单介绍了Java OOP的一些基本知识,在大量代码的情况下,相对于面对过程而言,面对对象进行编程会更加方便、快捷,将逻辑代码拆分装到以类为基本单元的结构中,变量以属性(全局变量)、方法参数、局部变量的方式呈现,逻辑控制和计算装到以方法体为基本单元的结构中,面对对象的编程也逐渐体现出程序设计的重要性。