文章目录
一、面向对象的概念
1.1 面向对象和面向过程的区别?
- 面向过程: 将问题分解成步骤,然后按照步骤实现函数,执行时依次调用函数。数据和对数据的操作是分离的。
- 面向对象: 将问题分解成对象,描述事物在解决问题的步骤中的行为。对象与属性和行为是关联的。
面对向象的优点是:具有封装、继承、多态的特性,因而容易维护、复用和扩展,可以设计出低耦合的系统;缺点是由于需要实例化对象,因此性能比面向过程低。
1.2对象和类的区别?
- 对象: 是现实世界中可以明确标识的实体,对象有自己独有的状态和行为。对象的状态由数据域的集合构成,对象的行为由方法的集合构成。
- 类: 是定义同一类型对象的结构,是对具有相同特征的对象的抽象。类是一个模板,用来定义对象的数据域和方法。可以从一个类创建多个对象,创建对象称为实例化。
也就是:类是对象的抽象,对象是类的实例。 通过new
来实例化一个对象。
代码如下:
//一个类
public class Person{}
//一个对象
new Person();
1.3面向对象的特征有哪些?
Java面向对象的三大特性:封装,继承,多态 、(抽象)
二、封装
2.1概念
概念:封装就是把过程和数据包装起来(属性私有化),对数据的访问只能通过调用已定义的方法。
封装好处:降低耦合、隐藏内部信息、只通过规定的方法访问数据。
封装关键字:private
、get/set
对外访问
举例:orm框架,操作数据库,我们就不需要关心链接是怎么建立的、sql是怎么执行的。只需要引入mybatis或者mybatis-plus,调用方法即可。
代码如下:
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;
}
}
2.2访问修饰符
java提供了四种访问权限,如下:
访问范围 | private | default(默认) | protected | public |
---|---|---|---|---|
同一个类 | 可访问 | 可访问 | 可访问 | 可访问 |
同一包中的其他类 | 不可访问 | 可访问 | 可访问 | 可访问 |
不同包中的子类 | 不可访问 | 不可访问 | 可访问 | 可访问 |
不同包中的非子类 | 不可访问 | 不可访问 | 不可访问 | 可访问 |
注意:
-
接口里的变量都隐式声明为
public static final
,而接口里的方法默认情况下访问权限为public
。 -
被声明为 private 的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为 private。声明为私有访问类型的变量只能通过类中公共的 getter 方法被外部类访问。
-
protected 可以修饰数据成员,构造方法,方法成员,不能修饰类(内部类除外)。接口及接口的成员变量和成员方法不能声明为 protected。
三、继承
3.1概念
概念:从现有类派生出新类,继承类被称为子类,被继承的类称为父类、基类。子类可以继承父类的方法和属性,并且可以修改或增加新的方法和属性。private属性和方法无法继承。
通过 extends
关键字,可以声明一个子类继承另外一个父类,子类可以直接访问父类的非私有化成员变量,访问父类的私有化成员变量可以使用super.方法()
。
继承好处:提高代码复用性、是多态的前提(类与类产生联系)。
代码如下:
//公共类
class SuperClass {
private int n;
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(int n)");
this.n = n;
}
}
// SubClass 类继承
class SubClass extends SuperClass{
private int n;
SubClass(){ // 自动调用父类的无参数构造器
System.out.println("SubClass");
}
public SubClass(int n){
super(300); // 调用父类中带有参数的构造器
System.out.println("SubClass(int n):"+n);
this.n = n;
}
}
//测试
public class TestSuperSub{
public static void main (String args[]){
System.out.println("------SubClass 类继承开始------");
SubClass sc1 = new SubClass();
SubClass sc2 = new SubClass(100);
System.out.println("------SubClass2 类继承结束------");
}
}
/*结果:
------SubClass 类继承开始------
SuperClass()
SubClass
SuperClass(int n)
SubClass(int n):100
------SubClass2 类继承结束------
*/
3.2特点
- 通过子类对象既可以调用自身的非private修饰的成员,也可以调用父类的非private 修饰的成员
- 父类不可以访问子类特有成员,即使是共有的。
- 子类的对象调用成员变量的时候,子类自己有,使用子类,子类自己没有则调用父类,出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用 super 关键字。
- 子类的对象调用方法的时候,子类自己有,使用子类,子类自己没有调用的父类,出现与父类一模一样的方法时,会出现覆盖操作,也称为 override 重写、覆盖。
3.3重写Overriding与重载Overloading的区别?
重载(Overloading):
在同一个类中,多个方法具有相同的方法名,不同的参数列表(数量、类型、顺序)。与返回值类型,修饰符无关,发送在编译时。
重写(Overriding):
发生在子父类中,子类重写父类的方法,重写的方法的访问修饰符不能严于父类、返回值是其父类的或者父类的子类、抛出的异常范围小于等于父类、相同的方法名、相同的参数列表。如果父类的访问修饰符为private则子类不能重写该方法。final 修饰的方法不允许在子类中覆盖;
3.4什么时候用重载,什么时候用重写?
(1)重载是多态的集中体现,在类中,要以统一的方式处理不同类型数据的时候,可以用重载。
(2)重写的使用是建立在继承关系上的,子类在继承父类的基础上,增加新的功能,可以用重写。
(3)简单总结:
重载是多样性,重写是增强剂;
目的是提高程序的多样性和健壮性,以适配不同场景使用时,使用重载进行扩展;
目的是在不修改原方法及源代码的基础上对方法进行扩展或增强时,使用重写;
3.5super与this
- super关键字可以在子类的构造方法中显示地调用父类的构造方法,super()必须为子类构造函数中的第一行。
- super可以用来访问父类的成员方法或变量,当子类成员变量或方法与父类有相同的名字时也会覆盖父类的成员变量或方法,这个时候要想访问父类的成员变量或方法只能通过super关键字来访问,子类方法中的super.方法名()不需要位于第一行。
- this关键字指向的是当前对象的引用,用来区分成员变量和局部变量(重名问题)
- this() 不能使用在普通方法中 只能写在构造方法中。
- 必须是构造方法中的第一条语句。
四、多态
4.1概念
概念:是指对象的多种形态 。
多态的调用格式:
- 普通类多态定义的格式:
父类 变量名 = new 子类();
- 抽象类多态定义格式:
抽象类 变量名 = new 抽象类子类();
- 接口多态定义的格式:
接口 变量名 = new 接口实现类();
多态存在的三个必要条件:继承、重写、父类引用指向子类对象。例如:Parent p = new Child();
多态好处:降低耦合、可扩展性、灵活、简化。
多态缺点:无法调用子类特有的方法。
注意:多态有编译时多态,运行时多态。
-
编译时多态: 对于方法重载而言,虽然多个方法的方法名相同,但是我们的编译器,可以根据方法调用代码推断出,所要调用的那个方法的方法签名,从而根据方法签名(
jvm
唯一的),确定要调用的方法 。 -
运行时多态: 在编译器编译的时候,无法知道,具体调用的是哪个方法的代码,只有当
jvm
具体真正执行到调用代码的地方,jvm
才能知道调用的究竟是哪个方法 。
4.2多态的转型
1.向上转型
概念:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。(也叫:隐式转型、自动转型)。
格式:父类类型 变量名 = new 子类类型()
。
使用: 当不需要面对子类类型时,或者使用父类的方法就能完成相应的操作,这时就可以使用向上转型 。
2.向下转型
概念: 一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。
格式:子类类型 变量名 = (子类类型) 父类类型的变量;
。
使用: 当要使用子类特有功能时,就需要使用向下转型。
问题:在向下转型时容易发生 ClassCastException
类型转换异常。在转换之前必须做类型判断。
4.3 instanceof 关键字
作用: 可以通过 instanceof
关键字来判断是否能够对象转化。也就是,一个引用型的变量,是不是这个类型的对象,提高向下转型的安全性;
格式: boolean b = 对象 instanceof 数据类型;
返回 true / false
五、克隆
(1)什么要使用克隆?
想对一个对象进行复制,又想保留原有的对象进行接下来的操作,这个时候就需要克隆了。
(2)如何实现对象克隆?
实现Cloneable接口,重写clone方法;
实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深克隆。
BeanUtils,apache和Spring都提供了bean工具,只是这都是浅克隆。
(3)深拷贝和浅拷贝区别是什么?
浅拷贝:仅仅克隆基本类型变量,不克隆引用类型变量;
深克隆:既克隆基本类型变量,又克隆引用类型变量;
六、类
6.1类的概念
1.普通类:
-
类是定义同一类型对象的结构,是对具有相同特征的对象的抽象。
-
类是一个模板,用来定义对象的数据域和方法。可以从一个类创建多个对象,创建对象称为实例化。
-
类的创建者负责在创建新的类时,只暴露必要的接口给客户程序员,同时隐藏其它所有不必要的信息。(Java提供了三个显示关键字来控制访问权限。)
例如:
public class User {
// ...
}
2.抽象类
- 用
abstract
关键字来修饰一个类时,这个类叫作抽象类。 - 抽象类是它的所有子类的公共属性的集合,是包含一个或多个抽象方法的类。
- 抽象类可以看作是对类的进一步抽象。在面向对象领域,抽象类主要用来进行类型隐藏。
例如:
public abstract class User {
// ...
}
6.2普通类和抽象类
- 抽象类不能被实例化;
- 抽象类可以有抽象方法,只需申明,无须实现;
- 有抽象方法的类一定是抽象类;
- 抽象类的子类必须实现抽象类中的所有抽象方法,否则子类仍然是抽象类;
- 抽象方法不能声明为静态、不能被static、final修饰。
例如:
public abstract class User {
// ...
}
6.2接口和抽象类
(1)接口
- 接口使用interface修饰;
- 接口不能实例化;
- 类可以实现多个接口;
- java8之前,接口中的方法都是抽象方法,省略了public abstract。
- java8之后,接口中可以定义静态方法,静态方法必须有方法体,普通方法没有方法体,需要被实现;
(2)抽象类
- 抽象类使用abstract修饰;
- 抽象类不能被实例化;
- 抽象类只能单继承;
- 抽象类中可以包含抽象方法和非抽象方法,非抽象方法需要有方法体;
- 如果一个类继承了抽象类,①如果实现了所有的抽象方法,子类可以不是抽象类;②如果没有实现所有的抽象方法,子类仍然是抽象类。