• java中的编译时与运行时


    ----?基础知识

        -- 编译时

        编译器将源代码翻译成机器能够读懂的代码,如java中就是翻译成jvm能够读懂的字节码文件。简单说,编译时就是机器帮我们检查代码是否有出现语法错误,关键字写错之类的,是为之后的类加载做好准备,所以,在这个过程中并不会出现什么分配内存之类的操作。

       -- 运行时

        这个过程是指将编译好后的储存在磁盘上的字节码文件(.class文件)加入到内存中运行,在运行的过程中,会进行一系列的类型检查,如空间内存分配,逻辑判断之类的。因此,在这个过程中经常会出现一些我们无法预知的错误。

    ---- 举个栗子

    public class ConstantFolding {
     
     static final int number1 = 5;
     
     static final int number2 = 6;
     
     static int number3 = 5;
     
     static int number4= 6;
     
     public static void main(String[ ] args) {
     
     int product1 = number1 * number2; //line A
     
     int product2 = number3 * number4; //line B
     
     }
     
    }

    --- 分析

        同时被static和final修饰的常量称作编译时常量,所以number1 和 number2在编译时已经被加载了,即product1 在编译期间就已经确定好了值为多少。而number3 和number4 只有在运行时,分配好了内存空间并且才能被成功赋值,所以product2 的值只有在运行时才能够确定是多少。反编译如下:

    public class ConstantFolding
    {
     static final int number1 = 5;
     static final int number2 = 6;
     static int number3 = 5;
     static int number4 = 6;
     
     public static void main(String[ ] args)
     {
     int product1 = 30;
     int product2 = number3 * number4;
     }
    }

    ---- 举个栗子

       方法的重载:这个是发生在编译时的。方法重载也被称为编译时多态,因为编译器可以根据参数的类型来选择使用哪个方法。

    public class Test{
     public static void A(String param1); // method #1
     public static void A(int param1); // method #2
    }

       如果编译器调用的方法是下面

    new Test().A("classlodaer");

       那么它就会在编译的时候自己去寻找menthod #1的方法

    ---- 举个栗子

       方法覆盖:这个是在运行时发生的。方法重载被称为运行时多态,因为在编译期编译器不知道并且没法知道该去调用哪个方法。JVM会在代码运行的时候做出决定。

    public class A {
     public int compute(int input) { //method #3
     return 3 * input;
     } 
    }
     
    public class B extends A {
     @Override
     public int compute(int input) { //method #4
     return 4 * input;
     } 
    }

       如果编译器遇到如下代码,就在编译时就无法判断究竟传入的参数是A类型还是B类型,只有在运行时才能够进行确定,进而来判断要调用方法#3还是#4

    public int evaluate(A reference, int arg2) {
     int result = reference.compute(arg2);
    }

    ---- 举个栗子

      泛型(又称类型检验):这个是发生在编译期的。编译器负责检查程序中类型的正确性,然后把使用了泛型的代码翻译或者重写成可以执行在当前JVM上的非泛型代码。这个技术被称为“类型擦除“。

        public class Test4 {
            public static void main(String[] args) {
                ArrayList<String> arrayList1=new ArrayList<String>();
                arrayList1.add("abc");
                ArrayList<Integer> arrayList2=new ArrayList<Integer>();
                arrayList2.add(123);
                System.out.println(arrayList1.getClass()==arrayList2.getClass());
            }
        }

    ---- 分析

       在这个例子中,我们定义了两个ArrayList数组,不过一个是ArrayList<String>泛型类型,只能存储字符串。一个是ArrayList<Integer>泛型类型,只能存储整形。最后,我们通过arrayList1对象和arrayList2对象的getClass方法获取它们的类的信息,最后发现结果为true。说明泛型类型String和Integer都被擦除掉了,只剩下了原始类型

    ---- 举个栗子

      异常:分为编译时异常和运行时异常

      运行时异常(RuntimeException)也称作未检测的异常(unchecked exception),这表示这种异常不需要编译器来检测。RuntimeException是所有可以在运行时抛出的异常的父类。一个方法除要捕获异常外,如果它执行的时候可能会抛出。RuntimeException的子类,那么它就不需要用throw语句来声明抛出的异常。

       例如:NullPointerException,ArrayIndexOutOfBoundsException,等等

      受检查异常(checked exception)都是编译器在编译时进行校验的,也称为编译时异常,通过throws语句或者try{}cathch{} 语句块来处理检测异常。编译器会分析哪些异常会在执行一个方法或者构造函数的时候抛出。

  • 相关阅读:
    cxVerticalGrid赋值是实时更新
    cxGrid类似pagecontrol的效果
    cxgrid属性说明,每次用的时候费时费力查找。
    做一个平均数,合计数的sql查询
    FDMemTable 提示操作速度尤其是循环
    手机号码验证
    取字符串长度
    DELPHI 获取本月 的第一天 和 最后一天
    SQL Server 断开某个数据库所有连接(还原的时候需要)转自用保留
    元宇宙六大核心技术
  • 原文地址:https://www.cnblogs.com/liangyueyuan/p/9952458.html
Copyright © 2020-2023  润新知