抽象、接口和内部类
抽象、接口和内部类
共勉
不要哀求,学会争取。若是如此,终有所获。
抽象方法
定义
所谓抽象方法,就是将公共的行为(方法)抽取到一个父类后,由于每个子类中执行的内容是不一致的,所以父类中无法确认具体的方法体,此时就可以将该方法定义为抽象方法。
格式
要定义一个抽象方法,那么需要遵循以下的格式,要注意,抽象方法一般都是没有定义
public abstract 返回值类型 方法名(参数列表);
以下是一个抽象方法定义的具体实例。
public abstract void welcome(String name);
抽象类
定义
知道了什么是抽象方法,那么抽象类就很简单了,如果我们发现一个类中存在着抽象方法,那么这个类一定要声明为抽象类。
格式
public abstract class 类名{
}
public abstract class Person{
}
注意
- 抽象类不能实例化。
- 抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类。
- 抽象类中可以有构造方法。
- 如果一个类的父类是抽象类,那么这个类要么是抽象类,要么重写父类中所有的抽象方法。
作用
在抽取共性时,如果无法确定方法体,此时就可以将该方法定义为抽象方法。然后强制让子类按照某种格式重写。
接口
定义
接口是一种规则,是对行为的抽象。
格式
public interface 接口名{
}
注意
- 接口和抽象类一样,不能被实例化。
- 接口和类之间是实现关系,通过关键字
implements
表示,实现格式为:
public class 类名 implements 接口名{
}
- 如果一个类实现了某个接口,那么这个类要么是抽象类,要么就得重写接口中所有的抽象方法。
- 不同于类单继承的特点,一个类是可以实现多个接口的。
成员的特点
- 成员变量
接口中,成员变量只能是常量,默认修饰符为 public static final
。
- 构造方法
接口中不存在构造方法。
- 成员方法
JDK 7
之前,只能是抽象方法,其默认修饰符为 public abstract
。JDK 8
时,能够定义有方法体的方法,JDK 9
中,有带来了可以定义私有方法的特性。
默认方法
自 JDK 8
之后,就允许在接口中定义默认方法,但是需要使用关键字 default
来修饰,从而解决接口升级的问题。
接口中的默认方法的定义格式为:
public default 返回值类型 方法名(参数列表){}
使用默认方法时,需要注意:
- 接口中的默认方法不是抽象方法,所以没有要求强制被重写。但如果要重写默认方法,重写时就需要去掉默认方法的关键字
default
。 - 默认方法中的权限空置房
public
可以省略不写,但关键字default
不能省略。 - 如果一个类实现了多个接口,而且着多个接口中还存在着重名的默认方法,那么该类就必须对重名的默认方法进行重写。
以下是一个存在重名默认方法必须重写的实例。
public interface InterOne{
public abstract void method1();
public default void method2(){
System.out.println("默认方法 method2");
}
}
public interface InterTwo{
public default void method2(){
System.out.println("默认方法 method2");
}
public abstract void method3();
}
public class Main implements InterOne, InterTwo{
@Override
public void method1(){
System.out.println("抽象方法 1");
}
@Override
public void method3(){
System.out.println("抽象方法 3");
}
@Override
// 注意重写需要去掉关键字 default
public void method2(){
System.out.println("默认方法 2");
}
}
静态方法
除了默认方法,JDK 8
以后还可以在接口中定义静态方法,此时需要用关键字 static
修饰。
接口中 静态方法 的定义格式为:
public static 返回值类型 方法名(参数列表){}
在接口中使用静态方法时,需要注意:
- 静态方法只能通过接口名调用,不能通过实现接口的类名或者对象名来调用。
- 权限控制符
public
可以省略,但关键字static
不能省略。
以下是一个在接口中定义静态方法和调用接口中静态方法的实例。
public interface Inter{
public static void method(){
System.out.println("静态方法 method");
}
}
public class Main implements Inter{
public static void main(String[] args){
// 调用接口中的静态方法
Inter.method();
}
}
私有方法
除了上述的静态方法和默认方法之外,JDK 9
中又引入接口中定义私有方法的特性。
其中,接口中定义私有方法的格式如下:
private 返回值类型 方法名(参数列表){}
private static 返回值类型 方法名(参数列表){}
两者的区别在于:静态的私有方法(带关键字 static
)是为接口中的静态方法服务,而非静态的私有方法(不带关键字 static
) 则是为接口中的默认方法服务。
以下是在接口中定义私有方法的实例:
- 私有方法
public interface Inter{
private void method(){
System.out.println("私有方法 method");
}
public default void method1(){
method();
System.out.println("默认方法 method1");
}
}
- 静态私有方法
public interface Inter{
private static void method(){
System.out.println("私有方法 method");
}
public static void method1(){
method();
System.out.println("静态方法 method1");
}
}
接口和类之间的关系
- 类和类的关系
类与类之间只能存在继承关系,且只限于单继承,不能多继承,但是可以多层继承。
- 类和接口的关系
类和接口之间是实现关系,既可以单实现,也可以多实现,还能在继承一个类的同时实现多个接口。
- 接口和接口的关系
接口之间是继承关系,但不同于类和类之间的关系,接口之间既可以单继承,也可以多继承。
内部类
定义
顾名思义,所谓内部类就是定义在类中的类。比如说在 A
类的内部定义了一个 B
类,那么我们就说 B
是内部类。其中 B
类表示的是 A
类的一部分,而且 B
类单独存在时没有任何意义。
public class Outer{
public class Inner{
}
}
特点
如果一个类中定义了一个内部类,那么这个内部类就能够直接访问外部类的所有成员,包括私有成员。
但是,如果一个外部类要访问内部类的成员,那么此时就必须创建对象。
public class Outer{
private String name;
private String address;
public class Inner{
String id;
String age;
public void show(){
// 内部类可以直接访问外部类的所有成员
System.out.println(id + " " + age + " " + name + " " + address)
}
}
}
分类
Java
中,内部类主要分为以下四种:
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
成员内部类
写在成员位置,属于外部类的成员,其中成员内部类也能够被常用的修饰符 public、private、protected、static
等所修饰。
public class Outer{
private String name;
private String address;
public class Inner{
String id;
String age;
}
}
要想获取成员内部类对象,可以通过以下两种方式:
- 在外部类中编写方法,然后对外提供内部类的对象。
public class Outer{
private String name;
private String address;
public class Inner{
String id;
String age;
}
public Inner getInnerInstance(){
return new Inner();
}
}
- 直接创建,创建格式为:
外部类名.内部类名 对象名 = 外部类对象.内部类对象
。
public class Main{
public static void main(String[] args){
Outer.Inner inner = new Outer().new Inner();
}
}
静态内部类
静态内部类就是用关键字 static
修饰的内部类。静态内只能访问外部类中的静态变量和静态方法,如果要访问非静态的变量和方法就需要创建对象。
public class Outer{
private String name;
private String address;
static String birth = "20220222";
static class Inner{
String id;
String age;
public static void show(){
System.out.println("静态方法" + birth);
}
public void display(){
System.out.println("非静态方法");
}
}
}
创建静态内部类对象的格式为:外部类名.内部类对象名 = new 外部类名.内部类名();
调用非静态方法的格式:先创建对象,然后用对象调用。
调用静态方法的格式:外部类名.内部类名.方法名();
public class Main{
public static void main(String[] args){
Outer.Inner inner = new Outer().new Inner();
// 调用非静态方法
inner.display();
// 调用静态方法
Outer.Inner.show();
}
}
局部内部类
如果一个类被定义在方法中,那么这个类就叫做局部内部类。外界是无法直接使用局部内部类,需要在方法内部创建对象并使用。同时,这个内部类既可以访问外部类的成员,也可以访问方法中的局部变量。
public class Outer{
public String id;
public void show(){
class Inner{
String name;
public void show(){
System.out.println("局部类内部方法");
System.out.println(id);
System.out.println(name);
}
}
Inner inner = new Inner();
System.out.println(inner.name);
inner.show();
}
}
匿名内部类
匿名内部类就是没有名字的内部类,也正因为名字,所以匿名内部类只能使用一次。而且使用匿名内部类还有个前提条件:必须继承一个父类或者实现一个接口。
new 类名/接口名(){
重写方法;
}
public interface Inner{
public abstract void method();
}
public class Main{
public static void main(String[] args){
new Inner(){
@Override
public void method(){
System.out.println("方法重写");
}
}
}
}
⏳ 联系
想解锁更多知识?不妨关注我的微信公众号:村雨遥(id:JavaPark)。
扫一扫,探索另一个全新的世界。