Home  >  Article  >  Java  >  Detailed introduction to verify whether Java is a pure object-oriented language

Detailed introduction to verify whether Java is a pure object-oriented language

黄舟
黄舟Original
2017-03-25 11:12:011438browse

Java——Is it truly “Purely Oriented to Objects”? Let's delve into the world of Java and try to prove it.

A few years before I started learning Java, I learned from books that Java follows the "Object Oriented Programming paradigm". In the Java world, everything is an object, even strings, which are objects (in C language, strings are character arrays). At that time, I thought Java was an object-oriented language.

But later, I saw many developers on the Internet saying that "Java is actually not purely object-oriented, because not everything in the Java world is an object." Many of their arguments can be summarized as the following two points:

  • All static content (variables and methods modified by the static key) do not belong to any objects, so these are non-object things.

  • All basic types (char, boolean, byte, short, int, long, float, double) are not objects because we cannot do operations similar to those of normal objects (such as : Use "." to access the properties and methods of the object).

At that time, due to my limited personal knowledge and experience, I easily believed the above argument, and also began to think that "Java is not a pure object-oriented programming language."

Later, during my JVM learning process, I made a new discovery:

When the JVM creates an object, it will actually create two Objects:

  • One is an instance object.

  • The other is the Class object. The Class object will only be loaded once in the JVM. The static methods and static properties of the class are also loaded together. The JVM uses the Class object to create specific instance objects (such as the above object).

For example, in the following Java statement, two objects will be created:

Employee emp = new Employee();

One is the instance object emp; the other is the Class object, we It can be referenced through Employee.class; this Class object has all the static variables and static methods defined by this class. At the same time, if we access the static content through the emp object, we will find that the object it actually points to is Employee.class.

This also reveals another mystery: why the static content changes in one object (whether emp or emp2) and also changes in another object at the same time, because both objects change Contents inside the same object of Employee.class.

Now, we are going to cancel the first argument mentioned above. Because static content is indeed confirmed to belong to an object.

But we also need to confirm the second argument: As mentioned earlier, primitive types are not objects in Java, and they cannot do object-like operations. In order to solve this problem, Java officially launched a corresponding wrapper class for each primitive type (for example: Integer corresponds to int, Long corresponds to long, and Character corresponds to char). Therefore, in fact, now we can create A wrapper object, while performing object-related operations on them. And, thanks to automatic unboxing, we can assign a primitive type value to a reference to its corresponding wrapper class. But we still can't do object operations on these primitive types - we need to create objects of corresponding wrapper classes.

For example:

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

So far, from an end-user perspective, we can confirm that "original categories are not objects". (Java developers are the end users of Java because we are using it, not creating it).

If you look at the JVM's perspective, you will have new discoveries:

In fact, from the JVM's point of view, it treats all "primitive types" as objects." To prove this You can check it through the source code of the Class class or the description of the Class class in Javadoc

According to the source code of the java.lang.Class class, the annotation of this class is:

Java official description:

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.

Reference translation:

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 Classc0f559cc8d56b43654fcbe4aa9df7b4a 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内部,原始类型就是被当作对象来处理的。但是我们开发者直接把 “原始类型” 当作对象使用,开发者应该使用对应的包装来。

The above is the detailed content of Detailed introduction to verify whether Java is a pure object-oriented language. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn