Hablando sobre el objeto y referencia

Objetos y referencias

nuevo objeto

El ejemplo más sencillo:

new Object();

En pocas palabras, new Object () es una instancia de tipo de objeto creado (ejemplo), asignado en la memoria de pila JVM

Para método público como un ejemplo, mira:

PD: si el método es público o privado / protegido / método de paquete, o método de construcción es, incluso en un bloque estático, las variables estáticas, variables de instancia, nuevo objeto de esta acción, es mucho lo mismo

public class Test {
	public void fun1() {
        Object o = new Object();
    }
}

En el método fun1 de la clase de prueba se crea una instancia de un objeto, y se asigna a una variable de tipo Object, cuando se llama a este método, ¿qué pasó?

1. Realice javac Test.javacompilados a Test.classarchivos

2. ejecución javap -v Test.class, se puede ver el compilado .classarchivo de código de bytes. Éstos son sólo fun1

public void fun1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class java/lang/Object
         3: dup
         4: invokespecial #1                  // Method java/lang/Object."<init>":()V
         7: astore_1
         8: return
      LineNumberTable:
        line 3: 0
        line 4: 8

la sección del Código de enfoque

pila = 2 indica que el proceso requiere una profundidad de pila de operandos 2

locales = 2 indica que el proceso requiere de dos espacio variable local de Slot

Aquí es seguido por el desplazamiento y el correspondiente conjunto de instrucciones JVM, podemos analizar estos paso a paso conjunto de instrucciones para hacer algo

En primer lugar, la inicialización de la pila de operandos y el espacio variable local es tal que:

Juego de operaciones código correspondiente
0: nuevo, crear una instancia de un tipo java.lang.Object, y su valor de referencia en la pila de operandos de la pila (PS: Esto no se refiere a un valor de referencia Object o)
de la pila de operandos: [libre], [ObjectRef]
tabla de variables locales: [del presente], [libre]
new Object ()
3: dup, copia la pila valor del operando pila, y apile el valor del operando en la pila
de operando pila: [ObjectRef], [ObjectRef]
tabla de variables locales: [el este], [libre]
new Object ()
4: invokespecial, llamando a la java.lang.Object " ": () V El método de
la pila de operandos: , [ObjectRef] [libre]
tabla de variables locales: [el este], [libre]
new Object ()
7: astore_1, el valor de referencia de la parte superior de la pila en las variables locales segunda
pila de operandos: [libre], [libre]
tabla de variables locales: [el este], [ObjectRef]
Object o = new Object (), principalmente el operador de asignación
8: retorno, desde el actual método devuelve void

A partir del análisis de los pasos anteriores se puede encontrar, un método simple en una nueva operación de objeto, la JVM se ejecuta tres instrucciones, a saber:

  • Crear el objeto y la pila de valor de referencia
  • Copiar la parte superior del valor de la pila
  • Llamar al constructor de la superclase

Este valor de referencia ObjectRef conducir más fácilmente a la ambigüedad, se suele decir que la referencia es a Object o = new Object()la dar al operador la izquierda del objeto O , señalar que esta sentencia no crea una referencia, pero la referencia a la instancia del objeto, en las variables locales

VS no se asigna la asignación

Al crear objetos a utilizar, en esta situación

Object o = new Object();
o.toString();

Crear una instancia del tipo de objeto, y luego llamar a su toStringmétodo

El mismo texto también puede ser de esta manera:

new Object().toString();

¿Hay alguna diferencia de estos dos métodos? Por instrucciones de la JVM para mirar

fuente:

public class Test {
	public void invokeWithoutReference() {
		new Object().toString();
	}
	public void invokeWithReference() {
		Object o = new Object();
		o.toString();
	}
}

conjunto de instrucciones ( javap -v Test.classconservando solamente la sección del conjunto de instrucciones):

public void invokeWithoutReference();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: new           #2                  // class java/lang/Object
         3: dup
         4: invokespecial #1                  // Method java/lang/Object."<init>": ()V
         7: invokevirtual #3                  // Method java/lang/Object.toString:()Ljava/lang/String;
        10: pop
        11: return

  public void invokeWithReference();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class java/lang/Object
         3: dup
         4: invokespecial #1                  // Method java/lang/Object."<init>": ()V
         7: astore_1
         8: aload_1
         9: invokevirtual #3                  // Method java/lang/Object.toString:()Ljava/lang/String;
        12: pop
        13: return

No hay ninguna diferencia entre la referencia y es la referencia, en invokeWithReferencela generación de Objectlos ejemplos, ejecutado astore_1y aload_1dos instrucciones, en donde:

astore_1Shows un valor de referencia de pila se almacena en la segunda ranura de la mesa variable local, lo que representa el operador de asignación ( =) hacen

aload_1Dicho segundo tipo de referencia pila variable local inserta en la pila de operandos

Específicamente, en dos métodos diferentes de conjuntos de ejecución de instrucciones:

invokeWithoutReference

Juego de operaciones código correspondiente
0: nuevo, crear una instancia de un tipo java.lang.Object, pila y su valor de referencia en el operando pila
operando pila: [libre], [ObjectRef]
tabla de variables locales: [el este]
new Object ()
3: dup, copia la pila valor del operando pila, y apile el valor del operando en la pila
de operando pila: [ObjectRef], [ObjectRef]
tabla de variables locales: [el este]
new Object ()
4: invokespecial, llamando a la java.lang.Object " ": () V El método de
la pila de operandos: , [ObjectRef] [libre]
tabla de variables locales: [el este]
new Object ()
7: invokevirtual, método toString java.lang.Object invocación porque el método toString devuelve un valor, el resultado se realizará donde la pila se empuja en
la pila de operandos: , [java.lang.String] [libre]
tabla de variables locales : [el este]
new Object () .toString ();
10: pop, la parte superior de la pila pop valor de
funcionamiento de la pila: [libre], [libre]
locales tabla de variables: [del presente]
new Object () .toString ();
11: Vuelve, vuelve vacío desde el método actual

invokeWithReference

Juego de operaciones código correspondiente
0: nuevo, crear una instancia de un tipo java.lang.Object, y su valor de referencia en la parte superior de la pila de operando pila de
la pila de operandos: [libre], [ObjectRef]
tabla de variables locales: [el este], [inactivo ]
new Object ()
3: dup, copia la pila valor del operando pila, y apile el valor del operando en la pila
de operando pila: [ObjectRef], [ObjectRef]
tabla de variables locales: [el este], [libre]
new Object ()
4: invokespecial, llamando a la java.lang.Object " ": () V El método de
la pila de operandos: , [ObjectRef] [libre]
tabla de variables locales: [el este], [libre]
new Object ()
7: astore_1, el valor de referencia de la parte superior de la pila en las variables locales segunda
pila de operandos: [libre], [libre]
tabla de variables locales: [el este], [ObjectRef]
Objeto O = new Object ();
8: aload_1,将第二个本地变量推入栈顶
操作数栈:[空闲], [objectref]
局部变量表:[this], [objectref]
9: invokevirtual,调用java.lang.Object的toString方法,因为toString方法有返回值,所以这里会将执行的结果推入栈顶
操作数栈:[空闲], [java.lang.String]
局部变量表:[this], [objectref]
new Object().toString();
12: pop,将栈顶数值弹出
操作数栈:[空闲], [空闲]
局部变量表:[this], [objectref]
new Object().toString();
13: return,从当前方法返回void

引用?

首先,什么是引用?

《深入理解JVM虚拟机》一书中多次对Java的引用进行了讨论

对象引用(reference类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)——《深入理解JVM虚拟机》 2.2.2 Java虚拟机栈

建立对象是为了使用对象,我们的Java程序需要通过栈上的reference数据来操作堆上的具体对象。——《深入理解JVM虚拟机》 2.3.3 对象的访问定位

一般来说,虚拟机实现至少都应当能通过这个引用做到两点,一是从此引用中直接或间接地查找到对象在Java堆中地数据存放地起始地址索引,二是此引用中直接或间接地查找到对象所属数据类型在方法区中的存储的类型信息 ——《深入理解JVM虚拟机》 8.2.1 局部变量表

对于new Object()来说,JVM执行的new(0xbb)指令天然的就会将新实例的引用压入操作数栈的栈顶

Object o = new Object()只是利用=运算符,让JVM执行了astore_n指令,将这个引用保存到了局部变量表中,以便我们以后可以直接通过o.xxx()来对这个实例做一些操作

等到我们需要使用的时候,JVM再通过aload_n将指定的局部变量表中的引用类型值推到操作数栈的栈顶进行后续操作

所以在我看来,Object o其实是一个引用类型的本地变量

创建对象到底赋值吗?

回到初衷,是否定义一个引用类型的本地变量,没有一个绝对的优劣

Object o = new Object()仅仅是比new Object()多在局部变量表中保存了一个Object o引用类型,但它可以让我们在创建了实例之后,重复对这个实例进行操作

new Object()在进行了new Object().toString()这种方式的调用之后,由于局部变量表中没有了该实例的引用,操作数栈中的那个两个由dup产生的两个引用,也已经分别因为invokespecialinvokevirtual弹出栈了,所以这个对象已经没有指向它的引用了

如果我们对于实例只是一次性调用,那么直接new Object()的方式也未尝不可

Supongo que te gusta

Origin www.cnblogs.com/shiyu404/p/12574905.html
Recomendado
Clasificación