抽象类(abstract class)和接口(interface)分析

个人博客:www.letus179.com

概念

抽象类包含抽象方法的类就称为 抽象类
接口抽象方法的集合,方法没有具体实现即不包含方法体


两者异同

相同点

  1. 不能被实例化;
  2. 接口的实现类抽象类的子类必须实现接口抽象类中的方法后才能被实例化

不同点

  1. 接口中的方法是高度抽象的,只有定义,没有具体的实现抽象类可以有定义也可以有实现
  2. 接口中的方法默认为public abstract, 可以直接写public, 可以都省略不写;接口中方法修饰符不能是private, 接口需要实现,所以私有的方法没有意义;抽象类中的具体实现的方法和普通的类一样,而只有定义的方法必须用abstract修饰,不然编译不通过;而且抽象方法的修饰符不能是privatestaticsynchronizednative,能用默认的publicprotected
  3. 接口中定义变量默认为public static final, 并且要赋予初始值,不然编译不通过;抽象类和普通的类一样,可以有自己的成员变量,可以重新赋值;
  4. 接口需要实现(implements)抽象类需要继承(extends)一个类可以实现多个接口,但是只能继承一个抽象类(单继承多实现)

接口三问

接口方法能否用private修饰

不能。因为接口是对外开放的,需要具体的类来实现其中的方法,私有的方法作用范围为本类,在接口中定义私有方法没有任何意义,编译不会通过。

接口方法能否用synchronized修饰

不能。synchronized是一种同步锁,在修饰方法时,需要具体逻辑,而接口只是定义,因为直接修饰接口中的方法没意义,可以用来修饰接口方法的具体实现

接口方法能否用static修饰

这和jdk版本有关。jdk8之前:不能;jdk8新特性: 能。
——参见JDK8新特性之接口的静态方法和默认方法


举例

这里提供两种方式:jad反编译反射来获取成员变量和方法的相关内容。

jad反编译

下面先给出对应源码,再用jad反编译.class文件。反编译执行命令如下:

jad -a -o -s java 类名.class

jad详细命令参见反编译小工具:jad常用命令介绍

接口.java源码

MyInterface.java接口源码如下:

public interface MyInterface {

  String name = "MyInterface";

  void add();
}
接口.class反编译

MyInterface.class反编译结果如下:

public interface MyInterface {

    public abstract void add();

    public static final String name = "MyInterface";
}

可以看到,

1.在成员变量(常量)中默认的修饰符是public static final;
2.在方法中,默认的修饰符是public abstract

抽象类.java源码

MyAbstract抽象类源码如下:

public abstract class MyAbstract {

  public String name;

  void get() {
    System.out.println("MyAbstract get() ");
  }

  // 抽象类中的没有实现的方法必须是“abstract”
  abstract void delete();
}
抽象类.class反编译
public abstract class MyAbstract {

    public MyAbstract() {

    }

    void get() {
        System.out.println("MyAbstract get() ");
    }

    abstract void delete();

    public String name;
}

可以看到,成员方法和成员变量和普通类一样,是什么修饰就是什么。

反射获取

这里新建一个MyTest类,继承抽象类MyAbstract,并且实现接口MyInterface

反射代码
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class MyTest extends MyAbstract implements MyInterface {

    public static void main(String[] args) {

        Field[] abstractFields = MyAbstract.class.getDeclaredFields();
        Method[] abstractMethods = MyAbstract.class.getDeclaredMethods();

        System.out.println("抽象类MyAbstract成员变量反射信息:");
        for (Field f : abstractFields) {
            System.out.println("变量名:" + f.getName());
            System.out.println("修饰符:" + Modifier.toString(f.getModifiers()));
            System.out.println("变量类型:" + f.getType());
        }

        System.out.println();
        System.out.println("抽象类MyAbstract成员方法反射信息:");
        for (Method m : abstractMethods) {
            System.out.println("方法名:" + m.getName());
            System.out.println("修饰符:" + Modifier.toString(m.getModifiers()));
            System.out.println("返回类型:" + m.getReturnType()  + "\n");
        }

        Field[] interfaceFields = MyInterface.class.getDeclaredFields();
        Method[] interfaceMethods = MyInterface.class.getDeclaredMethods();

        System.out.println();
        System.out.println("接口MyInterface成员变量反射信息:");
        for (Field f : interfaceFields) {
            System.out.println("变量名:" + f.getName());
            System.out.println("修饰符:" + Modifier.toString(f.getModifiers()));
            System.out.println("变量类型:" + f.getType());
        }

        System.out.println();
        System.out.println("接口MyInterface成员方法反射信息:");
        for (Method m : interfaceMethods) {
            System.out.println("方法名:" + m.getName());
            System.out.println("修饰符:" + Modifier.toString(m.getModifiers()));
            System.out.println("返回类型:" + m.getReturnType());
        }

    }

    @Override
    public void add() {

    }

    @Override
    void delete() {

    }
}
运行结果
抽象类MyAbstract成员变量反射信息:
变量名:name
修饰符:public
变量类型:class java.lang.String

抽象类MyAbstract成员方法反射信息:
方法名:get
修饰符:
返回类型:void

方法名:delete
修饰符:abstract
返回类型:void

接口MyInterface成员变量反射信息:
变量名:name
修饰符:public static final
变量类型:class java.lang.String

接口MyInterface成员方法反射信息:
方法名:add
修饰符:public abstract
返回类型:void

可以看到,和jad反编译的结果是一样的。

具体的反射机制请参见另一篇博文反射机制基础解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值