抽象方法不能是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");
	}
}

运行结果为:

[email protected]

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

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

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

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

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

public class MonitorVehicleTracker {
	public static void main(String[] args){
		Door door = new AlarmDoor();
		door.get();
	}
}
abstract class Door{
	public static  void get() {
		System.out.print("Door");
	}
}
class AlarmDoor extends Door{
	public static void get(){
		System.out.print("AlarmDoor");
	}
}

运行结果不说自明,有兴趣的可以运行一下哈 ~ ~

时间: 2024-08-25 17:30:08

抽象方法不能是static或native或synchroniz 原因及误解的相关文章

抽象方法不能是static或native或synchroniz

abstract 是抽象了,只有声明,没有具体的实现方法 static是静态的,是一种属于类而不属于对象的方法或者属性,而我们知道,类其实也是一个对象,他是在class文件加载到虚拟机以后就会产生的对象,通常来说它是单例的,就是整个虚拟机中只有一个这样的类对象(当然,如果用新的类加载器也会生成新的类的对象). 3.synchronized 是同步,是一种相对线程的锁. 4.native 本地方法,这种方法和抽象方法及其类似,它也只有方法声明,没有方法实现,但是它与抽象方法不同的是,它把具体实现移

为什么构造器不能是abstract, static, final, native or synchronized的?

Unlike methods, a constructor cannot be abstract, static, final, native  or synchronized. 1. A constructor is not inherited, so there is no need to declare it final 2. As the same reason above, an abstract constructor could never be implemented. 3. A

Java修饰符------>static、native和final以及super和this关键字

修饰符修饰符的作用是让被修饰的内容具备特定的功能,在程序中合理使用修饰符可以在语法和功能上实现很多需要的效果.Java 语言中的修饰符主要有 5个:static.final.native.abstract 和 synchronized.这里首先讲解 static.final 和 native 的作用. static 修饰符static 关键字的中文意思是静态的,该修饰符可以修饰成员变量,成员常量和成员方法.使用该关键字修饰的内容,在面向对象中 static 修饰的内容是隶属于类,而不是直接隶属于

The handler class should be static or leaks might occur原因及解决方法

翻译自http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html 在主线程中使用Handler对象,比如下面的代码 public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Handler() { @Override public void handleMessage(Mes

spring boot 项目 freemarker 无法加载static 中 js css 文件 原因(报错404)

去掉@EnableWebMvc  注解 ,相关原因请看原博文 https://blog.csdn.net/testcs_dn/article/details/80249894 原文地址:https://www.cnblogs.com/0kuxia0/p/9605436.html

JAVA基础——Native关键字

一:native声明 在Java中native是关键字.它一般在本地声明,异地用C和C++来实现.它的声明有几点要注意: 1)native与访问控制符前后的关系不受限制. 2)必须在返回类型之前. 3)它一般为非抽象类方法. 4)native方法在异地实现,象抽象方法一样,所以没有方法体,以分号结束.如下列5种声明: native public void f();                         正确. private native void f();              

抽象方法与抽象类

类更多是规范,我只告诉你你需要做,具体怎样做是子类自己去实现----规范 抽象方法只能在抽象类中--如果不在抽象类,那么调用方法的时候却没有实现. 一. 父类也不知道子类到底如何实现,它只是告诉子类必须去实现. abstract  抽象的:一种概念,一个声明,它是没有任何实现的 抽象方法必须在抽象类中,但是抽象类中不仅仅只包含抽象方法,还可以有非抽象成员---子类继承使用 构造函数也可以让子类通过base方式调用 子类不一定需要去实现父类的抽象成员,但是必须是重写方法,同时将重写的方法也定义为a

Java static和final

java提高篇(七)-----关键字static static 在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个"伪全局"的概念,在Java中static表示"全局"或者"静态"的意思,用来修饰成员变量和成员方法,当然也可以修饰代码块. Java把内存分为栈内存和堆内存,其中栈内存用来存放一些基本类型的变量.数组和对象的引用,堆内存主要存放一些对象.在JVM加载一个类的时候,若该类存在static修饰的成员变量和成员方法

C#抽象方法与抽象实例--C#基础

1.抽象方法与抽象类的声明 1)抽象类和抽象方法声明必须包含abstract 2)抽象方法的声明没有方法体:public abstract void fly(); 3)抽象类和抽象法前加上public,不加默认会是private. 4)抽象类的声明就是为了派生和继承,标记为sealed,是不可以继承的. 5)抽象类不能实例化,也就是不能用new.sealed,必须通过继承由派生类实现其抽象方法 6)抽象类可以包含非抽象方法 7)笔记原文: Program.cs: using System;usi