继承
一、什么是继承
为什么需要继承:多个类中存在相同的属性和行为的时候,讲这些内容抽取到一个单独的一个类 中。那么多个类无需再定义这些属性和行为,只要继承即可。这个单独的类称作父类,其他类叫做子 类。可满足 is - a 的关系即可用继承实现。使用extends实现继承。作用:使用继承的出现减少了代码冗余,提高的了代码的复用性。 继承的出现,更有利于功能的扩展
java是单继承和多层继承。不能多继承。一个子类只能继承一个父类。一个父类可以有多个子类。
二、什么能继承
访问修饰符 | 本类 | 同包 | 子类 | 其他任意地方 |
---|---|---|---|---|
private | √ | |||
默认(friendly|default) | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
对于class的访问权限只可以用public和default(缺省)。public类可以在任意地方被访问,但default类只可以在同包中被访问。
三、super用法
在Java类中使用super来调用父类中的指定操作:
super可用于访问父类中定义的属性
super可用于调用父类中定义的成员方法
super可以用在子类构造器中调用父类中的构造器
尤其当父子类出现同名成员时,可以用super表明调用的是父类中的成员
super.父类方法名(参数列表);super(参数列表);super.父类属性
子类构造方法需调用父类构造方法时,需要放在第一行
四、super与this的区别
区别 | this | super |
---|---|---|
访问属性 | 访问本类中的属性,如果本类中没有,就在父类中找该属性 | 直接访问父类属性 |
调用方法 | 访问本类中的方法,如果本类中没有,就在父类中找该方法 | 直接访问父类方法 |
调用构造方法 | 调用本类的构造方法其他方法,必须放在首行 | 调用父类中的构造方法,必须放在首行 |
子类中的构造方法默认有super();,但父类中若没有无参构造方法,需要自己调用super(参数列表);但如果子类构造方法中有this调用了自己的构造方法,便不存在super调用父类的构造方法。,不管几次调用,一定要调用父类中的构造方法(可以在最后调用的构造方法中添加super)。
五、重写
重载:同一个类中,方法名相同,参数列表不同。与访问惨饰符和返回值类型都无关。
重写:发生在继承关系中,子类去重写父类的方法。方法名相同,参数列表相同,访问修饰符不能比父类的严格,返回值类型相同或是父类方法返回值类型的子类。
六、抽象类
- 抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。
- 抽象类不可以创建实例,原因:调用抽象方法没有意义。
- 只有覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。否则该子类还是一个抽象类。之所 以继承,更多的是在思想,是面对共性类型操作会更简单.
- 抽象类中的方法不一定都是抽象方法.
- 有构造函数,虽然不能给自己的对象初始化,但是可以给自己的子类对象初始化。
- 类和抽象类它们都是用来描述事物的。它们之中都可以定义属性和行为。
- abstract一般不和final、private、static共存
多态
同一种事物,由于条件不同,产生的结果也不同 生活中的多态:同一个引用类型,使用不同的实例而执行不同操作
编译是父类的类型,运行是子类的方法称为–动态绑定
指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
多态的两种表现形式:重载与重写
多态的必要条件: 要有继承 要有重写 父类的引用指向子类对象
package 多态;
//接口
public abstract class Pet {
public void eat(){
System.out.println("会吃");
}
public abstract void sport();
}
//实现类
public class Dog extends Pet{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sport() {
System.out.println("狗会跳");
}
public void function(){
System.out.println("会看家");
}
}
//实现
public class test {
public static void main(String[] args) {
Pet pet = new Dog();
pet.eat();
pet.sport();
//pet.function();报错,编译看左边,执行看右边
if (pet instanceof Dog){
Dog dog = (Dog) pet;//向下转型
dog.function();
}
}
}
父类转换为子类:在进行向上转型后,会发现 子类中特有的属性与方法已经丢失,也就是只能调用父类中 声明的方法,再运行的时候,实际执行的是子类重写后的方法,属性不存在覆盖。此时需要进行向下转型 (强制类型转化)。(容易抛出ClassCastException异常)。为了防止以上异常的出现,可以使用 instanceof判断该实例究竟是哪个类的类型。
向上转型——子类转换为父类,自动进行类型转换
向下转型——父类转换为子类,结合instanceof运算符进行强制类型转换
一、==和equals 方法
==:判断的是两个数据的地址、值…都要相同
equals:方法一般需要自己根据需要进行改写,比如判断一个类的两个对象的是否相等,只需要判断对象中的某些属性是否相等即可,并不要求地址…处处相等
public boolean equals(Object o) {
if (this == o) return true;//判断两个对象是否是同一个对象
if (o == null || getClass() != o.getClass()) return false;//判断两个对象是否是同一个类
Dog dog = (Dog) o;
return age == dog.age;//如果一个类的两个对象需要对比时,我们只需要对比对象中的某些值是否相等即可
}
二、toString()方法重写
package 多态;
class person{
int age;
String name;
}
public class test {
public static void main(String[] args) {
person per = new person();
System.out.println(per);
}
}
//输出:多态.person@66d3c617
//对toString()方法重写
package 多态;
class person{
int age;
String name;
@Override
public String toString() {
return "姓名是:"+name+"\n"+"年龄是:"+age;
}
}
public class test {
public static void main(String[] args) {
person per = new person();
System.out.println(per);
}
}
//输出:
//姓名是:null
//年龄是:0