Java基础学习笔记整理了我从零开始学习Java时所学习到的内容。
以下内容参考尚硅谷Java教程。
六.面向对象(中)
1 面向对象的特征二:继承性
1.1 为什么要有继承性?
- 减少代码冗余,提高代码的复用性;
- 便于功能的拓展;
- 为之后的多态性的使用,提供了前提。
1.2 继承的格式
class A extends B{}
A:子类、派生类、subclass
B:父类、超类、superclass
1.3 继承的作用
- 一旦子类A继承了父类B后,子类A就获取了父类B中声明的所有的属性和方法。
特别的,父类中声明为private的属性和方法,子类继承父类后,仍然认为子类获取了父类中私有的结构。只是因为封装性的影响,使得子类无法调用父类的私有结构。
- 子类继承父类以后,还可以声明自己特有的属性和方法:实现功能的拓展。
子类和父类的关系,不同与子集和集合的关系。
1.4 Java中继承性的说明
- 一个类可以被多个子类继承;
- Java中类的单继承性:一个类只能有一个父类;
- 子父类是相对的概念;
- 子类直接继承的父类,称为:直接父类。子类间接继承的父类称为:间接父类;
- 子类继承父类后,子类就获取了父类中声明的所有的属性和方法。
1.5 java.lang.Object类的理解
- 如果我们没有显式的声明一个类的父类,则此类直接继承于java.lang.Object类;
- 所有的java类(除java.lang.Object类以外)都直接或间接继承于java.lang.Object类;
- 所有的java类都具有java.lang.Object类声明的功能。
2 方法的重写
2.1 重写的定义
子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作。
2.2 重写的应用
重写以后,当创建子类对象后,通过子类对象调用子父类中同名同参数的方法时,实际执行的是子类重写父类的方法
2.3 举例
class Circle{
public double findArea(){}//求圆面积
}
class Cylinder extends Circle{
@override
public double findArea(){}//求圆柱表面积
}
2.4 重写的规则
方法的声明:
权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型{
方法体;
}
约定俗成:子类叫重写的方法,父类中叫被重写的方法。
- 子类重写的方法的方法名和形参列表与父类中被重写的方法的方法名和形参列相同;
- 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符;
特殊情况:子类不能重写父类中声明为private权限的方法 - 返回值类型:
- 父类被重写的方法返回值类型是void,则子类重写的方法的返回值类型只能是void;
- 父类被重写的方法返回值类型是A类型,则子类重写的方法的返回值可以是A类或者A类的子类;
- 父类被重写的方法返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(也必须是double)。
- 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
子类和父类同名同参数的方法要么声明都为非static的
面试题:如何区分方法的重写和重载
- 从概念上看:
重载:在同一个类中声明方法名相同形参列表不同的方法
重写:子类对父类中同名同参数的方法进行重写
- 重载和重写的具体规则
- 重载:不表现为多态性
重写:表现为多态性
3 关键字super
super可以理解为:父类的
3.1 可以用来调用的结构
属性、方法、构造器
3.2 super调用属性、方法
- 我们可以在子类的方法或者构造器中,通过"super.属性"或"super.方法"的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯忽略"super.";
- 特殊情况:当子类和父类中定义了同名的属性和方法时,想要调用在父类中被声明的属性和方法时,就需要显式的使用"super.属性"或"super.方法"。
3.3 子类对象实例化过程
- 从结果上看
子类继承父类后,就获取了父类中声明的属性或方法。
创建子类的对象,在堆空间中,就会加载父类中声明的属性 - 从过程上看
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的构造器,…直到调用了java.lang.Object类中空参的构造器为止。
正因为加载过所有的父类的结构,所以才可以看见内存中父类的结构 ,子类对象才可以考虑进行调用。
- 强调说明:
虽然创建子类对象时,调用了父类的构造器,但是自始自终就创建过一个对象,即new的子类对象。
4 面向对象的特征二:多态性
4.1 多态性的理解
可以理解为一个事物的多种形态。
多态性:父类的引用指向子类的对象(或者子类的对象赋给父类的引用)
举例:
Person p = new Man();
Object obj = new Date();
4.2 多态性的使用
虚拟方法调用
有了对象的的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
总结:编译看左边,运行看右边。
使用前提:
类的继承关系
方法的重写
4.3 多态性的应用举例
4.4 多态性使用的注意点
多态性只适用于方法,不适用于属性。
4.5 关于向上转型和向下转型
4.5.1 向上转型:多态
4.5.2 向下转型:
为什么使用向下转型:
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致
- 编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。
- 如何调用子类特有的属性和方法?使用强制类型转换符:()
注意点:
使用强转时,可能会出现ClassCastException的异常。
为了避免在向下转型时出现ClassCastException的异常,我们在进行向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
使用:
- a instanceof A:判断对象a是否是类A的实例。
- 如果 a instanceof A 返回true,则a instanceof B 也返回true。其中,类B是类A的父类。
- 要求x所属的类和类A必须是子类和父类的关系,否则编译错误。
番外:面试题
- 谈谈你对多态性的理解?
①实现代码的通用性;
②Object类中定义的public boolean equals(Object obj){};
JDBC:使用Java程序操作;
③抽象类、接口的使用体现了多态性。
- 多态是编译时行为还是运行时行为?
运行时行为。
5 Object类的使用
5.1 Object类的说明
- Object类是所有Java类的根父类;
- 如果在类的声明中未使用extends关键字指明其父类,则默认继承于Java.lang.Object类;
- Object类中的功能(属性、方法)具有通用性:
属性:无
方法:equals() / toString() / getClass() 等 - Object类只声明了一个空参的构造器。
5.2 equals()方法
5.2.1 equals()的使用
- 是一个方法而非运算符;
- 只能适用于引用数据类型;
- Object类中的equals():
public boolean equals(Object obj){
return (this == obj);
}
说明:Object类中定义的equals()和==的作用是相同的:都是比较对象的地址值是否相同;
- 像String、Date 、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的是两个对象的“实体内容”是否相同;
- 通常情况下我们也会对equals()进行重写。
5.2.2 如何重写equals()
- 手动重写
class User{
String name;
int age;
public boolean equals(Objcet obj){
if(obj == this){
return true;
}
if(obj instanceof User){
User u = (User)obj;
return this.age == u.age && this.name.equals(u.name);
}
return false;
}
}
}
5.2.3 开发中如何重写equals()
自动生成
5.3 toString()方法
5.3.1 toString()的使用:
- 当我们输出一个对象的引用时,实际上就是调用当前对象的toString();
- Object类中toString()的定义:
public String toString(){
return getClass().getName() + "@"+Integer.toHexString(hashCode());
}
- 像String、Date、File、包装类等都重写了Object类中的toString()方法,使得在调用这些对象的toString()时,返回实体内容信息;
- 自定义类也可以重写toString()方法。
5.3.2 toString()的重写
@Override
public String toString(){
return "Customer [name"+name+",age="+age+"]";
}
也可以自动生成toString()方法。
6 包装类
6.1 包装类的意义
为了使基本数据类型的变量具有类的特征,引入包装类。
6.2 基本数据类型与其对应的包装类
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
6.3 类型间的相互转换
基本数据类型<—>String<—>包装类(三角形双箭头
基本数据类型<—>包装类:自动装箱与自动拆箱
基本数据类型、包装类—>String:调用String重载的valueOf(Xxx xxx)
String—>基本数据类型、包装类:调用包装类的parseXxx(String s)
- 转换时,可能会报NumberFormatException
6.4 应用场景
Vector类中关于添加元素,只定义了形参为Object类型的方法:v.addElement(Object obj)。