java编译时与运行时概念与实例详解 -------------------(*************************)

Java编译时与运行时很重要的概念,但是一直没有明晰,这次专门博客写明白概念.

基础概念

编译时 

编译时顾名思义就是正在编译的时候.那啥叫编译呢?就是编译器帮你把源代码翻译成机器能识别的代码.(当然只是一般意义上这么说,实际上可能只是翻译成某个中间状态的语言.比如Java只有JVM识别的字节码,.另外还有啥链接器.汇编器.为了了便于理解我们可以统称为编译器)

那编译时就是简单的作一些翻译工作,比如检查老兄你有没有粗心写错啥关键字了啊.有啥词法分析,语法分析之类的过程.就像个老师检查学生的作文中有没有错别字和病句一样.如果发现啥错误编译器就告诉你.所以有时一些人说编译时还分配内存啥的肯定是错误的说法.

运行时 

所谓运行时就是代码跑起来了.被装载到内存中去了.(你的代码保存在磁盘上没装入内存之前是个死家伙.只有跑到内存中才变成活的).而运行时类型检查就与前面讲的编译时类型检查(或者静态类型检查)不一样.不是简单的扫描代码.而是在内存中做些操作,做些判断.(这样很多编译时无法发现的错误,在运行就可以发现报错了,最好还是写的的时候就避免这个逻辑错误就好了)

举列子

?


1

2

3

4

int arr[] = {1,2,3};

int result = arr[4];

System.out.println(result);

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 4

上面的代码你一瞧你知道是错误的代码,数组越界了.但用编译器没有报错,run后才出现了ArrayIndexOutOfBoundsException.可见编译器其实还是挺笨的,还没你脑瓜子那么聪明啊,于是你想虽然编译器笨了点,但运行起来时发现了错误也还不算太坏.

面试题

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

理解这几个概念可以更好地帮助你去了解一些基本的原理。下面是初学者晋级中级水平需要知道的一些问题。

Q.下面的代码片段中,行A和行B所标识的代码有什么区别呢?

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

 }

}

A.在行A的代码中,product的值是在编译期计算的,行B则是在运行时计算的。如果你使用Java反编译器(例如,jd-gui)来反编译ConstantFolding.class文件的话,那么你就会从下面的结果里得到答案。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

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;

 }

}

常量折叠是种Java编译器使用的优化技术。由于final变量的值不会改变,因此就可以对它们优化。Java反编译器和javap命令都是查看编译后的代码(例如,字节码)的利器。

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

?


1

2

3

4

public class {

 public static void evaluate(String param1); // method #1

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

}

如果编译器要编译下面的语句的话:

1evaluate(“My Test Argument passed to param1”); 

它会根据传入的参数是字符串常量,生成调用#1方法的字节码

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

?


1

2

3

4

5

6

7

8

9

10

11

12

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;

 }

}

子类B中的compute(..)方法重写了父类的compute(..)方法。如果编译器遇到下面的代码:

?


1

2

3

public int evaluate(A reference, int arg2) {

 int result = reference.compute(arg2);

}

编译器是没法知道传入的参数reference的类型是A还是B。因此,只能够在运行时,根据赋给输入变量“reference”的对象的类型(例如,A或者B的实例)来决定调用方法#3还是方法#4

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

换句话来说,编译器会擦除所有在尖括号里的类型信息,来保证和版本1.4.0或者更早版本的JRE的兼容性。

1List myList = new ArrayList(10); 

编译后成为了:

1List myList = new ArrayList(10); 

异常(Exception):你可以使用运行时异常或者编译时异常。

运行时异常(RuntimeException)也称作未检测的异常(unchecked exception),这表示这种异常不需要编译器来检测。

RuntimeException是所有可以在运行时抛出的异常的父类。一个方法除要捕获异常外,如果它执行的时候可能会抛出

RuntimeException的子类,那么它就不需要用throw语句来声明抛出的异常。

例如:NullPointerException,ArrayIndexOutOfBoundsException,等等

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

原文地址:https://www.cnblogs.com/yunliu0603/p/11138552.html

时间: 2024-08-29 13:40:00

java编译时与运行时概念与实例详解 -------------------(*************************)的相关文章

Java开发之I/O读取文件实例详解

在java开发或者android开发中,读取文件是不可避免的,以下对java开发中读取文件做了归纳和详解: 1.按字节读取文件内容2.按字符读取文件内容3.按行读取文件内容 4.随机读取文件内容 public class ReadFromFile { /** * 以字节为单位读取文件,常用于读二进制文件,如图片.声音.影像等文件. */ public static void readFileByBytes(String fileName) { File file = new File(fileN

TaskScheduler内幕天机:Spark shell案例,TaskScheduler和SchedulerBackend、FIFO与FAIR、Task运行时本地性算法详解

TaskSchedulerBackend与SchedulerBackend FIFO与FAIR两种调度模式 Task数据本地性资源的分配 一.TaskScheduler运行过程(Spark-shell角度) 1.启动Spark-shell 当我们spark-shell本身的时候命令终端返回来的主要是ClientEndpoint和SparkDeploySchedulerBakcend.这是因为此时还没有任何应用程序Job的触发,这是启动Application本身而已,所以主要就是实例化SparkC

程序编译后运行时的内存分配

原文地址不详,我的转载的来源:http://blog.sina.com.cn/s/blog_5420e0000101a0w1.html 一.编译时与运行时的内存情况 1.编译时不分配内存 编译时是不分配内存的.此时只是根据声明时的类型进行占位,到以后程序执行时分配内存才会正确.所以声明是给编译器看的,聪明的编译器能根据声明帮你识别错误. 2.运行时必分配内存 运行时程序是必须调到"内存"的.因为CPU(其中有多个寄存器)只与内存打交道的.程序在进入实际内存之前要首先分配物理内存. 3.

Java如何在运行时识别类型信息?

在日常的学习工作当中,有一些知识是我们在读书的时候就能够习得:但有一些知识不是的,需要在实践的时候才能得到真知--这或许就是王阳明提倡的"知行合一". 在Java中,并不是所有的类型信息都能在编译阶段明确,有一些类型信息需要在运行时才能确定,这种机制被称为RTTI,英文全称为Run-Time Type Identification,即运行时类型识别,有没有一点"知行合一"的味道?运行时类型识别主要由Class类实现. 一.Class类 在Java中,我们常用&quo

实例详解:反编译Android APK,修改字节码后再回编译成APK

本文详细介绍了如何反编译一个未被混淆过的Android APK,修改smali字节码后,再回编译成APK并更新签名,使之可正常安装.破译后的apk无论输入什么样的用户名和密码都可以成功进入到第二个Activity. 有时难免要反编译一个APK,修改其中的若干关键判断点,然后再回编译成一个全新的可用的apk,这完全是可实现的.若要完成上述工作,需要以下工具,杂家后面会把下载链接也附上.这些软件截止本文发布时,经过杂家确认都是最新的版本. 1.APK-Multi-Toolv1.0.11.zip 用它

事件驱动模型实例详解(Java篇)

或许每个软件从业者都有从学习控制台应用程序到学习可视化编程的转变过程,控制台应用程序的优点在于可以方便的练习某个语言的语法和开发习惯(如.net和java),而可视化编程的学习又可以非常方便开发出各类人机对话界面(HMI).可视化编程或许是一个初学者开始对软件感兴趣的开始,也可能是一个软件学习的里程碑点,因为我们可以使用各类软件集成开发环境(IDE)方便的在现成的界面窗口上拖放各类组件(Component),这类组件包括我们常见的按钮(Button),单选按钮(Radio Button),复选框

java网页爬虫简单实例详解——获取天气预报。

[本文介绍] 爬取别人网页上的内容,听上似乎很有趣的样子,只要几步,就可以获取到力所不能及的东西,例如呢?例如天气预报,总不能自己拿着仪器去测吧!当然,要获取天气预报还是用webService好.这里只是举个例子.话不多说了,上看看效果吧. [效果] 我们随便找个天气预报的网站来试试:http://www.weather.com.cn/html/weather/101280101.shtml 从图中可用看出,今天(6日)的天气.我们就以这个为例,获取今天的天气吧! 最终后台打印出: 今天:6日

java 流操作对文件的分割和合并的实例详解_java - JAVA

文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 java 流操作对文件的分割和合并的实例详解 学习文件的输入输出流,自己做一个小的示例,对文件进行分割和合并. 下面是代码: package com.dufy.file; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import jav

Storm概念、原理详解及其应用(一)BaseStorm

本文借鉴官文,添加了一些解释和看法,其中有些理解,写的比较粗糙,有问题的地方希望大家指出.写这篇文章,是想把一些官文和资料中基础.重点拿出来,能总结出便于大家理解的话语.与大多数"wordcount"代码不同的是,并不会有如何运行第一storm代码等内容,只有在运行完代码后,发现需要明白:"知其然,并知其所以然". Storm是什么?为什么要用Storm?为什么不用Spark? 第一个问题,以下概念足以解释: Storm是基于数据流的实时处理系统,提供了大吞吐量的实