编译和运行时的界限在哪儿?

两个概念:

一,编译单元:一个.java文件就是一个编译单元。一个.java文件会被编译成一个或多个.class文件。在eclipse等IDE中,默认自动编译,即,一旦.java文件被改动则重新编译并产生.class文件。

二,类的加载:一旦已运行的程序第一次访问一个类的静态数据或者创建一个类的对象时,jvm就会根据包名及类名到classpath下的对应文件夹中找到相应的.class文件将其加载到内存中,此时,程序进入运行时。

所以,编译期和运行时的物理边界是类的加载时。

如果一段程序在运行时每次执行都产生固定的结果,那么这段程序完全可以在编译时直接输出该结果,从而减轻运行时的压力。这是编译期和运行时的另一种边界。

三、绑定:将一个方法调用(既指向方法所在内存的引用)同一个方法主体(内存中的代码块)关联起来的过程。

//RandomTest.java文件中public Class RandomTest {
    private Random rand = new Random(47);
    public int getRandomNum() {
        return rand.nextInt(3);
    }
}
//RandomInt.java文件中
public Class RandomInt {
    public static void main(String[] args) {
        RandomTest rdt1 = new RandomTest();
        RandomTest rdt2 = new RandomTest();
        int randomNum1 = rdt1.getRandomNum();
        int randomNum2 = rdt2.getRandomNum();
        System.out.println(randomNum1);
        System.out.println(randomNum2);
    }
}输出:2     1

当main方法中的getRanomNum方法执行时,getRandomNum方法已经被编译完成了。但最终却产生了不同的结果,说明nextInt方法是在运行时才产生结果,而非编译时就产生结果。

一次编译、两次运行、两个结果。说明了在运行时才产生了最终的结果而非编译时。

//A.java中
public class A {
    public void m() {
        System.out.print("A");
    }
}

public class B extends A {
    public void m() {
        System.out.print("B");
    }
}

public class C extends A {
    public void m() {
        System.out.print("C");
    }
}

//Test.java中
public class TestA {
    public static void testA(A a) {
        a.m();
    }
}
public class Test {
    public static void main(String[] args) {
        TestA testA = new TestA();
        B b = new B();
        C c = new C();
        testA(b);
        testA(c);
    }
}
输出:B
     C

同理,对于TestA()方法来说,一次编译,两次执行,产生了两个结果。

说明,在编译TestA时,a.m()并没有指向具体的方法体(内存地址)。而是在运行时,jvm根据入参的类型,才将a.m()指向不同的方法体(内存地址)。

时间: 2024-08-02 18:56:35

编译和运行时的界限在哪儿?的相关文章

关于指针变量编译和运行时

指针变量编译时只能运行编译时的方法,不能调用运行时类型的方法,即使它实际所指对象确实包含该方法. Father* fa=[[Son alloc]init]; 编译时是:Father 运行时时:Son 解决方法: 强制转换成子类类型,这样 编译和运行时的类型就相同了 //下面编译时类型和运行时类型不一样,多态发生 FKBase* ploymophicBc=[[FKSubclass alloc]init]; [ploymophicBc base]; [ploymophicBc test]; //FK

编译和运行时,库在何处

在编译程序是,-L或者-l直接指明,搜索库在/lib /usr/lib 寻找,或者在LD_LIBRARY_PATH(包括/etc/ld.so.conf)中指明,以及用pkg-config工具的配置文件和变量PKG_CONFIG_PATH指明, 为了加速寻找LD_LIBRARY_PATH下的库,/etc/ld.so.conf还有个缓存,/etc/ld.so.cache,用ld-config来管理. 程序在运行搜索库时,主要向这几个地方找,LD_LIBRARY_PATH或者ld.so.conf的配置

探讨:编译时常量和运行时常量

编译时常量和运行时常量 C#有2种不同的常量定义方式:编译时常量(compile-time)和运行时常量(runtime).他们的行为方式有很大的不同,如果选用了错误的一个,那么将让程序的性能和正确性产生商榷.当然,一个系统最好没有任何问题,但是如果一定会存在一个问题,那么一个稍慢的但强壮的系统比一个速度更快的但很脆弱的系统要好.基于以上理由,在二者选其一的时候,你最好选择运行时常量. 运行时常量以 readonly 关键字定义,编译时是常量以 const 关键字定义: public const

什么叫编译时和运行时

以前经常听说编译时和运行时的概念.但没太搞明白具体代表啥意思.后面花了点时间研究了下.总算知道个大概意思了. 编译时 编译时顾名思义就是正在编译的时候.那啥叫编译呢?就是编译器帮你把源代码翻译成机器能识别的代码.(当然只是一般意义上这么说,实际上可能只是翻译成某个中间状态的语言.比如Java只有JVM识别的字节码,C#中只有CLR能识别的MSIL.另外还有啥链接器.汇编器.为了了便于理解我们可以统称为编译器) 那编译时就是简单的作一些翻译工作,比如检查老兄你有没有粗心写错啥关键字了啊.有啥词法分

方法区和运行时常量区溢出 转

方法区和运行时常量池溢出 由于运行时常量池是方法区的一部分,因此这两个区域的溢出测试就放在一起进行.前面提到JDK 1.7开始逐步“去永久代”的事情,在此就以测试代码观察一下这件事对程序的实际影响. String.intern()是一个Native方法,它的作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象:否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用.在JDK 1.6及之前的版本中,由于常量

vue.js2.0的独立构建和运行时构建

转自:https://jingsam.github.io/2016/10/23/standalone-vs-runtime-only-build-in-vuejs2.html?utm_source=tuicool&utm_medium=referral 在使用 Vue.js 2.0 时,有独立构建(standalone)和运行时构建(runtime-only)两种版本可供选择.而在 Vue.js 1.0 中,却没有这种版本区别.到底该使用哪一个版本?这让我有点懵逼的感觉.本着知其然还要知其所以然

编译系统和运行时的系统

编译系统和运行时的系统(参照编译原理第三版第11章) 源程序---预处理器---修改后的源程序--编译器---汇编程序----汇编器----可重定位的目标程序----链接器(加入库文件和可重定位的目标文件)----可执行的目标程序 大多数编译系统提供一个驱动程序来调用预处理器.编译器.汇编器.链接器.以支持用户完成从源程序到可执行的目标文件.比如GCC. 如 gcc -v-o swap main.c swap.c 预处理器: 预处理器产生编译器的输入,主要有以下功能: 1.文件包含: 预处理器可

Java虚拟机系列一:一文搞懂 JVM 架构和运行时数据区

前言 之前写博客一直比较随性,主题也很随意,就是想到什么写什么,对什么感兴趣就写什么.虽然写起来无拘无束,自在随意,但也带来了一些问题,每次写完一篇后就要去纠结下一篇到底写什么,看来选择太多也不是好事儿,更重要的是不成体系的内容对读者也不够友好.所以以后的博客尽量按系列来写,不过偶尔也会穿插其他的内容.接下来一段时间我会把写博客的重点放在 JVM (Java Virtual Machine) 和 JUC (java util concurrent ) 上,对 Java 虚拟机和 Java 并发编

一文搞懂 JVM 架构和运行时数据区 (内存区域)

前言 了解 JVM 是对 Java 开发人员的基本要求,JVM 的相关内容自然也成了现在 Java 程序员面试的重要考点.不过估计很多小伙伴和我一样,长时间醉心于 CRUD,却忘了去了解一下更底层.更基础的东西,殊不知这些才是决定你能在这条路上走多远的关键因素,那接下来我们就一起来深入学习一下看似神秘的 JVM 吧.JVM 总体来看内容还是很多的,我会把最重要的内容介绍给大家,不过如果你有时间和精力的话,还是推荐你去看一下<深入理解Java虚拟机>这本书,确实是有口皆碑.本文也会引用很多此书的