java面向对象语言_Java到底是不是一种纯面向对象语言?

英文原文:Why Java Is a Purely Object-Oriented Language Or Why Not

Java是否确实是 “纯面向对象”?让我们深入到Java的世界,试图来证实它。

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

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

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

所有基本类型(char,boolean,byte,short,int,long,float,double)都不是对象,因

为我们不能做类似对象的所具有的操作(例如:使用“.”来访问对象的属性和方法)。

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

到了更后来,我发现JVM在创建对象的时候,实际上会创建两个对象:

一个是实例对象。

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

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

Employee emp = new Employee ();

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

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

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

但是我们还要确认第二个论点:正如早前提到的,原始类型在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 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确实是一个纯粹的面向对象语言”的证实过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267053.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python--DBUtil

Python--DBUtil包 1 简介 DBUtils是一套Python数据库连接池包&#xff0c;并允许对非线程安全的数据库接口进行线程安全包装。DBUtils来自Webware for Python。 DBUtils提供两种外部接口&#xff1a; PersistentDB &#xff1a;提供线程专用的数据库连接&#xff0c;并自动管理…

java calendar计时器_Java Calendar setTimeInMillis()用法及代码示例

Calendar类中的setTimeInMillis(long mill_sec)方法用于根据传递的long值设置由此Calendar表示的Calendars时间。用法:public void setTimeInMillis(long mill_sec)参数&#xff1a;该方法采用long类型的一个参数mill_sec&#xff0c;表示要设置的给定日期。返回值&#xff1a;…

找出两个字符串数组中的相同元素

public static List<String> getAllSameElement1(String[] strArr1,String[] strArr2) { if(strArr1 null || strArr2 null) { return null; } List<String> strList1 new ArrayList<String>(Arrays.asList(strArr1)); //----------代码段1 List<…

@ConfigurationProperties和@Value不同的使用场景,@Bean添加组件 (6.spring boot配置文件注入)...

接上文 注释掉ConfigurationProperties使用Value注解 /*** <bean class"Person">* <property name"lastName" value"字面量/${key}从环境变量、配置文件中获取值/#{spel}"></property>* <bean/>*/ //Spring底层注解…

sqlite的数据导入 导出

数据导入的来源可以是其他应用程序的输出&#xff0c;也可以是指定的文本文件&#xff0c;这里采用指定的文本文件。 1. 首先&#xff0c;确定导入的数据源&#xff0c;这里是待导入的&#xff0c;按固定格式的文本文件。 2. 然后&#xff0c;依照导入的文件格式&#xff0…

java继承孙子类_Java:类与继承

Java&#xff1a;类与继承对于面向对象的程序设计语言来说&#xff0c;类毫无疑问是其最重要的基础。抽象、封装、继承、多态 这四大特性都离不开类&#xff0c;只有存在类&#xff0c;才能体现面向对象编程的特点&#xff0c;今天我们就来了解一些类与继承的相关知识。首先&am…

linux 下安装JDK

安装配置JDK 下载JDK 因为Elasticsearch需要Java环境&#xff0c;所以需先下载JDK&#xff0c;并配置Java的环境\ 下载地址&#xff1a;http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html\ 这里我选择jdk-8u151-linux-x64.tar.gz解压安装…

在ubuntu上搭建LNMP服务器

LNMP Linux Nginx MySQL PHP 安装Nginx 执行以下命令即可: apt-get install nginx不过源里的版本是0.7.65&#xff0c;不喜欢老旧的玩意&#xff0c;可以尝试编译安装。 编译安装nginx. 1.准备编译环境 apt-get install libpcre3-dev build-essential libssl-dev在这里 htt…

java 后端开发好吗_后端开发学Java好还是学c++好呢?

C与 java 的抉择为了找工作&#xff1a;选Java。为挑战自我&#xff1a;选C。很多人都说会C就能会快掌握Jave。C是不好学&#xff0c;但是我告诉你java也不好学。C难是难在语言本身&#xff0c;java难是难在各种框架和库。你单纯学个java语法&#xff0c;你什么玩意也做不了&am…

mysql表名忽略大小写

MYSQL表名忽略大小写 问题描述&#xff1a;一开发同事在linux下调一个程序老是报错说找不到表&#xff0c;但是登陆mysql&#xff0c;show tables查看明明是已经创建了这张表的&#xff01;&#xff01;如下&#xff1a; 1234567891011121314151617181920212223mysql> show …

邮件联系人,如何恕不部分字母就能显示邮件联系人

新装的电脑&#xff0c;邮件pst文件已经导入成功&#xff0c;但是我想给别人发邮件时&#xff0c;输入个别英文字母就能显示对方的邮件地址&#xff0c;这样该如何操作呢&#xff1f;PST文件已经导入成功&#xff0c;邮件联系人中也能看到公司所有人的联系方式。转载于:https:/…

java的class和object_Java中Class/Object/T的关系

Object 对象Object是Java中的基类&#xff0c;大部分的对象都是继承于这个类。public class Object {....public native int hashCode();public boolean equals(Object obj) {...}public String toString() {...}}以上是其定义&#xff0c;可以看出来其定义了一些基础方法&…

P2787 语文1(chin1)- 理理思维

题目背景 蒟蒻HansBug在语文考场上&#xff0c;挠了无数次的头&#xff0c;可脑子里还是一片空白。 题目描述 考试开始了&#xff0c;可是蒟蒻HansBug脑中还是一片空白。哦不&#xff01;准确的说是乱七八糟的。现在首要任务就是帮蒟蒻HansBug理理思维。假设HansBug的思维是一长…

使用jstree创建无限分级的树(ajax动态创建子节点)

首先来看一下效果 页面加载之初 节点全部展开后 首先数据库的表结构如下 其中Id为主键,PId为关联到自身的外键 两个字段均为GUID形式 层级关系主要靠这两个字段维护 其次需要有一个类型 public class MenuType{public Guid Id { get; set; }public Guid PId { get; set; }publi…

oracle长连接超时设置

方法一、在sqlnet.ora中设置参数 如需要设置客户端空闲10分钟即被中断&#xff0c;则在sqlnet.ora的末尾添加SQLNET.EXPIRE_TIME10注&#xff1a;sqlnet.ora文件的路径在$ORACLE_HOME/network/admin下。 方法二、Oracle Profile中设置 生产库上执行如下操作&#xff1a; SQL>…

linux syslog 笔记

原文地址 Linux日记系统由系统日志监控程序syslogd和内核日志监控程序klogd组成。从它们的命名可以看到&#xff0c;这两个监控程序都是守护程序&#xff08;daemon&#xff09;&#xff0c;且都注册成了系统服务。换句话说&#xff0c;我们可以在目录/etc/init.d/下找到它们对…

Jenkins构建Spring+Nodejs项目

构建node.js环境1.安装 node.js 2.项目目录下执行 npm i -production 安装依赖的包install时会在项目目录下生成node_modules目录&#xff0c;使用-production只会下载依赖相关的包&#xff0c;否则会下所有的包&#xff08;太大了&#xff09;。因为编译主机不能联网&#xff…

解析Hibernate的结构

在学习Hibernate的时候&#xff0c;首先要了解Hibernate的大体结构&#xff0c;这样才能更好的理解其中的知识&#xff0c;下面就开始分析Hibernate的体系结构 1.HIbernate简要的体系结构如下图所示&#xff1a; 通过上图能够发现HIbernate需要一个hibernate.properties文件&am…

Java反梯形图案_梯形法求定积分(一)设计梯形法求积分的类模板,梯形法

/*设计梯形法求积分的类模板&#xff0c;梯形法求积分的函数被定义为成员函数&#xff0c;可以求任意函数的定积分&#xff0c;用积分类的模板参数T引入被积函数*/#include#include#includeusing namespace std;class Mysin{public:double fun(double x){return (sin(x));}};cl…

排序算法杂谈(三) —— 归并排序的非递归实现

1. 递归 在众多排序算法中&#xff0c;归并排序&#xff08;Merge Sort&#xff09;和快速排序&#xff08;Quick Sort&#xff09;都是时间复杂度为 O(nlog2n) 的高效排序。 这两种排序有一种共性&#xff0c;就是运用到了递归的思想。 在程序设计中&#xff0c;递归是一个很有…