一、关于面向对象
1.1简介
Java 是一种面向对象编程语言,其核心思想是面向对象编程(Object-Oriented Programming,OOP)。
面向对象编程是一种程序设计范式,它将数据与操作数据的方法(函数)捆绑在一起,以对象的形式呈现,从而使程序更容易理解、灵活和可维护。
1.2背景
1.2.1面向过程的优缺点
面向过程(Procedural Programming)是一种以过程为中心的编程方法,它通过一系列定义好的步骤来完成任务。面向过程与面向对象编程相比,有以下优点和缺点:
优点:
- 简单易懂:面向过程的编程模式具有简单的语法结构和直观的流程,易于学习和掌握。
- 执行效率高:由于面向过程的程序不涉及到对象的创建和销毁等复杂的操作,因此执行效率比面向对象的程序高。
- 内存占用小:面向过程的程序通常需要较少的内存空间,因为它不需要为对象创建额外的内存空间。
缺点:
- 缺乏灵活性:面向过程的编程模式通常需要编写大量的代码,并且代码的复杂度和维护难度都很高。面对变化的需求,修改和维护代码将变得困难。
- 不易扩展:在面向过程的编程模式中,程序被分为许多函数,函数之间的数据交换通过参数来完成。如果需要添加新的功能,可能需要修改许多函数的参数,这将影响程序的可维护性和扩展性。
- 不够直观:由于面向过程的程序通常是一系列的函数调用,函数之间的关系可能不够明显,代码的结构不够直观,难以理解和维护。
综上所述,虽然面向过程的编程模式具有一些优点,但其缺点更为突出,难以满足现代软件开发的需要。因此,在现代软件开发中,更多地采用面向对象编程方法来实现更加灵活、可扩展和易于维护的软件系统。
1.2.2面向过程到面向对象
人们从面向过程发展出了面向对象,是因为面向过程在处理大型软件系统时面临的问题越来越明显。面向过程将数据和操作分离,导致代码结构复杂、维护困难,难以适应现代软件开发的快速变化和需求的不断增加。
相比之下,面向对象更加注重对象和行为,将数据和操作集成在一个对象中。这种编程模式使得代码更加简洁、清晰、易于理解和维护,而且可以更好地适应变化和扩展需求。例如,面向对象提供了封装、继承和多态等特性,可以更加灵活地组织代码,实现高内聚、低耦合的代码结构。
另外,随着软件规模的增加,面向对象可以更好地管理和组织代码,将复杂的系统分解为一些独立的对象,并将其相互关联起来,以更好地满足业务需求。面向对象还可以提高代码的重用性,通过继承、接口和抽象类等机制,避免了重复编写相似的代码,提高了开发效率。
综上所述,面向对象是一种更加现代、灵活、易于维护和扩展的编程模式,它在处理大型软件系统时具有明显的优势,因此成为了当今软件开发的主流编程模式。
1.2.3面向对象优缺点
面向对象编程(OOP)有以下优点和缺点。
优点:
- 可重用性:面向对象编程的一个主要优点是可以重用代码。面向对象编程中的继承和多态使得代码可以更容易地重用。通过继承,子类可以重用父类的代码,而不必重新编写。通过多态,不同的对象可以共享相同的接口,并根据需要提供不同的实现。
- 可维护性:面向对象编程可以使代码更易于维护。由于面向对象编程中的代码是基于对象和类的,因此修改一个对象或类的代码不会影响其他代码。这使得代码更易于维护和修改。
- 灵活性:面向对象编程的另一个优点是灵活性。面向对象编程的抽象概念使得代码可以更好地适应需求的变化。由于代码是基于对象和类的,因此可以更容易地添加新的对象或类,并使代码更易于扩展。
- 可读性:面向对象编程可以使代码更易于理解。由于代码是基于对象和类的,因此可以更容易地理解代码的意图。此外,面向对象编程中的继承和多态也使得代码更易于理解。
缺点:
- 复杂性:面向对象编程的一个主要缺点是复杂性。由于面向对象编程涉及到多个对象和类之间的交互,因此代码可能会变得非常复杂。此外,面向对象编程还涉及到抽象概念,这可能使代码更难理解。
- 性能问题:面向对象编程可能会带来一些性能问题。由于面向对象编程涉及到多个对象和类之间的交互,因此可能会涉及到许多函数调用和内存分配,这可能会对程序的性能产生负面影响。
- 学习曲线:面向对象编程需要对抽象概念和面向对象编程的范例有一定的理解和掌握。因此,学习面向对象编程可能需要更多的时间和精力,这可能会使得初学者更难入门。
总之,面向对象编程具有可重用性、可维护性、灵活性和可读性等优点,但也存在复杂性、性能问题和学习曲线等缺点。
1.2.4面向过程与面向对象区别
面向对象的优点:容易维护、易扩展、易复用面向对象有封装、继承、多态的特征、可以设计出低耦合的系统,使系统更加灵活、
面向对象的缺点:性能比面向过程差
二者都是一种思想,面向对象是相对于面向过程而言的
1-面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做
2-面向对象:将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做
面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象,分类,继承,聚合,多态等
1.3面向对象核心思想
面向对象编程是一种程序设计的方法,它将程序中的数据和操作封装在一个对象中。这个对象有自己的属性和方法,可以与其他对象交互。面向对象编程的核心思想是把现实世界中的对象抽象成计算机程序中的对象,这样就可以更加自然地描述问题和解决问题。
在面向对象编程中,每个对象都有自己的状态和行为。状态表示对象当前的属性,而行为表示对象能够进行的操作。通过将数据和操作封装在对象中,我们可以隐藏实现细节并提供简单的接口,这使得程序更容易理解、维护和重用。
另一个重要的概念是继承。继承可以帮助我们避免重复编写代码,并且使代码更容易扩展。当一个类继承另一个类时,它将继承其所有属性和方法,同时还可以添加自己的属性和方法。
最后,多态是面向对象编程的一个重要特征。多态意味着不同的对象可以对相同的方法做出不同的响应。这使得代码更加灵活,可以更好地适应不同的场景。
总之,面向对象编程是一种强大的编程方法,它可以使代码更加模块化、易于理解和维护。通过把现实世界中的对象抽象成程序中的对象,我们可以更好地解决复杂的问题。
1.3.1面向对象分析方法分析问题的思路和步骤
/*
* 程序员从面向过程的执行者转化成了面向对象的指挥者
* 面向对象分析方法分析问题的思路和步骤:
* 1-根据问题 需要,选择问题所针对的现实世界中的实体
* 2-从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类
* 3-把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义,即借助某种程序语言,把类构造成计算机能够识别和处理的 数据结构
- 4-将类实例化成计算机世界中的对象,对象是计算机世界中解决问题的最终工具
1.4Java如何实现面向对象思想
Java是一种面向对象编程语言,它实现了面向对象编程思想。以下是Java如何实现面向对象编程的几个主要方面:
- 类和对象:在Java中,类是创建对象的模板。通过定义类,我们可以定义对象的属性和方法。而对象是类的实例,它具有类定义的属性和方法。Java中的对象是通过使用new操作符实例化类来创建的。
- 封装:Java支持封装,这意味着我们可以将类的内部实现隐藏起来,并通过公共接口提供对类的访问。通过将数据和操作封装在类中,我们可以更好地控制数据的访问和修改,并提供更安全的编程环境。
- 继承:Java支持继承,这意味着一个类可以从另一个类继承属性和方法。继承可以帮助我们避免重复编写代码,并使代码更容易扩展。在Java中,我们可以通过extends关键字创建子类并继承父类的属性和方法。
- 多态:Java支持多态,这意味着不同的对象可以对相同的方法做出不同的响应。在Java中,我们可以通过方法的重载和覆盖来实现多态。
- 接口:Java支持接口,这是一种描述类所需实现的方法的结构。接口提供了一种方便的方式来定义类之间的协议,并支持多重继承。
总之,Java通过类和对象、封装、继承、多态和接口等特性实现了面向对象编程思想。这些特性提供了一种方便的方式来描述和解决问题,并使得Java代码更加模块化、易于理解和维护。
二、类与对象
2.1简介
- 类:类是一个模板,它描述一类对象的行为和状态。
- 对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
①类是对一类事物的描述,是抽象的,概念上的定义
②对象是实际存在的该类事物的每个个体,因而也称其为实例(instance)
下图中汽车为类(class) ,而具体的每辆车为该汽车类的对象(object) ,对象包含了汽车的颜色、品牌、名称等。
对象是实际存在的该类事物的每个个体,因而也称其为实例(instance)
现实世界中,我们定义了“人”这种抽象概念,而具体的人则是“小明”、“小红”、“小军”等一个个具体的人。所以,“人”可以定义为一个类(class),而具体的人则是实例(instance):
现实世界 | 计算机模型 | Java代码 |
---|---|---|
人 | 类 / class | class Person { } |
小明 | 实例 / ming | Person ming = new Person() |
小红 | 实例 / hong | Person hong = new Person() |
小军 | 实例 / jun | Person jun = new Person() |
同样的,“书”也是一种抽象的概念,所以它是类,而《Java核心技术》、《Java编程思想》、《Java学习笔记》则是实例:
现实世界 | 计算机模型 | Java代码 |
---|---|---|
书 | 类 / class | class Book { } |
Java核心技术 | 实例 / book1 | Book book1 = new Book() |
Java编程思想 | 实例 / book2 | Book book2 = new Book() |
Java学习笔记 | 实例 / book3 | Book book3 = new Book() |
2.2示例
2.2.1定义class
在Java中,创建一个类,例如,给这个类命名为Person
,就是定义一个class
:
class Person {
public String name;
public int age;
}
一个class
可以包含多个字段(field
),字段用来描述一个类的特征。
上面的Person
类,我们定义了两个字段,一个是String
类型的字段,命名为name
,一个是int
类型的字段,命名为age
。因此,通过class
,把一组数据汇集到一个对象上,实现了数据封装。
public
是用来修饰字段的,它表示这个字段可以被外部访问。
2.2.2创建实例
定义了class,只是定义了对象模版,而要根据对象模版创建出真正的对象实例,必须用new操作符。
new操作符可以创建一个实例,然后,我们需要定义一个引用类型的变量来指向这个实例:
Person ming = new Person();
上述代码创建了一个Person类型的实例,并通过变量ming
指向它。
注意区分Person ming
是定义Person
类型的变量ming
,而new Person()
是创建Person
实例。
有了指向这个实例的变量,我们就可以通过这个变量来操作实例。访问实例变量可以用变量.字段
,例如:
ming.name = "Xiao Ming"; // 对字段name赋值
ming.age = 12; // 对字段age赋值
System.out.println(ming.name); // 访问字段name
Person hong = new Person();
hong.name = "Xiao Hong";
hong.age = 15;
上述两个变量分别指向两个不同的实例,它们在内存中的结构如下:
┌──────────────────┐
ming ──────>│Person instance │
├──────────────────┤
│name = "Xiao Ming"│
│age = 12 │
└──────────────────┘
┌──────────────────┐
hong ──────>│Person instance │
├──────────────────┤
│name = "Xiao Hong"│
│age = 15 │
└──────────────────┘
两个instance
拥有class
定义的name
和age
字段,且各自都有一份独立的数据,互不干扰。
一个Java源文件可以包含多个类的定义,但只能定义一个public类,且public类名必须与文件名一致。如果要定义多个public类,必须拆到多个Java源文件中。
2.2.3构造方法
每个类都有构造方法。如果没有显式地为类定义构造方法,Java 编译器将会为该类提供一个默认构造方法。
在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法。
下面是一个构造方法示例:
public class Puppy{
public Puppy(){
}
public Puppy(String name){
// 这个构造器仅有一个参数:name
}
}
2.3面向对象的三大特征
2.3.1简介
面向对象的三个特征:封装、继承、多态
继承:让某个类型的对象获取另一个类型的对象的属性的方法,继承就是子类继承父类的特征和行为,使子类的对象具有父类的方法,或者子类从父类继承方法 是子类具有父类相同的行为 使用extends关键字实现继承 继承就是子类自动共享父类的数据和方法,是类与类之间的一种关系 提高了软件的可重用性和可扩展性
封装:隐藏部分对象的属性和行为,对数据的访问只能通过对外公开的接口,通过这种方式对象对内部数据提供了不同级别的保护,防止程序中无关紧要的部分意外的改变或者出错的是用来对象的私有部分
多态:多态就是在声明的时候使用父类在实现或调用的时候使用具体的子类,不修改代码既可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态这就是多态 对于同一个行为,不同的子类对象具有不同的表现形式,多态的存在要满足三个条件:
(1)继承
(2)方法重写
(3)父类引用指向子类的对象
2.3.2封装
简介
封装(Encapsulation)是面向对象编程的三大特性之一,它指的是将数据(属性)和行为(方法)捆绑在一起,对外部隐藏对象的内部实现细节,只提供有限的访问方式。通过封装,我们可以控制对对象的访问,确保数据的安全性和一致性。
特点
- 数据隐藏:封装可以将对象的内部状态(字段)隐藏起来,只允许通过对象的方法来访问和修改数据,而不直接暴露给外部。
- 访问控制:通过封装,可以使用访问修饰符(如 private、protected、public)来控制对类的成员的访问权限,确保数据的安全性。
- 信息隐藏:封装可以隐藏对象的内部实现细节,只展示对外提供的接口,降低了代码的耦合度,使得对象更易于维护和扩展。
示例
- 修改属性的可见性来限制对属性的访问(一般限制为private),例如:
public class Person {
private String name;
private int age;
}
这段代码中,将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
- 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:
public class Person{
private String name;
private int age;
public int getAge(){
return age;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
}
采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
2.3.3继承
简介
继承(Inheritance)是面向对象编程的重要特性之一,它允许一个类(子类)基于另一个类(父类)来构建自己的特性和行为。通过继承,子类可以获得父类的属性和方法,同时可以重写父类的方法或添加新的方法和属性。
特点
- 子类和父类:在 Java 中,一个类可以派生出一个或多个子类,子类继承了父类的属性和方法。
- extends 关键字:通过使用
extends
关键字,子类可以继承父类的非私有属性和方法。 - 重写方法:子类可以重写父类的方法,以实现自己的特定逻辑。子类的方法签名必须与父类的方法相匹配。
- super 关键字:子类可以使用
super
关键字调用父类的构造方法和方法。
优点:
代码复用:继承允许子类重用父类的属性和方法,减少了重复编码。
多态性:通过继承,可以实现多态性,即不同子类对象对同一消息做出不同响应。
层次结构:通过继承,可以建立类之间的层次结构,提高代码的可维护性和扩展性。
示例
父类:
package cn.csu.ksh;
public class Person {
private int a=1;//父类私有成员变量
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
public void say() {
System.out.println("person say..");
}
public void run() {
System.out.println("person run....");
}
//父类的私有方法
private void show() {
System.out.println("person show...");
}
}
子类
package cn.csu.ksh;
public class Student extends Person {
@Override
public void say() {
super.say();
}
@Override
public void run() {
super.run();
}
public static void main(String[] args) {
Student stu = new Student();
//stu.a=1;//子类对象对父类的私有成员变量使用报错!
//stu.show();//子类对象调用父类的私有方法,同样报错!
stu.say();
stu.run();
}
}
继承的好处是实现代码的复用以及扩展,子类通过对父类代码的复用,可以不用再定义父类中已经定义的成员变量,方法上直接对父类的方法进行重写实现了扩展。
2.3.4多态
简介
多态性(Polymorphism)是面向对象编程的重要概念之一,它允许对象以不同的方式展现出其行为。多态性使得同一个方法可以在不同的对象上具有不同的行为,这提高了代码的灵活性、可维护性和可扩展性。
多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
特点
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
实现方式
- 方法重写(Override) :子类可以重写父类的方法,当调用该方法时,根据实际的对象类型决定执行哪个版本的方法。在运行时动态绑定方法调用。
- 接口实现(Interface Implementation) :通过接口,一个类可以实现多个接口,在不同的上下文中表现出不同的行为。
示例
接口
package cn.csu.ksh;
public interface Animal {
void shout();
}
实现类
package cn.csu.ksh;
public class Dog implements Animal{
@Override
public void shout() {
System.out.println("wangwang...");
}
}
实现类
package cn.csu.ksh;
public class Cat implements Animal {
@Override
public void shout() {
System.out.println("miaomiao...");
}
}
测试:
package cn.csu.ksh;
public class AnimalTest {
public static void main(String[] args) {
//父类的引用指向子类对象
Animal d = new Dog();
animalShout(d);
//父类的引用指向子类对象
Animal c= new Cat();
animalShout(c);
}
public static void animalShout(Animal animal) {
animal.shout();
}
}
2.4接口
2.4.1简介
接口(interface)是一种抽象类型,它定义了一组方法的签名但没有具体的实现。接口可以包含常量、方法声明、默认方法、静态方法和私有方法。接口提供了一种将方法声明与实现分离的方式,使得不同类可以实现相同的接口并提供自己的具体实现。
在Java中,接口可以使用interface关键字来定义。
2.4.2示例
在这个示例中,我们定义了一个名为Swimable的接口,并添加了一个公共方法swim。
public interface Swimable {
public void swim();
}
接口可以被类实现,实现接口的类必须实现接口中定义的所有方法。以下是一个示例代码,展示了如何使用接口来实现Swimable接口:
public class Duck implements Swimable {
public void swim() {
System.out.println("The duck is swimming.");
}
}
在这个示例中,我们定义了一个名为Duck的类,并使用implements关键字来实现Swimable接口,并实现了接口中定义的方法swim。
总之,Java的接口可以用于各种应用程序的开发,可以帮助开发人员更好地描述和解决问题,并使得Java代码更加模块化、易于理解和维护。
2.5抽象类
2.5.1简介
抽象类(Abstract Class)是一种特殊的类,它不能被实例化,只能被用作其他类的父类。抽象类通常用于定义子类共同的属性和方法,以便子类继承和实现这些方法。
2.5.2特点
- 不能被实例化:抽象类不能直接实例化对象,只能用作其他类的父类。
- 包含抽象方法:抽象类中可以包含抽象方法,这些方法没有具体的实现,需要子类去实现。
- 可以包含普通方法:抽象类中可以包含普通的方法,这些方法有具体的实现,子类可以选择性地重写这些方法。
抽象类的优点:
- 提高代码的复用性:将公共的方法抽象到抽象类中,可以被多个子类共享。
- 约束子类:通过抽象类定义抽象方法,强制子类去实现这些方法,确保子类的一致性。
2.5.3示例
// 抽象类
abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// 抽象方法
public abstract double calculateArea();
// 普通方法
public void displayColor() {
System.out.println("The color of the shape is: " + color);
}
}
// 子类
class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
public class AbstractClassExample {
public static void main(String[] args) {
Shape circle = new Circle("Red", 5.0);
System.out.println("Area of the circle: " + circle.calculateArea());
circle.displayColor();
}
}
Shape 是一个抽象类,定义了一个抽象方法 calculateArea 和一个普通方法 displayColor。Circle 类继承自 Shape 类,并实现了 calculateArea 方法。在主类 AbstractClassExample 中,创建了一个 Circle 对象,并调用了其方法。