`
liumingwei2009
  • 浏览: 9524 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

面向接口编程(转载)

 
阅读更多

<!-- [if !mso]> <mce:style><!-- v/:* {behavior:url(#default#VML);} o/:* {behavior:url(#default#VML);} w/:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} --> <!-- [endif]--><!-- [if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:PunctuationKerning/> <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing> <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery> <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:Compatibility> <w:SpaceForUL/> <w:BalanceSingleByteDoubleByteWidth/> <w:DoNotLeaveBackslashAlone/> <w:ULTrailSpace/> <w:DoNotExpandShiftReturn/> <w:AdjustLineHeightInTable/> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:UseFELayout/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!-- [if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]--> <!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:微软雅黑; panose-1:2 11 5 3 2 2 4 2 2 4; mso-font-charset:134; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-2147483001 705641554 22 0 262175 0;} @font-face {font-family:"/@微软雅黑"; panose-1:2 11 5 3 2 2 4 2 2 4; mso-font-charset:134; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-2147483001 705641554 22 0 262175 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} --> <!-- [if gte mso 10]> <mce:style><!-- /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} --> <!-- [endif]-->

1. 面向接口编程和面向对象编程是什么关系

首先,面向接口编程和面向对象编程并不是平级的,它并不是比面向对象编程更先进的一种独立的编程思想,而是附属于面向对象思想体系,属于其一部分。或者说,它是面向对象编程体系中的思想精髓之一。

2. 接口的本质

接口,在表面上是由几个没有主体代码的方法定义组成的集合体,有唯一的名称,可以被类或其他接口所实现(或者也可以说继承)。它在形式上可能是如下的样子:

<!-- [if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter"/> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0"/> <v:f eqn="sum @0 1 0"/> <v:f eqn="sum 0 0 @1"/> <v:f eqn="prod @2 1 2"/> <v:f eqn="prod @3 21600 pixelWidth"/> <v:f eqn="prod @3 21600 pixelHeight"/> <v:f eqn="sum @0 0 1"/> <v:f eqn="prod @6 1 2"/> <v:f eqn="prod @7 21600 pixelWidth"/> <v:f eqn="sum @8 21600 0"/> <v:f eqn="prod @7 21600 pixelHeight"/> <v:f eqn="sum @10 21600 0"/> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/> <o:lock v:ext="edit" aspectratio="t"/> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" alt="" style='width:8.25pt; height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image001.gif" mce_src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image001.gif" o:href="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"/> </v:shape><![endif]--><!-- [if !vml]--><!-- [endif]--> interface InterfaceName
<!-- [if gte vml 1]><v:shape id="Codehighlighter1_24_121_Open_Image" o:spid="_x0000_i1026" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image002.gif" mce_src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image002.gif" o:href="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif"/> </v:shape><![endif]--><!-- [if !vml]--><!-- [endif]--><!-- [if gte vml 1]><v:shape id="Codehighlighter1_24_121_Closed_Image" o:spid="_x0000_i1027" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image003.gif" mce_src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image003.gif" o:href="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif"/> </v:shape><![endif]--><!-- [if !vml]--><!-- [endif]-->
<!-- [if gte vml 1]><v:shape id="_x0000_i1032" type="#_x0000_t75" alt="" style='width:11.25pt;height:15pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image004.gif" mce_src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image004.gif" o:href="http://www.cnblogs.com/Images/dot.gif"/> </v:shape><![endif]--><!-- [if !vml]--><!-- [endif]--> {
<!-- [if gte vml 1]><v:shape id="_x0000_i1028" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image005.gif" mce_src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image005.gif" o:href="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif"/> </v:shape><![endif]--><!-- [if !vml]--><!-- [endif]-->
void Method1();
<!-- [if gte vml 1]><v:shape id="_x0000_i1029" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image005.gif" mce_src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image005.gif" o:href="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif"/> </v:shape><![endif]--><!-- [if !vml]--><!-- [endif]-->
void Method2( int para1);
<!-- [if gte vml 1]><v:shape id="_x0000_i1030" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image005.gif" mce_src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image005.gif" o:href="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif"/> </v:shape><![endif]--><!-- [if !vml]--><!-- [endif]-->
void Method3( string para2, string para3);
<!-- [if gte vml 1]><v:shape id="_x0000_i1031" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image006.gif" mce_src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/02/clip_image006.gif" o:href="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif"/> </v:shape><![endif]--><!-- [if !vml]--><!-- [endif]-->}

那么,接口的本质是什么呢?或者说接口存在的意义是什么。我认为可以从以下两个视角考虑:

1 )接口是一组规则的集合,它规定了实现本接口的类或接口必须拥有的一组规则。体现了自然界“如果你是……则必须能……”的理念。

例如,在自然界中,人都能吃饭,即“如果你是人,则必须能吃饭”。那么模拟到计算机程序中,就应该有一个IPerson (习惯上,接口名由“I ”开头)接口,并有一个方法叫Eat() ,然后我们规定,每一个表示“人”的类,必须实现IPerson 接口,这就模拟了自然界“如果你是人,则必须能吃饭”这条规则。

从这里,我想各位也能看到些许面向对象思想的东西。面向对象思想的核心之一,就是模拟真实世界,把真实世界中的事物抽象成类,整个程序靠各个类的实例互相通信、互相协作完成系统功能,这非常符合真实世界的运行状况,也是面向对象思想的精髓。

2 )接口是在一定粒度视图上同类事物的抽象表示。注意这里我强调了在一定粒度视图上,因为“同类事物”这个概念是相对的,它因为粒度视图不同而不同。

例如,在我的眼里,我是一个人,和一头猪有本质区别,我可以接受我和我同学是同类这个说法,但绝不能接受我和一头猪是同类。但是,如果在一个动物学家眼里,我和猪应该是同类,因为我们都是动物,他可以认为“人”和“猪”都实现了IAnimal 这个接口,而他在研究动物行为时,不会把我和猪分开对待,而会从“动物”这个较大的粒度上研究,但他会认为我和一棵树有本质区别。

现在换了一个遗传学家,情况又不同了,因为生物都能遗传,所以在他眼里,我不仅和猪没区别,和一只蚊子、一个细菌、一颗树、一个蘑菇乃至一个SARS 病毒都没什么区别,因为他会认为我们都实现了ID escendable 这个接口(注:descendvi. 遗传),即我们都是可遗传的东西,他不会分别研究我们,而会将所有生物作为同类进行研究,在他眼里没有人和病毒之分,只有可遗传的物质和不可遗传的物质。但至少,我和一块石头还是有区别的。

可不幸的事情发生了,某日,地球上出现了一位伟大的人,他叫列宁,他在熟读、恩格斯的辩证唯物主义思想巨著后,颇有心得,于是他下了一个著名的定义:所谓物质,就是能被意识所反映的客观实在。至此,我和一块石头、一丝空气、一条成语和传输手机信号的电磁场已经没什么区别了,因为在列宁的眼里,我们都是可以被意识所反映的客观实在。如果列宁是一名程序员,他会这么说:所谓物质,就是所有同时实现了“IReflectabe ”和“IEsse ”两个接口的类所生成的实例。(注:reflect v. 反映 esse n. 客观实在)

也许你会觉得我上面的例子像在瞎掰,但是,这正是接口得以存在的意义。面向对象思想和核心之一叫做多态性,什么叫多态性?说白了就是在某个粒度视图层面上对同类事物不加区别的对待而统一处理。而之所以敢这样做,就是因为有接口的存在。像那个遗传学家,他明白所有生物都实现了IDescendable 接口,那只要是生物,一定有Descend ()这个方法,于是他就可以统一研究,而不至于分别研究每一种生物而最终累死。

可能这里还不能给你一个关于接口本质和作用的直观印象。那么在后文的例子和对几个设计模式的解析中,你将会更直观体验到接口的内涵。

3. 面向接口编程综述

通过上文,我想大家对接口和接口的思想内涵有了一个了解,那么什么是面向接口编程呢?我个人的定义是: 在系统分析和架构中,分清层次和依赖关系,每个层次不是直接向其上层提供服务(即不是直接实例化在上层中),而是通过定义一组接口,仅向上层暴露其接口功能,上层对于下层仅仅是接口依赖,而不依赖具体类

这样做的好处是显而易见的,首先对系统灵活性大有好处。当下层需要改变时,只要接口及接口功能不变,则上层不用做任何修改。甚至可以在不改动上层代码时将下层整个替换掉,就像我们将一个WD60G 硬盘换成一个希捷的160G 的硬盘,计算机其他地方不用做任何改动,而是把原硬盘拔下来、新硬盘插上就行了,因为计算机其他部分不依赖具体硬盘,而只依赖一个IDE 接口,只要硬盘实现了这个接口,就可以替换上去。从这里看,程序中的接口和现实中的接口极为相似,所以我一直认为,接口(interface )这个词用的真是神似!

使用接口的另一个好处就是不同部件或层次的开发人员可以并行开工,就像造硬盘的不用等造CPU 的,也不用等造显示器的,只要接口一致,设计合理,完全可以并行进行开发,从而提高效率。

本篇文章先到这里。最后我想再啰嗦一句:面向对象的精髓是模拟现实,这也可以说是我这篇文章的灵魂。所以,多从现实中思考面向对象的东西,对提高系统分析设计能力大有脾益。

下篇文章,我将用一个实例来展示接口编程的基本方法。

而第三篇,我将解析经典设计模式中的一些面向接口编程思想,并解析一下.NET 分层架构中的面向接口思想。

对本文的补充:

仔细看了各位的回复,非常高兴能和大家一起讨论技术问题。感谢给出肯定的朋友,也要感谢提出意见和质疑的朋友,这促使我更深入思考一些东西,希望能借此进步。在这里我想补充一些东西,以讨论一些回复中比较集中的问题。

1. 关于“面向接口编程”中的“接口”与具体面向对象语言中“接口”两个词

看到有朋友提出“面向接口编程”中的“接口”二字应该比单纯编程语言中的interface 范围更大。我经过思考,觉得很有道理。这里我写的确实不太合理。我想,面向对象语言中的“接口”是指具体的一种代码结构,例如C# 中用interface 关键字定义的接口。而“面向接口编程”中的“接口”可以说是一种从软件架构的角度、从一个更抽象的层面上指那种用于隐藏具体底层类和实现多态性的结构部件。从这个意义上说,如果定义一个抽象类,并且目的是为了实现多态,那么我认为把这个抽象类也称为“接口”是合理的。但是用抽象类实现多态合理不合理?在下面第二条讨论。

概括来说,我觉得两个“接口”的概念既相互区别又相互联系。 “面向接口编程”中的接口是一种思想层面的用于实现多态性、提高软件灵活性和可维护性的架构部件,而具体语言中的“接口”是将这种思想中的部件具体实施到代码里的手段。

2. 关于抽象类与接口

看到回复中这是讨论的比较激烈的一个问题。很抱歉我考虑不周没有在文章中讨论这个问题。我个人对这个问题的理解如下:

如果单从具体代码来看,对这两个概念很容易模糊,甚至觉得接口就是多余的,因为单从具体功能来看,除多重继承外(C#Java 中),抽象类似乎完全能取代接口。但是,难道接口的存在是为了实现多重继承?当然不是。 我认为,抽象类和接口的区别在于使用动机。使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。 所以,如果你在为某个地方该使用接口还是抽象类而犹豫不决时,那么可以想想你的动机是什么。

看到有朋友对IPerson 这个接口的质疑,我个人的理解是,IPerson 这个接口该不该定义,关键看具体应用中是怎么个情况。如果我们的项目中有WomenMan ,都继承Person ,而且WomenMan 绝大多数方法都相同,只有一个方法DoSomethingInWC ()不同(例子比较粗俗,各位见谅),那么当然定义一个AbstractPerson 抽象类比较合理,因为它可以把其他所有方法都包含进去,子类只定义DoSomethingInWC (),大大减少了重复代码量。

但是,如果我们程序中的WomenMan 两个类基本没有共同代码,而且有一个PersonHandle 类需要实例化他们,并且不希望知道他们是男是女,而只需把他们当作人看待,并实现多态,那么定义成接口就有必要了。

总而言之,接口与抽象类的区别主要在于使用的动机,而不在于其本身。而一个东西该定义成抽象类还是接口,要根据具体环境的上下文决定。

再者,我认为接口和抽象类的另一个区别在于,抽象类和它的子类之间应该是一般和特殊的关系,而接口仅仅是它的子类应该实现的一组规则。(当然,有时也可能存在一般与特殊的关系,但我们使用接口的目的不在这里)如,交通工具定义成抽象类,汽车、飞机、轮船定义成子类,是可以接受的,因为汽车、飞机、轮船都是一种特殊的交通工具。再譬如Icomparable 接口,它只是说,实现这个接口的类必须要可以进行比较,这是一条规则。如果Car 这个类实现了Icomparable ,只是说,我们的Car 中有一个方法可以对两个Car 的实例进行比较,可能是比哪辆车更贵,也可能比哪辆车更大,这都无所谓,但我们不能说“汽车是一种特殊的可以比较”,这在文法上都不通。

分享到:
评论

相关推荐

    转载面向对象的理解

    在软件开发领域,编程范式是组织代码的方式,常见的编程范式包括面向过程编程(Procedural Programming)和面向对象编程(Object-Oriented Programming,简称OOP)。这两种编程范式在解决问题时有着不同的思维方式和...

    java编程事项(转载收集整理版)

    1. **基本语法**:Java是一种静态类型的面向对象编程语言,其语法严谨。学习Java首先要了解变量声明、数据类型(如int、String等)、运算符、控制结构(如if语句、for循环、while循环)以及方法定义。 2. **类与...

    C语言实现对象编程之多态代码.rar

    C语言实现对象编程之多态代码.rar 在C语言中还可以实现更深入的面向对象编程多态特性。例如:使用接口(interface)包含多个指向函数的指针,这样就可以实现操作的"多态性"。 在面向对象语言C++的实现上,使用了虚...

    C++的学习方法及书籍推荐 (转载).doc

    接口编程是OOP的一个重要方面,通过接口,程序员可以编写与实现细节分离的代码。 泛型编程是C++的另一大特色,主要由模板机制实现。模板允许在编译时创建针对不同类型的函数和类,实现泛型代码,增强了代码的复用性...

    [转载]QQ示例源码(供学习C++网络编程参考)

    3. **TCP编程**:TCP提供面向连接的服务,确保数据的顺序和可靠性。在C++中,使用`socket()`函数创建套接字,`bind()`函数将套接字与特定地址绑定,`listen()`设置服务器为监听状态,`accept()`接收客户端连接,最后...

    socket_套接字_

    套接字是应用程序与网络协议栈之间的接口,它为程序员提供了底层网络通信的能力。在本文中,我们将深入探讨如何实现两台计算机之间的套接字通信,包括服务端和客户端的源码实现。 首先,我们需要理解套接字的工作...

    java编程思想习题及答案

    这份资料可能是从www.pigkrtv.com等网站转载而来,旨在帮助学习者深化对Java编程语言的理解,提高编程技能。 在Java编程学习过程中,掌握基本概念、语法以及解决问题的能力至关重要。这份习题集涵盖了以下几个关键...

    转载object pascal语法介绍

    Object Pascal是一种具有面向对象特性的Pascal编程语言,由Borland公司为了增强Pascal而开发,主要用于Delphi集成开发环境。Delphi以其简洁、高效的语法吸引了许多开发者,尤其是那些觉得Basic结构不够严谨,C语言读...

    unix 编程应用问答中文版

    - **风险提示**: 文档中可能包含未公开、未文档化或不符合规范的接口和技术细节。因此,提供的内容仅供参考,不保证其正确性、效率或唯一性。 - **法律责任**: 维护者不对文档中技术引发的任何后果负责,包括但不...

    展现C#世界[转载]

    C#是一种由微软公司开发的现代、面向对象的编程语言,它源于C/C++,但具有许多简化和优化的设计,旨在提高开发效率和代码安全性。C#的主要特点包括简单性、现代性、面向对象、类型安全、版本控制和兼容性。 1. **...

    下一代数据编程:服务数据编程

    此书由BEA系统有限公司和国际商业机器公司(IBM)联合出版,版权信息明确指出,未经两家公司书面授权,不得以任何形式进行转载和使用。这体现了出版双方对SDO这一理念的重视程度。 #### 驱动因素与目标 SDO的开发...

    c#试题 网络转载 很不错啊!

    1. 面向对象语言的特点:面向对象编程(OOP)的核心特性包括封装、继承和多态。封装是将数据和操作这些数据的方法绑定在一起,形成一个独立的单元。继承允许一个类(子类)继承另一个类(父类)的属性和方法,从而...

    淘宝客C#开源码(转载下载)

    1. **C#编程基础**:理解C#的基本语法、类、对象、接口、继承、多态等面向对象概念是必不可少的。开发者需要熟悉.NET Framework或.NET Core,这是C#开发的基础平台。 2. **ASP.NET框架**:如果该项目是基于ASP.NET...

    java编写建议(转载)

    #### 五、面向接口编程与抽象类 **5.1 接口与抽象类** - 当不确定类的具体实现细节时,优先选择定义接口。 - 抽象类适合于提供部分实现,而具体实现留给子类完成。 - 在设计时考虑未来可能的变化,以便于扩展而不...

    Python车辆违章查询系统源码.zip

    10. 面向对象编程:Python支持面向对象编程,源码中可能会定义类来封装数据和行为,如VehicleViolation类来表示违章信息。 通过学习和分析这个Python车辆违章查询系统的源码,我们可以提升对Python编程、网络请求、...

    java面试资料(转载)

    接下来是继承,这是面向对象编程的核心概念之一。Java支持单一继承,即一个类只能直接继承自一个父类,但可以通过接口实现多重继承的效果。面试中可能会涉及子类如何重写父类方法,super关键字的使用,以及访问控制...

    转载:cglib动态代理介绍(一)

    - **AOP(面向切面编程)**:在Spring框架中,CGlib常用来实现类级别的AOP代理,当目标类没有实现接口时,Spring会自动选择CGlib来生成代理。 - **性能优化**:对于那些不支持接口或者性能要求较高的场景,CGlib比...

    hibernate官方入门教程 (转载)

    标题“hibernate官方入门教程 (转载)”表明这是一份关于Hibernate框架的基础教学资源,可能是从官方文档或者其他可靠来源整理而来的,适合初学者了解和学习Hibernate。 描述中提到的“NULL”意味着没有具体的描述...

Global site tag (gtag.js) - Google Analytics