继承
1. 何为继承
继承是面向对象的三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法。
继承是指在原有类的基础上,进行功能扩展,创建新的类型。
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
JAVA中类只有单继承,没有多继承!
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
子类和父类之间,从意义上讲应该具有"is a"的关系。
extends的意思是“扩展”,子类是父类的扩展。
2. 继承的优点和缺点
继承好处:
实现了数据和方法的共享
提高了代码的复用性(多个类相同的成员可以放到同一个类中)
提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
提高了代码的可扩展性
继承弊端
继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟看变化,削弱了子类的独立性
3. Object类
Object类是Javajava.lang
包下的核心类,Object类是所有类的父类,何一个类时候如果没有明确的继承一个父类的话,那么它就是Object的子类;
- clone()
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
- getClass()
final方法,返回Class类型的对象,反射来获取对象。
- toString()
该方法用得比较多,一般子类都有覆盖,来获取对象的信息。
- finalize()
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
- equals()
比较对象的内容是否相等
- hashCode()
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
- wait()
wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
其他线程调用了该对象的notify方法。
其他线程调用了该对象的notifyAll方法。
其他线程调用了interrupt中断该线程。
时间间隔到了。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。
- notify()
该方法唤醒在该对象上等待的某个线程。
- notifyAll()
该方法唤醒在该对象上等待的所有线程。
Object类的常用方法
toString方法
toString():取得对象信息,返回该对象的字符串表示
在使用对象直接输出的时候,默认输出的是一个对象在堆内存上的地址值;如若要输出该对象的内容,则要覆写toString()
方法
覆写Person中的toString()
方法
equals方法
equals():对象比较
String类对象比较 使用的是 equals()方法,实际上String类的equals()方法就是覆写 Object类中的equals()方法
基本数据类型的比较用 == (如: a == 3,b == 4, a == b,比较的是值是否相等)
引用类型数据比较:调用 equals()方法进行比较直接调用
equals()方法默认进行比较的是两个对象的地址。
在源码中,传递来的Object对象和当前对象比较地址值,返回布尔值。
但是,new一下就会在堆上创建新空间,两个对象地址自然不会相同,所以为false。
但是在判断两个对象是否相等时,比如要判断一个Person类的两个对象的姓名是否相同时,此时要重新覆写equals()
还是上面的例子,覆写equals()方法
所以,引用类型的数据在进行比较时,应该先覆写equals()
方法,不然比较的还是两个对象的堆内存地址值,必然不会相等.
4. 方法重写
子类继承父类,继承父类当中的方法,但是父类中的方法并不一定能满足子类中的功能需要,所以子类中需要把方法重写。
在继承关系中,方法名称一样,参数列表也一样。也叫:覆盖,覆写
方法重写只存在于子类和父类(包括直接父类和间接父类)之间。在同一个类中方法只能被重载,不能被重写.
静态方法不能重写
a. 父类的静态方法不能被子类重写为非静态方法,编译会出错
b. 父类的非静态方法不能被子类重写为静态方法,编译会出错
c. 子类可以定义与父类的静态方法同名的静态方法(但是这个不是覆盖
私有方法不能被子类重写,子类继承父类后,是不能直接访问父类中的私有方法的,那么就更谈不上重写了。
方法重写规则
方法名必须相同
参数列表必须相同
访问控制修饰符可以被扩大,但是不能被缩小
public > protected > default > private
范围:
public----哪里都可以
protect----同包/子类(子类可以是不同包下的)
default—同包
private-----同类
注:一般情况下,重写的方法会和父类中的方法的声明完全保持一致,只有方法的实现不同。(也就是大括号中代码不一样)
@Override:写在覆写代码前面,用来检测是不是有效的正确覆盖重写 。
抛出异常类型的范围可以被缩小,但是不能被扩大。
ClassNotFoundException --> Exception
返回类型可以相同,也可以不同,如果不同的话,子类重写后的方法返回类型必须是父类方法返回类型的子类型
例如:父类方法的返回类型是Person,子类重写后的返回类可以是Person也可以是Person的子类型。
方法重写和方法重载区别
方法重载:
1、同一个类中
2、方法名相同,参数列表不同(参数顺序、个数、类型)
3、方法返回值、访问修饰符任意
4、与方法的参数名无关
方法重写:
1、有继承关系的子类中
2、方法名相同,参数列表相同(参数顺序、个数、类型),方法返回值相同
3、访问修饰符,访问范围需要大于等于父类的访问范围
4、与方法的参数名无关
5. super关键字
super 关键字的用法和 this 关键字的用法相似
-
this:代表本类对象的引用(this关键字指向调用该方法的对象一般我们是在当前类中使用this关键字所以我们常说this代表本类对象的引用)
-
super:代表父类存储空间的标识(可以理解为父类对象引用)
关键字 访问成员变量 访问构造方法 访问成员方法 this this.成员变量
访问本类成员变量this(...)
访问本类构造方法this.成员方法(...)
访问本类成员方法super super.成员变量
访问父类成员变量super(...)
访问父类构造方法super,成员方法(...)
访问父类成员方法例如:定义一个父类Fu public class Fu { public int age = 10; } 定义一个子类Zi public class Zi extends Fu { public int age = 20; public void show() { int age = 30; System.out.println(age); // 30 // 访问本类中的成员变量age System.out.println(this.age); // 访问Fu类中的成员变量age System.out.println(super.age); } }
6. final关键字
final关键字代表最终、不可改变的。
常见四种用法:
1. 可以用来修饰一个类
2. 可以用来修饰一个方法
3. 还可以用来修饰一个局部变量
4. 还可以用来修饰一个成员变量
final修饰类:太监类,没有儿子
1)当final关键字用来修饰一个类的时候,格式:
public final class 类名称 { // ... }
含义:当前这个类不能有任何的子类。(太监类)
注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子。)
final修饰方法
1.含义:
当final关键字用来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写。
2.格式:
修饰符 final 返回值类型 方法名称(参数列表) {
// 方法体
}
3.注意事项:
对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。有抽象方法的abstract类被继承时,其中的方法必须被子类Override,而final不能被Override。
final修饰局部变量
对于基本类型来说,不可变说的是变量当中的数据不可改变
对于引用类型来说,不可变说的是变量当中的地址值不可改变
final修饰成员变量
对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变。
由于成员变量具有默认值,所以用了final之后必须手动赋值,不会再给默认值
对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。二者选其一
必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值。
如果选择在构造方法中赋值,则要把setname( )函数取消掉
标签:重写,继承,子类,对象,父类,方法,final From: https://www.cnblogs.com/zpjd/p/18342998