1.继承(extend)
1.1 格式:
class 父类{
....
}
class 子类 extend 父类{
...
}
1.2 继承后的特点
1.成员变量
如果子类和父类中没有重名的成员变量,则不受影响,如果有的话要使用关键字 super
public class fu {
int num=5;
}
public class Zi extends fu {
int num1=6;
public void show(){
System.out.println(num);
System.out.println(num1);
}
public static void main(String[] args) {
Zi zi=new Zi();
zi.show();//5 6
}
}
此情况,子类和父类中没有重名的成员的变量,相互没有影响。
如果子类和父类中有重名的成员变量的情况:
public class fu {
int num=5;
}
public class Zi extends fu {
int num=6;
public void show(){
System.out.println(num); // 6
System.out.println(super.num); //5
}
public static void main(String[] args) {
Zi zi=new Zi();
zi.show();
}
}
此种情况,在子类中要想调用父类的成员变量,就要借用super关键字。
super.成员变量 调用父类的成员变量
this.成员变量 调用本类的成员变量。
2 .成员方法
如果子父类中的成员方法不重名,则没有影响。如果出现了重名的成员方法,这时的访问是一种特殊的情况,叫做方法重写。
方法重写:子类中出现和父类一样的方法(返回值,方法名,参数都相同),会出现覆盖重写的效果,在子类中会重新实现该方法。用于方法的更新。
public class fu {
public void show(){
System.out.println("父类的show方法");
}
}
public class Zi extends fu {
@Override
public void show(){
super.show();
System.out.println("子类show方法更新了");
}
public static void main(String[] args) {
Zi zi=new Zi();
zi.show(); //父类的show方法 子类show方法更新了
}
}
注: 子类方法覆盖重写父类方法时,必须保证权限要大于父类方法的权限
子类方法覆盖重写父类方法时,返回值类型、函数名、参数列表要保持一样。
3 构造方法
构造方法的定义格式和作用:
构造方法的名字是和类名一致的,所以子类无法继承父类的构造方法。
构造方法的作用是初始化成员变量的。因此子类在初始化成员变量的过程中,必须先执行父类的初始化成员变量的动作。在子类的构造方法中有一个默认的super(),该方法表示调用父类的构造方法,在父类的成员变量初始化之后,子类才能进行初始自己的成员变量。如果在子类的构造方法中不写super(),系统会默认赠送一个,写了就按照写的方法执行。
public class fu {
int n;
public fu() {
System.out.println("父类的构造方法");
}
}
public class Zi extends fu {
int m;
public Zi() {
super(); //不写系统会赠送一个无参的super()
System.out.println("子类的构造方法执行了");
}
public static void main(String[] args) {
Zi zi=new Zi(); //父类的构造方法 子类的构造方法执行了
}
}
构造方法的访问
this(.....) 本类的构造方法
super(...) 父类的构造方法
this()和super() 都必须要在构造方法的 第一行,所以他们不能同时出现。
2.抽象类
2.1定义:
包含抽象方法的类叫做抽象类。抽象方法是指没有方法体的方法。
2.2 abstract 关键字的使用格式
抽象方法:
使用abstract关键字修饰的方法就是抽象方法,抽象方法中只包含一个方法名,没有方法体。
格式 : 修饰符 abstract 返回值类型 方法名 (参数列表);
例: public abstrac void run();
抽象类:
如果一个类包含抽象方法,那么该类必须是抽象类。
格式:abstract class 类名字{ }
例:public abstrac class Animal{
public abstrac void run();
}
2.3 抽象类的使用
继承抽象类的子类,必须要覆盖重写抽象类中所有的抽象方法。
public abstract class fu {
public abstract void run();
}
public class Zi extends fu {
public void run(){
System.out.println("重写了抽象父类中的抽象方法");
}
public static void main(String[] args) {
Zi zi=new Zi();
zi.run(); //重写了抽象父类中的抽象方法
}
}
2.4 注意事项
1. 抽象类无法直接创建对象
2.抽象类中,可以有构造方法,是提供给子类创建对象时,初始化父类成员变量使用的。
3.抽象类中,不一定含有抽象方法,但是含有抽象方法的类一定是抽象类。
4.抽象类的子类必须覆盖重写父类中所有的抽象方法。
3.接口
3.1 概念:
接口是Java语言中的一种引用类型,是方法的集合,接口的内部封装了方法,包括抽象方法、默认方法、静态方法和私有方法。 接口的定义,与类的定义方式相似,使用的是interfa关键字,它也会被编译成.class文件,但是要明确接口不是类,它是另一种引用数据类型。
引用数据类型:数组、类、接口
接口的使用,它不能直接创建对象,需要被类实现(interface)。一个实现接口的类,可以看作是接口的子类,它必须要重写接口中的所有抽象方法,才能实例化。
3.2 接口的定义格式
public interface 接口名称{
//抽象方法
//默认方法
//静态方法
//私有方法
}
接口中含有抽象方法:使用abstrac关键字修饰,关键字可以省略,没有方法体,该方法提供给子类实现使用。
public interface 接口名称{
public abstract void method();//抽象方法
}
接口中含有默认方法和静态方法:
默认方法使用default 关键字修饰,不可省略,可以供子类调用或者子类重写。
静态方法使用static 关键字修饰,供接口直接调用。
public interface 接口名称{
public default void method1(){ 执行语句} //默认方法
public statict void method2(){ 执行语句} //静态方法
}
接口中含有私有方法和静态私有方法:
私有方法使用private关键字修饰,供接口中的默认方法或者静态方法调用。
public interface 接口名称{
private void method(){执行语句} //私有方法
}
3.3 接口的基本实现
类与接口之间的关系为实现关系,类实现接口,使用implement 关键字,该类称为接口的实现类,也叫接口的子类。
如果实现类不是抽象类,就必须重写接口中所有的抽象方法,也会继承接口的默认方法,对这些默认方法,可以直接调 用,也可以重写。
接口中含有抽象方法的实现:
public interface interfa {
public abstract void method1();//不省略
public void method2();//省略abstr
void method3();//全省略
}
public class realize implements interfa {
@Override
public void method1(){
System.out.println("重写第一个抽象方法");
}
@Override
public void method2(){
System.out.println("重写第二个抽象方法");
}
@Override
public void method3(){
System.out.println("重写第三个抽象方法");
}
public static void main(String[] args) {
realize r=new realize();
r.method1(); //重写第一个抽象方法
r.method2(); //重写第二个抽象方法
r.method3(); //重写第二个抽象方法
}
}
含有默认方法的实现:可以被继承,可以重写,但是只能通过实现类的对象来调用。
public interface interfa {
public default void method1(){
System.out.println("接口中的默认方法1");
}
default void method2(){ //默认方法中public可以省略 ,default不可省略
System.out.println("接口中的默认方法2");
}
}
public class realize implements interfa {
@Override
public void method1(){
System.out.println("重写了默认方法1");
}
public static void main(String[] args) {
realize r=new realize();
r.method1();//重写了默认方法1
r.method2(); //接口中的默认方法2
}
}
含有静态方法的实现:静态和.class文件相关,只能通过接口名调用,不能通过实现类的类名或者实现类的对象调用
public interface interfa {
public static void method1(){ //public可省
System.out.println("接口中的静态方法");
}
}
public class realize implements interfa {
//实现类没法重写接口中的静态方法
public static void main(String[] args) {
realize r=new realize();
//r.method1(); 错误写法 接口中静态方法,只能通过接口名称调用
interfa.method1();//接口中的静态方法
}
}
含有私有方法的使用: 私有方法可供默认方法调用。 静态私有方法可供默认方法和静态方法调用
如果接口中有多个默认方法,并且默认方法中有重复的内容,那么就可以把重复的内容抽取出来,封装在私有方法中,简化代码的冗余。
public interface interfa {
private void method1(){
System.out.println("私有方法1");
}
private static void method2(){
System.out.println("静态私有方法2");
}
default void method(){
method1();//默认方法可以调用接口的私有方法
method2();//默认方法可以调用接口的静态私有方法
}
static void method3(){
method2();//静态方法只能调用接口中的静态方法
}
}
3.4 接口的多实现
一个类可以实现多个接口
格式:class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【不重名时可选】
}
注: 1.在实现多个接口中,必须在实现类中覆盖重写每个接口中的所有抽象方法,如果不同接口中有重名的抽象方法,只需 要重写一次即可。
2.在实现多个接口中,有多个默认方法时,实现类都可以继承使用,如果接口中的默认方法有重名的情况,那么在实现 类中必须要重写该重名的方法。
3. 静态方法,多个接口中,存在同名的静态方法并无影响,因为静态方法只能通过接口名称调用。
4 当一个类继承一个父类同时又实现多个接口时候,当父类中的成员方法和接口中的默认方法重名时,子类就会就近选 择执行父类中的成员方法。
5.一个接口可以继承多个接口,使用extends关键字,如果父类口中有重名的默认方法,那么早子接口中要重写该默认方 法。
6.接口中无法定义成员变量,但是可以定义常量使用用public static final修饰,接口中没有构造方法,不能创建对象,没 有静态代码块。
4 多态
4.1 概念:多态是指同一种行为有不同的表现形式。
多态的前提: 1.继承类或者实现接口
2.方法的重写(方法不重写多态没意义)
3.父类引用指向子类对象(格式的体现)
4.2 多态的体现
格式: 父类类型 变量名 = new 子类对象;
变量名.方法名();
当使用多态的方式调用方法时,首先要检查父类中是否有该方法,若是没有,则编译错误,若是有,执行的是子类中的重 写的该方法。
public abstract class fu {
public abstract void method();
}
public class zi extends fu {
@Override
public void method(){
System.out.println("zi重写父类的方法");
}
}
public class zi1 extends fu{
@Override
public void method(){
System.out.println("zi1重写父类的方法");
}
}
public class text {
public static void main(String[] args) {
fu zi=new zi();
zi.method(); //zi重写父类的方法
fu zi2=new zi1();
zi2.method(); //zi1重写父类的方法
}
}
4.3 引用类型转换:向上转型 向下转型
向上转型:多态的本身就是子类类型想父类类型向上转型的过程,这个是默认的。
格式:父类类型 变量名 = new 子类类型();
向下转型:父类类型向子类类型转型的向下过程,这个过程是强制的、不安全的
一个已经向上转型的子类对象,再将父类引用转成子类引用,可以使用向下转型,这种是强制类型转换的格式。
格式:子类类型 变量名 = (子类类型) 父类变量名;
为什么要向下转型:当我们使用多态的时候,调用方法时,首先要先检查,父类中是否有该方法,若是没有,则编译错误,若是有,则调用子类对象中重写的该方法。但是我们在使用多态时,要想调用子类中有但是父类中没有的方法时应该怎么办呢?这就是多态给我们带来的麻烦。这时候只能使用向下转型来解决这个麻烦。
向下转型是不安全的,我们提供饿了instance of关键字,给向下转型的变量进行检查,避免错误的发生。
public abstract class fu {
public abstract void method();
}
public class zi extends fu {
@Override
public void method(){
System.out.println("zi重写父类的方法");
}
public void method1(){
System.out.println("这是zi特有的方法");
}
}
public class zi1 extends fu{
@Override
public void method(){
System.out.println("zi1重写父类的方法");
}
public void method2(){
System.out.println("这是zi1特有的方法");
}
}
public class text {
public static void main(String[] args) {
fu z=new zi();
z.method(); //zi重写父类的方法
//向下转型
if(z instanceof zi1){//z 不是zi1的实现对象,所以下面的不会执行
zi z1=(zi)z;
z1.method1();
}
}
}