1 什么是“内嵌”,内嵌如何消除函数调用
即内联,“java也有类似c++中inline函数的机制,即在函数调用时直接将被调用函数的代码拷贝副本过来运行,而不进行普通的压栈当前运行地址,压栈参数,跳转执行然后再返回的过程。在早期版本中,使用final关键字可以建议编译器以内联函数的方式处理这个函数。但是在后来的几个版本中,编译器进行了优化,会自动将适合内联的“小函数”以内联的方式处理,而只有在真正需要禁止override的时候才使用final关键字以避免混乱。”
2 什么是即时编译器
引用:
“
作者:sbbic
链接:https://www.zhihu.com/question/36746487/answer/69645836
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
引用“实际上很多解释器内部是以“编译器+虚拟机”的方式来实现的,先通过编译器将源码转换为AST或者字节码,然后由虚拟机去完成实际的执行。所谓“解释型语言”并不是不用编译,而只是不需要用户显式去使用编译器得到可执行代码而已。 ”
3 Java没有头文件,如何实现头文件的功能?
#import确保引用的文件只会被引用一次,这样就不会陷入递归包含的问题中。
”
你把#include理解成将要include的代码复制粘贴到指定位置就可以了~~~ import 是引入了一个类或包,为了让你使用这个类的小名,不必在任何地方都使用它的大名 |
说的比较清楚的:http://zhua547.blog.163.com/blog/static/309625220091184578260/(import避免了交叉引用)
引用:http://www.aichengxu.com/java/18973.htm
”
ava的import与C++的#include浅析,有需要的朋友可以参考下。
相信很多人对这两者的到底有什么不同都不了解,而我搜了一下相关文章,单独介绍的很多,但把这两者做对比的不多。我就根据自己的理解写一下,希望大家指正我的不足。
首先,要说java的import就需要说一下package,package就相当于我们的姓,class就像是我们的名字。package名字很长的时候就类似复姓。例如:java.lang.String,可以理解为复姓为java.lang,名字叫做String。而且,按照Sun的规范取名字,理论上每个人创建的类名字都不会相同,也就不会发生命名冲突。
但是这个时候就出现问题了,复杂的程序和继承使得很多类的名字非常长,这样在写程序的时候就会变得麻烦,于是乎,import就来了。import就是在程序开始的时候说明会用到哪些类,写的时候就可以直接写它的名字,而不用写它的姓了。还是看java.lang.String。如果没有 import java.lang.String 。那么我们在每次创建String对象时都得写java.lang.String string = new blah blah。而现在只需String string=new blah
blah。是不是一下子简单了很多。所以,这就是import的作用,简化代码,编程方便,就这么简单,编译器也不会把import所导入的类写到.class中。具体的分为单类型导入和按需类型导入,本文侧重比较import和#include,不再做具体的介绍了。网上的讲解很多。
C++中,include是预处理器的一部分,所谓预处理,顾名思义就是在编译器之前运行。一个源文件,.c .cpp和它所包含的文件一起,在经过预处理之后就形成一个源码文件,标准的叫法是translation unit(编译单元),它包括一系列的声明和定义。一个程序由若干(>=1)编译单元组成。编译器将各个编译单元编译为目标代码(.obj),通过linker(连接器)将这些目标代码连接成完整的指令序列(可执行文件、静态库、动态库等)。所以,#include后的头文件名,预处理过后是写到了编译单元里的,这和java有着本质的不同
“
4 为什么要设置执行路径
引用:http://www.cnblogs.com/wangchenyang/archive/2011/08/17/2143620.html
”
1. PATH环境变量。作用是指定命令搜索路径,在shell下面执行命令时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序。我们需要把 jdk安装目录下的bin目录增加到现有的PATH变量中,bin目录中包含经常要用到的可执行文件如javac/java/javadoc等待,设置好 PATH变量后,就可以在任何目录下执行javac/java等工具了。
2. CLASSPATH环境变量。作用是指定类搜索路径,要使用已经编写好的类,前提当然是能够找到它们了,JVM就是通过CLASSPTH来寻找类的。我们 需要把jdk安装目录下的lib子目录中的dt.jar和tools.jar设置到CLASSPATH中,当然,当前目录“.”也必须加入到该变量中。
3. JAVA_HOME环境变量。它指向jdk的安装目录,Eclipse/NetBeans/Tomcat等软件就是通过搜索JAVA_HOME变量来找到并使用安装好的jdk。
“
5 如何理解Java的“接口”概念
6 何为字节码
引用:http://tec.5lulu.com/detail/110k8n1h9n13j8y26.html
”Java 字节码(英语:Java bytecode)是Java虚拟机执行的一种指令格式。大多数操作码都是一个字节长,而有些操作需要参数,导致了有一些多字节的操作码。而且并不是所有可能的256个操作码都被使用;其中有51个操作码被保留做将来使用。除此之外,原始Java平台开发商,升阳微系统,额外保留了3个代码永久不使用。“
Java字节码的计算模型是面向堆栈结构计算机的。例如,一个x86处理器的汇编代码如下
- mov eax, byte [ebp-4]
- mov edx, byte [ebp-8]
- add eax, edx
- mov ecx, eax
这段代码将两个数值相加,并存入另一个地址。相似的反汇编字节码如下
- 0 iload_1
- 1 iload_2
- 2 iadd
- 3 istore_3
在这里,需要相加的两个操作数被放入堆栈,而相加操作就在栈中进行,其结果也被放入堆栈。存储指令之后把栈顶的数据放入一个变量地址。在每条指令前面的数字仅仅是表示这条指令到方法开始处的偏移值。这种堆栈结构也可以推广到面向对象模型上。
7 何为Java解释器,何为“增量式链接”
“如果一种语言的主流实现是解释器,其内部是编译器+虚拟机,而虚拟机又是采用解释方式实现的,或者内部实现是编译器+树遍历解释器,那它就是名副其实的“解释型语言”。如果内部用的虚拟机是用编译方式实现的,其实跟普遍印象中的“解释器”还是挺不同的…”
引用:http://www.cnblogs.com/nbsofer/archive/2013/06/26/3157619.html
“ 增量链接(Incremental Linking)这个词语在使用Visual C++时经常会遇到(其实
不只是VS系列,其它链接器也有这个特性), 就比如经常遇到的:上一个增量链接没有
生成它, 正在执行完全链接. 但是它是什么意思呢? 很多人只是经常看到, 但是不
明白这是什么. 首先说明一下, 这个特性是链接器为了<提高链接速度>而增加的功
能. 说是这样, 可能不理解, 下面就说说其原理:
有一个源代码文件, 你写了许多许多行, 你正在调试它, 你突然发现某个地方
有一个小BUG, 你打算改正, 好了, 错误改正了, 但是链接器该采用何种方式链接新代码?
其一: 可以把obj删除, 然后重新生成.
其二: 为每个函数预留一部分空间, 编译链接时, 只是修改你修改过的函数
对应的代码, 其它二进制代码保持不变.
可能你已经明白了, 为目标(函数)代码"预留一部分空间", 这就是"增量"的含
义. 当代码修改后, 只需要修改这一部分的目标代码即可快速完成编译与链接!
这就为调试代码时快速修改编译提高了速度! 这也是为什么调试器
支持 "Edit and Continue" 特性!
这不浪费程序空间么? 你可能会想, 不过确实如此. 正因为如此, Debug版本的
目标文件会远远大于Release版本的目标文件(不单因为此). 在Release编译时, 是
不能启用增量链接模式的!
好了, 先就介绍这些, 其实我也只是知道部分原理, 本文的讲解并不深入!
”
8 什么是虚拟机
http://rednaxelafx.iteye.com/blog/492667
引用“一般认为输入是满足某种指令集架构(instruction set architecture,ISA)的指令序列,中间转换为目标ISA的指令序列并加以执行,输出为程序的执行结果的,就是VM。源与目标ISA可以是同一种,这是所谓same-ISA VM。
前面提到解释器中的编译器的输出可能是AST,也可能是字节码之类的指令序列;一般会把执行后者的程序称为VM,而执行前者的还是笼统称为解释器或者树遍历式解释器(tree-walking interpreter)。这只是种习惯而已,并没有多少确凿的依据。只不过线性(相对于树形)的指令序列看起来更像一般真正机器会执行的指令序列而已。
其实我觉得把执行AST的也叫VM也没啥大问题。”
9 Java中包的概念
引用:http://blog.chinaunix.net/uid-21411227-id-4138629.html
”
1.包的概念
包(package)是Java提供的一种区别类的名字空间的机制,是类的组织方式,是一组相关类和接口的集合,它提供了访问权限和命名的管理机制。
Java中提供的包主要有以下3种用途:
1) 将功能相近的类放在同一个包中,可以方便查找与使用。
2) 由于在不同包中可以存在同名类,所以使用包在一定程度上可以避免命名冲突。
3) 在Java中,某次访问权限是以包为单位的。
1.1创建包
创建包可以通过在类或接口的源文件中使用 package语句实现,package语句的语法格式如下:
package 包名;
包名:必选,用于指定包的名称,包的名称为合法的 Java标识符。当包中还有包时,可以使用“包1.包2.…….包n”进行指定,其中,包1为最外层的包,而包n则为最内层的包。
package 语句通常位于类或接口源文件的第一行。例如,定义一个类Circ,将其放入com.wgh包中的代码如下:
package com.wgh;
public class Circ {
final float PI=3.14159f; //定义一个用于表示圆周率的常量PI
// 定义一个绘图的方法
public void draw(){
System.out.println("画一个圆形!");
}
}
说明:
在Java中提供的包,相当于系统中的文件夹。例如,上面代码中的Circ类如果保存到C盘根目录下,那么它的实际路径应该为C:\com \wgh\Circ.java。
2 使用包中的类
类可以访问其所在包中的所有类,还可以使用其他包中的所有public类。访问其他包中的public类可以有以下两种方法。
1) 使用长名引用包中的类
使用长名引用包中的类比较简单,只需要在每个类名前面加上完整的包名即可。例如,创建Circ类(保存在com.wgh包中)的对象并实例化该对象的代码如下:
com.wgh.Circ circ=new com.wgh.Circ();
2) 使用import语句引入包中的类
由于采用使用长名引用包中的类的方法比较繁琐,所以Java提供了import语句来引入包中的类。import语句的基本语法格式如下:
import 包名1[.包名2.……].类名|*;
当存在多个包名时,各个包名之间使用“.”分隔,同时包名与类名之间也使用“.”分隔。
*:表示包中所有的类。
例如,引入com.wgh包中的Circ类的代码如下:
import com.wgh.Circ;
如果 com.wgh包中包含多个类,也可以使用以下语句引入该包下的全部类。
import com.wgh.*;
“