Java – Ist es wirklich „rein auf Objekte ausgerichtet“? Lassen Sie uns in die Welt von Java eintauchen und versuchen, es zu beweisen.
Einige Jahre bevor ich anfing, Java zu lernen, habe ich aus Büchern gelernt, dass Java dem „Paradigma der objektorientierten Programmierung“ folgt. In der Java-Welt ist alles ein Objekt, sogar Strings (Strings) sind Objekte (in der C-Sprache sind Strings Zeichenarrays). Damals dachte ich, Java sei eine objektorientierte Sprache.
Aber später sah ich viele Entwickler im Internet sagen, dass „Java eigentlich nicht rein objektorientiert ist, weil nicht alles in der Java-Welt ein Objekt ist.“ Viele ihrer Argumente lassen sich wie folgt zusammenfassen:
Alle statischen Inhalte (Variablen und Methoden, die durch den statischen Schlüssel geändert werden) gehören zu keinem Objekt, daher sind diese nicht- Objekt Dinge.
Alle Grundtypen (char, boolean, byte, short, int, long, float, double) sind keine Objekte, da wir keine Operationen wie normale Objekte ausführen können (z. B.: Verwenden Sie „. " um auf die Eigenschaften und Methoden des Objekts zuzugreifen).
Damals glaubte ich aufgrund meines begrenzten persönlichen Wissens und meiner Erfahrung leicht an das obige Argument und begann auch zu denken, dass „Java keine reine objektorientierte Programmiersprache ist.“ "
Später, während meines JVM-Lernprozesses, machte ich eine neue Entdeckung:
JVM erstellt tatsächlich zwei Objekte, wenn ein Objekt erstellt wird Objekte:
Eines ist ein Instanzobjekt.
Das andere ist das Klasse-Objekt. Das Klassenobjekt wird nur einmal in die JVM geladen. Die statischen Methoden und statischen Eigenschaften der Klasse werden auch zusammen geladen. Die JVM verwendet das Klassenobjekt, um bestimmte Instanzobjekte (wie das obige Objekt) zu erstellen.
In der folgenden Java-Anweisung werden beispielsweise zwei Objekte erstellt:
Employee emp = new Employee();
Eines ist das Instanzobjekt emp; das andere ist das Klassenobjekt. Wir können über Employee.class darauf verweisen. Dieses Klassenobjekt verfügt über alle von dieser Klasse definierten statischen Variablen und statischen Methoden. Wenn wir gleichzeitig über das emp-Objekt auf den statischen Inhalt zugreifen, stellen wir fest, dass es tatsächlich auf das Objekt verweist to ist die Employee-Klasse.
Dies enthüllt auch ein weiteres Rätsel: Warum sich der statische Inhalt in einem Objekt (ob emp oder emp2) und gleichzeitig auch in einem anderen Objekt ändert, weil beide Objekte den Inhalt innerhalb desselben Objekts von Employee.class ändern .
Jetzt werden wir das erste oben erwähnte Argument annullieren. Denn es wird tatsächlich bestätigt, dass statischer Inhalt zu einem Objekt gehört.
Aber wir möchten auch das zweite Argument bestätigen: Wie bereits erwähnt, sind primitive Typen in Java keine Objekte und können keine objektähnlichen Operationen ausführen. Um dieses Problem zu lösen, hat Java offiziell eine entsprechende Wrapper-Klasse für jeden primitiven Typ eingeführt (zum Beispiel: Integer entspricht int, Long entspricht long und Character entspricht char). Jetzt können wir ein Wrapper-Objekt erstellen und gleichzeitig objektbezogene Vorgänge an ihnen ausführen. Und dank des automatischen Unboxings können wir der entsprechenden Wrapper-Klassenreferenz einen primitiven Typwert zuweisen. Aber wir können immer noch keine Objektoperationen für diese primitiven Typen durchführen – wir müssen Objekte der entsprechenden Wrapper-Klassen erstellen.
Zum Beispiel:
Integer obj = new Integer(5); // here we can do i.toString(); int i = 5; // but we can't do i.toString() here
Bisher können wir aus Sicht des Endbenutzers bestätigen, dass „Originalkategorien keine Objekte“ sind. (Java-Entwickler sind die Endbenutzer von Java, weil wir es verwenden und nicht erstellen.)
Wenn Sie aus der Perspektive von JVM stehen, werden Sie neue Entdeckungen machen:
Tatsächlich werden aus der Perspektive von JVM alle „primitiven Typen“ als Objekte behandelt.“ Um dies zu beweisen Ein Punkt kann über den Quellcode der Class-Klasse oder die Beschreibung der Class-Klasse in Javadoc gefunden werden
Laut dem Quellcode der Klasse java.lang.Class lautet die Annotation dieser Klasse:
Offizielle Java-Beschreibung:
Instanzen der Klasse Class repräsentieren Klassen und Schnittstellen in einer laufenden Java-Anwendung. Eine Aufzählung ist eine Art Schnittstelle Array gehört auch zu einer Klasse, die als Klassenobjekt dargestellt wird, das von allen Arrays mit demselben Elementtyp und derselben Anzahl an Dimensionen gemeinsam genutzt wird. Die primitiven Java-Typen (boolean, byte, char, short, int, long, float und double). ) und das Schlüsselwort void werden ebenfalls als Klassenobjekte dargestellt.
Referenzübersetzung:
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内部,原始类型就是被当作对象来处理的。但是我们开发者直接把 “原始类型” 当作对象使用,开发者应该使用对应的包装来。
Das obige ist der detaillierte Inhalt vonDetaillierte Einführung zur Überprüfung, ob Java eine reine objektorientierte Sprache ist. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!