阅读更多

33顶
5踩

研发管理

翻译新闻 优秀的程序 vs. 糟糕的程序

2012-11-19 15:50 by 副主编 wangguo 评论(75) 有21174人浏览
开发者Rahul Singh近日在其个人博客中列出了他眼中的优秀的程序和糟糕的程序:

引用
优秀的程序可以使复杂的东西看起来很简单;糟糕的程序让原本简单的东西变得复杂。

优秀的程序不需要加以说明;糟糕的程序需要大量注释。

优秀的程序编写时需要更多时间,但未来花费的时间却更少;糟糕的程序往往花费较少的时间,但会在未来浪费掉更多时间。

优秀的程序需要考虑当前和未来的需求;糟糕的程序只侧重于现在,在未来可能无法正常工作。

优秀的程序非常易于维护;糟糕的程序难以维护。

优秀的程序有更长的生命周期,甚至应用范围超出预期;糟糕的程序在其工作范围之外几乎无法使用。

优秀的程序如同良好的习惯,其影响将持续很长一段时间,几乎可以永久地解决问题;糟糕的程序如同止痛药,其效果只有很短的时间,解决问题大多是暂时的。

优秀的程序是整洁的、遵守规律的;糟糕的程序是混乱的。

优秀的程序可以令人学到很多编程方法和经验;糟糕的程序只能令人越学越糟。

优秀的程序中,该重用的地方重用,该发明的地方发明;糟糕的程序会重新发明轮子,并在适合发明的地方重用。

优秀的程序依靠程序员的直觉和知识,并经过了多年良好程序习惯的熏陶;糟糕的程序往往盲目依赖他人的知识和经验,而没有自己的理解。

优秀的程序可以很容易地从一个程序员转移给另一个程序员;糟糕的程序只能被编写者理解和实施。

优秀的程序员不会刻意去记忆一段代码,他依赖于他的逻辑思维能力和理解,并能在未来轻松改善代码;糟糕的程序员往往会记住很多自己不理解的代码。

优秀的程序都有相同的特征,如简单、可读性强、效率高;糟糕的程序各有糟糕之处。

优秀的程序比程序员存在的时间要更久;糟糕的程序存在的时间很短。


英文原文:Good Programming, Bad Programming

相关阅读:优秀的开发者 vs. 差的开发者
33
5
评论 共 75 条 请登录后发表评论
75 楼 hfkiss44 2012-12-28 10:05
怎么说呢   大家看开源代码的源码也不少了  明明很简单的事情确实封装再封装  封装再封装 一旦牵扯方法的深层次调用  必须自己在源码里面写注释  一点一点写 写完了之后还是被绕的云里来雾里去  我觉得没必要为了代码的优雅而去刻意封装  只要大家能看的懂  不影响运行效率就行   什么叫好代码 我觉得就是能很快移交到别人手里的代码才是好代码越复杂越是这样
74 楼 hongbo.wu 2012-12-19 15:04
个人觉得,
最简单通用的写法(不是说代码字少的那种,指计算简单、算法通用、简洁明了、无简写代码等),适应的注释就可以了
本身很多代码的命名就相当注释了可以看得懂,重要核心的部份应当明确注释,解释其意图。

注释只是一个方面
还有一个很重要的就是格式,
一个类、方法的行数数量并不代表什么,当然能公共的应当抽取提供方法
其实很多人根本就没有注意 代码格式,如什么地方换行,什么地方不该换行

还有变量、常量、类、方法的命名、以及统一的问题其实也是很常见的,很多人的
风格不一样,所以命名方式也是不一样的。 这个重点是统一

楼下那位写贴代码的朋友, 你的代码,写法还是不错,不能算最好。
理由:
1,采用了简单写法
2,方法名没有注释,
3,大括号没有换行,代码格式不立马使人看出代码段快的开始与结束段,
   应当一行一语句,这样别人更容易看懂
4,常量变量命名用了简写,如果用简写,应当注释

上以仅个人意见,当然,这段代码总体来说是不错的,

73 楼 wushexu 2012-12-14 14:24
注释是个小问题,但能反映一个程序员对程序的见解,乃至程序员的性格。
在商业化的环境下,大型的优秀的程序是不太能出现的,这要求一个团队每个成员都达到相当的水准,以及追求精品的理念、精益求精的态度。当然机构决策层首先要有这样的理念和追求。
但中小规模的优秀程序就比较容易出现,较小的这样的团队比较容易建立。
72 楼 waynelewis 2012-12-13 09:52
在商业化的现实中,有几个人或者说有几个机构能够编写出所谓的优秀的程序?
71 楼 11lingxian 2012-12-03 15:47
在这么深刻的主题下居然主要讨论神马“注释”,要么是老外写的太教条了,要么是读者的思想深度不够
70 楼 dwangel 2012-11-30 16:30
怎么 觉得评论里的讨论,其实到最后并不是 注释的作用,
而是工程师愿不愿意 花时间整理思路,让自己的思路清晰,易懂,
并注重让别人能够方便地理解自己的代码。

而不仅仅是完成任务就好。

实现让自己的思路可以被阅读代码的人可以理解(包括以后回过来维护这段代码的编写者),可以通过合理的编码习惯,也可以通过注释。

把注释写好不见得比把函数写好简单,对某些人而言……
69 楼 abiandbel 2012-11-30 10:55
if(i!=我){} 写道
ewth126 写道
wxyzyu 写道
ewth126 写道
注释还是要把,到时候生成说明什么的更加方便!你的程序不能只是为了让懂的人看懂,还要让后辈们,或者是在学习中的人看懂,程序员是一种传承。
我觉得注释真的很重要。试想3000多行的代码的一个类没有注释。后来修改的人怎么做?再加上偶尔strTemp这种蛋疼的全局变量。

对的,我觉得注释的重要性远大于代码,毕竟你不能保证你写的代码以后的效率依然是最高。大家都让别人方便,自然维护就方便了。

笑话!注释的重要性大于代码?还远大于?还有上上一层的“3000多行的代码”,更是个笑话!

之前接过一个做一半的项目,最大一个类2000多行、一个方法300多行,各种标识,各种重复。最后业务层我删了1/2代码,而且完成了更多的功能。没怎么加注释,但没人敢说他看不懂。

永远记住一句话:设计大于实现,规则大于编码——远大于!



狂顶你这句话。。。。。
设计大于实现,规则大于编码——远大于!
我现在就是认为 软件架构设计 远远大于一切。
目前中国软件开发急缺的就是好的软件架构师。
写程序容易,写好程序绝对不容易。
胡编乱造的程序太多了。
看见什么写什么,设计在他心中简直就是一坨屎。
目前中国这样的“管理者”太多了。
68 楼 dwangel 2012-11-23 14:19
槽点很多,懒得吐了。
67 楼 wushexu 2012-11-23 13:31
再具体一些,我给出可能的注释(都是类层次的。内部注释没有好的例子),每条都有写或不写的理由。看看你的选择。


1、

1)NameStrategy用在哪里(存取数据库时的转换,要说吗)
2)使用NameStrategy时会不会检查类型(还是有propertyToField、fieldToProperty就可以(duck type))
3)propertyToField和fieldToProperty是闭包属性,不是方法
4)为什么定义为闭包属性,而不是方法
5)propertyToField和fieldToProperty内部有没有缓存(不管数据量有多少,property和field是有限的,故可以缓存),调用它的程序有没有必要自己缓存
6)为什么NameStrategy不实现Cloneable


2、

1)Pagination是什么,怎么使用
2)offset和page是基于1的
3)为什么让offset和page基于1
4)perPage默认是300
5)为什么perPage默认是300
6)total和pages允许null
7)为什么total和pages要允许null


3、

1)McfAggregator在哪里使用,为什么不在数据库汇总而用它
2)汇总分组是按organId、accitemId
3)利率是按余额加权求平均
4)pushMcf(mcf),要求mcf实现Cloneable
5)mcf会先clone(),以后对mcf修改没影响
6)mcf的endingBalance、rate属性应该是double,如果是Double,不会检查空值
7)McfAggregator不是线程安全的,不能多个线程调用pushMcf。
8)为什么不做成线程安全的,将来是否准备做成线程安全的
9)调用done()后内部数据被清除了
10)原始数据量和汇总后的数据量。如,某年月日测试,push 100万条,done 得到 5万条。
66 楼 Mybeautiful 2012-11-23 13:18
观点陈述清楚就好了,没有绝对的对与错;每个人都有合适自己(自己团队)的方法。
65 楼 kidneyball 2012-11-23 11:04
wushexu 写道
kidneyball 写道
kidneyball 写道


第一段代码,把replace里的字面量抽取为命名常量。(更好且运行效率更高地方式把Pattern.compile出来后的Pattern实例定义为常量,然后调用MY_NAMED_PATTERN.matcher(s).replaceAll()方法。

第二段代码,"1 based"放到getter和setter上,写成JavaDoc。作为API文档,还应该写得更详细点。

第三段代码,算式抽出来,金山词霸一下“加权平均值”的英文,作为方法名称。还不放心的话,把这个新方法再抽到一个工具类上做成静态方法,在JavaDoc上用中文写上“求加权平均值”


嗯,第三段把foreach这整块抽出来似乎更好,方法名可以是calculateWeightedAverageRate。


McfAggregator是在内存做汇总,这是简化了的代码,实际处理的并不仅仅是rate、endingBalance。

提供例子主要为了讨论关于注释的看法。
请phk070832、ewth126、wxyzyu、if(i!=我){}、java_user等发表看法。


不管你在做什么,都可以通过重构把内部注释干掉。我之所以不喜欢内部注释,不仅仅因为它难以维护,还在于明明有更好的替代方式。
64 楼 kidneyball 2012-11-23 10:56
wushexu 写道
在具体问题上才好看出观点差异。给你们几段代码(无关业务)供讨论。

1、
class NameStrategy {
	
	def propertyToField={ propertyName ->
		propertyName.replaceAll('[A-Z]',{'_'+it[0].toLowerCase()})
	}
	
	def fieldToProperty={ fieldName ->
		fieldName.toLowerCase().replaceAll('_(.)',{it[1].toUpperCase()})
	}
}



2、
class Pagination implements Serializable,Cloneable {
	
	int perPage=300
	
	Integer total
	
	// 1 based
	Integer offset
	
	Integer pages
	
	// 1 based
	int page=1
	
	Integer getOffset(){
		if(offset==null){
			offset=perPage * (page-1) + 1
		}
		return offset
	}
	
	Integer getPages(){
		if(pages==null){
			if(total==null){
				return null
			}
			pages=total/perPage
			if(total%perPage!=0){
				pages++
			}
		}
		return pages
	}
}


3、
class McfAggregator {
	
	protected Map dataMap=[:]
	
	private genMcfKey(m){
		"${m.organId}|${m.accitemId}"
	}
	
	void pushMcf(mcf){
		def key=genMcfKey(mcf)
		Object mcfd=dataMap[key]
		if(mcfd==null){
			dataMap[key]=mcf.clone()
			return
		}
		mcfd.endingBalance+=mcf.endingBalance
		mcfd.rate+=mcf.endingBalance*mcf.rate
	}
	
	List done(){
		
		dataMap.each{ key,mcfd ->
			def endingBalance=mcfd.endingBalance
			if(endingBalance>0.0){
				//加权平均利率
				mcfd.rate=mcfd.rate/endingBalance
			}
		}
		
		List cfs=dataMap.values() as List
		
		dataMap.clear()
		
		return cfs
	}
}


再说说内部注释问题(三连发,不好意思,上班时间,用重启服务器的时间来逛论坛的)。第一段代码没有注释就不说了。第二段,“以1为基数”这种与用法相关的东西显然应该让用户知道。内部注释如果人家不跑进来看你就白写了。第三段,很有可能不久后就有人把整个done方法复制到别处,保留foreach结构,里面算式改掉,但是没有改注释。另外,在“done”方法里面有一段算加权平均利率的实现代码有点bad smell,这里需要特别注释也说明了这段代码与上下文不匹配。抽出来(甚至应该改成在上层调用时在done之前调用)会清晰很多。
63 楼 wushexu 2012-11-23 10:48
kidneyball 写道
kidneyball 写道


第一段代码,把replace里的字面量抽取为命名常量。(更好且运行效率更高地方式把Pattern.compile出来后的Pattern实例定义为常量,然后调用MY_NAMED_PATTERN.matcher(s).replaceAll()方法。

第二段代码,"1 based"放到getter和setter上,写成JavaDoc。作为API文档,还应该写得更详细点。

第三段代码,算式抽出来,金山词霸一下“加权平均值”的英文,作为方法名称。还不放心的话,把这个新方法再抽到一个工具类上做成静态方法,在JavaDoc上用中文写上“求加权平均值”


嗯,第三段把foreach这整块抽出来似乎更好,方法名可以是calculateWeightedAverageRate。


McfAggregator是在内存做汇总,这是简化了的代码,实际处理的并不仅仅是rate、endingBalance。

提供例子主要为了讨论关于注释的看法。
请phk070832、ewth126、wxyzyu、if(i!=我){}、java_user等发表看法。
62 楼 kidneyball 2012-11-23 10:37
kidneyball 写道
wushexu 写道
在具体问题上才好看出观点差异。给你们几段代码(无关业务)供讨论。

3、
class McfAggregator {
	
	protected Map dataMap=[:]
	
	private genMcfKey(m){
		"${m.organId}|${m.accitemId}"
	}
	
	void pushMcf(mcf){
		def key=genMcfKey(mcf)
		Object mcfd=dataMap[key]
		if(mcfd==null){
			dataMap[key]=mcf.clone()
			return
		}
		mcfd.endingBalance+=mcf.endingBalance
		mcfd.rate+=mcf.endingBalance*mcf.rate
	}
	
	List done(){
		
		dataMap.each{ key,mcfd ->
			def endingBalance=mcfd.endingBalance
			if(endingBalance>0.0){
				//加权平均利率
				mcfd.rate=mcfd.rate/endingBalance
			}
		}
		
		List cfs=dataMap.values() as List
		
		dataMap.clear()
		
		return cfs
	}
}


第一段代码,把replace里的字面量抽取为命名常量。(更好且运行效率更高地方式把Pattern.compile出来后的Pattern实例定义为常量,然后调用MY_NAMED_PATTERN.matcher(s).replaceAll()方法。

第二段代码,"1 based"放到getter和setter上,写成JavaDoc。作为API文档,还应该写得更详细点。

第三段代码,算式抽出来,金山词霸一下“加权平均值”的英文,作为方法名称。还不放心的话,把这个新方法再抽到一个工具类上做成静态方法,在JavaDoc上用中文写上“求加权平均值”


嗯,第三段把foreach这整块抽出来似乎更好,方法名可以是calculateWeightedAverageRate。
61 楼 kidneyball 2012-11-23 10:24
wushexu 写道
在具体问题上才好看出观点差异。给你们几段代码(无关业务)供讨论。

1、
class NameStrategy {
	
	def propertyToField={ propertyName ->
		propertyName.replaceAll('[A-Z]',{'_'+it[0].toLowerCase()})
	}
	
	def fieldToProperty={ fieldName ->
		fieldName.toLowerCase().replaceAll('_(.)',{it[1].toUpperCase()})
	}
}



2、
class Pagination implements Serializable,Cloneable {
	
	int perPage=300
	
	Integer total
	
	// 1 based
	Integer offset
	
	Integer pages
	
	// 1 based
	int page=1
	
	Integer getOffset(){
		if(offset==null){
			offset=perPage * (page-1) + 1
		}
		return offset
	}
	
	Integer getPages(){
		if(pages==null){
			if(total==null){
				return null
			}
			pages=total/perPage
			if(total%perPage!=0){
				pages++
			}
		}
		return pages
	}
}


3、
class McfAggregator {
	
	protected Map dataMap=[:]
	
	private genMcfKey(m){
		"${m.organId}|${m.accitemId}"
	}
	
	void pushMcf(mcf){
		def key=genMcfKey(mcf)
		Object mcfd=dataMap[key]
		if(mcfd==null){
			dataMap[key]=mcf.clone()
			return
		}
		mcfd.endingBalance+=mcf.endingBalance
		mcfd.rate+=mcf.endingBalance*mcf.rate
	}
	
	List done(){
		
		dataMap.each{ key,mcfd ->
			def endingBalance=mcfd.endingBalance
			if(endingBalance>0.0){
				//加权平均利率
				mcfd.rate=mcfd.rate/endingBalance
			}
		}
		
		List cfs=dataMap.values() as List
		
		dataMap.clear()
		
		return cfs
	}
}


第一段代码,把replace里的字面量抽取为命名常量。(更好且运行效率更高地方式把Pattern.compile出来后的Pattern实例定义为常量,然后调用MY_NAMED_PATTERN.matcher(s).replaceAll()方法。

第二段代码,"1 based"放到getter和setter上,写成JavaDoc。作为API文档,还应该写得更详细点。

第三段代码,算式抽出来,金山词霸一下“加权平均值”的英文,作为方法名称。还不放心的话,把这个新方法再抽到一个工具类上做成静态方法,在JavaDoc上用中文写上“求加权平均值”
60 楼 wushexu 2012-11-23 10:09
在具体问题上才好看出观点差异。给你们几段代码(无关业务)供讨论。

1、
class NameStrategy {
	
	def propertyToField={ propertyName ->
		propertyName.replaceAll('[A-Z]',{'_'+it[0].toLowerCase()})
	}
	
	def fieldToProperty={ fieldName ->
		fieldName.toLowerCase().replaceAll('_(.)',{it[1].toUpperCase()})
	}
}



2、
class Pagination implements Serializable,Cloneable {
	
	int perPage=300
	
	Integer total
	
	// 1 based
	Integer offset
	
	Integer pages
	
	// 1 based
	int page=1
	
	Integer getOffset(){
		if(offset==null){
			offset=perPage * (page-1) + 1
		}
		return offset
	}
	
	Integer getPages(){
		if(pages==null){
			if(total==null){
				return null
			}
			pages=total/perPage
			if(total%perPage!=0){
				pages++
			}
		}
		return pages
	}
}


3、
class McfAggregator {
	
	protected Map dataMap=[:]
	
	private genMcfKey(m){
		"${m.organId}|${m.accitemId}"
	}
	
	void pushMcf(mcf){
		def key=genMcfKey(mcf)
		Object mcfd=dataMap[key]
		if(mcfd==null){
			dataMap[key]=mcf.clone()
			return
		}
		mcfd.endingBalance+=mcf.endingBalance
		mcfd.rate+=mcf.endingBalance*mcf.rate
	}
	
	List done(){
		
		dataMap.each{ key,mcfd ->
			def endingBalance=mcfd.endingBalance
			if(endingBalance>0.0){
				//加权平均利率
				mcfd.rate=mcfd.rate/endingBalance
			}
		}
		
		List cfs=dataMap.values() as List
		
		dataMap.clear()
		
		return cfs
	}
}
59 楼 kidneyball 2012-11-23 09:48
kidneyball 写道
phk070832 写道
kidneyball 写道
phk070832 写道

我明白你的意思,你就是想碰到问题后一行行的看代码来解决。


这有什么问题吗?不但一行行看,还要看前后两级以上的调用关系。顺便还重构一下,删掉一些过期(没闲功夫改,如果注释过期了与其放着误导人,干脆删掉)或者不必要的注释。


确实没问题,但是你没注意到工作效率的问题。


你确认我的平均工作效率会比你低吗?我倒能举出一堆被过期或歧义的注释误导影响而造成损失的例子。


最大问题是,根本就没有任何有效,可管理的方法可以保证注释不过期,没歧义,不被胡乱复制粘贴。一个系统里有一万条注释,按常理来说,保守估计有十分一是不可信的。你想保证效率,最好的办法就是不要轻信任何一条注释,而是先检查一遍注释和代码是否对应。问题是,你不看懂代码,就无法检查,而既然你都已经看懂了,那还要那条注释来干什么。如果那段代码很难懂,你看的过程中把它改得好懂点不就完了吗。
58 楼 kidneyball 2012-11-23 09:42
phk070832 写道
kidneyball 写道
phk070832 写道

我明白你的意思,你就是想碰到问题后一行行的看代码来解决。


这有什么问题吗?不但一行行看,还要看前后两级以上的调用关系。顺便还重构一下,删掉一些过期(没闲功夫改,如果注释过期了与其放着误导人,干脆删掉)或者不必要的注释。


确实没问题,但是你没注意到工作效率的问题。


你确认我的平均工作效率会比你低吗?我倒能举出一堆被过期或歧义的注释误导影响而造成损失的例子。
57 楼 phk070832 2012-11-23 09:34
kidneyball 写道
phk070832 写道

我明白你的意思,你就是想碰到问题后一行行的看代码来解决。


这有什么问题吗?不但一行行看,还要看前后两级以上的调用关系。顺便还重构一下,删掉一些过期(没闲功夫改,如果注释过期了与其放着误导人,干脆删掉)或者不必要的注释。



确实没问题,但是你没注意到工作效率的问题。
56 楼 kidneyball 2012-11-23 09:32
kidneyball 写道
phk070832 写道

我明白你的意思,你就是想碰到问题后一行行的看代码来解决。


这有什么问题吗?不但一行行看,还要看前后两级以上的调用关系。顺便还重构一下,删掉一些过期(没闲功夫改,如果注释过期了与其放着误导人,干脆删掉)或者不必要的注释。


或者这么说吧,有A和B两个程序员。A写的程序是结构清晰,自描述的,但从不写内部注释。B写的程序一团浆糊,但通过写注释能让人看懂。在排错时,对于有完善注释的程序,A比B的速度慢一半,对于没有注释的程序,A的速度保持不变,B则慢数倍或被完全卡住(临急抱佛脚读程序的后果)。你是项目经理,你选谁?

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • JVM类装载器详解

    JVM类装载器详解

  • JVM类装载器机制

    加载:查找并加载类全限定名的二进制字节流,转为方法区数据结构(特殊的堆),在Java堆中生成对应的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。 注意:对于数组类,情况就有所不同,数组类本身不...

  • java类验证和装载顺序_一张图看懂JVM之类装载系统

    原标题:一张图看懂JVM之类装载系统 导读在之前的文章中,我们通过一张图的方式(图????)整体上了解了JVM的结构,并重点讲解了JVM的内存结构、内存回收算法及回收器方面的知识。收到了不少读者朋友们的反馈和指正,在...

  • JVM类加载器(类装载子系统)

    加载:通过类的全限定名获取此类的字节流,将流代表的静态存储结构转化为方法区(作为一个内存区域,jdk1.7以前永久代,1.8之后元空间)的运行时数据结构,在内存中生成一个代表该类的java.lang.class对象,作为方法区这个类...

  • JVM之类装载子系统

    如果一个类是用户类加载器加载的,JVM会将类加载器的引用作为类的一部分信息保存在方法区当中,当解析一个类型到另一个类型引用的时候,JVM则必须保证两个类加载器是相同的。(动态链接) JVM中对类的使用分为主动和...

  • JVM系列之三:类装载器子系统

     虚拟机类装载器子系统:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。  类的加载指的是将类的.class文件中的二进制数据读入到...

  • JVM类加载器子系统

    JVM Class Loader SubSystem概述类加载的过程加载阶段(Loading)链接阶段(Linking)初始化阶段(Initialization)3种类加载器& 自定义加载器获取 ClassLoader的4种方式自定义类加载器(User Defined ClassLoader)双亲...

  • JVM学习笔记02-类加载器子系统

    1、类加载器子系统的作用 2、类加载器ClassLoader角色 3、类的加载过程 3.1、加载 3.2、链接 4、类加载器的分类 4.1、引导类加载器(Bootstrap ClassLoader) 4.2、扩展类加载器(Extension Class Loader) ...

  • JVM(二)类装载子系统

    类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。 ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine(执行引擎)决定。 加载的类信息存放于...

  • JVM—类加载子系统

    类加载器执行引擎在Java的日常应用程序开发中,类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方式。为什么要自定义类加载器?隔离加载类修改类加载的方式...

  • JVM类加载子系统

    类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。 ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine(执行引擎)决定。 加载的类信息存放于...

  • [JVM]超详细JVM系列文(1):整体结构+类加载子系统+运行时数据区—程序计数器、栈(多图长文)

    按照Java代码执行的流程,从类装载器子系统出发,剖析其各个子模块的结构与功能。结合Java语言中的相关设计思路(变量的初始化、存储;对象的生命周期、方法的调用)、OOP(继承、多态),在JVM进行追根溯源,解释其...

  • JVM一:类加载器子系统

    类加载器子系统(ClassLoader):将class字节码文件加载到JVM内存中,是否会执行该字节码文件由 执行引擎决定。 类加载器子系统(Class loader subSystem)只负责将class文件加载进内存中,并且类在仅需要时加载,...

  • 【JVM】VM是什么?JVM是什么?JVM作用是什么?JVM特点?JVM位置?JVM组成?

    1、类加载子系统类加载的角色?类加载的过程?① 加载 Loading② 链接 Linking③ 初始化 Initialization类什么时候初始化?类的初始化顺序?类加载器分类?双亲委派机制是什么?双亲委派的优点?类的主动使用/被动...

  • JVM第二章-类加载子系统

    类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。 ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。 加载

  • JVM-类加载子系统

    System . out . println("你的大恩大德,我下辈子再报!");} }它的加载过程是怎么样的呢?...完成后调用 HelloLoader 类中的静态方法 main加载失败则抛出异常完整流程JVM严格来讲支持两种类型的类加载器。...

  • JVM总结之类加载子系统

    一个类的完整生命周期如下 类加载过程 Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚拟机是如何加载这些 Class 文件呢? 系统加载 Class 类型的文件主要三步:加载->连接->初始化。连接过程又...

  • JVM系列之类加载子系统

    1、类加载器与类的加载过程 1.1、类加载器 1.1.1、类加载器子系统的作用 负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识,魔术,CA FA BA BE Classloader只负责class文件的加载,...

  • 4. JVM-类加载子系统

    类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。 ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。 加载的类信息存放于一块称为...

  • 【JVM】类加载子系统

    一,内存结构 二,类加载器及类加载过程 三,类加载器的分类 四,ClassLoader的常用方法及获取方式 五,双亲委派机制 六,其他

Global site tag (gtag.js) - Google Analytics