一、对象创建与访问指令的概述


Java是面向对象的程序设计语言,虚拟机平台从字节码层面就对面向对象做了深层次的支持。有一系列指令专门用于对象操作,可进一步细分为创建指令、字段访问批令、数组操作指令、类型检查指令

二、创建指令


虽然类实例和数组都是对象,但ava虚拟机对类实例和数组的创建与操作使用了不同的字节码指令:

创建类实例的指令:
  • 创建类实例的指令: new
  • 它接收一个操作数为指向Q量池的索引,表示要创建的类型,执行完成后,将对象的引用压入栈
创建数组的指令:
  • 创建数组的指令: newarray、 anewarray、multianewarrayc
  • newarray:创建基本类型数组
  • anewarray:创建引用类型数组
  • multianewarray:创建多维数组

上述创建指令可以用于创建对象或者数组

并且由于对象和数组在Java中的广泛使用,这些指令的使用频率也非常高

接下来我们针对于创建类的指令的基本测试,请看以下示例代码

public class NewTest{
     //1.创建指令
    public void newInstance(){    
        Object obj = new Object();
        File file = new File("atguigu.avi");
    }
}

接下来我们编译该代码,看看方法的字节码是用什么指令进行对象创建的?

image.png

接下来我们根据字节码指令进行图示解析分析,具体做了哪些操作?
image.png
image.png
image.png
image.png
image.png

接下来我们针对于创建类的指令的基本测试,请看以下示例代码

public class NewTest{
     
    public void newArray() i
        int[] intArray = new int[10];
        Object[] objArray = new Object[10];
        int[][]mintArray = new int[10][10];
        String[][] strArray = new String[10][];
    }
}

接下来我们编译该代码,看看方法的字节码是用什么指令进行对象创建的?

image.png

三、字段访问指令


对象创建后,就可以通过对象访问指令获取对象实例或数组实例中的字段或者数组元素。

  • 访问类字段(static字段,或者称为类变量)的指令: getstatic、putstatic
  • 访问类实例字段(非static字段,或者称为实例变量)的指令: getfield、putfield

以getstatic指令为例它含有一个操作数,为指向常量池的Fieldref索引。

它的作用就是获取Fieldref指定的对象或者值,并将其压入操作数栈。

接下来我们针对于字段访问的指令的基本测试,请看以下示例代码

public class NewTest{
     
    //2.字段访问指令
    public void sayHello(){
        system.out.print1n("hello");
    }
}

接下来我们编译该代码,看看方法的字节码是用什么指令的?

image.png
image.png
image.png
image.png

接下来我们结合前面的创建对象指令与字段访问指令,看看又是怎么样的效果?

public class NewTest{
     
    public void setorderId(){
        order order = new Order();
        order.id = 1001;
        System.out.println(order.id);
    I
        order.name = "ORDER";
        System.out.println(order.name);
    }
}

class order{
    int id;
    static string name;
}

接下来我们编译该代码,看看方法的字节码是用什么指令的?

image.png

接下来我们根据字节码指令进行图示解析分析,具体做了哪些操作?

image.png
image.png
image.png
image.png

四、数组操作指令


数组操作指令主要有: xastore和xaload指令。具体为:

把一个数组元素加载到操作数栈的指令:

baload、caload、saload、iaload、laload、faload、daload、aaload

将一个操作数栈的值存储到数组元素中的指令:

bastore、castore、sastore、iastore、 lastore、fastore、dastore、aastore

image.png

取数组长度的指令:arraylength

该指令弹出栈顶的数组元素,获取数组的长度,将长度压入栈。

指令xaload表示将数组的元素压栈,比如saload、caload分别表示压入short数组和char数组

指令xaload在执行时要求操作数中栈顶元素为数组索引i,栈顶顺位第2个元素为数组引用a,该指令会弹出栈顶这两个元素,并将a[i]重新压入堆栈。

xastore则专门针对数组操作,以iastore为例,它用于给一个int数组的给定索引赋值。

在iastore执行前操作数栈顶需要以此准备3个元素:值、索引、数组引用

iastore会弹出这3个值,并将值赋给数组中指定索引的位置。

接下来我们针对于数组操作指令的基本测试,请看以下示例代码

public class NewTest{
     
    //3.数组操作指令
    public void setArray(){
        int[] intArray = new int[10];
        intArray[3] = 20;
        System.out.println(intArray[1]);
    }
}

接下来我们编译该代码,看看方法的字节码是用什么指令的?

image.png
image.png
image.png

接下来我们再针对于数组操作指令的基本测试,请看以下示例代码

public class NewTest{
     
    / /3.数组操作指令
    public void setArray(){
        int[] intArray = new int[10];
        intArray[3] = 20;
        System.out.println(intArray[1]);
        
        boolean[] arr = new boolean[10];
        arr[1] = true;
    }
}

接下来我们编译该代码,看看方法的字节码是用什么指令的?

image.png

接下来我们再针对于数组操作指令的基本测试,请看以下示例代码

public class NewTest{
     
    public void arrLength( ){
        double[ ] arr = new double[10];
        system.out.println( arr.length);
    }
}

接下来我们编译该代码,看看方法的字节码是用什么指令的?
image.png

五、类型查找指令


检查类实例或数组类型的指令: instanceof、 checkcast

指令checkcast用于检查类型强制转换是否可以进行

如果可以进行那么checkcast指令不会改变操作数栈,否则它会抛出C1asscastException异常。

指令instanceof用来判断给定对象是否是某一个类的实例,它会将判断结果压入操作数栈。

接下来我们针对于类型查找指令的基本测试,请看以下示例代码

public class NewTest{
     
    //4.类型检查指令
    public String checkcast(Object obj){
        if (obj instanceof String) {
            return (String)obj;
        }else{
            return null;
        }
    }
}

接下来我们编译该代码,看看方法的字节码是用什么指令的?

image.png
image.png


28640
116 声望25 粉丝

心有多大,舞台就有多大