Java不是100%的面向对象

最近看到一篇外文,阐释了为什么java不是100%的面向对象,外文翻译如下:

几年前,当我开始学习Java时,我知道Java遵循  面向对象的编程范例,Java中的所有东西都是一个对象 - 一个String(在C中是一个char数组)或一个数组本身。

但后来我发现人们在互联网上说Java实际上不是纯粹的面向对象,因为Java中的所有内容都不是对象; 例如:

  1. 所有基本类型(char,boolean,byte,short,int,long,float,double)都不是对象,因为我们无法对它们执行任何类似对象的操作(使用“。”和调用方法)。
  2. 我还发现有些人说所有静态内容(变量和方法)都不属于任何对象,因此它们是非对象的东西。

由于我的知识匮乏和经验不足,我很容易接受这些原因并开始相信Java不是纯粹的面向对象的编程语言。

但后来我发现JVM为每个对象创建了两个对象:

  1. 对象本身。
  2. 还有一个Class级别对象(由ClassName.class语法引用),只有在Classloader将类加载到内存时才会创建一次。该类的所有静态内容都属于此Class对象,该类的所有其他对象都引用所有静态内容的此类级对象。

例如,在以下语句中,将创建两个对象:

Employee  emp  =   new  Employee();

一个是emp本身,另一个是employee类的类级对象,我们可以通过Employee.class引用它。此类级别对象包含Employee类的所有静态内容,它是变量或方法。如果我们通过emp对象访问任何静态内容,它指向Employee.class对象来访问它。

这就是为什么静态变量为每个对象更改的原因,即使我们为单个emp对象更改它,因为所有emp对象都指向Employee.class对象中该变量的相同副本。

现在第二个点被取消,因为静态内容属于一个对象。但第一点仍然存在,我们仍然在Java中有原始数据类型,它们不是对象。

如前所述,原始类型不是对象,因为我们无法对它们执行任何与对象相关的功能。为了克服这个问题,Java为每个基本类型引入了Wrapper类(例如,Integer用于int,Long用于long,Character用于char)。现在我们可以为基本类型创建对象,并对它们执行所有与对象相关的操作。

由于自动装箱(自动拆箱装箱,装箱拆箱),我们可以直接将原始文字分配给其Wrapper类参考。但是我们仍然无法对原始变量执行这些操作 - 我们总是需要创建相应Wrapper类的对象。

例如:

整数 obj  =  new  Integer(5); //这里我们可以做i.toString();
int  i  =  5 ; //但我们不能在这里做i.toString()

到目前为止,很明显原始类型不是对象,但实际上这是最终用户的观点(Java开发人员是Java的最终用户,因为我们正在使用它,而不是创建它)。

JVM在内部将所有基本类型视为对象,并且可以在源代码或类Class的Javadoc中找到对此的证明。根据类Class的源代码:

类Class的实例表示正在运行的Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组也属于一个类,它反映为一个Class对象,由具有相同元素类型和维数的所有数组共享。原始Java类型(boolean,byte,char,short,int,long,float和double)和关键字void也表示为Class对象。

Class.isPrimitive()方法的Javadoc代码:

public boolean isPrimitive() 
确定指定的Class对象是否表示基本类型。 
有九个预定义的Class对象来表示八种基本类型和void。它们由Java虚拟机创建,并且与它们表示的基本类型具有相同的名称,即boolean,byte,char,short,int,long,float和double。 
这些对象只能通过以下公共静态final变量访问,并且是此方法返回true的唯一Class对象。 
返回:
当且仅当此类表示基本类型时返回 true 
自: 
JDK1.1 
参见: 
Boolean.TYPE,  Character.TYPE,  字节.TYPE,  Short.TYPEInteger.TYPE,  Long.TYPE,  Float.TYPE,  Double.TYPE,  Void.TYPE

如果打开类Class的Javadoc 并对单词“primitive”执行Ctrl + F,您会发现很多理由认为JVM在内部将所有原始类型视为对象。

让我们打开上面的  Integer.TYPE条目。在本节中,您将找到:

public static final  Class <  Integer > TYPE 
表示基本类型int的Class实例。

如果您使用Eclipse在程序中编写以下行:

Integer.TYPE i = 5;

您将收到编译错误,指出无法将Integer.TYPE解析为带有Eclipse提示的类型,以将其更改为int。

我们为什么要使用原始类型

如果JVM为所有基本类型创建对象,为什么我们需要使用基本类型而不是使用相应的Wrapper类创建对象?这是因为JVM在内部为原始类型创建了这些本机对象,并且这些对象非常轻量级,并且比它们各自的包装类对象更优化; 因此他们的功能较少(例如我们不能在他们身上调用方法,因为他们没有任何功能)。

我们应该使用原始类型:

  1. 因为它们很快(例如,以下程序需要9秒才能在我的机器上运行,而如果我将Long sum转换为长总数需要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);
}
  1. 它们允许我们使用本机相等运算符“==”:
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,因为256个整数最接近零[-128; 缓存由JVM缓存,因此它们返回相同的对象。但是,超出该范围,它们不会被缓存,因此会创建一个新对象。

所以我们可以说JVM在内部将所有原始类型视为对象,但我们不能以这种方式使用它们; 相反,我们有Wrapper类。

原文:https://dzone.com/articles/why-java-is-purely-object-oriented-language-or-why-1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值