java 编译时_java中的编译时与运行时

----?基础知识

-- 编译时

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

-- 运行时

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

---- 举个栗子

public classConstantFolding {static final int number1 = 5;static final int number2 = 6;static int number3 = 5;static int number4= 6;public static voidmain(String[ ] args) {int product1 = number1 * number2; //line A

int product2 = number3 * number4; //line B

}

}

--- 分析

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

public classConstantFolding

{static final int number1 = 5;static final int number2 = 6;static int number3 = 5;static int number4 = 6;public static voidmain(String[ ] args)

{int product1 = 30;int product2 = number3 *number4;

}

}

---- 举个栗子

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

public classTest{public static void A(String param1); //method #1

public static void A(int param1); //method #2

}

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

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

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

---- 举个栗子

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

public classA {public int compute(int input) { //method #3

return 3 *input;

}

}public class B extendsA {

@Overridepublic int compute(int input) { //method #4

return 4 *input;

}

}

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

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

}

---- 举个栗子

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

public classTest4 {public static voidmain(String[] args) {

ArrayList arrayList1=new ArrayList();

arrayList1.add("abc");

ArrayList arrayList2=new ArrayList();

arrayList2.add(123);

System.out.println(arrayList1.getClass()==arrayList2.getClass());

}

}

---- 分析

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

---- 举个栗子

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

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

例如:NullPointerException,ArrayIndexOutOfBoundsException,等等

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值