在JAVA
编程语言中,接口是一个抽象类型,是抽象方法的集合。
接口通常以interface
来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。类的继承只能单继承,但可以通过接口实现(伪)多继承。
- 接口代表一种能力,实现接口,则表示具备了某种功能
- 接口代表一种规范,在实现接口的时候必须遵循相应的规范,比如说重新实现方法的时候参数的要求、返回值的要求等等
接口中定义了一些抽象方法,如果类要实现该接口,则必须给出这些抽象方法的具体实现。因此说接口时一种能力。
interface关键字
声明接口public static final型变量
public abstract 类型
implements关键字
实现接口。在类声明中Implements关键字
放在class声明后面。package com.oop_extends.www; //声明一个接口,接口名称为Sing interface Sing { int vol = 10;//接口中定义的变量会隐式地指定为 public static final变量,一般不会再接口中声明变量 //public static final int vol = 10; boolean isSing = true; //接口主要是一系列抽象方法的集合,接口中的方法会被隐式地指定为 public abstract 类型 //因为方法都是抽象方法,因此接口里的方法也都是只有方法名,没有方法体,需要实现接口的类来提供方法的具体细节实现 void singSong(People people); } abstract class People { //声明一个抽象类,名称为People abstract void speak();//声明一个抽象方法,speak } class Boy extends People { //继承抽象类要重写父类中的抽象方法speak @Override void speak() { System.out.println("男孩说话"); } } class Singer extends People implements Sing {//创建一个子类Singer,继承于父类People,实现接口Sing //当类要实现接口的时候,除非该类是抽象类,否则该类要重写实现接口里的所有抽象方法 //重写sing接口中的singSong方法, @Override public void singSong(People people) { //在实现接口的抽象方法singSong时,调用父类的抽象方法speak this.speak(); } @Override void speak() { //对于父类中的抽象方法,子类要重写给出具体实现 System.out.println("歌手唱歌"); } } public class Jiekou { public static void main(String[] args) { //实例化一个Singer类的对象 //调用Singer类所实现的接口Sing中的singSong方法, //实例化一个Boy类对象,将其作为参数传递给singSong方法 new Singer().singSong(new Boy()); //singSong的参数类型为People,接收boy后自动转换 //转换后执行当前类的speak方法,当前类为Singer,因此执行”歌手唱歌“ } } -------------------------------------------------- 运行结果: 歌手唱歌
可以看到,编写接口的方式和类很相似。但是接口不是类。
类(实现接口)需要(重写接口)中声明的抽象方法。但是重写接口中声明的方法时,需要注意以下规则:
在实现接口时也应注意一些规则:
implements关键字
后面,类里面要重写所有接口的抽象方法。一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字
,子接口继承父接口的方法。
public interface Sports { public void setHomeTeam(String name); public void setVisitingTeam(String name); } //实现Football接口的类需要实现五个方法,其中两个来自于Sports接口。 public interface Football extends Sports { public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter); } //Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。 public interface Hockey extends Sports { public void homeGoalScored(); public void visitingGoalScored(); public void endOfPeriod(int period); public void overtimePeriod(int ot); } //java支持多继承,因此下面语句也是合法的 public interface Hockey extends Sports, Event
1.1 什么是内部类?
内部类就是在一个类的内部再定义一个类。比如,A类中定义了一个B类,则B类相对于A类来说称为内部类,A类相对于B类来说就是一个外部类。
使用内部类的好处:每个内部类都能独立地继承一个(接口的)实现,无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
使用内部类最大的优点:解决多重继承的问题
1.2 内部类主要分为:
内部类分类
成员位置:在成员位置定义的类,被称为成员内部类
局部位置:在局部位置定义的类,被称为局部内部类
成员内部类
静态内部类
局部内部类
匿名内部类
内部类访问特点
public class Outer { int num = 10; private int a = 100; //定义成员内部类 class Inner { int b = 109; public void innerShow() { System.out.println("内部类的show方法"); } //内部类可以直接访问外部类的成员,包括私有 public void innerTest(){ System.out.println(num); System.out.println(a); outerShow(); outerTest(); } } public void outerShow() { System.out.println("这是外部类的show方法"); } private void outerTest() { System.out.println("这是外部类的show方法"); } //外部类,想要访问内部类的成员,得创建内部类的对象 public void method(){ //创建内部类的对象 Inner inner = new Inner(); System.out.println(inner.b); inner.innerShow(); } } //测试类 public class MyTest { public static void main(String[] args) { Outer outer = new Outer(); System.out.println(outer.num); outer.outerShow(); System.out.println("----------------"); //使用成员内部类的属性和方法 //创建成员内部类的语法 Outer.Inner inner=new Outer().new Inner(); System.out.println(inner.b); inner.innerShow(); System.out.println("---------------"); outer.method(); } } //输出 10 这是外部类的show方法 ---------------- 109 内部类的show方法 --------------- 109 内部类的show方法
//定义类 class Body {//外部类,身体 private boolean life= true;//生命状态 public class Heart { //内部类,心脏 public void jump() { System.out.println("心脏噗通噗通的跳") System.out.println("生命状态" + life); //访问外部类成员变量 } } } public static void main(String[] args) {//访问内部类 //创建内部类对象 Body.Heart bh = new Body().new Heart(); //调用内部类中的方法 bh.jump(); }
成员内部类的修饰符
private 为了保证数据的安全性
static 为了方便访问数据
注意:静态内部类访问的外部类数据必须用静态修饰,成员方法可以是静态的也可以是非静态的
class Outer { public int num = 10; class Inner { public int num = 20; public void show() { int num = 30; System.out.println(num); //30 System.out.println(this.num); //20 System.out.println(new Outer().num); //10 System.out.println(Outer.this.num);// 和上面new Outer().num一个意思 } } } class InnerClassTest { public static void main(String[] args) { Outer.Inner oi = new Outer().new Inner(); oi.show(); } }
局部内部类,定义在外部类方法中的局部位置。与访问方法中的局部变量相似,可通过调用方法进行访问(在方法内部定义类)
class 外部类 { 修饰符 返回值类型 方法名(参数) { class 内部类 { //其他代码 } } }
访问方式
在外部类方法中,创建内部类对象,进行访问
package com.inner; public class Demo02 { int a = 100; public void show(int a ){ int num =0; class nei{ public void neiShow() { //局部内部类,访问外部类的局部变量,局部变量必须加上final修饰,JDK1.8 默认就加上了 System.out.println(num); System.out.println(a); } } nei nei=new nei(); nei.neiShow(); } public static void main(String[] args) { Demo02 demo02= new Demo02(); demo02.show(55); } } ---------------------------------- 0 55
匿名内部类的作用:临时定义某一指定类型的子类 ,定义后即刻创建刚刚定义的这个子类的对象
格式:
new 父类或接口(){
//进行方法重写
};
public static void main(String[] args) { //匿名内部类:是局部内部类的简写 //匿名内部类,本质上是一个对象,是谁的对象,是实现了该接口或继承了该抽象类的子类对象 new AA(){ @Override public void show() { System.out.println("重写了show方法"); } }.show(); } } abstract class AA{ public abstract void show(); } //输出:重写了show方法
private(私有的) , 默认 , protected(受保护的) , public(公共的)
本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类) private Y 默认 Y Y protected Y Y Y public Y Y Y Y