如何阅读他人的程序代码(上)——技巧学习篇

2023-10-26

一、读懂程序代码,使心法皆为我所用 
 
程序代码是别人写的,只有原作者才真的了解程序代码的用途及涵义。许多程序人心里都有一种不自觉的恐惧感,深怕被迫去碰触其他人所写的程序代码。但是,与其抗拒接收别人的程序代码,不如彻底了解相关的语言和惯例,当成是培养自我实力的基石。 


对大多数的程序人来说,撰写程序代码或许是令人开心的一件事情,但我相信,有更多人视阅读他人所写成的程序代码为畏途。许多人宁可自己重新写过一遍程序代码,也不愿意接收别人的程序代码,进而修正错误、维护它们、甚至加强功能。  
  
这其中的关键究竟在何处呢?若是一语道破,其实也很简单,程序代码是别人写的,只有原作者才真的了解程序代码的用途及涵义。许多程序人心里都有一种不自觉的恐惧感,深怕被迫去碰触其他人所写的程序代码。这是来自于人类内心深处对于陌生事物的原始恐惧。  

读懂别人写的程序代码,让你收获满满  
  
过,基于许多现实的原因,程序人时常受迫要去接收别人的程序代码。例如,同事离职了,必须接手他遗留下来的工作;也有可能你是刚进部门的菜鸟,而同事经验 值够了、升级了,风水轮流转,一代菜鸟换菜鸟。甚至,你的公司所承接的项目,必须接手或是整合客户前一个厂商所遗留下来的系统,你们手上只有那套系统的原 始码(运气好时,还有数量不等的文件)。  
  
诸如此类的故事,其实时常在程序人身边或身上持续上演着。许多程序人都将接手他人的程序代码,当做一件悲惨的事情。每个人都不想接手别人所撰写的程序代码,因为不想花时间去探索,宁可将生产力花在产生新的程序代码,而不是耗费在了解这些程序代码上。  
  
遗憾的是,上述的情况对程序人来说很难避免。我们总是必须碰触到其他人所写成的程序代码,甚至必须了解它、加以修改。对于这项需求,在现今开放原始码的风 气如此盛行的今日,正如之前的「程序设计2.0」文中所提到的,你可以透过开放原始码学习到新的技术、学习到高手的架构设计,大幅提高学习的效率及效果。 你甚至可以直接自开放原始码项目中抽取、提炼出自己所需的程序代码,站在巨人的肩膀上,直接由彼端获得所需的生产力。从这个观点来看,读懂别人所写的程序 代码,就不再只是从负面观点的「被迫接收」,而是极具正面价值的「汲取养份」。  

先了解系统架构与行为模式,再细读 
  
倘若撰写程序代码是程序人的重要技艺之一,那么读懂别人的程序代码、接着加以修改,也势必是另一个重要的技艺。  
  
如果你不能熟悉这项工作,不仅在遭逢你所不愿面对的局面时,无法解决眼前接手他人程序代码的难题,更重要的是,当你看着眼前现成的程序代码,却不知如何从中撷取自己所需,导致最后只能入宝山空手回,望之兴叹。  
  
接触他人的程序代码,大致上可以分为三种程度:一、了解,二、修改、扩充,三、抽取、提炼。  
  
了解别人的程序代码是最基础的工作,倘若不能了解自己要处理的程序代码,就甭论修改或扩充,更不可能去芜存菁,从中萃取出自己所需,回收再利用别人所撰写的程序代码。  
  
虽说是「阅读」,但程序代码并不像文章或小说一样,透过这种做法,便能够获得一定程度的了解。阅读文章或小说时,几乎都是循序地阅读,你只消翻开第一页,一行行阅读下去即可。但是,有许多程序人在试着阅读其他人的程序代码时,却往往有不知如何读起的困难。  
  
或许找到系统的第一页(也就是程序代码执行的启始点)并不难,但是复杂度高的系统,有时十分庞大,有时千头万绪。  
  
程序代码的启始点开始读起,一来要循序读完所有的程序代码旷日费时,二来透过这种方式来了解系统,很难在脑中构建出系统的面貌,进而了解到系统真正的行 为。所以,阅读程序代码的重点,不在于读完每一行程序代码,而是在于有效率地透过探索及阅读,从而了解系统的架构及行为模式。以便在你需要了解任何片段的 细节实作时,能够很快在脑上对映到具体的程序代码位置,直到那一刻,才是细读的时机。  

熟悉沟通语言与惯例用语  
  
不论如何,有些基本的准备,是阅读他人程序代码时必须要有的。  
  
首先,你最好得了解程序代码写成的程序语言。想要读懂法文写成的小说,总不能连法文都不懂吧。有些情况则很特殊。我们虽然不懂该程序代码撰写所用的语言,但是因为现代语言的高阶化,而且流行的程序语言多半都是血统相近,所以即使不那么熟悉,有时也可勉力为之。  
  
除了认识所用语言之外,再来就是要先确认程序代码所用的命名惯例(naming convention)。了解命名惯例很重要,不同的程序人或开发团队,差异可能很大。  
  
这命名惯例涵盖的范围通常包括了变量的名称、函式的名称、类别(如果是面向对象的话)的名称、原始码档案、甚至是项目建构目录的名称。倘若使用了像设计模式之类的方法,这些名称更有一些具体的表述方式。  
  

名惯例有点像是程序人在程序语言之上,另行建构的一组沟通行话。程序人会透过共通约束、遵守的命名惯例,来表达一些较高阶的概念。例如,有名的匈牙利式命 名法,便将变量名称以属性、型别、说明合并在一起描述。对程序人来说,这种方式能够提供更丰富的信息,以了解该变量的作用及性质。  


程序代码阅读来说,熟悉这个做法之所以重要,是因为当你了解整个系统所采用的惯例时,你便能试着以他们所共同操用的语汇来进行理解。倘若,不能了解其所用 的惯例,那么这些额外提供的信息,就无法为你所用。像以设计模式写成的程序代码,同样处处充满着模式的名称,诸如:Factory、Facade、 Proxy等等。以这些名称指涉的类别,也直接透过名称,表达了它们自身的作用。对于懂得这命名惯例的读者来说,不需要深入探索,也能很快捕捉到这些类别 的意义。  
  
当你拿到一套必须阅读的程序代码时,最好先取得命名惯例的说明文件。然而,并不是每套程序代码都附有此类的说明文件。另一个方式,就是自己到程序代码中,大略浏览一遍,有经验的程序人可以轻易发掘出该系统所用的命名惯例。  
  
常见的命名方式不脱那几类,这时候经验就很重要,倘若你知道的惯例越多,就越能轻易识别他人所用的惯例。如果运气很糟,程序代码所用的惯例是前所未见的,那么你也得花点时间归纳,凭自己的力量找出这程序代码命名上的规则。  
 
掌握程序代码撰写者的心态与习惯  
  
多数的程序代码,基本上都依循一致的命名惯例。不过运气更差的时候,一套系统中可能会充斥着多套命名惯例。这有可能是因为开发团队由多组人马所构成,每组 人马都有不同的文化,而在项目开发管理又没有管控得宜所造成。最糟的情况,程序代码完全没有明显的惯例可言,这时候阅读的难度就更高了。  
  
想要阅读程序代码,得先试着体会程序代码作者的「心」。想要这么做,就得多了解对方所使用的语言,以及惯常运用的语汇。在下一回中,我们将继续探讨阅读程序代码的相关议题。 


   二、摸清架构,便可轻松掌握全貌 
  
在本文中,我们的重点放在:要了解一个系统,最好是采取由上至下的方式。先试着捕捉系统架构性的观念,不要过早钻进细节,因为那通常对于你了解全貌,没有多大的帮助。阅读程序代码不需要从第一行读起,我们的目的并不是在于读遍每一段程序代码。 
 
基于许多原因,程序人需要阅读其他人所写成的程序代码。而对程序设计2.0时代的程序人来说,最正面的价值在于,能读懂别人程序的人,才有能力从中萃取自己所需的程序,藉以提高生产力。  
 
阅读程序代码的目的,在于了解全貌而非细节  
  
想要读懂别人程序代码的根本基础,便是了解对方所用的程序语言及命名惯例。有了这个基础之后,才算是具备了基本的阅读能力。正如我之前提到的──想要读懂法文写成的小说,总不能连法文都不懂吧。阅读程序代码和阅读文学作品,都需要了解撰写所用的语言及作者习用的语汇。  
  

但我们在阅读文学作品通常是采循序的方式,也就是从第一页开始,一行一行地读下去,依循作者为你铺陈的步调,逐渐进到他为你准备好的世界里。  


阅读程序代码却大大不同。我们很少从第一行开始读起,因为除非它是很简单的单线程程序,否则很少这么做。因为要是这么做,就很难了解整个系统的全貌。  
  
是的,我们这边提到了一个重点,阅读程序代码的目的在于了解系统的全貌,而不是在于只是为了地毯式的读遍每一段程序代码。  
  
拿面向对象程序语言所写成的系统来说,整个系统被拆解、分析成为一个个独立的类别。阅读个别类别的程序代码,或许可以明白每项类别对象个别的行为。但对于 各类别对象之间如何交互影响、如何协同工作,又很容易陷入盲人摸象的困境。这是因为各类别的程序代码,只描述个别对象的行为,而片段的阅读就只能造就片面 的认识。  
  
由上而下厘清架构后,便可轻易理解组成关系  
  
如果你想要跳脱困境,不 想浪费大量时间阅读程序代码,却始终只能捕捉到对系统片段认识,就必须转换到另一种观点来看待系统。从个别的类别行为着手,是由下至上(Bottom- Up)的方法;在阅读程序代码时,却应该先采由上至下(Top-Down)的方式。对程序代码的阅读来说,由上至下意谓着,你得先了解整个系统架构。  
  
系统的架构是整个系统的骨干、支柱。它表现出系统最突出的特征。知道系统架构究竟属于那一种类型,通常大大有益于了解系统的个别组成之间的静态及动态关系。  
  
有些系统因为所用的技术或框架的关系,决定了最上层的架构。例如,采用Java Servlet/JSP技术的应用系统,最外层的架构便是以J2EE(或起码J2EE中的Web Container)为根本。  
  
使 Java Servlet/JSP技术时,决定了某些组成之间的关系。例如,Web Container依据web.xml的内容加载所有的Servlets、Listeners、以及Filters。每当Context发生事件(例如初 始化)时,它便会通知Listener类别。每当它收到来自客户端的请求时,便会依循设定的所有Filter Chain,让每个Filter都有机会检查并处理此一请求,最后再将请求导至用来处理该请求的Servlet。  
  
当我们明白某个 系统采用这样的架构时,便可以很容易地知道各个组成之间的关系。即使我们还不知道究竟有多少Servlets,但我们会知道,每当收到一个请求时,总是会 有个相对应的Servlet来处理它。当想要关注某个请求如何处理时,我应该去找出这个请求对应的Servlet。  
 
了解架构,必须要加上层次感  
  
样的,以Java写成的Web应用程序中,也许会应用诸如Struts之类的MVC框架,以及像Hibernate这样的数据存取框架。它们都可以视为最 主要的架构下的较次级架构。而各个应用系统,甚至有可能在Struts及Hibernate之下,建立自有的更次级的架构。  
  
也就 是说,当我们谈到「架构」这样的观念时,必须要有层次感。而不论是那一层级的架构,都会定义出各自的角色,以及角色间的关系。对阅读者来说,相较于直接切 入最细微的单一角色行为,不如了解某个特定的架构中,究竟存在多少角色,以及这些角色之间的互动模式,比较能够帮助我们了解整个系统的运作方式。  
  
是一个很重要的关键,当你试着进到最细节处之前,应该先试着找出参与的角色,及他们之间的关系。例如,对事件驱动式的架构而言,有3个很重要的角色。一个 是事件处理的分派器(Event Dispatcher)、一个是事件产生者(Event Generator)、另一个则是事件处理器(Event Handler)。  
  
事件产生器产生事件,并送至事件分派器,而事件分派器负责找出各事件相对应的事件处理器,并且转交该事件,并命令事件处理器加以处理。像Windows的GUI应用程序,便是采用事件驱动式的架构。  
  
当你知道此类的应用程序皆为事件驱动式的架构时,你便可以进一步得知,在这样的架构下会有3种主要的角色。虽然也许还不清楚整个系统中,究竟会需要处理多少事件的类型,但对你而言,已经建立了对系统全貌最概观的认识。  
  
虽然你还不清楚所有的细节,但诸如确切会有那些事件类型之类的信息,在此刻还不重要──不要忘了,我们采取的是由上而下的方式,要先摸清楚主建筑结构,至于壁纸的花色怎么处理,那是到了尾声时才会做的事。  
  
   
  
探索架构的第一件事:找出系统如何初始化  
  
有经验的程序人,对于时常被运用的架构都很熟悉。常常只需要瞧上几眼,就能明白一个系统所用的架构,自然就能够直接联想到其中会存在的角色,以及角色间的关系。  
  
然而,并不是每个系统所用的架构,都是大众所熟悉,或是一眼能够望穿的。这时候,你需要探索。目标同样要放在界定其中的角色、以及角色间的静态、动态关系。  
  
论某个系统所采用的架构是否为大部分人所熟知的,在试着探索一个系统的长相时,我们应该找出来几个答案,了解在它所用的架构下,下列这件事是如何被完成 的:一、系统如何初始化,二、与这个系统相接的其他系统(或用户)有那些,而相接的接口又是什么;三、系统如何反应各种事件,四、系统如何处理各种异常及 错误。  
  
系统如何初始化是很重要的一件事,因为初始化是为了接下来的所有事物而做的准备。从初始化的方式、内容,能知道系统做了什么准备,对于系统会有什么行为展现,也就能得窥一二了。  
  
之所以要了解与系统相接的其他系统(或用户),为的是要界定出系统的边界。其他的系统可能会提供输入给我们所探索的系统,也可能接收来自这系统的输出,了解这边界所在,才能确定系统的外观。  
  
而系统所反应的事件类型、以及如何反应,基本上就代表着系统本身的主要行为模式。最后,我们必须了解系统处理异常及错误的方式,这同样也是系统的重要行为,但容易被忽略。  
  
之前,我们提到必须先具备一个系统的语言基础,才能够进一步加以阅读,而在本文中,我们的重点放在:要了解一个系统,最好是采取由上至下的方式。先试着捕捉系统架构性的观念,不要过早钻进细节,因为那通常对于你了解全貌,没有多大的帮助。 
  
   
  
   三、优质工具在手,读懂程序非难事 
  
系统的复杂度往往超过人脑的负荷。阅读程序代码的时候,你会需要更多工具提供协助。使用好的集成开发环境(IDE)或文本编辑器,就能提供最基本的帮助。 
 
阅读程序代码的动作,可以是很原始的,利用最简单的文本编辑器,逐一开启原始码,然后凭借着一己的组织能力,在不同的程序代码间跳跃,拼凑出脑中想要构建的图像。  
  
不过,系统的复杂度往往超过人脑的负荷。阅读程序代码的时候,你会需要更多工具提供协助。使用好的集成开发环境(IDE)或文本编辑器,就能提供最基本的帮助。  
 
善用文本编辑器或IDE,加速解读程序代码  
  
多文本编辑器提供了常见程序语言的语法及关键词标示功能。这对于阅读来说,绝对能够起很大的作用。有些文本编辑器(例如我常用的EditPlus及偶而使 用的Notepad++),甚至能够自动列出某个原始档中所有定义的函式清单,更允许你直接从清单中选择函式,直接跳跃到该函式的定义位置。这对于阅读程 序代码的人来说,就提供了极佳的便利性。  
  
因为在阅读程序代码时,最常做的事,就是随着程序中的某个控制流,将阅读的重心,从某个函式移至它所呼叫的另一个函式。所以对程序人来说,阅读程序代码时最常做的事之一就是:找出某个函式位在那一个原始档里,接着找到该函式所在的位置。  
  
好的IDE能够提供的协助就更多了。有些能够自动呈现一些额外的信息,最有用的莫过于函式的原型宣告了。例如,有些IDE支持当光标停留在某函式名称上一段时间后,它会以Tooltip的方式显示该函式的原型宣告。  
  
对阅读程序代码的人来说,在看到程序代码中呼叫到某个函式时,可以直接利用这样的支持,立即取得和这个函式有关的原型信息,马上就能知道呼叫该函式所传入的各个自变量的意义,而不必等到将该函式的定义位置找出后,才能明白这件事。  
 
grep是一个基本而极为有用的工具  
  
了选用好的文本编辑器或IDE之外,还有一个基本、但却极为有用的工具,它就是grep。熟悉Unix操作系统的程序人,对grep这个公用程序多半都不 陌生。Grep最大的用途,在于它允许我们搜寻某个目录(包括递归进入所有子目录)中所有指定档案,是否有符合指定条件(常数字符串或正规表示式)档 案。  
  
倘若有的话,则能帮你指出所在的位置。这在阅读程序代码时的作用极大。当我们随着阅读的脚步,遇上了任何一个不认识、但自认为重要的类别、函式、数据结构定义或变量,我们就得找出它究竟位在这茫茫程序代码海中的何处,才能将这个图块从未知变为已知。  
  
grep 之所以好用,就是在于当我们发现某个未知的事物时,可以轻易地利用它找出这个未知的事物究竟位在何方。此外,虽说grep是Unix的标准公用程序之一, 但是像Windows这样子的平台,也有各种类型的grep程序。对于在Windows环境工作的程序人来说,可以自行选用觉得称手的工具。  
 
gtags可建立索引,让搜寻更有效率  
  
grep虽然好用,但是仍然有一些不足之处。第一个缺点在于它并不会为所搜寻的原始码档案索引。每当你搜寻时,它都会逐一地找出所有的档案,并且读取其中的所有内容,过滤出满足指定条件的档案。当项目的原始码数量太大时,就会产生搜寻效率不高的问题。  
  
第二个缺点是它只是一个单纯的文本文件搜寻工具,本身并不会剖析原始码所对应的语言语法。当我们只想针对「函式」名称进行搜寻时,它有可能将批注中含有该名称的原始码,也一并找了出来。  
  
grep的缺点,打算阅读他人程序代码的程序人,可以考虑使用像是gtags这样子的工具。gtags是GNU GLOBAL source code tag system,它不只搜寻文字层次,而且因为具备了各种语言的语法剖析器,所以在搜寻时,可以只针对和语言有关的元素,例如类别名称、函式名称等。  
  
而且,它能针对原始码的内容进行索引,这意谓一旦建好索引之后,每次搜寻的动作,都毋需重新读取所有原始码的内容并逐一搜寻。只需要以现成的索引结构为基础,即可有效率的寻找关键段落。  
  
gtags 提供了基于命令行的程序,让你指定原始码所在的目录执行建立索引的动作。它同时也提供程序让你得如同操作grep一般,针对索引结构进行搜寻及检索。它提 供了许多有用的检索方式,例如找出项目中定义某个数据结构的档案及定义所在的行号,或者是找出项目中所有引用某数据结构的档案,以及引用处的行号。  
  
这么一来,你就可以轻易地针对阅读程序代码时的需求予以检索。相较于grep所能提供的支持,gtags这样的工具,简直是强大许多。  
 
再搭配htags制作HTML文件,更是如虎添翼  
  
有一个绝对需要一提的工具。这个叫做htags的工具,能够帮你将已制作完成的索引结构,制作成为一组相互参考的HTML文件。基本上,利用这样的 HTML文件阅读程序代码,比起单纯地直接阅读原始码,来得更有结构。原因是阅读程序代码时,这样的HTML文件,已经为你建立起在各个原始码档案片段间 跳跃的链结。例如,图一(略)是针对一个有名的开放原始码项目ffmpeg,由gtags所产生出来的HTML文件首页的一部分。  
  
htags工具首先为你找出所有定义main()函式的档案,并且列出所在的函式。找出main()函式,时常是阅读程序代码的第一步,因为main()函式是程序的主要入口点,所有的动作皆由此启动,它是一切事物的源头。  
  
凭借htags制作的HTML文件,你可以轻易地点击超链接,直接进到main()函式所在的代码段,如图二(略)。  
  
当我们检视上述原始码时,发现av_register_all()是个陌生、无法了解的事物,而想要搞懂它究竟是什么,可以再继续点击这个函式,如图三(略)。这真是太方便了!阅读至此,你会猛然发现,gtags彷佛就是为了阅读程序代码而专门量身打造的利器。  

❤提问/互动请留言,可直接在最底右下方"写留言即可"

Java初高级一起学习分享,共同学习才是最明智的选择,喜欢的话可以我的学习群64弍46衣3凌9,或加资料群69似64陆0吧3(进群备注csdn)

❤如果觉得写得不错请点击“订阅”,每天更新全新的内容!

❤你们的喜欢和关注就是我最大的动力支撑!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何阅读他人的程序代码(上)——技巧学习篇 的相关文章

  • Spring 配置:无法找到 Spring NamespaceHandler

    配置问题 无法找到 XML 模式名称空间的 Spring NamespaceHandler http www springframework org schema tx http www springframework org schema
  • 检查 Java servlet 的 HTTP POST 请求的内容类型

    我编写了一个简单的 servlet 它接受 HTTP POST 请求并发回一个简短的响应 这是 servlet 的代码 import java io BufferedInputStream import java io ByteArrayI
  • PDFBox 更改线条颜色

    我使用 pdfbox 1 8 5 并尝试使用绘制彩色线PDPageContentStream drawLine 我尝试过PDPageContentStream setNonStrokingColor 255 0 0 但它不起作用 我也没有找
  • 将jquery日期选择器集成到jsf中

    我正在关注这些例子here http jqueryui com demos datepicker icon trigger and here http jqueryui com demos datepicker icon trigger但我
  • 为什么要使用继承? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么源码中的根包叫“com”? [复制]

    这个问题在这里已经有答案了 在大多数源代码中 根包 文件夹被命名为 com 为什么会这样 它只是约定俗成还是代表着什么 The 习俗 http download oracle com javase tutorial java package
  • 改变 H2 中的序列

    我在生产中使用 Postgres 数据库 在测试中使用 H2 我想为现有表创建一个新序列 所以在 Liquibase 中我写了这个
  • Apache Poi 无法读取工作表名称

    我们在通过 Apache Poi 读取 Excel 工作表时遇到了一个奇怪的错误 我们使用的是5 0版本 该代码以前可以工作 但现在已停止在我们所有的生产环境中工作 它在本地测试时仍然有效 因此事实证明这很难调试 问题是我们返回了空工作表名
  • Hibernate - 一对多关系和孤儿删除级联

    我有一个基本的一对多关系父 子关系 就像 Hibernate 参考书第 21 章中一样 级联仅从子级到父级 保留级联只是因为我不想在删除子级时删除父级 当我向父级添加一个子级并保存该子级时 出现 TransientObjectExcepti
  • 有没有一种简单的方法来加密java对象?

    我想将序列化对象存储到文件中 但我想对其进行加密 它不需要非常强的加密 我只是想要一些简单的东西 最好是最多几行代码 这会让其他人加载起来更加困难 我已经研究过 SealedObject 但关键是阻止我 理想情况下 我只想传递一个字符串作为
  • 如何处理过时的连接?

    我们的应用程序是一个 J2EE 应用程序 在 Websphere 6 1 上通过 Mainframe DB2 后端使用 Struts EJB Hibernate 最近已投入生产 我们收到过时的连接异常当用户第一次或有时登录应用程序时 此异常
  • Java HTTPS客户端证书认证

    我对HTTPS SSL TLS我对客户在使用证书进行身份验证时到底应该提供什么内容感到有点困惑 我正在编写一个 Java 客户端 需要执行一个简单的操作POST数据到特定的URL 这部分工作正常 唯一的问题是它应该重新完成HTTPS The
  • 将 AOP 与 OSGI 结合使用的最佳解决方案?

    我正在使用 Equinox 因此 Equinox Aspect 项目似乎是理所当然的 但该项目似乎处于非活动状态 并且只有一页文档 让我最终悬而未决 除了那个项目之外 我没有看到在 OSGI 中使用 AOP 的很多选项 让我知道你们的想法以
  • Dao 和服务接口的需求

    我是Spring Mvc的新手 在很多教程中 我发现有一个像这样的Dao接口 public interface StudentDAO public List
  • JUnit 5 中的参数化 beforeEach/beforeAll

    我想为一个小型的类似数据库的应用程序编写一个测试 此应用程序使用查询 查询应返回正确的结果 这在 JUnit 5 中很容易实现 比如 BeforeEach void before database prepareDatabase Test
  • 如何使用 jasper 从 jsp 生成 pdf 格式的报告

    在我的应用程序中 我可以连接到数据库并获取数组结果集 并使用 JSP 代码迭代该数组并使用 HTML 在网页中显示报告 我希望 HTML 网页中生成的报告可以以 PDF 格式导出并保存在某个 pdf 文件中 请告诉我如何实现这样的技术来实现
  • java中如何在另一个类中使用嵌套类?

    我有一些情况 我想在另一个类中使用另一个类的内部类 喜欢 public class ListData public static class MyData public String textSongName textArtistName
  • 如何强制 JTable 在包含阿拉伯字符的情况下不反转文本?

    我有以下文字 word 但是当它显示在我的 JTable 上时 它看起来像这样 word 在每个 JLabel 或 TextArea 或任何其他输入中 它确实看起来像原始文本 word 仅在 JTable 上我遇到这样的问题 我不在乎它是否
  • Android 每个 Activity 中的通用进度条

    我已经修改了解决方案 我可以获得进度条 但进度条永远不会隐藏 这是创建具有相对布局的进度条的类 public class ProgressBarHandler private ProgressBar mProgressBar private
  • List 和 List 之间的区别[重复]

    这个问题在这里已经有答案了 我读过很多这方面的内容 我知道 List listOfObject new ArrayList

随机推荐

  • Intellij Idea插件开发-创建项目层级的右键菜单

    在使用Android Studio的过程中 发现自带的一些插件无法满足项目的实际需要 便着手自己开发对应的插件 下面是我开发插件过程中的一个记录 会持续和大家分享 分享一 创建Project右键菜单 1 按照项目向导一步一步创建一个Demo
  • 刷脸支付通过人脸识别就可以完成付款

    发展个人码质优价廉所以说 刷脸支付是建立在长达几年的技术积累和市场认可的基础上建立起来的产品 并非是一蹴而就的 刷脸支付的到来 让我们的支付交易手段迈入一个新的阶梯 也可以说是进入了支付的时代 刷脸支付成为新的支付趋势的原因 缓解对外部媒介
  • 最小二乘法

    首先给出公式 最小二乘法的公式 y a x b 其中式中N是数据点的个数 注意 以上两式具有相同的分母 指逐项加法计算 取和 x指对所有的x值求和 y指对所以的y值求和 x 2 指对所有x的平方求和 xy指对所有的积xy进行取和计算 应注意
  • java-es查询

    目录 1 检索ES数据库 2 检索下级数据 3 1 检索多个字段 匹配同一个值 3 2 must 3 3 should 3 3 1 should 一个key多个value 4 java中匹配ES中多个字段查询 为什么加上 keyword反而
  • iis多进程下的全局变量_全局变量初始化顺序探究

    缘起 上一篇文章 调试实战 dll 加载失败之全局变量初始化篇 中 跟大家分享了一个由于全局变量初始化顺序导致的 dll 加载失败的例子 感兴趣的小伙伴儿可以点击阅读 虽然我们知道了是由于全局变量初始化顺序导致的问题 也给出了解决方案 但是
  • 【HarmonyOS】【FAQ】HarmonyOS应用开发相关问题解答(四)

    贴接上回 往期FAQ参考 HarmonyOS FAQ HarmonyOS应用开发相关问题解答 一 HarmonyOS FAQ HarmonyOS应用开发相关问题解答 二 HarmonyOS FAQ HarmonyOS应用开发相关问题解答 三
  • 穷举法解锁华为手机bootloader

    理论 理论一次解锁0 025s 穷举要9999999999999999 0 025 60 60 24 365 190258751年 建议大家还是用dc unlocker解锁 shell 脚本 运气好的可以试试 bin bash gt unl
  • 10_react页面跳转方式

    一 声明式导航 react router 6 之前 match
  • 【PCIe】1: PCIe 硬件时序初始化过程

    目录 1 前言 2 PCIe理论带宽 3 PCIe连接器引脚定义 4 关键信号描述 4 1 PERST 4 2 REFCLK 和REFCLK 信号
  • Java运行时动态加载类之ClassLoader加载class及其依赖jar包

    需求场景是 通过ClassLoader动态加载外部class文件 class文件又依赖某个具体jar包 需要动态加载jar包 采用URLClassLoader 1 xml配置文件
  • 封装v-loading全局自定义指令

    当我们刷新页面或者是首次加载的时候 如果后端数据请求比较慢的情况下 页面是会出现白屏情况的 所以我们可以使用 v loading 去优化一下 增加用户的体验性 我们可以有两种方式去实现 1 定义一个 loading 的组件 然后在每一个需要
  • Python---自动生成二维码

    专栏 python 个人主页 HaiFan 专栏简介 本专栏主要更新一些python的基础知识 也会实现一些小游戏和通讯录 学时管理系统之类的 有兴趣的朋友可以关注一下 自动生成二维码 二维码的本质上 就是一段字符串 我们可以把任意的字符串
  • 一位大三学生(准大四)面试网络工程师后的一些想法

    首先声明 这是我面试一家公司的网络工程师后想要表达的一些东西 早就面试完了 但是一直现在才发 以上均为个人想法 本科大学就不说名字了吧 非211 985 是省重点建设高校 省内知名 省外无名 本人专业通信 但是对这个专业无感 所以投身于了网
  • 成为一名黑客(网络安全),需要掌握哪些黑客技能?

    前言 黑客技能是一项非常复杂和专业的技能 需要广泛的计算机知识和网络安全知识 你可以参考下面一些学习步骤 系统自学网络安全 在学习之前 要给自己定一个目标或者思考一下要达到一个什么样的水平 是学完找工作 进大厂 还是兴趣学习提升 成为一个黑
  • Etcd恢复报错:error listing data dir: /var/lib/etcd/default.etcd

    通过systemd托管的etcd数据备份还原无法启动服务并且报错 error listing data dir var lib etcd default etcd 但是单独执行启动命令可以 usr bin etcd debug name d
  • 各种数据结构的时间复杂度分析

    对于同一个数据结构来说 底层实现的不同往往会呈现出不同的时间复杂度 以数组为例 普通数组实现 顺序数组实现 二分搜索树 平衡 插入 O 1 O n O logn 查找 O n O logn O logn 删除 O n O n O logn
  • 青龙面板及使用(拔毛助长)

    提示 码文不易 来源 学习日常 前言 简单说一下这个原理吧 就是把写好的脚本挂在面板上 让他定时运行 得有个服务器 我用的是腾讯的 搭建的问题 直接搜吧 我就不在过多说些什么了 最好有俩种设备 安卓 苹果 知识储备的话 懂点python j
  • c语言中空格算空行吗,1、程序中空格与空行使用规范

    在程序代码中 善用空格与空行 可使程序板式更加优美 空格 使用 1 在C语言的关键字 像if for while switch等 之后要留有空格 以突显出该关键字 在函数之后不要留空格 紧跟左括号 以与关键字作区别 但在函数定义的参数之间
  • NAT技术详解

    前言 我们知道现在流行的IPv4的IP地址是32位的 那说明IP地址总数是2 32次方个 但是随着互联网的发展 现在的入网设备早就超过了2 32次方个了 拿为什么我们现在的主机IP还够用呢 这里用到了NAT技术来解决 一 NAT技术概念 在
  • 如何阅读他人的程序代码(上)——技巧学习篇

    一 读懂程序代码 使心法皆为我所用 程序代码是别人写的 只有原作者才真的了解程序代码的用途及涵义 许多程序人心里都有一种不自觉的恐惧感 深怕被迫去碰触其他人所写的程序代码 但是 与其抗拒接收别人的程序代码 不如彻底了解相关的语言和惯例 当成