接口的介绍
接口在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。 编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法,接口则包含类要实现的方法
接口的成员:
自定义常量
抽象方法
默认方法
静态方法
私有方法
内部接口
接口的优点
提高代码的复用性,从而提高开发效率
提高代码的扩展性
接口可以避免继承的局限性
接口也是学习多态的前提条件之一
接口的格式
public interface 接口名{
}
public class (父类)类名 (extends 父类类名) implements 接口名1,接口名2......接口名n{}
类和接口的关系
实现关系,类似于继承关系
对于接口来说,实现接口的类叫实现类
接口中的成员介绍
1.自定义常量
自定义常量的格式:
[public] [static] [final] 数据类型 常量名=初始化值;
中括号中的写于不写都一样,JVm会自动补上,自定义常量访问方式:接口名.常量名。
2.默认方法
格式:[public] default 返回值类型 方法名(){},中括号中的写于不写都一样,JVm会自动补上
当子类同时继承父类和实现父接口,父类的实例方法和夫接口中的默认方法发生同名的时候,通过子类调用优先执行的是父类方法。.当子类继承父类,但同时实现多个父接口,多个父接口存在同名默认方法时,JVM会编译报错处理,要求必须重写这个重名的默认方法。
3.静态方法:在继承关系中,可以通过子类类名调用父类静态方法。在实现关系中,不可以通过实现类类名调用接口静态方法。
4. 抽象方法:
抽象方法的格式:
[public] [abstract] 返回值类型 方法名
中括号中的写于不写都一样,JVm会自动补上,权限修饰符固定时public
在接口中子类必须重写父接口中的抽象方法。
接口的定义实现:
//接口定义
public interface interfacedemo {
//自定义常量
final int num=10;
public abstract void methon();
void methon2();
public default void eat(){
System.out.println("我爱吃汉堡包");
}
//静态方法
public static void play(){
System.out.println("打球");
}
//默认方法
public default void methon1(){
System.out.println("1");
}
}
//子类方法
public class Aimpl implements interfacedemo{
@Override
public void methon(){
System.out.println("这是多接口类的重写");
}
public void methon2(){
System.out.println("这是多接口类的重写2");
}
}
多态的介绍
多态时指编译时形态与运行是形态时不是一样的。我们生活中也有许多多态的现象,比如对猫的称呼,我们有时又把它称为喵星人,或者小动物。而在我们编译程序的过程中,多态的实现是由前提条件的
1.必须有继承或者实现的关系
2.必须含有方法的重写(没有方法重写代码不会编译报错,但是这样的多态毫无意义)
3.如果是继承关系:
父类的引用指向子类对象(父类new子类)
如果是实现关系
父接口的引用指向实现类对象(父接口new实现类)
多态定义的格式:
继承关系下:父类类名 对象名=new 子类类名();
实现关系下:父接口名 对象名=new 实现类名();
定义代码如下
public class demo01try {
public static void main(String[] args) {
superclass son=new sonclass();//superclass是事先定义好的父类,而sonclass是其子类
}
}
多态情况下成员的特点
1.构造器多态情况下的的特点
和原来的new子类对象的情况一样
2.实例变量在多态情况下的特点:
和以前打印变量的规则一样
3.实例方法在多态情况下的特点
当使用多态形式创建对象时,通过对象的先看父类(父接口)是否含有这个方法,如果有执行子类重写后的方法,如果父类没有就会编译报错。
多态的优点与弊端
多态的好处
直接将方法参数写成父类类型或者父接口类型,当调用方法时,直接传递给其子类类型或实现类类型即可
如下述示例代码
//代码测试类
public class demo02try {
public static void main(String[] args) {
//创建猫和狗的对象
cat cat=new cat(3,"白色");
dog dog=new dog(3,"黄色");
//创建饲养员
person p=new person();
p.feedpet(cat,"鱼");//在传递参数的时候发生了多态animal a=cat/dog
p.feedpet(dog,"骨头");
}
}
//person封装类
public class person {
/* public void feedpet(dog dog,String somrthing){
dog.eat(somrthing);
}
public void feedpet(cat cat,String somrthing){
cat.eat(somrthing);
}*/
public void feedpet(animal a,String somrthing){
a.eat(somrthing);
}
}
其中dog实例与cat实例都是继承于animal类的。代码中实现了人喂食猫与狗的输出,因为cat与dog并不是同一个类中的实例,cat属于cat类,dog属于dog类。正常情况下在person中定义连个不同的传参方法才能实现猫狗的喂食输出功能。但由于猫狗有相同的父类,而eat是cat类与dog类相似的方法。我们现在只要在父类中进行方法的抽象定义,person类就可以进行参数的多态转换。实现一个方法输出。
多态的弊端:
多态的弊端也很明显就是不可以调用子类特有的功能方法,为了解决这个问题,我们就要用到引用数据类型的数据转换
引用数据类型的转换的方法:
1.自动类型的转换(向上转换)
将子类类型(实现类类型)转化为父类类型(父接口类类型),其实就是多态
2.强制类型转换(向下转换)
将父类类型(父接口类类型)转化为子类类型(实现类类型),
格式:
子类类型或者实现类类型 对象名=(子类类型或实现类类型)父类类型或父接口类型的对象
转化的实现代码如下
public class demo02try {
public static void main(String[] args) {
animal cat=new cat(3,"白色");
cat c=(cat) cat;//将animal cat强制转换成cat c
}
当然强制类型的转换比不是万能的如果进行转换的对象不是实例的子类,就会发生转换异常,所以我们在转化之前要判断对象是否属于该类型。这里就要用到关键字instanceof。
instanceof关键字:判断对象是否属于该类型
格式
对象名 instanceof 类名
含义:判断该对象在内存中是否为指定的类型,如果是返回true,否则返回false
instanceof的使用示例如下:
public class demo02try {
public static void main(String[] args) {
//创建猫和狗的对象
animal cat=new cat(3,"白色");
animal dog=new dog(3,"黄色");
if(cat instanceof cat){
System.out.println("对象是cat类型对象");
}
if(dog instanceof cat){
System.out.println("对象是cat类型对象");
}else {
System.out.println("对象不是cat类型对象");
}
}
}