Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java是一种纯面向对象的语言吗?

Java是一种纯面向对象的语言吗?

作者头像
森七
修改于 2020-04-15 02:27:02
修改于 2020-04-15 02:27:02
1.1K0
举报
文章被收录于专栏:博客圈博客圈

在刚开始学习 Java 的前面几年,我从书本里知道了 Java 是遵循 “面向对象编程范式(Object Oriented Programming paradigm)”的。在Java世界内一切都是对象,甚至包括字符串(String)这些都是对象(在 C 语言中,字符串是字符数组),那时候,我认为 Java是一种面向对象的语言。

但是在后来,我在互联网站上陆续看到不少开发者说 “Java实际上不是纯粹的面向对象,因为并不是所有的东西在 Java 世界都是一个对象”。他们很多的论点都可以概括为以下两点:

所有的静态内容( static 关键修饰的变量和方法)不属于任何对象,所以这些是非对象的东西。

所有基本类型(char,boolean,byte,short,int,long,float,double)都不是对象,因为我们不能做类似正常对象的所具有的操作(例如:使用“.”来访问对象的属性和方法)。

在那时,由于个人知识经验储备有限,我又很容地相信上面的论点,并且也开始认为 “Java 不是纯粹的面向对象编程语言”。

到了更后来,在我的一次JVM学习过程中,我有了新的发现:

JVM 在创建对象的时候,实际上会创建两个对象:

一个是实例对象。

另一个是Class 对象。该 Class 对象在JVM内仅仅会装载一次,该类的静态方法和静态属性也一同装载,JVM使用该 Class 对象来创建具体的实例对象(如上面的对象)。

例如,在下面的 Java 语句中,将有两个对象被创建:

Employee emp = new Employee();

一个是实例对象 emp ;另一个则是 Class对象,我们可以通过 Employee.class 引用到它;这个 Class 对象拥有所有的这个类定义的静态变量和静态方法,同时,如果我们访问 通过 emp 对象来访问静态内容,会发现它其实指向的对象就是 Employee.class 。

这也揭开了另一个迷:为什么静态内容在一个对象中(不管是emp还是emp2)改变了,在另一个对象中也同时改变,因为这两个对象改变的都是在 Employee.class 同一个对象里面的内容。

现在,上面说到的第一个论点我们要取消了。因为,静态内容确实被证实属于一个对象。

但是我们还要确认第2个论点:正如早前提到的,原始类型在Java中不是对象,它们无法做类似对象的操作。为了解决这个问题,Java 官方为每一个原始类型推出了对应的包装类(比如:Integer 对应 int,Long 对应 long,Character 对应 char),所以,其实现在我们可以为原始类型创建一个包装对象,同时对它们做对象相关的操作。并且,由于自动拆装箱,我们可以把一个原始类型值赋值给它对应的包装类的引用。但是我们仍然不能对这些原始类型做对象的操作——我们需要创建对应包装类的对象。

例如:

Integer obj = new Integer(5); // here we can do i.toString();

int i = 5; // but we can't do i.toString() here

到目前为止,从一个最终用户的角度上来看的,我们可以确认 “原始类别不是对象”。( Java开发人员是Java的最终用户,因为我们正在使用它,而不是创造它 )。

如果站在JVM的视角,会有新的发现:

其实,在JVM看来它把所有的 “原始类型” 都是当作对象处理” ,要证明这一点可以通过 Class类的源代码 或者 Javadoc中Class类的说明。

根据 java.lang.Class 类的源代码,该类的注释是(Java官方描述):

Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.

参考译文:

Class类的实例表示正在运行的Java应用程序的类和接口。像枚举是一种类和注解则是一种接口。每个数组也属于被反射作为由具有相同的元素类型和尺寸的数目的所有阵列共享一类对象的类。原始的Java类型(boolean, byte, char, short, int, long, float, and double)和关键字void也表示为Class对象。

同时也根据Javadoc中对Class.isPrimitive()方法的定义,来判断(Java官方描述):

public boolean isPrimitive()

Determines if the specified Class object represents a primitive type.

There are nine predefined Class objects to represent the eight primitive types and void. These are created by the Java Virtual Machine, and have the same names as t he primitive types that they represent, namely boolean,byte, char, short, int, long, float, and double.

These objects may only be accessed via the following public static final variables, and are the only Class objects for which this method returns true.

Returns:

true if and only if this class represents a primitive type

Since:

JDK1.1

参考翻译:

public boolean isPrimitive()

判断指定的Class对象是否代表一个基本类型。

一共有9种设定好的Class对象来表示对应的基本类型和void关键字。这些对象都是由JVM创建的。…

return

当且仅当该类表示一个真正的基本类型

以上都说明,在JVM内部,其实原始类型就是对象。

当你打开 Javadoc 对 Class 类的定义中,通过 “CTRL+F ” 查找关键字 “primitive”, 将会发现证据在表面 “在JVM里,它把基本类型当作对象来处理的”。

我们可以再来看一个例子: Integer.TYPE,在这部分文档清晰记录着(Java官方描述):

public static final Class<Integer> TYPE

The Class instance representing the primitive type int.

以上都说明,在JVM内部,其实原始类型就是对象。

那么,既然说 “JVM”会为所有的基本类型创建一个对象,那我们为什么还那么常用 “原始类型”, 而不是直接使用对应的包装类对象呢?

这是因为,为 “原始类型” 创建的对象,在JVM内部是很轻量级的,相对与我们直接创建的对应包装类对象做了许多优化; 也正因为轻量的缘故,这些原始类的功能就比较少(例如我们不能调用其内部的方法,因为他们内部已经优化成没有方法了)

使用实际的例子来说明,为什么我们更应该使用 “原始类型”:

“原始类型”有更快的速度(例如,下面的代码执行,在我们的机器上需要9秒,但当我把 Long 改成 long 之后,0秒内就完成了)

public static void main(String[] args) {

   long millis = System.currentTimeMillis();

   Long sum = 0L; // uses Long, not long

   for (long i = 0; i <= Integer.MAX_VALUE; i++) {

       sum += i;

   }

   System.out.println(sum);

   System.out.println((System.currentTimeMillis() - millis) / 1000);

}

“原始类型”允许我们直接使用 “==”来进行比较

new Integer(3) == new Integer(3); // false

new Integer(100) == new Integer(100); // false

Integer.valueOf(5) == Integer.valueOf(5); //true

Integer.valueOf(200) == Integer.valueOf(200); //false

我们注意看第四句,输出结果确实为 “false” 。这个是因在 [-128; 127] 这个区间的265个整数会被 JVM 缓存存放, 所以在这个区间, JVM返回相同的对象;然而,超出这个区间, JVM就不再有缓存了,将会创建新的对象,所以结果是不等的。

所以总结一下是: 在JVM内部,原始类型就是被当作对象来处理的。但是我们开发者直接把 “原始类型” 当作对象使用,开发者应该使用对应的包装来。

以上就是为什么我说 “ Java确实是一个纯粹的面向对象语言 ”的证实过程。如果你们对这个有什么其他的观点,请在评论留言,一起讨论。

来自计算机技术微信

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java到底是不是一种纯面向对象语言?
Java——是否确实的 “纯面向对象”?让我们深入到Java的世界,试图来证实它。
哲洛不闹
2018/09/18
4410
Java到底是不是一种纯面向对象语言?
「JAVA」Java 一切皆对象,基本类型也没下,包装类自动拆装箱来相助
故此,针对Java基本数据类型封装了包装类,每一个基本类型都有一个对应的包装类,以下是详情:
老夫编程说
2020/04/25
5120
「JAVA」Java 一切皆对象,基本类型也没下,包装类自动拆装箱来相助
Java实用类(二)-包装类
​ Java中的基本类型功能简单,不具备对象的特性,为了使基本类型具备对象的特性,所以出现了包装类,就可以像操作对象一样操作基本类型数据;包装类不是为了取代基本数据类型,而是在数据类型需要使用对象表示的时候,才使用包装类;
化羽羽
2022/10/28
4110
Java八种包装类、常量池
还记得 Java八种基本数据类型及对应包装类、四种引用类型吗?如果忘记可以到这里重温复习Java数据类型(八种基本数据类型 + 四种引用类型)、数据类型转换
寻求出路的程序媛
2024/04/27
2350
Java八种包装类、常量池
Java 自动装箱对性能的影响大还是小?如何解决 Java 自动装箱性能问题?
原始类型代表了用代码表示数据的最简单,最直接的方法。即使 Java 中最复杂的类也可以简化为它们所表示的原始数据类型集。但是原始类型不是对象,这带来了一个问题。
用户2242639
2021/06/29
1.6K0
为什么Java不是纯面向对象语言?
纯面向对象语言或完全面向对象语言是指完全面向对象的语言,它支持或具有将程序内的所有内容视为对象的功能。它不支持原始数据类型(如int,char,float,bool等)。编程语言满足七种标准可以就可以称为纯粹的面向对象语言,他们是:
淡定的蜗牛
2019/09/11
1.2K0
Java面向对象进阶
Java提供的基本类型包装类,使得Java能够更好的体现面向对象的思想,同时也使得基本类型能够支持对象操作
用户9645905
2023/10/23
2190
Java面向对象进阶
Java核心-面向对象(下)
之前说完了类、对象、方法以及面向对象的三大特性封装、继承和多态,现在来了解一下接口、代码块和一些常见的类如抽象类、包装类等。
reload
2024/02/21
1510
Java核心-面向对象(下)
面试官六连问拆箱装箱Integer那些事,给我整懵圈了!
小萌:由于基本数据类型不是对象,所以java并不是纯面向对象的语言,好处是效率较高(全部包装为对象效率较低)。Java是一个面向对象的编程语言,基本类型并不具有对象的性质,为了让基本类型也具有对象的特征,就出现了包装类型(如我们在使用集合类型Collection时就一定要使用包装类型而非基本类型),它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作。
乔戈里
2020/02/21
5630
面试官六连问拆箱装箱Integer那些事,给我整懵圈了!
JVM - 基本类型的包装类和对象池
java中基本类型的包装类的大部分都实现了常量池技术(严格来说应该叫对象池,在堆上),这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类Float 、Double则没有实现。
小小工匠
2021/08/17
5100
【趣学程序】java面向对象(二)
Integer,Byte,Float,Double,Short,Long都是Number类的子类。Character和Boolean都是Object直接子类;这8个类都是final修饰的(不可被继承)。
趣学程序-shaofeer
2019/07/27
3920
JAVA自动拆装箱、equals与==比较
自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。
chenchenchen
2023/01/30
4410
Java基础(十四):包装类
Java微观世界
2025/01/21
1040
Java基础(十四):包装类
007-014:关于包装类的面试题
Java的类型系统由两部分组成:基本类型(primitive)和引用类型(reference type)。包装类指的是Java基础类型对应的引用类型。每个基本类型都有一个对应的包装类:
阿杜
2019/03/12
6990
面试真题:Integer(128)引发的思考
Hey小伙伴们,今天要给大家安利一篇操作实践的文章,相信大家通过仔细阅读,一定会有所收货!
不惑
2024/11/26
4020
面试真题:Integer(128)引发的思考
Java 包装类
​  Java为每一个基本数据类型提供了对应的一个包装类。包装类是一个类,这样Java就可以在包装类中提供常用的方法等供我们使用。   java并不是纯面向对象的语言,java语言是一个面向对象的语言,但是java中的基本数据类型却不是面向对象的,但是我们在实际使用中经常将基本数据类型转换成对象,便于操作,比如,集合的操作中,这时,我们就需要将基本类型数据转化成对象!
愷龍
2022/09/26
6420
Java 包装类
Java 为什么需要包装类,如何使用包装类?
Java 是号称面向对象的语言,所有的类型都是引用类型。 Object 类是所有类的父类,而且是唯一不用指定明确继承的类。但是基本类型如 int 不是引用类型,也不是继承自 Object,所以 Java 需要一个这样的包装类来使其面向对象的完整性。 包装类同时也可以实现可空类型,即一个数值是空的。Java 集合中也只能放入包装类型,而不支持基本类型。
水货程序员
2018/11/13
6.8K0
夯实Java基础系列2:Java基本数据类型,以及自动拆装箱里隐藏的秘密
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
程序员黄小斜
2019/09/25
3.5K0
Java面向对象基础(8)常用类
Java是面向对象的语言,但并不是“纯面向对象”的,因为我们经常用到的基本数据类型就不是对象。但是我们在实际应用中经常需要将基本数据转化成对象,以便于操作。比如:将基本数据类型存储到Object[]数组或集合中的操作等等。
徐建国
2021/08/03
4890
Java面向对象基础(8)常用类
如何理解Java中的自动拆箱和自动装箱?
回到家后小伟赶紧查资料,我透,这不就是问基本类型跟封装类型吗,面试官整啥名词呢...
niceyoo
2020/05/28
1.5K0
相关推荐
Java到底是不是一种纯面向对象语言?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档