精华内容
下载资源
问答
  • 内部函数和外部函数

    千次阅读 2017-07-16 17:49:04
    很多在问 static 和extern的区别 或者他们的用途,通过看这篇博客以及我写的全局变量的类型的那篇博客相信大家都会深深的理解他俩的用途和区别。1.内部函数 如果一个函数只能被本文件中的其他函数所调用,称它...

    很多人在问 static 和extern的区别  或者他们的用途,通过看这篇博客以及我写的

    全局变量的类型的那篇博客相信大家都会深深的理解他俩的用途和区别。


    1.内部函数
    如果一个函数只能被本文件中的其他函数所调用,称它为内部函数。内部函数又称为静态函数。在定义内部函数时,在函数名和函数类型前加 static .如下:
    static 类型标识符 函数名 ()
    {
    函数体。
    }
    使用内部函数,可以使函数的作用域只局限于所在文件,在不同的文件中又同名的内部函数,互不干扰。通常把只能由同一文件使用的函数和外部变量放在一个文件夹中,在它们前面加上static使其局部化,其他文件不能调用。

    2.外部函数
    除内部函数外,其余的函数都可以被其他文件中的函数所调用,同时在调用的函数的文件上应加上 extern 关键字说明。定义如下:
    extern 类型标识符 函数名 ()
    {
    函数体。
    }
    c语言规定,如果在定义函数时省略 extern ,则默认为外部函数。

    展开全文
  • 产品的内部质量与外部质量

    千次阅读 2013-10-28 11:46:25
     产品的质量可以划分为外部质量与内部质量。外部质量是用户可见、用户可以体验到的质量,比如你新买了一辆车,你可以感受到车的外观、车提速的快慢等,这是车的外部质量;再如我们买了新房子,我们可以看到房子的...

            质量是我们天天挂在嘴边的词,质量的真正含义到底是什么?不同的标准中有不同的定义。我们不去讨论其严格的定义,换一种角度来看产品的质量。

            产品的质量可以划分为外部质量与内部质量。外部质量是用户可见、用户可以体验到的质量,比如你新买了一辆车,你可以感受到车的外观、车提速的快慢等,这是车的外部质量;再如我们买了新房子,我们可以看到房子的地面是否水平、墙皮是否脱落等。内部质量是用户难以看到、难以体验到的质量,是制造方、维修方等可以体验到的质量,比如车是否易于维修等,有些车打开前盖后,可以看到内部走线的情况,好车的内部走线很清晰,而差的车内部走线则是一团乱;再如也有新闻报道新买的房子在装修中发现墙皮内塞满了塑料泡沫。内部质量是隐蔽工程,客户难以直接感受到。

           

            对于软件工程而言,我们的内外部质量是什么呢?对客户、最终用户、间接用户的需求满足程度即是产品的外部质量。客户是出资者,是花钱购买软件的一方,最终用户是使用者、操作者,是真正使用软件人,间接用户即不出资也不使用软件,但是间接用户影响了系统的成败或系统的成败影响到了他,比如证监会就是我们证劵与期货交易软件的间接用户,它制定了相关的标准与规范,约束了系统的行为。软件的内部质量最主要的就是软件的可维护性!在公司内对代码的编写要求遵守编码规范,对于设计要求符合基本的设计原则,这些都是软件的内部质量!

            在我们面试新员工时,对此人有一个评价,这个评价是表面的,是暂时的,我们可能当时觉得此人很好,当此人进入公司后,大家合作了一段时间后,可能就对此人的评价没有最初那么好了,为什么呢?日久见人心,时间长了,才能发现一个人的本质,这个本质就是内部质量。内部质量决定了外部质量!当然也有少数人,可以伪装的时间比较长。

            产品的外部质量是短期利益,产品的内部质量是长期利益。企业要发展,丧失了长期利益,是不可能成为百年老店的。系统不关注内部质量,系统的生命周期就会比较短。软件项目的生命周期比较短,软件产品的生命周期比较长,项目经理关注的是短平快的结束掉项目,关注的是短期利益,而产品经理关注的是整个产品的生命周期管理,如果在企业中没有明确区分这2个角色,则项目经理也要承担产品经理的部分责任,关注产品的长期利益,关注产品的内部质量。前人栽树,后人乘凉,否则就会父债子还,利息越来越高,产品的后续维护成本就会大大增加。

    展开全文
  • 内部碎片 外部碎片

    千次阅读 2013-10-29 23:07:44
    这种方法从内部碎片来看是代价极高的,但系统可以彻底避免外部碎片,达到支持的最大存储量。  将相邻空闲内存块连接起来是一种可以显著减少内存碎片的技术。如果没有这一方法,某些分配算法(如最先适合算法)将...

    内存碎片的产生:

            内存分配有静态分配和动态分配两种
           静态分配在程序编译链接时分配的大小和使用寿命就已经确定,而应用上要求操作系统可以提供给进程运行时申请和释放任意大小内存的功能,这就是内存的动态分配。
            因此动态分配将不可避免会产生内存碎片的问题,那么什么是内存碎片?内存碎片即“碎片的内存”描述一个系统中所有不可用的空闲内存,这些碎片之所以不能被使用,是因为负责动态分配内存的分配算法使得这些空闲的内存无法使用,这一问题的发生,原因在于这些空闲内存以小且不连续方式出现在不同的位置。因此这个问题的或大或小取决于内存管理算法的实现上。

           为什么会产生这些小且不连续的空闲内存碎片呢?

           实际上这些空闲内存碎片存在的方式有两种:a.内部碎片 b.外部碎片 。
           内部碎片的产生:因为所有的内存分配必须起始于可被 4、8 或 16 整除(视处理器体系结构而定)的地址或者因为MMU的分页机制的限制,决定内存分配算法仅能把预定大小的内存块分配给客户。假设当某个客户请求一个 43 字节的内存块时,因为没有适合大小的内存,所以它可能会获得 44字节、48字节等稍大一点的字节,因此由所需大小四舍五入而产生的多余空间就叫内部碎片。
          外部碎片的产生: 频繁的分配与回收物理页面会导致大量的、连续且小的页面块夹杂在已分配的页面中间,就会产生外部碎片。假设有一块一共有100个单位的连续空闲内存空间,范围是0~99。如果你从中申请一块内存,如10个单位,那么申请出来的内存块就为0~9区间。这时候你继续申请一块内存,比如说5个单位大,第二块得到的内存块就应该为10~14区间。如果你把第一块内存块释放,然后再申请一块大于10个单位的内存块,比如说20个单位。因为刚被释放的内存块不能满足新的请求,所以只能从15开始分配出20个单位的内存块。现在整个内存空间的状态是0~9空闲,10~14被占用,15~24被占用,25~99空闲。其中0~9就是一个内存碎片了。如果10~14一直被占用,而以后申请的空间都大于10个单位,那么0~9就永远用不上了,变成外部碎片。


     

    如何解决内存碎片:

            采用Slab Allocation机制:整理内存以便重复使用
            最近的memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。
            下面来看看Slab Allocator的原理。下面是memcached文档中的slab allocator的目标:he primary goal of the slabs subsystem in memcached was to eliminate memory fragmentation issuestotally by using fixedsizememory chunks coming from a few predetermined size classes.
            也就是说,Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。Slab Allocation的原理相当简单。将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合)(图2.1)。

      slab allocator还有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用

    Slab Allocation的主要术语
        Page
        分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。
        Chunk
        用于缓存记录的内存空间。
        Slab Class
        特定大小的chunk的组。

    在Slab中缓存记录的原理
    下面说明memcached如何针对客户端发送的数据选择slab并缓存到chunk中。memcached根据收到的数据的大小,选择最适合数据大小的slab(图2.2)。memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。

     
    图2.2:选择存储记录的组的方法
    实际上,Slab Allocator也是有利也有弊。下面介绍一下它的缺点。

    Slab Allocator的缺点
    Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了

     对于该问题目前还没有完美的解决方案,但在文档中记载了比较有效的解决方案。
    The most efficient way to reduce the waste is to use a list of size classes that closely matches (if that's at all
    possible) common sizes of objects that the clients of this particular installation of memcached are likely to
    store.
           就是说,如果预先知道客户端发送的数据的公用大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的组的列表,就可以减少浪费。但是很遗憾,现在还不能进行任何调优,只能期待以后的版本了。但是,我们可以调节slab class的大小的差别

     

    最佳适合与最差适合分配程序
      最佳适合算法在功能上与最先适合算法类似,不同之处是,系统在分配一个内存块时,要搜索整个自由表,寻找最接近请求存储量的内存块。这种搜索所花的时间要比最先适合算法长得多,但不存在分配大小内存块所需时间的差异。最佳适合算法产生的内存碎片要比最先适合算法多,因为将小而不能使用的碎片放在自由表开头部分的排序趋势更为强烈。由于这一消极因素,最佳适合算法几乎从来没有人采用过。
      最差适合算法也很少采用。最差适合算法的功能与最佳适合算法相同,不同之处是,当分配一个内存块时,系统在整个自由表中搜索与请求存储量不匹配的内存快。这种方法比最佳适合算法速度快,因为它产生微小而又不能使用的内存碎片的倾向较弱。始终选择最大空闲内存块,再将其分为小内存块,这样就能提高剩余部分大得足以供系统使用的概率。
      伙伴(buddy)分配程序与本文描述的其它分配程序不同,它不能根据需要从被管理内存的开头部分创建新内存。它有明确的共性,就是各个内存块可分可合,但不是任意的分与合。每个块都有个朋友,或叫“伙伴”,既可与之分开,又可与之结合。伙伴分配程序把内存块存放在比链接表更先进的数据结构中。这些结构常常是桶型、树型和堆型的组合或变种。一般来说,伙伴分配程序的工作方式是难以描述的,因为这种技术随所选数据结构的不同而各异。由于有各种各样的具有已知特性的数据结构可供使用,所以伙伴分配程序得到广泛应用。有些伙伴分配程序甚至用在源码中。伙伴分配程序编写起来常常很复杂,其性能可能各不相同。伙伴分配程序通常在某种程度上限制内存碎片。
      固定存储量分配程序有点像最先空闲算法。通常有一个以上的自由表,而且更重要的是,同一自由表中的所有内存块的存储量都相同。至少有四个指针:MSTART指向被管理内存的起点,MEND 指向被管理内存的末端,MBREAK 指向 MSTART 与 MEND 之间已用内存的末端,而 PFREE[n]则是指向任何空闲内存块的一排指针。在开始时,PFREE 为 NULL,MBREAK 指针为MSTART。当一个分配请求到来时,系统将请求的存储量增加到可用存储量之一。然后,系统检查 PFREE[ 增大后的存储量 ] 空闲内存块。因为PFREE[ 增大后的存储量 ] 为 NULL,一个具有该存储量加上一个管理标题的内存块就脱离 MBREAK,MBREAK 被更新。
      这些步骤反复进行,直至系统使一个内存块空闲为止,此时管理标题包含有该内存块的存储量。当有一内存块空闲时,PFREE[ 相应存储量 ]通过标题的链接表插入项更新为指向该内存块,而该内存块本身则用一个指向 PFREE[ 相应存储量 ]以前内容的指针来更新,以建立一个链接表。下一次分配请求到来时,系统将 PFREE[ 增大的请求存储量 ]链接表的第一个内存块送给系统。没有理由搜索链接表,因为所有链接的内存块的存储量都是相同的。
      固定存储量分配程序很容易实现,而且便于计算内存碎片,至少在块存储量的数量较少时是这样。但这种分配程序的局限性在于要有一个它可以分配的最大存储量。固定存储量分配程序速度快,并可在任何状况下保持速度。这些分配程序可能会产生大量的内部内存碎片,但对某些系统而言,它们的优点会超过缺点。

      减少内存碎片
      内存碎片是因为在分配一个内存块后,使之空闲,但不将空闲内存归还给最大内存块而产生的。最后这一步很关键。如果内存分配程序是有效的,就不能阻止系统分配内存块并使之空闲。即使一个内存分配程序不能保证返回的内存能与最大内存块相连接(这种方法可以彻底避免内存碎片问题),但你可以设法控制并限制内存碎片。所有这些作法涉及到内存块的分割。每当系统减少被分割内存块的数量,确保被分割内存块尽可能大时,你就会有所改进。
      这样做的目的是尽可能多次反复使用内存块,而不要每次都对内存块进行分割,以正好符合请求的存储量。分割内存块会产生大量的小内存碎片,犹如一堆散沙。以后很难把这些散沙与其余内存结合起来。比较好的办法是让每个内存块中都留有一些未用的字节。留有多少字节应看系统要在多大
    程度上避免内存碎片。对小型系统来说,增加几个字节的内部碎片是朝正确方向迈出的一步。当系统请求1字节内存时,你分配的存储量取决于系统的工作状态。
      如果系统分配的内存存储量的主要部分是 1 ~ 16 字节,则为小内存也分配 16字节是明智的。只要限制可以分配的最大内存块,你就能够获得较大的节约效果。但是,这种方法的缺点是,系统会不断地尝试分配大于极限的内存块,这使系统可能会停止工作。减少最大和最小内存块存储量之间内存存储量的数量也是有用的。采用按对数增大的内存块存储量可以避免大量的碎片。例如,每个存储量可能都比前一个存储量大20%。在嵌入式系统中采用“一种存储量符合所有需要”对于嵌入式系统中的内存分配程序来说可能是不切实际的。这种方法从内部碎片来看是代价极高的,但系统可以彻底避免外部碎片,达到支持的最大存储量。
      将相邻空闲内存块连接起来是一种可以显著减少内存碎片的技术。如果没有这一方法,某些分配算法(如最先适合算法)将根本无法工作。然而,效果是有限的,将邻近内存块连接起来只能缓解由于分配算法引起的问题,而无法解决根本问题。而且,当内存块存储量有限时,相邻内存块连接可能很难实现。
      有些内存分配器很先进,可以在运行时收集有关某个系统的分配习惯的统计数据,然后,按存储量将所有的内存分配进行分类,例如分为小、中和大三类。系统将每次分配指向被管理内存的一个区域,因为该区域包括这样的内存块存储量。较小存储量是根据较大存储量分配的。这种方案是最先适合算法和一组有限的固定存储量算法的一种有趣的混合,但不是实时的。
      有效地利用暂时的局限性通常是很困难的,但值得一提的是,在内存中暂时扩展共处一地的分配程序更容易产生内存碎片。尽管其它技术可以减轻这一问题,但限制不同存储量内存块的数目仍是减少内存碎片的主要方法。
      现代软件环境业已实现各种避免内存碎片的工具。例如,专为分布式高可用性容错系统开发的 OSE 实时操作系统可提供三种运行时内存分配程序:内核alloc(),它根据系统或内存块池来分配;堆 malloc(),根据程序堆来分配; OSE 内存管理程序alloc_region,它根据内存管理程序内存来分配。
      从许多方面来看,Alloc就是终极内存分配程序。它产生的内存碎片很少,速度很快,并有判定功能。你可以调整甚至去掉内存碎片。只是在分配一个存储量后,使之空闲,但不再分配时,才会产生外部碎片。内部碎片会不断产生,但对某个给定的系统和八种存储量来说是恒定不变的。
      Alloc是一种有八个自由表的固定存储量内存分配程序的实现方法。系统程序员可以对每一种存储量进行配置,并可决定采用更少的存储量来进一步减少碎片。除开始时以外,分配内存块和使内存块空闲都是恒定时间操作。首先,系统必须对请求的存储量四舍五入到下一个可用存储量。就八种存储量而言,这一目标可用三个 如果语句来实现。其次,系统总是在八个自由表的表头插入或删除内存块。开始时,分配未使用的内存要多花几个周期的时间,但速度仍然极快,而且所花时间恒定不变。
      堆 malloc() 的内存开销(8 ~ 16 字节/分配)比 alloc小,所以你可以停用内存的专用权。malloc()分配程序平均来讲是相当快的。它的内部碎片比alloc()少,但外部碎片则比alloc()多。它有一个最大分配存储量,但对大多数系统来说,这一极限值足够大。可选的共享所有权与低开销使 malloc() 适用于有许多小型对象和共享对象的 C++应用程序。堆是一种具有内部堆数据结构的伙伴系统的实现方法。在 OSE 中,有 28 个不同的存储量可供使用,每种存储量都是前两种存储量之和,于是形成一个斐波那契(Fibonacci)序列。实际内存块存储量为序列数乘以 16 字节,其中包括分配程序开销或者 8 字节/分配(在文件和行信息启用的情况下为 16 字节)。
      当你很少需要大块内存时,则OSE内存管理程序最适用。典型的系统要把存储空间分配给整个系统、堆或库。在有 MMU 的系统中,有些实现方法使用 MMU 的转换功能来显著降低甚至消除内存碎片。在其他情况下,OSE 内存管理程序会产生非常多的碎片。它没有最大分配存储量,而且是一种最先适合内存分配程序的实现方法。内存分配被四舍五入到页面的偶数——典型值是 4 k 字节。

    展开全文
  • Java内部类与外部

    千次阅读 2013-09-29 16:51:01
    如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为...

    错误提示:

    没有任何类型 TestThread 的外层实例可访问。必须用类型 TestThread 的外层实例(例如,x.new A(),其中 x 是 TestThread 的实例)来限定分配。

    public class CarTest {
    	public class Car{
    		String engine;
    		String Wheel;
    		public void run(){
    			System.out.println("汽车在奔跑");
    		}
    	}
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		//CarTest obj = new CarTest();
            //Car car = obj.new Car();
    		//或者
    		Car car = new CarTest().new Car();
    		
              car.engine = "奇瑞";
              car.run();
    	}
    } 
    
    运行测试:
    汽车在奔跑

    以上是内部类。

    内部类是指在一个外部类的内部再定义一个类。类名不需要和文件夹相同。
    *内部类可以是静态static的,也可用public,default,protected和private修饰。(而外部顶级类即类名和文件名相同的只能使用public和default)。
     
    注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。
    1. 成员内部类
          成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的。同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取。
          要注意的是,成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的,了解这一点,就可以明白更多事情,在此省略更多的细节了。
          在成员内部类要引用外部类对象时,使用outer.this来表示外部类对象;
          而需要创建内部类对象,可以使用outer.inner  obj = outerobj.new inner();
    1. public class Outer { 
    2.     public static void main(String[] args) { 
    3.         Outer outer = new Outer(); 
    4.         Outer.Inner inner = outer.new Inner(); 
    5.         inner.print("Outer.new"); 
    6.  
    7.         inner = outer.getInner(); 
    8.         inner.print("Outer.get"); 
    9.     } 
    10.  
    11.     // 个人推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 
    12.     public Inner getInner() { 
    13.         return new Inner(); 
    14.     } 
    15.  
    16.     public class Inner { 
    17.         public void print(String str) { 
    18.             System.out.println(str); 
    19.         } 
    20.     } 
    2. 局部内部类
          局部内部类,是指内部类定义在方法和作用域内。Thinking in Java给了这么两个例子:
    定义在方法内:
    1. public class Parcel4 { 
    2.     public Destination destination(String s) { 
    3.         class PDestination implements Destination { 
    4.             private String label; 
    5.  
    6.             private PDestination(String whereTo) { 
    7.                 label = whereTo; 
    8.             } 
    9.  
    10.             public String readLabel() { 
    11.                 return label; 
    12.             } 
    13.         } 
    14.         return new PDestination(s); 
    15.     } 
    16.  
    17.     public static void main(String[] args) { 
    18.         Parcel4 p = new Parcel4(); 
    19.         Destination d = p.destination("Tasmania"); 
    20.     } 
     定义在作用域里:
    1. public class Parcel5 { 
    2.     private void internalTracking(boolean b) { 
    3.         if (b) { 
    4.             class TrackingSlip { 
    5.                 private String id; 
    6.                 TrackingSlip(String s) { 
    7.                     id = s; 
    8.                 } 
    9.                 String getSlip() { 
    10.                     return id; 
    11.                 } 
    12.             } 
    13.             TrackingSlip ts = new TrackingSlip("slip"); 
    14.             String s = ts.getSlip(); 
    15.         } 
    16.     } 
    17.  
    18.     public void track() { 
    19.         internalTracking(true); 
    20.     } 
    21.  
    22.     public static void main(String[] args) { 
    23.         Parcel5 p = new Parcel5(); 
    24.         p.track(); 
    25.     } 
          局部内部类也像别的类一样进行编译,但只是作用域不同而已,只在该方法或条件的作用域内才能使用,退出这些作用域后无法引用的。
    3. 嵌套内部类
           嵌套内部类,就是修饰为static的内部类。声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说我们可以直接引用outer.inner,即不需要创建外部类,也不需要创建内部类。
          嵌套类和普通的内部类还有一个区别:普通内部类不能有static数据和static属性,也不能包含嵌套类,但嵌套类可以。而嵌套类不能声明为private,一般声明为public,方便调用。
    4. 匿名内部类
          有时候我为了免去给内部类命名,便倾向于使用匿名内部类,因为它没有名字。例如:
    1. ((Button) findViewById(R.id.start)).setOnClickListener(new Button.OnClickListener() { 
    2.     @Override 
    3.     public void onClick(View v) { 
    4.         new Thread() { 
    5.  
    6.             @Override 
    7.             public void run() { 
    8.                 // TODO Auto-generated method stub 
    9.             } 
    10.  
    11.         }.start(); 
    12.     } 
    13. }); 
          匿名内部类是不能加访问修饰符的。要注意的是,new 匿名类,这个类是要先定义的,看下面例子:
    1. public class Outer { 
    2.     public static void main(String[] args) { 
    3.         Outer outer = new Outer(); 
    4.         Inner inner = outer.getInner("Inner""gz"); 
    5.         System.out.println(inner.getName()); 
    6.     } 
    7.  
    8.     public Inner getInner(final String name, String city) { 
    9.         return new Inner() { 
    10.             private String nameStr = name; 
    11.  
    12.             public String getName() { 
    13.                 return nameStr; 
    14.             } 
    15.         }; 
    16.     } 
    17.  
    18. //注释后,编译时提示类Inner找不到 
    19. /* interface Inner { 
    20.     String getName(); 
    21. } */ 
    同时在这个例子,留意外部类的方法的形参,当所在的方法的形参需要被内部类里面使用时,该形参必须为final。这里可以看到形参name已经定义为final了,而形参city 没有被使用则不用定义为final。为什么要定义为final呢?在网上找到本人比较如同的解释:
     “这是一个编译器设计的问题,如果你了解java的编译原理的话很容易理解。  
    首先,内部类被编译的时候会生成一个单独的内部类的.class文件,这个文件并不与外部类在同一class文件中。  
    当外部类传的参数被内部类调用时,从java程序的角度来看是直接的调用例如:  
    public void dosome(final String a,final int b){  
      class Dosome{public void dosome(){System.out.println(a+b)}};  
      Dosome some=new Dosome();  
      some.dosome();  
    }  
    从代码来看好像是那个内部类直接调用的a参数和b参数,但是实际上不是,在java编译器编译以后实际的操作代码是  
    class Outer$Dosome{  
      public Dosome(final String a,final int b){  
      this.Dosome$a=a;  
      this.Dosome$b=b;  
    }  
      public void dosome(){  
      System.out.println(this.Dosome$a+this.Dosome$b);  
    }  
    }}  
    从以上代码看来,内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。  
    这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在。”
     (简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变)
     
          因为匿名内部类,没名字,是用默认的构造函数的,无参数的,那如果需要参数呢?则需要该类有带参数的构造函数:
    1. public class Outer { 
    2.     public static void main(String[] args) { 
    3.         Outer outer = new Outer(); 
    4.         Inner inner = outer.getInner("Inner""gz"); 
    5.         System.out.println(inner.getName()); 
    6.     } 
    7.  
    8.     public Inner getInner(final String name, String city) { 
    9.         return new Inner(name, city) { 
    10.             private String nameStr = name; 
    11.  
    12.             public String getName() { 
    13.                 return nameStr; 
    14.             } 
    15.         }; 
    16.     } 
    17.  
    18. abstract class Inner { 
    19.     Inner(String name, String city) { 
    20.         System.out.println(city); 
    21.     } 
    22.  
    23.     abstract String getName(); 
    注意这里的形参city,由于它没有被匿名内部类直接使用,而是被抽象类Inner的构造函数所使用,所以不必定义为final。
     
          而匿名内部类通过实例初始化,可以达到类似构造器的效果:
    1. public class Outer { 
    2.     public static void main(String[] args) { 
    3.         Outer outer = new Outer(); 
    4.         Inner inner = outer.getInner("Inner""gz"); 
    5.         System.out.println(inner.getName()); 
    6.         System.out.println(inner.getProvince()); 
    7.     } 
    8.  
    9.     public Inner getInner(final String name, final String city) { 
    10.         return new Inner() { 
    11.             private String nameStr = name; 
    12.             private String province; 
    13.  
    14.             // 实例初始化 
    15.             { 
    16.                 if (city.equals("gz")) { 
    17.                     province = "gd"
    18.                 }else { 
    19.                     province = ""
    20.                 } 
    21.             } 
    22.  
    23.             public String getName() { 
    24.                 return nameStr; 
    25.             } 
    26.  
    27.             public String getProvince() { 
    28.                 return province; 
    29.             } 
    30.         }; 
    31.     } 
    32.  
    33. interface Inner { 
    34.     String getName(); 
    35.     String getProvince(); 
    5.内部类的继承
          内部类的继承,是指内部类被继承,普通类 extents 内部类。而这时候代码上要有点特别处理,具体看以下例子:
    1. public class InheritInner extends WithInner.Inner { 
    2.  
    3.     // InheritInner() 是不能通过编译的,一定要加上形参 
    4.     InheritInner(WithInner wi) { 
    5.         wi.super(); 
    6.     } 
    7.  
    8.     public static void main(String[] args) { 
    9.         WithInner wi = new WithInner(); 
    10.         InheritInner obj = new InheritInner(wi); 
    11.     } 
    12.  
    13. class WithInner { 
    14.     class Inner { 
    15.  
    16.     } 
    可以看到子类的构造函数里面要使用父类的外部类对象.super();而这个对象需要从外面创建并传给形参。
     
    至于内部类的重载,感觉Thinking in Java的例子很复杂,在平常应用中应该很少,因为有点难懂,不清晰。而内部类和闭包之间的事情,暂时放下,以后再看。

     

    展开全文
  • 外部碎片和内部碎片

    千次阅读 2016-06-19 10:04:07
    所谓“外部碎片”,是指系统无法把它分配出去供用户使用的那部分存储空间。对于教材而言,单一连续区存储管理、固定分区存储管理、分页式存储管理和请求页式存储管理都会出现内部碎片。只是前两种存储管理造成的内部...
  • C语言外部函数与内部函数

    万次阅读 2017-12-18 17:09:11
    C语言中,根据函数能否被其他源文件调用,分为内部函数和外部函数 外部函数,可以被其他源文件调用的函数 内部函数,只在定义的文件中有效外部函数开发大型项目,可能包含很多源文件来分别实现,最终,再整合在...
  • Hive 内部外部表 及 适用场景

    千次阅读 2019-06-21 18:31:05
    内部表:看名字,限于内部使用。 删除内部表时,表的元数据和数据都会被删除。 外部表:看名字,可以外部共享。 删除外部表时,表的元数据会被删除,但是...而内部表仅限于少数使用,比如存储自己的中间结果。 ...
  • 彻底理解android中的内部存储与外部存储

    万次阅读 多人点赞 2015-12-12 10:05:34
    我们先来考虑这样一个问题:打开手机设置,选择应用管理,...在android开发中我们常常听到这样几个概念,内存,内部存储,外部存储,很多常常将这三个东西搞混,那么我们今天就先来详细说说这三个东西是怎么回事?内
  • vue不是内部外部命令

    万次阅读 多人点赞 2019-05-21 20:56:40
    无论怎么查找网上的教程,还是解决不了“vue不是内部外部的命令”诸如此类的问题。 好在功夫不负有心,终于在多次的试验下,成功解决了这个问题。 第一种情况: vue不是内部外部命令 :首先确定是否安装了...
  • C语言是外部函数与内部函数

    千次阅读 2019-07-19 09:55:50
    本身还有一些可以调配的方法,比如当你家人跟你说,家里没有盐了,你去买袋盐,去买盐就是他人调用你的方法,那么能被外人调用的方法称谓外部方法。 在C语言中不能被其他源文件调用的函数称谓内部函数,内部函数...
  • 细说Android的内部存储和外部存储

    千次阅读 2019-02-19 21:32:06
    无论哪种存储,都会涉及到手机的存储空间,而其中比较绕的就是Android手机的内部存储和外部存储了,这两天花了点时间总结了一番,这里写成博客权当记录。 内部存储 概念:注意内部存储不是内存,它是手机中的一...
  • 外部时钟与内部时钟区别 作用 使用条件
  • hive内部表与外部

    千次阅读 2017-07-16 22:08:27
    hive内部表与外部表hive的内部表与外部表之间的区别 区别 创建表过程 删除表过程 内部表 会将数据移动到数据仓库指向的路径 元数据和实际数据一起删除 外部表 仅记录数据所在的路径,不会对数据的位置坐任何...
  • 内部碎片和外部碎片的区别

    千次阅读 2018-08-09 10:48:15
    一、在内存上(使用连续分配算法来管理分配内存时会产生)的外部碎片和内部碎片两个概念   这几天一直看操作系统,看到内存的连续分配时,对于外部碎片和内部碎片时甚是不解:   内存碎片分为:内部碎片和外部...
  • 关于内部存储和外部存储

    千次阅读 2015-10-23 17:05:00
    1. 关于内部存储和外部存储 2015年10月13日 15:52 1. 内部存储(internal storage)和外部存储(external storage)的概念区分和实际位置   开发层次: 1. 所有的安卓设备都有内部存储和外部存储 2. 内部存储一般指/...
  • vue不是内部外部文件

    千次阅读 2018-04-04 09:29:07
    今天准备用npm安装vue,但是我在cmd面板输入vue提示我vue不是内部外部文件,我一开始以为是node.js安装错了,又卸载从新安装还是提示我不是内部文件,这是什么情况,没办法百度吧,一搜还真有挺多跟我碰到同样问题...
  • linux系统内部命令和外部命令

    千次阅读 2018-03-14 01:08:51
    什么是内部命令和外部命令 Linux命令有内部(建)命令和外部命令之分,内部命令和外部命令功能基本相同,但有些细微差别。所谓的内部外部其实是相对SHELL自身来讲。Linux系统为了提高系统运行效率,将经常使用的轻...
  • ADB不是内部外部命令解决方法

    千次阅读 2018-11-06 17:12:19
    ADB不是内部外部命令解决方法
  • 内存碎片---内部碎片&外部碎片

    千次阅读 2018-05-05 20:44:01
    内部碎片的产生:因为所有的内存分配必须起始于可被 4、8 或 16 整除(视处理器体系结构而定)的地址或者因为MMU的分页机制的限制,决定内存分配算法仅能把预定大小...外部碎片的产生:频繁的分配与回收物理页面会导...
  • 外部碎片和内部碎片的区别

    万次阅读 多人点赞 2014-08-20 14:05:10
    外部碎片和内部碎片的区别 一、在内存上(使用连续分配算法来管理分配内存时会产生)的外部碎片和内部碎片两个概念 这几天一直看操作系统,看到内存的连续分配时,对于外部碎片和内部碎片时甚是不解: ...
  • @hellodba 发的一个帖子:“内部晋升越来越困难,但是外部来的大P越来越多,所以很多都选择跳槽”,之后我从三个方面简要的进行了回答:“外面来的总是有包装的,内部的都是肉身PK,此一输;外面来的总是小股人马...
  • Android的内部存储和外部存储

    千次阅读 2016-09-08 21:39:53
    在Android开发中我们常常听到这样几个概念,内存,内部存储,外部存储,很多常常将这三个东西搞混,那么我们今天就先来详细说说这三个东西是怎么回事? 内存,我们在英文中称作memory,内部存储,我们称为...
  • 'conda' 不是内部外部命令,也不是可运行的程序 或批处理文件。 查了一下网上资料,都说是环境变量没有添加或者添加少了,于是就去看了一下,确实没有添加。 一、查看环境变量 打开Anaconda Prompt,输入path,...
  • 内存分配和外部碎片和内部碎片

    千次阅读 2018-05-16 15:51:54
    内存分配 其实最为简单的内存分配的方法...当进程终止时,其分区可以被其他进程所使用,这种方法最开始是被IBM OS/360操作系统使用,当然现在不再使用,因为其的规模庞大,运行缓慢,没有什么使用 在可变分区方...
  • 文件存储前言文件存储内存内部存储外部存储内部存储操作API读写操作外部存储操作公共目录私有目录私有文件私有缓存 前言 众所周知,数据存储在每个应用中都会用到,那所用到的技术应该怎么选呢,这里Android给...
  • 前几天看到论坛有在问这个问题,我特意去做了这个实验,这样用外部SRAM就跟用内部SRAM一样,不用自己去申请内存,也不用考虑什么内存地址,一切让编译器自己去解决。  废话不多说,我直接拿原子哥的战舰开发板...
  • 一、内外之别 Internet网被分成多个域或多个自治系统(AS)。...外部网关协议(EGP)为两个相邻的位于各自域边界上的路由器提供一种交换消息和信息的方法。 内部网关协议IGP,是在AS(自治系统)内部使用的协议,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 387,796
精华内容 155,118
关键字:

外部人内部人