面向对象思想
面向过程&面向对象
Java的核心就是面向对象编程(Object Oriented Programming, OOP),那面向对象的思想和面向过程思想有什么区别呢?
面向对象是在搭建系统的框架时所需要的思想,就像一个房地产开发项目,一些人负责打地基,一些人负责砌砖,一些人负责刷墙等。面向过程是在具体实现时所需要的思想,因为角色具体做的工作需要面向过程的思想来设计具体的功能和方法。
方法回顾和加深
静态方法和非静态方法
- 静态方法指的是方法前面有static修饰的方法。
- 非静态方法的调用需要先实例化类之后再调用,通过对象.方法来调用。而静态方法可以不用创建对象,而直接通过类.方法来调用。如下所示:
- 静态方法的调用
静态方法可以互相调用:
非静态方法之间也可以互相调用:
非静态方法可以调用静态方法:
但静态方法不可以调用非静态方法,因为静态方法和类一起加载,非静态方法需要实例化之后才加载(存在),静态方法无法调用还不存在的非静态方法:
形参和实参
形参指的是方法定义时给参数的名字,而实参指的是调用方法时实际传入的参数值。如下所示,a和b是形参,1和2是实参。
值传递和引用传递
- 值传递指的是调用方法时传入的参数是该变量的值,相当于复制了一个变量,在方法中对该变量进行改变,并不会改变原来变量的值。
- 引用传递指的是调用方法时传入的参数是该变量的引用,相当于传入的是同一个变量,在方法中对该变量进行改变,会改变原来变量的值。
Java是值传递,看一个例子就清楚了:
输出:
但要注意当涉及到对象的时候,情况会有一点不一样,看下面的例子:
输出:
这是因为对象属于引用数据类型(数据类型中分为基本数据类型和引用数据类型),当一个变量是对象时,它的内存地址中存储的不是对象本身,而是这个对象的引用(即地址),所以当在方法中传入参数的时候,虽然Java是值传递,即会复制一份变量。但这里复制的是对象的引用,相当于复制了一份地址,由于地址不变,所以改变该变量,相当于改变原来的变量。
对象的创建与分析
类和对象的关系
对象的初始化与创建
例子1:通过new关键字创建Student的对象
- 首先定义Student类
2. 然后通过new关键字创建Student类的实例xiaoming和xiaohong。
输出:
例子2:构造器的使用
- 定义Person类,并定义了无参构造器和有参构造器。如果什么都不写,系统会定义一个无参的默认构造器,为属性分配默认值。String类型的默认值为null,int类型的默认值为0。
2.通过不传入参数和传入参数的方式分别使用无参构造器和有参构造器创建了两个不同对象。
输出:
- 一键生成构造器的快捷键:alt+insert
面向对象三大特性
封装
- 属性私有,通过关键词private来实现封装
例子:
1.创建一个学生类,其中包含名字和学号两个属性,属性名字通过private修饰符修饰。
2.在另一个类中试图访问学生的名字属性,出现红色字体报错,提示name是private属性,无法访问。
- get/set方法
提供一些公共(public)的可以操作私有属性的方法,约定俗成地将这些方法称为并定义为get/set方法。
例子:
1.在学生类中定义对name属性的get/set方法。
2.在其他类中就可以通过get/set方法来修改和访问name这个私有属性了。为什么拒绝直接访问而要设置get/set方法来提供访问呢?这是因为可以在get/set方法中做一些约束和判断,来限制对私有属性的操作。如设置只能对name赋值为String类型的值等。来防止将该属性篡改为非法值。
输出:
封装的意义
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 增加系统的可维护性
这些意义目前只需要稍微了解即可,在以后的学习中再慢慢体会加深理解。
继承
继承通过extends关键字来实现,子类继承父类,就会拥有父类的全部(除私有之外的)方法和属性。在IDEA中可以通过快捷键:Ctrl+H 查看类之间的继承关系。
- Object类
在java中所有类都默认继承object类,该类里写了很多基础方法,如toString,equals等 - super关键词
表示父类的,类似的关键词还有this,代表本身。
如下图所示,Student类继承了Person类,它的test方法中的name指的是方法中传入的参数,this.name指的是Student中的name属性,super.name指的是父类Person中的name属性。
在test方法中传入参数“卉火火”。
输出:
难点:构造器中的this和super
构造器可以有多个,每个构造器可以互相调用。调用自己的无参构造器通过this()来调用,调用自己的有参构造器通过this(参数)来调用。调用父类的无参构造器通过super来调用,调用父类的有参构造器通过super(参数)来调用。
例子1:通过super()调用父类构造器。
//父类
public class Person {
public Person() {
}
}
//子类
public class Student extends Person{
Student(){
super();
}
}
例子2:通过this()调用子类本身的构造器。
//子类,Student
public class Student extends Person{
Student(){
this("huihui");
}
Student(String name){
this.name=name;
}
String name;
}
-
方法重写
只和非静态方法有关,无法重写静态方法。注意和方法重载相区分。方法重载表示的是方法名相同,但参数不同。方法重写指的是子类继承父类时,重新定义父类的方法。
方法重写的前提:
1.需要有继承关系,子类重写父类的方法。
2.方法名和参数列表必须相同
3.修饰符:范围可以扩大但不能缩小:public>protected>default>private
4.抛出异常的范围:可以被缩小,但不能扩大:ClassNotFoundException–>Exception(大)为什么需要重写:
1.父类的功能,子类不一定需要,或者不一定满足快捷键:Alt+Insert : override
多态
- instanceof
用于判断对象是否属于某个类型,如果返回的时true,则可以进行强制类型转换:如将父类转换为子类(向下转型),或将子类转换为父类(向上转型)。
抽象类和接口
抽象类
抽象类通过修饰词abstract来修饰:
接口
通过关键词interface(和class相对应)定义接口:
通过关键词implements(和extends相对应)实现接口:
实现接口的快捷键:Alt+Enter