javaSE_Day_009
15 面向对象的三大特征:继承
继承属于面向对象三大特征之一,也是编写代码中使用的最为广泛的特征。
国内为了更好的学习面向对象编程思想,在翻译面向对象三大特征的时候,将extends翻译成了国人更好理解的词语“继承”,但是这个单词的实际含义应该是“拓展”。
(1)说明:类中定义的属性或方法可能会出现大量的重复操作,这些操作其实是没有必要的,为了能够解决这类问题Java在面向对象中提供了继承。通过继承可以实现只定义一次属性和方法,其它类就可以得到这个属性和方法,而不用重复的定义。
- 可以利用继承这个特征来提高代码的复用性,减少冗余,提高相同代码的重复利用,并且还能够使类与类之间建立关系。
- 继承在Java中指的是“一个类”可以继承自“另一个类”,被继承的类叫做父类、超类、基类,继承其它类的类叫做子类。继承之后子类可以拥有父类中的所有可见属性(成员变量和成员方法),这样一来子类就无需再进行定义操作。
- Java继承中子类只能继承父类的公有属性和方法,不能继承父类的私有属性和方法。
(2)extends关键字
- 使用extends关键字,可以是类与类之间建立继承关系。
- 语法:
class 父类{ ... }
class 子类 extends 父类 {
//此时子类就继承了父类
//此时子类是无法继承父类的构造方法的,所以子类需要提供自身的构造方法
//子类可以继承父类所有"可见"属性和方法
//子类还可以定义自己类中属性和方法
}
- 继承基于某个父类的定义加以扩展,从而产生新的子类的定义,子类可以继承父类中定义的可见属性和方法,从而减少子类中定义的代码,增加开发效率。
(3)Java中继承必须要遵守的原则
- Java中类与类之间的继承是单一继承(单继承),不允许出现多继承(即一个子类只能有一个父类)。
- 虽然Java中不允许多继承,但是允许多重(层)继承,即一个子类只能有一个直接父类,但是可以有多个间接父类。
(4)继承的作用:
- 解决了多个类之间存在重复性属性和方法的定义(无需重复定义,只要有一个父类即可)。
- 不要为了属性或方法随意的继承,要满足客观现实规律。
- 例如不能用动物类继承人类中的名字属性。
- 不要为了属性或方法随意的继承,要满足客观现实规律。
- 继承可以表现出一个完整的类体系,使类与类之间的联系更加紧密,但随之而来的就是耦合问题。
- 继承中提供继承信息的是父类,父类属于提供基础信息(属性和方法)。子类在继承父类之后不仅可以得到父类的基础信息,而且还可以在这个基础上加以修改和拓展,所以子类的定义是比父类更加强大的。
16 方法重写
(1)说明:子类继承父类之后,子类可以得到父类的可见方法和属性,属性多使用在继承方法(父类定义好子类直接使用即可),当父类提供的方法不能满足子类的实现需求时,子类可以重新实现父类提供的方法,这个过程就叫做方法重写。
什么是重载?什么是重写?
这两个词听起来很像,但是本质上并没有任何关联。重写主要是针对于继承关系,当父类提供的方法无法满足子类的实现需求时,子类可以选择重新实现父类方法。重载主要是针对多态,方法的重载要求是方法名相同但是参数列表不同。
(2)子类重写父类方法的要求:
- 必须是继承关系,一定是子类重写父类中的方法。
- 成员变量的方法签名必须相同(方法签名:方法名+参数列表)。
- 子类方法的返回值类型和父类方法的返回值类型要么相同,要么是子类类型。
- 子类可以返回一个更加具体的类。
- 子类重写的方法有异常,这个异常的抛出要么和父类的异常抛出一直,要么是异常的子类。
- 子类重写方法时,方法的权限修饰符,要等于或大于父类原有方法的权限修饰符。
- 如果父类中方法使用以下修饰符修饰,子类无法重写父类的方法:
- static
- private
- final
17 super关键字
super关键字只能使用在子类中(Java中所有创建出来的类都是子类)。super关键字代表的是父类对象,其最大的作用就是在子类的有参构造方法中帮助子类初始化从父类继承而来的属性。
(1)说明:super关键字和this关键字类似,可以通过super关键字调用父类的属性和方法,而且还可以调用父类的构造方法,this关键字允许作为方法参数传递,但是super关键字不允许作为方法参数传递。
- super关键字只能使用在子类的构造方法和成员变量中,静态方法中不允许使用super关键字。
(2)super关键字相关操作:
super.成员变量:调用父类的成员变量
super.成员方法:调用父类的成员方法
super():调用父类无参构造方法
super(参数值):调用父类有参构造方法
(3)总结:super关键字在开发中最大的作用就是辅助子类有参构造方法对父类继承而来的属性进行初始化,其余的super.成员变量和super.成员方法调用基本使用不上。
18 子类实例化的过程
(1)说明:Java中类与类之间发生继承关系后,子类的实例化过程是遵守客观现实规律的。子类创建之前一定是先创建父类对象,再创建子类对象。子类在创建对象时会默认执行父类的无参构造方法,所以父类需要提供无参构造方法,子类才可以正常创建对象。
- 如果父类并没有提供无参构造方法,而是提供其余的构造方法,这种情况下,需要在子类构造方法中使用super关键字明确调用父类的构造方法,才可以正常创建子类。
19 final官架子
(1)说明:fianl关键字代表最终的、不可改变的。
- final关键字主要是作为一个修饰符存在,final关键字可以修饰“类、方法、变量“。
19.1 final关键字修饰类
(1)说明:如果使用final关键字修饰类,则这个类作为最终类存在,不可继承。
- 在开发中如果发现一个类不需要其他类来继承,就可以使用final进行修饰。
- final修饰的类可以继承其它类,成为其它类的子类。
(2)格式:
访问权限修饰符 final class 类名{
这个类允许做所有基础类的操作(属性,方法和构造方法都可以)
}
19.2 final关键字修饰方法
(1)说明:如果方法使用fianl关键字进行修饰,则这个方法只能被子类继承,不能被子类重写。
- 创建父类时,如果父类某个方法只想让子类继承不想让其重写,就可以使用final进行修饰。
(2)格式:
访问权限修饰符 **final** 返回值类型 方法名(参数列表){
方法体;
return;
}
19.3 final关键字修饰变量
(1)说明:Java中除了字面常量之外,可以使用final关键字修饰某个变量,这个变量就会成为定义常量。
- 开发中为了方法常量与变量定义,常量名字全部使用大写字母定义。
20 访问权限修饰符
(1)说明:Java中为了控制对属性和方法进行访问,提供了四个权限修饰符,这四个权限修饰符可以修饰不同东西。
(2)专门修饰类修饰符:修饰类的修饰符只有public(共有,在项目任意位置都可以进行访问)、default(包权限,仅限当前包内可以访问)
(3)修饰方法和属性:
| 访问权限修饰符 | 本类 | 同包 | 子类(本包子类和跨包子类) | 不同包 |
|---|---|---|---|---|
| private(私有的) | 可以访问 | 不可以访问 | 不可以访问 | 不可以访问 |
| default、package(默认的、包权限) | 可以访问 | 可以访问 | (本包子类可以访问)(跨包子类不可以访问) | 不可以访问 |
| protected(保护的) | 可以访问 | 可以访问 | 可以访问 | 不可以访问 |
| public(公有的) | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
- 对于现在的开发而言,修饰符仅使用public和private。
21 Objects类和Object类
21.1 Objects类
(1)说明:这个类是Java7中所提供的类,其作用是作为辅助Object类来进行安全判断的一个工具类。
- Objects工具类的核心方法:
| static boolean | isNull(object obj):判断参数引用类型是否为null值,如果为null,则返回true;如果不为null则返回false。 |
| static boolean | nonNull(object obj):判断参数引用类型是否不为null值,如果不为null值,则返回true;如果为null,则返回false。 |
21.2 Object类
(1)说明:Object类是Java语言中所有类的类(根类、超级父类),只要是Java语言中的类(不论是系统API,还是自己创建的)都是继承自Object(直接继承或间接继承)。
(2)Object类中的常见方法:
| 方法修饰符合返回值类型 | 方法名 | 解释 |
|---|---|---|
| protected void | finalize() | 当垃圾回收器确定不存在该对象的引用时,由对象垃圾回收器调用此方法(垃圾回收器GC),此方法是系统自动调用的,不需要手动调用。 |
| public Class | getClass() | 通过getClass获取字节码(.class)中对象。 |
| public int | hashCode() | 返回该对象的哈希码值(地址十六进制换算而来),hashCode还决定了对象在Hash表中存在的位置,不同的对象hashCode值一定不一样。 |
| public boolean | equals(Object obj) | 拿当前对象(this)和参数obj进行比较(equals方法是引用类型比较相等使用)。 |
| public String | toString() | 将打印的对象以特定字符串输出( 原则:getClass().getName()+"@"+Integer.toHexString(hashcode()) ) |
21.3 重写toString()方法
@Override
public String toString() {
//这个方法的返回值是一个字符串,所以你只要把结果拼接成字符串什么都行
return "学生的姓名:"+name+" 学生的年龄:"+age;
}
21.4 重写equals方法
@Override
public boolean equals(Object o) {
/*
只需要在这个方法内部完成,类中属性判断是否相等即可
最终结果是true证明属性相等 false 证明属性不相等
比较学生年龄和姓名是否完全相等
会用当前对象和传入参数对象进行你比较,谁调用这个方法谁就是当前对象,谁传入这个方法参数谁就是传入对象
stu1.equals(stu2); stu1就是当前对象的 stu2就是传入对象
传入对象是接受的是Object类型,父类对象是无法调用子类特有(子类自己定义)属性和方法
需要父类转换为子类,这操作类似于强制类型转换
*/
Student other = (Student)o;
//name是String类型,而String已经重写Object中equals方法,所以可以直接判断内容使用无需重写
return this.name.equals(other.name) && this.age == other.age;
}
21.5 重写hashCode方法
/*
现在的equals并不是完整重写,因为hashcode是在Java中表示引用类型内存地址
原则:如果使用equals比较两个引用类型的值为true,那么他们的hashcode值也要相等
hashcode是根据实际真实内容地址换算而来一个int类型数据,所以我们就需要概念这个地址以达到相等equals
的引用类型hashcode一致的问题
在重写equals的同时就要重写hashcode
你在equals中使用那些属性进行比较,那么利用他们来进行hashcode计算
原则:如果是引用类型 就调用对应hashcode值
如果是整数类型就直接计算 如果是小数 就为整数计算 如果是char类型就为十进制计算 如果boolean转 true=1 false=0
这个hashcode更改不会影响真实的内存地址,只是Java中展示地址一种体现
因为后续要学HashSet集合,这个集合的排重原则就是根据hashcode计算,所以不提供这个操作无法排重
*/
@Override
public int hashCode() {
return name.hashCode() + age;
}
浙公网安备 33010602011771号