【Java基础】13、抽象方法不能是static或native或synchroniz 原因及误解
在网上看到过这么一篇文章,是关于抽象方法不能是static或native或synchroniz 的原因。其中提到了这些关键字的意义以及与 abstract 关键字的冲突,大体内容如下:
1、abstract是抽象的,指的是方法只有声明而没有实现,他的实现要放入声明该类的子类中实现。
2、static是静态的,是一种属于类而不属于对象的方法或者属性,而我们知道,类其实也是一个对象,他是在class文件加载到虚拟机以后就会产生的对象,通常来说它是单例的,就是整个虚拟机中只有一个这样的类对象(当然,如果用新的类加载器也会生成新的类的对象)。
3、synchronized 是同步,是一种相对线程的锁。
4、native 本地方法,这种方法和抽象方法及其类似,它也只有方法声明,没有方法实现,但是它与抽象方法不同的是,它把具体实现移交给了本地系统的函数库,而没有通过虚拟机,可以说是Java与其它语言通讯的一种机制。
然后作者逐个分析了冲突的原因:
首先abstract与static,其实一看他们的作用和属性就很容易辨别,abstract是没有实现的,而static一定要有实现,因为 abstract的类不能生产对象,但是static是属于类,而类已经是一个存在的对象,这两个关键字在这上面有一个关键的矛盾点。
synchronized 是同步,然而同步是需要有具体操作才能同步的,如果像abstract只有方法声明,那同步一些什么东西就会成为一个问题了,当然抽象方法在被子类继承以后,可以添加同步。
native,这个东西本身就和abstract冲突,他们都是方法的声明,只是一个吧方法实现移交给子类,另一个是移交给本地操作系统。如果同时出现,就相当于即把实现移交给子类,又把实现移交给本地操作系统,那到底谁来实现具体方法呢?
作者对于 synchronized 和 native 关键字冲突的原因分析笔者是没有异议的,关键就在于 static 冲突的原因。
在第三段中红色文字标出的部分中,作者说“类其实也是一个对象”,只要是对 JVM类加载机制懂一点的人来说,这个是没问题的。而在后面分析原因部分,作者说“abstract 的类不能产生对象,但是static属于类,类已经是一个存在的对象”,这个也是没有异议的。关键在于后面,作者又说 ”这两个关键字在这一个关键点上有矛盾“。对于这句话,作者混淆了类对象和实例对象的概念了。
不管是不是抽象类,只要使用到了该类,虚拟机总是会在方法区中为该类创建一个 Class 对象,用来描述该类的运行时结构。我们写一段代码做一个简单的测试,如下:
- public class MonitorVehicleTracker {
- public static void main(String[] args){
- System.out.print(Door.class.getClassLoader());
- }
- }
- abstract class Door{
- public static void set() {
- System.out.print("123");
- }
- }
运行结果为:
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
【Java基础】13、抽象方法不能是static或native或synchroniz 原因及误解的更多相关文章
- 抽象方法不能是static或native或synchroniz
abstract 是抽象了,只有声明,没有具体的实现方法 static是静态的,是一种属于类而不属于对象的方法或者属性,而我们知道,类其实也是一个对象,他是在class文件加载到虚拟机以后就会产生的对 ...
- Java基础13:反射与注解详解
Java基础13:反射与注解详解 什么是反射? 反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. Orac ...
- Java基础13:反射详解
本节主要介绍Java反射的原理,使用方法以及相关的技术细节,并且介绍了关于Class类,注解等内容. 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech ...
- 【java基础 13】两种方法判断hashmap中是否形成环形链表
导读:额,我介绍的这两种方法,有点蠢啊,小打小闹的那种,后来我查了查资料,别人都起了好高大上的名字,不过,本篇博客,我还是用何下下的风格来写.两种方法,一种是丢手绢法,另外一种,是迷路法. 这两种方法 ...
- java基础(13):static、final、匿名对象、内部类、包、修饰符、代码块
1. final关键字 1.1 final的概念 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子 ...
- java基础复习:final,static,以及String类
2.final 1)为啥String是final修饰的呢? 自己答: 答案: 主要是为了“效率” 和 “安全性” 的缘故.若 String允许被继承, 由于它的高度被使用率, 可能会降低程序的性能,所 ...
- Java基础学习笔记十 Java基础语法之final、static、匿名对象、内部类
final关键字 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承了这些特殊类之后,就可以对 ...
- java基础13 接口(及关键字:interface、implements)
接口 1.接口的定义格式 interface 接口名{ } interface :接口的关键字 implements:实现接口的关键字 2.接口的作用 1.程序的解耦.(低耦合) 2.定 ...
- Java基础:关键字final,static
一 . final 含义:adj.最后的,最终的; 决定性的; 不可更改的.在Java中是一个保留的关键字,可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了 ...
随机推荐
- C语言中的语句
• 表达式语句 表达式后加 ; 构成表达式语句. a = b+c; x+y i++ • 控制语句 完成一定的控制功能. if(...){...}else{...} ...
- Git学习篇之git remote add origin错误
提示出错信息:fatal: remote origin already exists. 解决办法如下: 1.先输入$ git remote rm origin 2.再输入$ git remote ad ...
- webapi 自定义缓存实现
定义一个Filter public class MyOutputCacheAttribute : ActionFilterAttribute { MemoryCacheDefault _cache = ...
- MyBatis 源码分析 - 插件机制
1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展.这样的好处是显而易见的,一是增加了框架的灵活性.二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作.以 My ...
- Lerning Entity Framework 6 ------ Handling concurrency With SQL Server Database
The default Way to handle concurrency of Entity Framework is using optimistic concurrency. When two ...
- HYSBZ2565最长双回文串 Manacher
顺序和逆序读起来完全一样的串叫做回文串.比如 acbca 是回文串,而 abc 不是( abc 的顺序为 “abc” ,逆序为 “cba” ,不相同). 输入长度为 n 的串 S ,求 S 的最长双回 ...
- AndroidStudio制作“我”的界面,设置,修改密码,设置密保和找回密码
前言 大家好,给大家带来AndroidStudio制作"我"的界面,设置,修改密码,设置密保和找回密码的概述,希望你们喜欢 学习目标 掌握修改密码功能的开发,和实现用户密码的修改: ...
- jQuery应用实例5:表单验证
1.validation插件的使用: 入门案例: <html> <head> <meta charset="UTF-8"> <title& ...
- Java学习笔记35(异常)
代码在运行中发生的问题就是异常 java中把多种异常封装多个类,当程序出现问题时候,就会创建异常类对象并且抛出相关信息 异常体系: Throwable类是Java中所有错误或异常的父类 Throwab ...
- python中基于queue的打印机仿真算法
使用打印机的模型是queue中最经典的应用之一,这里就回顾一下queue在这里的使用方法和 起的重要作用. 为了仿真打印状态,这里需要把真实环境中的三个物理模型要建模出来,分别是:打印者,打印 任务, ...