- 浏览: 806664 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (360)
- Java (101)
- JPA/Hibernate (10)
- Spring (14)
- Flex/BlazeDS (37)
- Database (30)
- Lucene/Solr/Nutch (0)
- Maven/Ant (25)
- CXF/WebService (3)
- RPC/RMI/SOAP/WSDL (1)
- REST (6)
- TDD/BDD/JUnit (1)
- Servlet/JSP (2)
- AI/MachineLearning (3)
- Resource (1)
- 字符编码 (2)
- OOA/OOPS/UML (5)
- DesignPattern (8)
- 算法与数据结构 (11)
- Web&App Server (13)
- 并发&异步&无阻塞 (7)
- Entertainment (4)
- JavaScript/ExtJS (45)
- CodeStyle&Quality (1)
- svn/git/perforce (8)
- JSON (2)
- JavaScriptTesting (4)
- Others (6)
- RegularExpression (2)
- Linux/Windows (12)
- Protocal (2)
- Celebrities (1)
- Interview (1)
- 计算机语言 (1)
- English (2)
- Eclipse (5)
- TimeZone/时区 (1)
- Finance (1)
- 信息安全 (1)
- JMS/MQ (2)
- XSD/XML/DTD (3)
- Android (4)
- 投资 (3)
- Distribution (3)
- Excel (1)
最新评论
-
qdujunjie:
如果把m换成具体的数字,比如4或者5,会让读者更明白
m阶B树中“阶”的含义 -
java-admin:
不错,加油,多写点文章
关于Extjs的mixins和plugin -
xiehuaidong880827:
你好,我用sencha cmd打包完本地工程后,把app.js ...
ExtJS使用Sencha Cmd合并javascript文件为一个文件 -
KIWIFLY:
lwpan 写道inverse = "true&qu ...
Hibernate中什么时候使用inverse=true -
luedipiaofeng:
good
消除IE stop running this script弹出框
原文
http://www.importnew.com/1796.html
在开发和设计的时候,我们需要考虑编译时,运行时以及构建时这三个概念。理解这几个概念可以更好地帮助你去了解一些基本的原理。下面是初学者晋级中级水平需要知道的一些问题。
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文件的话,那么你就会从下面的结果里得到答案。
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命令都是查看编译后的代码(例如,字节码)的利器。
Q.你能想出除了代码优化外,在什么情况下,查看编译过的代码是很有帮助的?
A.Java里的泛型是在编译时构造的,可以通过查看编译后的class文件来理解泛型,也可以通过查看它来解决泛型相关的问题。
Q.下面哪些是发生在编译时,运行时,或者两者都有?
A.
方法重载:这个是发生在编译时的。方法重载也被称为编译时多态,因为编译器可以根据参数的类型来选择使用哪个方法。
public class {
public static void evaluate(String param1); // method #1
public static void evaluate(int param1); // method #2
}
如果编译器要编译下面的语句的话:
evaluate(“My Test Argument passed to param1”);
它会根据传入的参数是字符串常量,生成调用#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;
}
}
子类B中的compute(..)方法重写了父类的compute(..)方法。如果编译器遇到下面的代码:
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的兼容性。
List<String> myList = new ArrayList<String>(10);
编译后成为了:
List myList = new ArrayList(10);
注解(Annotation):你可以使用运行时或者编译时的注解。
public class B extends A {
@Override
public int compute(int input){ //method #4
return 4 * input;
}
}
@Override是一个简单的编译时注解,它可以用来捕获类似于在子类中把toString()写成tostring()这样的错误。在Java 5中,用户自定义的注解可以用注解处理工具(Anotation Process Tool ——APT)在编译时进行处理。到了Java 6,这个功能已经是编译器的一部分了。
public class MyTest{
@Test
public void testEmptyness( ){
org.junit.Assert.assertTrue(getList( ).isEmpty( ));
}
private List getList( ){
//implemenation goes here
}
}
@Test是JUnit框架用来在运行时通过反射来决定调用测试类的哪个(些)方法的注解。
@Test (timeout=100)
public void testTimeout( ) {
while(true); //infinite loop
}
如果运行时间超过100ms的话,上面的测试用例就会失败。
@Test (expected=IndexOutOfBoundsException.class)
public void testOutOfBounds( ) {
new ArrayList<Object>( ).get(1);
}
如果上面的代码在运行时没有抛出IndexOutOfBoundsException或者抛出的是其他的异常的话,那么这个用例就会失败。用户自定义的注解可以在运行时通过Java反射API里新增的AnnotatedElement和”Annotation”元素接口来处理。
异常(Exception):你可以使用运行时异常或者编译时异常。
运行时异常(RuntimeException)也称作未检测的异常(unchecked exception),这表示这种异常不需要编译器来检测。RuntimeException是所有可以在运行时抛出的异常的父类。一个方法除要捕获异常外,如果它执行的时候可能会抛出RuntimeException的子类,那么它就不需要用throw语句来声明抛出的异常。
例如:NullPointerException,ArrayIndexOutOfBoundsException,等等
受检查异常(checked exception)都是编译器在编译时进行校验的,通过throws语句或者try{}cathch{} 语句块来处理检测异常。编译器会分析哪些异常会在执行一个方法或者构造函数的时候抛出。
面向切面的编程(Aspect Oriented Programming-AOP):切面可以在编译时,运行时或,加载时或者运行时织入。
编译期:编译期织入是最简单的方式。如果你拥有应用的代码,你可以使用AOP编译器(例如,ajc – AspectJ编译器)对源码进行编译,然后输出织入完成的class文件。AOP编译的过程包含了waver的调用。切面的形式可以是源码的形式也可以是二进制的形式。如果切面需要针对受影响的类进行编译,那么你就需要在编译期织入了。
编译后:这种方式有时候也被称为二进制织入,它被用来织入已有的class文件和jar文件。和编译时织入方式相同,用来织入的切面可以是源码也可以是二进制的形式,并且它们自己也可以被织入切面。
装载期:这种织入是一种二进制织入,它被延迟到JVM加载class文件和定义类的时候。为了支持这种织入方式,需要显式地由运行时环境或者通过一种“织入代理(weaving agent)“来提供一个或者多个“织入类加载器(weaving class loader)”。
运行时:对已经加载到JVM里的类进行织入
继承 – 发生在编译时,因为它是静态的
代理或者组合 – 发生在运行时,因为它更加具有动态性和灵活性。
Q.你有没有听说过“组合优于继承”这样的说法呢?如果听说过的话,那么你是怎么理解的呢?
A.继承是一种多态工具,而不是一种代码复用工具。有些开发者喜欢用继承的方式来实现代码复用,即使是在没有多态关系的情况下。是否使用继承的规则是继承只能用在类之间有“父子”关系的情况下。
不要仅仅为了代码复用而继承。当你使用组合来实现代码复用的时候,是不会产生继承关系的。过度使用继承(通过“extends”关键字)的话,如果修改了父类,会损坏所有的子类。这是因为子类和父类的紧耦合关系是在编译期产生的。
不要仅仅为了多态而继承。如果你的类之间没有继承关系,并且你想要实现多态,那么你可以通过接口和组合的方式来实现,这样不仅可以实现代码重用,同时也可以实现运行时的灵活性。
这就是为什么四人帮(Gang of Four)的设计模式里更倾向于使用组合而不是继承的原因。面试者会在你的答案里着重关注这几个词语——“耦合”,“静态还是动态”,以及“发生在编译期还是运行时”。运行时的灵活性可以通过组合来实现,因为类可以在运行时动态地根据一个结果有条件或者无条件地进行组合。但是继承却是静态的。
Q.你能够通过实例来区别编译期继承和运行时继承,以及指出Java支持哪种吗?
A.“继承”表示动作和属性从一个对象传递到另外一个对象的场景。Java语言本身只支持编译期继承,它是通过“extends”关键字来产生子类的方式实现的,如下所示:
public class Parent {
public String saySomething( ) {
return “Parent is called”;
}
}
public class Child extends Parent {
@Override
public String saySomething( ) {
return super.saySomething( ) + “, Child is called”;
}
}
“Child”类的saySomething()方法的调用会返回“Parent is called,Child is Called”,因为,子类的调用继承了父类的“Parenet is called”。关键字“super”是用来调用“Parent”类的方法。运行时继承表示在运行时构建父/子类关系。Java语言本身不支持运行时继承,但是有一种替代的方案叫做“代理”或者“组合”,它表示在运行时组件一个层次对象的子类。这样可以模拟运行时继承的实现。在Java里,代理的典型实现方式如下:
public class Parent {
public String saySomething( ) {
return “Parent is called”;
}
}
public class Child {
public String saySomething( ) {
return new Parent( ).saySomething( ) + “, Child is called”;
}
}
子类代理了父类的调用。组合可以按照下面的方式来实现:
public class Child {
private Parent parent = null;
public Child( ){
this.parent = new Parent( );
}
public String saySomething( ) {
return this.parent.saySomething( ) + “, Child is called”;
}
}
发表评论
-
sapjco3 notes
2019-03-21 14:51 1170sapjco https://support.sap.com/ ... -
使用RestTemplate发送post JSON请求
2019-01-12 17:30 4753private final String BASE_URL = ... -
使用RestTemplate发送post JSON请求
2019-01-12 17:30 3534private final String BASE_URL = ... -
Spring线程池ThreadPoolTaskExecutor
2018-08-06 09:51 1904<!-- spring thread pool ex ... -
Spring注解事物@Transactional不工作
2018-08-02 18:50 2686“In proxy mode (which is the de ... -
创建前缀索引报长度超出错误
2018-07-25 15:44 1740表结构定义如下: CREATE TABLE `sku` ( ` ... -
Mysql Varchar字符长度
2018-07-25 15:23 1356`sku_name` VARCHAR(200) NOT NUL ... -
使用 Spring RestTemplate 发送 post 请求
2018-07-23 18:49 11733注意点: 1)使用MultiValueMap设置入参,不要使 ... -
Java动态代理Dynamic Proxy
2018-07-21 16:33 831JAVA学习篇--静态代理VS动态代理 https://blo ... -
分布式实时日志分析解决方案 ELK 部署架构
2018-07-20 09:52 1195原文链接:http://www.importn ... -
为什么HashMap容量一定要为2的幂呢?
2018-07-19 10:07 1731原文链接:https://blog.csdn.net/wang ... -
为什么计算HashCode时通常选择31这个数?
2018-07-19 10:05 1427摘自http://www.importnew.com/2208 ... -
jackson自定义序列化和反序列化
2018-07-10 18:47 2247原文链接:https://blog.csdn.net/liu ... -
Pay special attention when modifying online running system
2017-06-23 10:25 0Never remove any properties, me ... -
Map中的Null key, Null Value
2017-06-14 10:52 1950ConcurrentHashMap的key和value都不能为 ... -
Java语法糖
2017-06-05 20:03 534Java语法糖之foreach http://www.imp ... -
Java集合相关
2017-05-24 17:55 0Java集合框架:ArrayList http://www. ... -
Java数据类型的转换:隐式(自动)转换与强制转换
2017-05-14 10:46 0http://blog.csdn.net/u011240877 ... -
分布式开放消息系统(RocketMQ)的原理与实践
2017-05-07 19:55 735分布式开放消息系统(RocketMQ)的原理与实践 http ... -
面试知识点复习(Interview knowledge review)
2017-05-07 18:39 0JVM,多线程相关知识 http://darrenzhu.it ...
相关推荐
### C语言性能提升:编译时与运行时优化深度解析 C语言作为一种高效且灵活的编程语言,在系统软件开发领域有着不可替代的地位。其特点包括简洁高效、接近硬件、良好的可移植性、丰富的库支持、支持结构化编程以及...
Java 编译时多态和运行时多态 Java 编译时多态和运行时多态是 Java 语言中两个重要的概念,它们都是多态性的实现方式,但它们在实现机制和应用场景上有所不同。 编译时多态 编译时多态是指在编译期根据参数列表的...
当你直接用`javac`命令编译单个源文件时,例如`javac HelloWorld.java`,编译后的类文件(HelloWorld.class)将被创建在与源文件相同的目录下。如果源文件包含`package`声明,例如`package com.test;`,那么`javac`...
在Android开发中,注解(Annotation)是一种强大的元数据,可以为代码添加额外的信息,而这些信息可以在编译时或运行时被解析和利用。ButterKnife是一款著名的Android视图绑定库,它通过注解简化了UI元素的绑定,...
Cannon-utils是一个可能与Java运行时动态编译相关的工具或库,但具体功能和使用方法需要查看其文档或源码才能详细了解。通常,这样的工具可能提供了辅助分析JIT编译效果、性能测试或者优化Java代码的功能。 总的来...
4. **多线程与并发**:运行时环境支持多线程和并发执行,允许多个任务同时进行,提升程序性能。 5. **动态绑定**:面向对象编程中的动态绑定,即方法调用在运行时确定,而非编译时,这允许了更多的灵活性,如多态性...
Java代码快捷编译运行工具是针对初学者设计的一款实用程序,旨在简化Java编程过程中常见的编译和运行步骤。对于刚接触Java编程的开发者来说,通过命令行(CMD)进行源码的javac编译和java运行可能会感到繁琐,而这款...
在开发和设计的时候,我们需要考虑编译时,运行时以及构建时这三个概念。理解这几个概念可以更好地帮助你去了解一些基本的原理。下面是初学者晋级中级水平需要知道的一些问题。 Q.下面的代码片段中,行A和行B所...
然而,对于初学者或需要快速测试代码的人来说,传统的编译和运行步骤可能会显得繁琐。这个名为“编译和运行Java程序的小工具”就是为了简化这一过程而设计的。下面将详细解释这款小工具的工作原理以及如何利用它来...
### Linux驱动编译与运行详解 #### 一、理解Linux驱动程序 Linux驱动程序是操作系统与硬件设备之间的桥梁,负责管理硬件资源并提供相应的服务。它们通常被编写为内核模块,可以动态加载或卸载,以适应系统需求的...
本文将深入探讨"JAVA范例 四)异常处理---编译时异常、运行时异常"这个主题,结合标签"源码"和"工具",我们可以理解这与实际编程实践和可能使用的开发工具如Struts2框架相关。 首先,我们来看编译时异常。编译时...
在实现Linux 0.01编译与运行时,作者采用了Redhat 9.0平台作为开发环境,GNU工具链作为开发工具,并使用GNU工具链的AT&T语法汇编器进行汇编程序的编译。在源代码语法的修改方面,作者参照Linux 0.11源代码,对Linux ...
**CALPUFF编译与运行流程** 1. **CALWRF编译和运行** - 源程序位于`CALWRF_v2.0.2_L131108/code`目录,编译脚本为`compile_ifort.sh`,需NETCDF库支持。 - 输入数据包括WRF输出文件`wrfout_d03_2019-03-21_00:00:...
**WPF MVVM工程示例及反编译后可运行示例** 本示例主要针对Windows Presentation Foundation(WPF)框架中的Model-View-ViewModel(MVVM)设计模式进行深入探讨,结合具体代码实例,帮助开发者更好地理解和运用这一...
### 关于交叉编译不能运行的问题 #### 一、交叉编译概述 交叉编译是一种特殊的编译方式,指的是在一个平台上编译代码,使其能在另一个不同的平台上运行。这种方式广泛应用于嵌入式系统的开发中,因为目标平台(如...
在使用 VS2010 进行编译时,可能会遇到程序在 XP 系统上不能运行的问题。这主要是由于 VS2010 编译出的程序依赖于 Microsoft Visual C++ 2010 Redistributable-x86,但 XP 系统可能没有安装这个组件。今天,我们将...
3. **运行与调试**:成功编译后的Java程序可以在服务器上运行,返回执行结果。部分在线编辑器还提供了运行控制台,显示程序输出,甚至支持简单的调试功能,如设置断点、单步执行等。 4. **版本控制**:为了便于多...
### 在虚拟机上编译、安装和运行VPP #### 安装环境需求 为了确保在虚拟机上顺利编译、安装并运行VPP,首先需要满足以下环境配置: - **虚拟机软件**:推荐使用VMware 12.5版本。 - **虚拟机操作系统**:Ubuntu ...
7. **32位与64位兼容性**:在选择编译器时必须注意,确保编译出的可执行文件与目标平台的位数匹配。例如,如果树莓派是32位系统,那么生成的可执行文件也应该是32位的。 8. **虚拟机环境**:在Windows上使用虚拟机...