java之抽象类与接口

目录

一、抽象类与抽象方法

      1、抽象类

      2、抽象方法

二、接口( interface )

      接口与类的相似点:

      接口与类的区别:

      接口与抽象类的区别:

      接口的特点:

补充:

1、默认方法

2、静态方法

3、私有方法


一、抽象类与抽象方法

      1、抽象类

       在面对对象的概念中,所有的对象都是通过类来描绘的,但是反之,并不是所有的类都是用来描绘对象的,抽象类就是这样的一种特殊的类。抽象类不能实例化对象,但是类的其他功能依然存在,正是因为抽象类不能实例化对象,所以抽象类必须被继承才能被使用。在java中抽象类表示的其实是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现对个接口。

       可能你会疑惑,既然抽象类不能实例化对象,但是又有其他类一样的功能,那要它干嘛,不是多余嘛?其实抽象类起的作用就是一个规范作用。抽象类为所有子类提供了一个通用模版,子类可以在这个模版基础上进行扩展。 通过抽象类,可以避免子类设计的随意性。通过抽象类,我们就可以做到严格限制子类的设计, 使子类之间更加通用。 

       抽象类的实现:在java中使用abstract 来定义抽象类。

      2、抽象方法

       抽象方法包含在抽象类中,它是一种特殊的成员方法,它没有方法体,只有声明,它与抽象类一样,定义的是一种“规范”,该方法具体的实现由它的子类确定。abstract关键字同样用来定义抽象方法,抽象方法没有定义,方法名后面直接跟分号,而不是花括号。

       声明抽象方法会造成两个结果:

              ①、如果一个类包含抽象方法,那么这个类必须是抽象类。

              ②、继承抽象方法的子类必须重写该方法,否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否        则,从最初的父类到最终的子类都不能用来实例化对象。

要点:

        1、抽象类和抽象方法必须用abstract关键字来修饰

        2、抽象类不能被实例化,只有抽象类的非抽象子类才可以创建对象;

        3、抽象类可以包含变量、方法和构造方法。

        4、抽象类中不一定含有抽象方法,但是有抽象方法的类必定是抽象类

        5、抽象类中的抽象方法只是声明,没有方法体。

        6、抽象类的子类必须给出抽象类中抽象方法的具体实现,否则该子类也是必须是抽象类。

        7、构造方法、类方法(用static修饰的方法)不能声明为抽象方法。

package cn.cou.pack;

public class TestAbstract {
	public static void main(String agrs[]) {
		
		//Animal animal = new Animal();   //抽象类不能实例化对象,所以此处不允许
		
		Lion lion = new Lion();//可以使用
		
		lion.name = "辛巴";
		lion.age = 3;
		lion.address = "非洲大草原";
		
		System.out.print(lion.name+",年龄"+lion.age+"岁,来自"+lion.address+",");
		lion.carnivore();
		
		lion.germ();//调用子类重写的germ方法
	}
}

abstract class Animal{   //定义Animal抽象类
	
	String name;
	int age;
	String address;
	
	void carnivore() {
		System.out.println("喜欢吃肉");
	}
	
	void herbivore() {
		System.out.println("喜欢吃草");
	}
	
	abstract void germ();//声明一个抽象方法;只有声明,没有方法体
	
}

class Lion extends Animal{  //子类Lion类继承抽象类
	
	void germ() {  //子类重写该抽象方法
	 
		System.out.println("微生物啥都吃");
	}
}

二、接口( interface )

      在java中,接口是一个抽象类型,是抽象方法的集合,是比“抽象类”还“抽象”的“抽象类”,(但是接口不是类,后面再说)可以更加规范的对子类进行约束。 接口可以简单理解为就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。接口的本质是契约,就像我们的法律一样。制定好后大家都必须遵守。 

       接口通常以interfce来声明。一个类通过继承接口的方式来继承接口的抽象方法。接口并不是类,它们属于不同的概念,但是编写接口的方式和类很相似。类描述对象的属性和方法。接口则包含类要实现的方法。接口无法被实例化,但是可以被实现。一个实现接口的类必须实现接口内所描述的所有方法,否则就必须声明为抽象类。

      接口与类的相似点:

             1、一个接口与一个类一样,都可以有多个方法

             2、接口文件保存在 .java结尾的文件中,文件名使用接口名(即在我们创建一个接口时,不在是点class,而是点interface)

             3、接口的字节码文件保存在 .class 结尾的文件中

             4、接口相应的字节码文件必须在与包名称相匹配的目录结构中

      接口与类的区别:

             1、接口不能用于实例化对象

             2、接口没有构造方法

             3、接口中所有的方法都必须是抽象方法

             4、接口不能包含成员变量,但是可以有static 和 final 变量

             5、接口不是被类继承了,而是要被类实现

             6、接口支持多继承

      接口与抽象类的区别:

             1、抽象类中的普通方法可以有方法体,能实现方法的具体功能;但是接口中的方法都是抽象方法,所以全部没有方法体,不能实现方法的具体功能。(注意:在jdk1.8以后,接口里可以有静态方法和方法体了,这个我在最后进行了补充,详情请看最后补充部分)

             2、抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的。

             3、接口中不能含有静态代码块以及静态方法,而抽象类是可以有的。

             4、一个类只能继承一个抽象类,而一个类可以实现多个接口。

      接口的特点:

             1、接口是隐式抽象的,当声明一个接口时,不必使用abstract关键字。

             2、接口中的每一个方法都是隐式抽象的,接口中的方法会被隐式的指定为 public abstract ,所以当声明方法时,也不必写abstract关键字,同时接口的方法都是公有的。

             3、接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final  变量。

             4、接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

      接口的声明:

public interface 接口名称 [extends 其他接口名]
{
    //声明变量
    //抽象方法
}

案例:

/*文件名 TestInterface.java  */
package cn.cou.pack;

public abstract interface TestInterface {
	
	public void eat();
	public void wear();
	public void live();
	public void move();
}

 

      接口的实现:类使用implements关键字实现接口,在类声明中,implements关键字放在class声明后面。在类实现接口的时候,要实现接口中所有的方法。否则,该类必须声明为抽象类。

案例:

/*文件名 TestInterfaceClass.java */

package cn.cou.pack;

public class TestInterfaceClass implements TestInterface {  //实现TestInterface接口
	public void eat() {    //重写方法时与接口的方法名保持一致
		System.out.println("吃");
	}
	public void wear() {
		System.out.println("穿");
	}
	public void live() {
		System.out.println("住");
	}
	public void move() {
		System.out.println("行");
	}
	
	public static void main(String[] args) {
		TestInterfaceClass tic = new TestInterfaceClass();
		tic.eat();
		tic.wear();
		tic.live();
		tic.move();
	}
}

      接口的继承:一个接口可以继承另一个接口,和类之间的继承方式相似。接口的继承也是使用extends 关键字。

案例:

/* 文件名: TestInterface1.java  */

package cn.cou.pack;

public interface TestInterface1 extends TestInterface{  //接口的继承
	
	public void study();
	public void play();
	
}
/*文件名 TestInterfaceClass1.java */

package cn.cou.pack;

public class TestInterfaceClass1 implements TestInterface1 {  //实现TestInterface1接口
	/*
	 * TestInterface1接口继承了TestInterface接口的四个方法,本身自己有2个方法,一共六个方法,必须全部实现
	 */
	
	public void eat() {    //重写方法时与接口的方法名保持一致
		System.out.println("吃");
	}
	public void wear() {
		System.out.println("穿");
	}
	public void live() {
		System.out.println("住");
	}
	public void move() {
		System.out.println("行");
	}
	
	public void study() {
		System.out.println("学习");
	}
	public void play() {
		System.out.println("玩");
	}
	
	public static void main(String[] args) {
		TestInterfaceClass tic = new TestInterfaceClass();
		tic.eat();
		tic.wear();
		tic.live();
		tic.move();
		tic.study();
		tic.play();
	}
}

接口的多继承:在java中,类的多继承是不合法的,但接口允许多继承。在接口的多继承中只使用extends一次,后面跟继承接口

​//程序片段
public interface 接口名称 extends 接口名称1,接口名称2...{

}​

一个类可以同时实现多个接口:

public class 类名称 implements 接口名称,接口名称1,接口名称2....{

}

注意:实现的接口中,父接口与子接口不能同时存在。

补充:

在前面我们说,接口中没有静态方法和方法体,但是在jdk1.8之后(后来更名后称为jdk8,如今最新的是jdk13),接口中开始允许定义默认方法和静态方法

1、默认方法

     格式:

public default 返回值类型 方法名(参数列表){
   //方法体
}

       默认方法是一种扩展接口的方法,而且不破坏现有代码。比如说:如果一个已经投入使用的接口需要扩展添加新的方法,在java8之前,我们必须在该接口的所有实现类中都新添加该方法的实现,否则就会编译出错,对于实现类少且有修改权限的可能工作量会小,但是对于实现类很多或者没有修改权限的就很难去解决了,而默认方法就提供了一个实现,这样新添加的方法就不破坏现有代码,而且大大减少了工作量。默认方法允许接口方法定义默认实现,子类方法不用必须实现此方法就可以拥有该方法及实现。

案例分析:

接口:

/*文件名 InterfaceSup.java */

public interface InterfaceSup {  //接口
	
	public void method();//
	
	public default void defaltMethod() {
		System.out.println("这个是新添加的默认方法");
	}
}

  实现类:

/* 文件名:InterfaceClass.java */

public class InterfaceClass implements InterfaceSup{  //实现类
	
	public void method() {
		System.out.println("重写接口中的抽象方法");
	}
	
	public static void main(String[] args) {

		InterfaceClass ic = new InterfaceClass();

		ic.method();
		ic.defaltMethod();//如果在实现类中重写了默认方法,则调用的是重写后的方法
	}

}

2、静态方法

     格式:

public static 返回值类型 方法名 (参数列表) {
     //方法体
}

       接口中的静态方法类似于类中的静态方法,接口中定义的静态方法可以独立于任何对象调用。所以,在调用静态方法时,不需要实现接口,也不用接口的实例,调用方法和类调用静态方法的方式类似。 

       值得注意的是:接口中的静态方法不能被子接口继承;使用static修饰的接口中的方法必须有主体;接口的静态方法不能被实现类重写或者直接调用;接口中的静态方法只能被接口本身调用。

案例:

接口:

/*文件名:InterfaceSup1.java */

public interface InterfaceSup1 {
	
	public void method1();
	
	public static void staticMethod() {
		System.out.println("静态方法");
	}
}

实现类:

/*文件名:InterfaceClass1.java */

public class InterfaceClass1 implements InterfaceSup1{
	
	public void method1() {
		System.out.println("重写抽象方法");
	}

	public static void main(String[] agrs) {
		
		InterfaceClass1 in = new InterfaceClass1();
		
		in.method1();
		//in.staticMethod();//不能被实现类的对象调用
		InterfaceSup1.staticMethod();//接口本身直接调用
	}
}

3、私有方法

      从java9开始,接口中允许定义私有方法,当我们在一个接口里写多个默认方法或者静态方法的时候,可能会遇到程序重复的问题,创建一个新方法,用private进行修饰,这样就创造了一个只有接口可以调用的私有方法。所以,私有方法又分为静态私有方法和普通私有方法。

 

普通私有方法:解决多个默认方法之间重复代码的问题

格式:

private 返回值类型 方法名称(参数列表) {
   //方法体
}

静态私有方法:解决多个静态方法之间重复代码的问题,静态私有方法不需要通过实现类使用,通过接口名直接调用,

格式:

private static 返回值类型 方法名称(参数列表){
    //方法体
}

案例分析:

接口:

/* 文件名:InterfaceSup2.java */


public interface InterfaceSup2 {

	private static void methodStaticPrivate() {
		System.out.println("静态私有方法");
	}
	
	private void methodDefaultPrivate() {
		System.out.println("普通私有方法");
	}
	
	
	public static void methodStatic() {
		System.out.println("静态方法");
		methodStaticPrivate();  //私有方法只能在本接口中使用
		
		//methodDefaultPrivate();//不能对非静态方法进行静态引用
	}
	public default void methodDefault() {
		System.out.println("默认方法");
		
		methodStaticPrivate();//静态方法可以进行非静态引用
		
		methodDefaultPrivate();
	}
}

实现类:

/*文件名: InterfaceClass2.java */

public class InterfaceClass2 implements InterfaceSup2{

	public static void main(String[] args) {
		
		InterfaceClass2  m = new InterfaceClass2();
		m.methodDefault();//实现类对象引用非静态方法
		System.out.println("\n");
		
		InterfaceSup2.methodStatic();//静态方法通过接口直接调用
	}
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值