Java接口
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化(不能和new运算符实例化一个接口),但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
相关知识
归纳下接口的知识点:
- 接口不能实例化对象。
- 接口没有构造方法。
- 接口中的方法都是抽象的(隐式,不用abstract进行申明)。
- 接口不是被类继承而是被类实现。
// Interface Animal.java public interface Animal { public void eat(); public void travel(); } // MammalInt.java package Interface; public class MammalInt implements Animal{ public void eat() { System.out.println("Mammal eat"); } public void travel() { System.out.println("Mammal travel"); } public static void main(String[] args) { MammalInt mammalInt = new MammalInt(); mammalInt.eat(); mammalInt.travel(); } }
- 接口之间能继承。
// Interface Sports.java public interface Sports { public void setHomeTeam(String name); public void setVisitingTeam(String name); } // Interface Football.java public interface Football extends Sports{ public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter); } // Interface Hockey.java public interface Hockey extends Sports { public void homeGoalScored(); public void visitingGoalScored(); public void endOfPeriod(int period); public void overtimePeriod(int ot); }
- 接口能够实现多继承。
public interface basketball extends Sports ,Football{ // 举例子 实际不符合 }
- 接口中能够存在变量但是都会被隐式的被声明为public static final 类型
- 为什么存在抽象类之后还要使用接口?1)接口的性质。2)接口能够实现多继承比如一个basketball,football可以继承Sports。但是如果是抽象类的Sports就不能进行这个层面的多继承(使用内部类可以进行继承)。
接口回调
通俗来说接口回调就是我主动叫你帮我做一件事,你做完之后通知我的这个动作就是接口回调。
java层面上来说就是:存在一个接口A和它的实现类A1,类B是接口A的引用,在B执行完方法之后,可以通过A的引用告诉A只进行完成了这个方法,由于A是一个接口具体的实现就在类A1中实现。
内部类
在类 A 中定义类 B,那么类 B 就是内部类,也称为嵌套类,相对而言,类 A 就是外部类。如果有多层嵌套,例如类 A 中有内部类 B,而类 B 中还有内部类 C,那么通常将最外层的类称为顶层类(或者顶级类)。内部类可以分为:实例内部类、静态内部类和成员内部类。
实例内部类
是指没有用 static 修饰的内部类,有的地方也称为非静态内部类。有以下特点:
- 在外部类的静态方法和外部类以外的其他类中,必须通过外部类的实例创建内部类的实例。
public class OuterClass { class Inner1 { } public void method1() { Inner1 inner1 = new Inner1(); // 同一外部类的非静态方法不同实例化外部类 } public static void method2() { Inner1 inner1 = new OuterClass().new Inner1(); // 同一内部类的静态方法需要实例化外部类 } class Inner2{ Inner1 inner1 = new Inner1(); // 同一外部类中其他类不需要实例化外部类 } } class otherClass{ Inner1 inner1 = new OuterClass().new Inner1(); // 不同外部类需要实例化外部类 }
- 在实例内部类中,可以访问外部类的所有成员。在外部类中不能直接访问内部类的成员,而必须通过内部类的实例去访问。如果类 A 包含内部类 B,类 B 中包含内部类 C,则在类 A 中不能直接访问类 C,而应该通过类 B 的实例去访问类 C
public class OuterClass { public String string = "外部类"; private int i = 1; final int k = 2; static int m = 3; class Inner1 { int j = i + 1; String string1 = string + "内部类"; int k1 = k + 1; int m1 = m + 1; } public static void main(String[] args) { Inner1 inner1 = new OuterClass().new Inner1(); System.out.println(inner1.j); System.out.println(inner1.string1); System.out.println(inner1.k1); System.out.println(inner1.m1); } }
- 在实例内部类中不能定义 static 成员,除非同时使用 final 和 static 修饰。
静态内部类
静态内部类是指使用 static 修饰的内部类。有以下的特点:
- 在创建静态内部类的实例时,不需要创建外部类的实例。
public class OuterClass { static class Inner{ } } class otherClass{ OuterClass.Inner inner = new OuterClass.Inner(); }
-
静态内部类中可以定义静态成员和实例成员。外部类以外的其他类需要通过完整的类名访问静态内部类中的静态成员,如果要访问静态内部类中的实例成员,则需要通过静态内部类的实例。
public class OuterClass { static class Inner{ int i = 1; static int j = 0; } public static void main(String[] args) { otherClass otherClass = new otherClass(); System.out.println(otherClass.m); System.out.println(otherClass.n); } } class otherClass{ OuterClass.Inner inner = new OuterClass.Inner(); int m = inner.i + 1; int n = inner.j + 1; }
-
静态内部类可以直接访问外部类的静态成员,如果要访问外部类的实例成员,则需要通过外部类的实例去访问。
public class OuterClass {
int a = 0;
static int b = 0; // static 修饰的变量属于整个类
static class Inner{
OuterClass outerClass = new OuterClass();
int a1 = outerClass.a;
int b1 = b; // 直接访问
}
}
局部内部类
局部内部类是指在一个方法中定义的内部类。特点如下:
- 局部内部类与局部变量一样,不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰。
- 局部内部类只在当前方法中有效。
- 局部内部类中不能定义 static 成员。
- 局部内部类中还可以包含内部类,但是这些内部类也不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰。
- 在局部内部类中可以访问外部类的所有成员。
- 在局部内部类中只可以访问当前方法中 final 类型的参数与变量。如果方法中的成员与外部类中的成员同名,则可以使用 <OuterClassName>.this.<MemberName> 的形式访问外部类中的成员。
public class Test { int a = 0; int d = 0; public void method() { int b = 0; final int c = 0; final int d = 10; class Inner { int a2 = a; // 访问外部类中的成员 // int b2 = b; // 编译出错 int c2 = c; // 访问方法中的成员 int d2 = d; // 访问方法中的成员 int d3 = Test.this.d; //访问外部类中的成员 } Inner i = new Inner(); System.out.println(i.d2); // 输出10 System.out.println(i.d3); // 输出0 } public static void main(String[] args) { Test t = new Test(); t.method(); } }
匿名内部类
匿名类是指没有类名的内部类,必须在创建时使用 new 语句来声明类。
- 匿名类和局部内部类一样,可以访问外部类的所有成员。如果匿名类位于一个方法中,则匿名类只能访问方法中 final 类型的局部变量和参数。
- 匿名类中允许使用非静态代码块进行成员初始化操作。
- 匿名类的非静态代码块会在父类的构造方法之后被执行。