博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Java基础】13、抽象方法不能是static或native或synchroniz 原因及误解
阅读量:6805 次
发布时间:2019-06-26

本文共 2230 字,大约阅读时间需要 7 分钟。

在网上看到过这么一篇文章,是关于抽象方法不能是static或native或synchroniz 的原因。其中提到了这些关键字的意义以及与 abstract 关键字的冲突,大体内容如下:

        1、abstract是抽象的,指的是方法只有声明而没有实现,他的实现要放入声明该类的子类中实现。

        2、static是静态的,是一种属于类而不属于对象的方法或者属性,而我们知道,类其实也是一个对象,他是在class文件加载到虚拟机以后就会产生的对象,通常来说它是单例的,就是整个虚拟机中只有一个这样的类对象(当然,如果用新的类加载器也会生成新的类的对象)。

        3、synchronized 是同步,是一种相对线程的锁。

        4、native 本地方法,这种方法和抽象方法及其类似,它也只有方法声明,没有方法实现,但是它与抽象方法不同的是,它把具体实现移交给了本地系统的函数库,而没有通过虚拟机,可以说是与其它语言通讯的一种机制。

 

然后作者逐个分析了冲突的原因:

        首先abstract与static,其实一看他们的作用和属性就很容易辨别,abstract是没有实现的,而static一定要有实现,因为 abstract的类不能生产对象,但是static是属于类,而类已经是一个存在的对象,这两个关键字在这上面有一个关键的矛盾点。

        synchronized 是同步,然而同步是需要有具体操作才能同步的,如果像abstract只有方法声明,那同步一些什么东西就会成为一个问题了,当然抽象方法在被子类继承以后,可以添加同步。

        native,这个东西本身就和abstract冲突,他们都是方法的声明,只是一个吧方法实现移交给子类,另一个是移交给本地。如果同时出现,就相当于即把实现移交给子类,又把实现移交给本地操作系统,那到底谁来实现具体方法呢?

 

作者对于 synchronized 和 native 关键字冲突的原因分析笔者是没有异议的,关键就在于 static 冲突的原因。

        在第三段中红色文字标出的部分中,作者说“类其实也是一个对象”,只要是对 JVM类加载机制懂一点的人来说,这个是没问题的。而在后面分析原因部分,作者说“abstract 的类不能产生对象,但是static属于类,类已经是一个存在的对象”,这个也是没有异议的。关键在于后面,作者又说 ”这两个关键字在这一个关键点上有矛盾“。对于这句话,作者混淆了类对象和实例对象的概念了。

        不管是不是抽象类,只要使用到了该类,虚拟机总是会在方法区中为该类创建一个 Class 对象,用来描述该类的运行时结构。我们写一段代码做一个简单的,如下:

 

[java]   
 
 
  1. public class MonitorVehicleTracker {  
  2.     public static void main(String[] args){  
  3.         System.out.print(Door.class.getClassLoader());    
  4.     }  
  5. }  
  6. abstract class Door{  
  7.     public static  void set() {  
  8.         System.out.print("123");  
  9.     }  
  10. }  

 

运行结果为:

        sun.misc.Launcher$AppClassLoader@15253d5

        我们可以看到,抽象类 Door 确实被加载了(因为我们可以访问到它的 Class 对象),而且,它是由应用程序类加载器加载的。

        也就是说,”abstract 类不能产生对象“的意思应该是 abstract 类在方法区有它对应的Class 对象,但是该Class 对象不能产生实例对象。因此,作者在这一点上分析 abstract 和 static 的矛盾是不正确的。

那么,abstract 和 static 不能同时使用的原因究竟是什么呢?

        我们知道,抽象方法存在的意义便是被子类覆盖,实现多态性。而静态的方法在内存中只能有一份,所以子类可以继承,但不可以重写。在利用引用访问对象的字段或静态方法时,是引用类型(type)决定了事实上访问的是哪个字段,而非当前引用实际代表的是哪个类。子类的静态方法完全体现不出多态。因此,如果方法即是抽象的并且是静态,这就颠覆了抽象类,抽象方法本身存在的意义!

        关于子类不能覆盖父类的静态方法,引用类型决定了访问哪个类的静态方法,测试代码如下:

 

public class Test {    public static void main(String[] args) {        Door door = new AlarmDoor();        door.get();    }}abstract class Door {    public static void get() {        System.out.print("Door");    }    abstract void set();}class AlarmDoor extends Door {    public static void get() {        System.out.print("AlarmDoor");    }    @Override    public void set() {        // TODO Auto-generated method stub            }}

输出结果:  Door

转载地址:http://lrjwl.baihongyu.com/

你可能感兴趣的文章
斐波纳契博弈
查看>>
oracle redo日志文件损坏恢复
查看>>
python 访问权限
查看>>
新手向-同步关键字synchronized对this、class、object、方法的区别
查看>>
樱道,空蝉,雨空,夏恋,雨道,彩月,幻昼,惊梦,白夜。这些纯音乐
查看>>
企业运维岗位笔试真题
查看>>
[翻译]通往T-SQL的楼梯
查看>>
Oracle计算时间差函数
查看>>
django-pure-pagination使用方法
查看>>
ubuantu 18.04 LTS 版本解决网易云安装启动问题
查看>>
Java分享笔记:泛型类的定义与使用
查看>>
springCloud全实战超详细代码demo+笔记
查看>>
Golang 知识点总结
查看>>
Bitmap
查看>>
(转)arcgis面状文件坐标导出方法
查看>>
LPC824 周立功AM824学习笔记
查看>>
SQL数据库学习之路(三)
查看>>
开发https应用
查看>>
js轮换广告
查看>>
墨菲定律
查看>>