Java - Est-il vraiment « Purement orienté vers des Objets » ? Plongeons dans le monde de Java et essayons de le prouver.
Quelques années avant de commencer à apprendre Java, j'ai appris dans des livres que Java suit le « paradigme de la programmation orientée objet ». Dans le monde Java, tout est objet, même les chaînes (Strings) sont des objets (en langage C, les chaînes sont des tableaux de caractères). A cette époque, je pensais que Java était un langage orienté objet.
Mais plus tard, j'ai vu de nombreux développeurs sur Internet dire que "Java n'est en fait pas purement orienté objet, car tout dans le monde Java n'est pas un objet". Beaucoup de leurs arguments peuvent être résumés par les deux points suivants :
Tous les contenus statiques (variables et méthodes modifiées par la clé statique) n'appartiennent à aucun objet, ils ne sont donc pas objets des choses.
Tous les types de base (char, boolean, byte, short, int, long, float, double) ne sont pas des objets car nous ne pouvons pas faire d'opérations comme les objets normaux (comme : Utiliser ". " pour accéder aux propriétés et méthodes de l'objet).
À cette époque, en raison de mes connaissances et de mon expérience personnelles limitées, j'ai facilement cru à l'argument ci-dessus et j'ai commencé à penser que "Java n'est pas un pur langage de programmation orienté objet".
Plus tard, au cours de mon processus d'apprentissage JVM, j'ai fait une nouvelle découverte :
JVM crée en fait deux objets lors de création d'un objet Objets :
L'un est un objet instance.
L'autre est l'objet Class. L'objet Class ne sera chargé qu'une seule fois dans la JVM. Les méthodes statiques et les propriétés statiques de la classe sont également chargées ensemble. La JVM utilise l'objet Class pour créer des objets d'instance spécifiques (tels que l'objet ci-dessus).
Par exemple, dans l'instruction Java suivante, deux objets seront créés :
Employee emp = new Employee();
L'un est l'objet d'instance emp ; l'autre est l'objet Class , nous pouvons le référencer via Employee.class ; cet objet Class possède toutes les variables statiques et méthodes statiques définies par cette classe. En même temps, si nous accédons au contenu statique via l'objet emp, nous constaterons que l'objet sur lequel il pointe réellement. à est la classe Employé.
Cela révèle également un autre mystère : pourquoi le contenu statique change dans un objet (que ce soit emp ou emp2) et change également dans un autre objet en même temps, car les deux objets changent de contenu à l'intérieur du même objet de Employee.class .
Maintenant, nous allons annuler le premier argument mentionné ci-dessus. Parce qu’il est effectivement confirmé que le contenu statique appartient à un objet.
Mais nous voulons également confirmer le deuxième argument : comme mentionné précédemment, les types primitifs ne sont pas des objets en Java et ils ne peuvent pas effectuer d'opérations de type objet. Afin de résoudre ce problème, Java a officiellement lancé une classe wrapper correspondante pour chaque type primitif (par exemple : Integer correspond à int, Long correspond à long et Character correspond à char). nous pouvons maintenant créer un objet wrapper, tout en effectuant des opérations liées aux objets sur eux. Et, grâce au déballage automatique, nous pouvons attribuer une valeur de type primitif à une référence à sa classe wrapper correspondante. Mais nous ne pouvons toujours pas effectuer d'opérations sur les objets sur ces types primitifs - nous devons créer des objets des classes wrapper correspondantes.
Par exemple :
Integer obj = new Integer(5); // here we can do i.toString(); int i = 5; // but we can't do i.toString() here
Jusqu'à présent, du point de vue de l'utilisateur final, nous pouvons confirmer que « les catégories originales ne sont pas des objets ». (Les développeurs Java sont les utilisateurs finaux de Java car nous l'utilisons et non le créons).
Si vous vous situez du point de vue de JVM, vous ferez de nouvelles découvertes :
En fait, du point de vue de JVM, elle traite tous les "types primitifs" comme des objets." Pour le prouver Un point peut être trouvé grâce au code source de la classe Class ou à la description de la classe Class dans Javadoc
Selon le code source de la classe java.lang.Class, l'annotation de cette classe est :
Description officielle de Java :
Les instances de la classe Class représentent des classes et des interfaces dans une application Java en cours d'exécution. Une énumération est une sorte de classe et une annotation est une sorte d'interface Every. array appartient également à une classe qui se reflète sous la forme d'un objet Class partagé par tous les tableaux avec le même type d'élément et le même nombre de dimensions. Les types Java primitifs (boolean, byte, char, short, int, long, float et double). ), et le mot-clé void sont également représentés en tant qu'objets Class.
Traduction de référence :
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内部,原始类型就是被当作对象来处理的。但是我们开发者直接把 “原始类型” 当作对象使用,开发者应该使用对应的包装来。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!