精华内容
下载资源
问答
  • java基础 java核心基础

    2011-09-21 20:17:08
    1 Java程序设计概述 1 1.1 冯诺依曼体系 1 1.2 计算机语言发展史 1 1.3 Java概述 1 1.3.1 Java发展简史 1 1.3.2 Java平台 1 1.3.3 Java特性 2 1.3.4 Java程序运行过程 2 1.3.5 垃圾回收器 3 1.4 Java开发环境的配置 ...
  • JAVA核心语法笔记

    千次下载 2009-05-07 18:25:04
    整理的培训机构的部分java核心语法的笔记,5月18号将上传一份125个java笔试题的文档及面试技巧,欢迎各位java爱好者来下载
  • JAVA核心】Java GC机制详解

    万次阅读 多人点赞 2018-10-17 16:30:13
    垃圾收集 Garbage Collection 通常被称为“GC”,本文详细讲述Java垃圾回收机制。 导读: 1、什么是GC 2、GC常用算法 3、垃圾收集器 4、finalize()方法详解 5、总结--根据GC原理来优化代码 正式阅读之前...

    垃圾收集 Garbage Collection 通常被称为“GC”,本文详细讲述Java垃圾回收机制。

    导读:

    1、什么是GC

    2、GC常用算法

    3、垃圾收集器

    4、finalize()方法详解

    5、总结--根据GC原理来优化代码

    正式阅读之前需要了解相关概念:

    Java 堆内存分为新生代和老年代,新生代中又分为1个 Eden 区域 和 2个 Survivor 区域。

     

    一、什么是GC:

    每个程序员都遇到过内存溢出的情况,程序运行时,内存空间是有限的,那么如何及时的把不再使用的对象清除将内存释放出来,这就是GC要做的事。

    理解GC机制就从:“GC的区域在哪里”,“GC的对象是什么”,“GC的时机是什么”,“GC做了哪些事”几方面来分析。

     

    1、需要GC的内存区域

    jvm 中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理,因此,我们的内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的。

     

    2、GC的对象

    需要进行回收的对象就是已经没有存活的对象,判断一个对象是否存活常用的有两种办法:引用计数和可达分析。

    (1)引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。

    (2)可达性分析(Reachability Analysis):从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象。

    在Java语言中,GC Roots包括:

    虚拟机栈中引用的对象。

    方法区中类静态属性实体引用的对象。

    方法区中常量引用的对象。

    本地方法栈中JNI引用的对象。

     

    3、什么时候触发GC

    (1)程序调用System.gc时可以触发

    (2)系统自身来决定GC触发的时机(根据Eden区和From Space区的内存大小来决定。当内存大小不足时,则会启动GC线程并停止应用线程)

    GC又分为 minor GC 和 Full GC (也称为 Major GC )

    Minor GC触发条件:当Eden区满时,触发Minor GC。

    Full GC触发条件:

      a.调用System.gc时,系统建议执行Full GC,但是不必然执行

      b.老年代空间不足

      c.方法去空间不足

      d.通过Minor GC后进入老年代的平均大小大于老年代的可用内存

      e.由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

     

    4、GC做了什么事

     主要做了清理对象,整理内存的工作。Java堆分为新生代和老年代,采用了不同的回收方式。(回收方式即回收算法详见后文)

     

    二、GC常用算法

    GC常用算法有:标记-清除算法标记-压缩算法复制算法分代收集算法。

    目前主流的JVM(HotSpot)采用的是分代收集算法。

     1、标记-清除算法

    为每个对象存储一个标记位,记录对象的状态(活着或是死亡)。分为两个阶段,一个是标记阶段,这个阶段内,为每个对象更新标记位,检查对象是否死亡;第二个阶段是清除阶段,该阶段对死亡的对象进行清除,执行 GC 操作。

    优点
    最大的优点是,标记—清除算法中每个活着的对象的引用只需要找到一个即可,找到一个就可以判断它为活的。此外,更重要的是,这个算法并不移动对象的位置。

    缺点
    它的缺点就是效率比较低(递归与全堆对象遍历)。每个活着的对象都要在标记阶段遍历一遍;所有对象都要在清除阶段扫描一遍,因此算法复杂度较高。没有移动对象,导致可能出现很多碎片空间无法利用的情况。

    图例

     

     

     

     2、标记-压缩算法(标记-整理)

    标记-压缩法是标记-清除法的一个改进版。同样,在标记阶段,该算法也将所有对象标记为存活和死亡两种状态;不同的是,在第二个阶段,该算法并没有直接对死亡的对象进行清理,而是将所有存活的对象整理一下,放到另一处空间,然后把剩下的所有对象全部清除。这样就达到了标记-整理的目的。

    优点
    该算法不会像标记-清除算法那样产生大量的碎片空间。
    缺点
    如果存活的对象过多,整理阶段将会执行较多复制操作,导致算法效率降低。
    图例

     

    左边是标记阶段,右边是整理之后的状态。可以看到,该算法不会产生大量碎片内存空间。

     

     3、复制算法

    该算法将内存平均分成两部分,然后每次只使用其中的一部分,当这部分内存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只使用这部分内存,循环下去。

    注意: 
    这个算法与标记-整理算法的区别在于,该算法不是在同一个区域复制,而是将所有存活的对象复制到另一个区域内。

    优点

    实现简单;不产生内存碎片

    缺点
    每次运行,总有一半内存是空的,导致可使用的内存空间只有原来的一半。

    图例

     

    4、分代收集算法

    现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代(Young)和老年代(Tenure)。在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记-整理 或者 标记-清除。

     具体过程:新生代(Young)分为Eden区,From区与To区

    当系统创建一个对象的时候,总是在Eden区操作,当这个区满了,那么就会触发一次YoungGC,也就是年轻代的垃圾回收。一般来说这时候不是所有的对象都没用了,所以就会把还能用的对象复制到From区。 

     

    这样整个Eden区就被清理干净了,可以继续创建新的对象,当Eden区再次被用完,就再触发一次YoungGC,然后呢,注意,这个时候跟刚才稍稍有点区别。这次触发YoungGC后,会将Eden区与From区还在被使用的对象复制到To区, 

    再下一次YoungGC的时候,则是将Eden区与To区中的还在被使用的对象复制到From区

    经过若干次YoungGC后,有些对象在From与To之间来回游荡,这时候From区与To区亮出了底线(阈值),这些家伙要是到现在还没挂掉,对不起,一起滚到(复制)老年代吧。 

    老年代经过这么几次折腾,也就扛不住了(空间被用完),好,那就来次集体大扫除(Full GC),也就是全量回收。如果Full GC使用太频繁的话,无疑会对系统性能产生很大的影响。所以要合理设置年轻代与老年代的大小,尽量减少Full GC的操作。

     

    三、垃圾收集器

    如果说收集算法是内存回收的方法论,垃圾收集器就是内存回收的具体实现

    1.Serial收集器

    串行收集器是最古老,最稳定以及效率高的收集器
    可能会产生较长的停顿,只使用一个线程去回收
    -XX:+UseSerialGC

    • 新生代、老年代使用串行回收
    • 新生代复制算法
    • 老年代标记-压缩

    2. 并行收集器

    2.1 ParNew

    -XX:+UseParNewGC(new代表新生代,所以适用于新生代)

    • 新生代并行
    • 老年代串行

    Serial收集器新生代的并行版本
    在新生代回收时使用复制算法
    多线程,需要多核支持
    -XX:ParallelGCThreads 限制线程数量

     

    2.2 Parallel收集器

    类似ParNew 
    新生代复制算法 
    老年代标记-压缩 
    更加关注吞吐量 
    -XX:+UseParallelGC  

    • 使用Parallel收集器+ 老年代串行

    -XX:+UseParallelOldGC 

    • 使用Parallel收集器+ 老年代并行

     

    2.3 其他GC参数

    -XX:MaxGCPauseMills

    • 最大停顿时间,单位毫秒
    • GC尽力保证回收时间不超过设定值

    -XX:GCTimeRatio 

    • 0-100的取值范围
    • 垃圾收集时间占总时间的比
    • 默认99,即最大允许1%时间做GC

    这两个参数是矛盾的。因为停顿时间和吞吐量不可能同时调优

    3. CMS收集器

    • Concurrent Mark Sweep 并发标记清除(应用程序线程和GC线程交替执行)
    • 使用标记-清除算法
    • 并发阶段会降低吞吐量(停顿时间减少,吞吐量降低)
    • 老年代收集器(新生代使用ParNew)
    • -XX:+UseConcMarkSweepGC

    CMS运行过程比较复杂,着重实现了标记的过程,可分为

    1. 初始标记(会产生全局停顿)

    • 根可以直接关联到的对象
    • 速度快

    2. 并发标记(和用户线程一起) 

    • 主要标记过程,标记全部对象

    3. 重新标记 (会产生全局停顿) 

    • 由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正

    4. 并发清除(和用户线程一起) 

    • 基于标记结果,直接清理对象

     

    这里就能很明显的看出,为什么CMS要使用标记清除而不是标记压缩,如果使用标记压缩,需要多对象的内存位置进行改变,这样程序就很难继续执行。但是标记清除会产生大量内存碎片,不利于内存分配。 

    CMS收集器特点:

    尽可能降低停顿
    会影响系统整体吞吐量和性能

    • 比如,在用户线程运行过程中,分一半CPU去做GC,系统性能在GC阶段,反应速度就下降一半

    清理不彻底 

    • 因为在清理阶段,用户线程还在运行,会产生新的垃圾,无法清理

    因为和用户线程一起运行,不能在空间快满时再清理(因为也许在并发GC的期间,用户线程又申请了大量内存,导致内存不够) 

    • -XX:CMSInitiatingOccupancyFraction设置触发GC的阈值
    • 如果不幸内存预留空间不够,就会引起concurrent mode failure

    一旦 concurrent mode failure产生,将使用串行收集器作为后备。

    CMS也提供了整理碎片的参数:

    -XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次整理

    • 整理过程是独占的,会引起停顿时间变长

    -XX:+CMSFullGCsBeforeCompaction  

    • 设置进行几次Full GC后,进行一次碎片整理

    -XX:ParallelCMSThreads 

    • 设定CMS的线程数量(一般情况约等于可用CPU数量)

    CMS的提出是想改善GC的停顿时间,在GC过程中的确做到了减少GC时间,但是同样导致产生大量内存碎片,又需要消耗大量时间去整理碎片,从本质上并没有改善时间。 

     

    4. G1收集器

    G1是目前技术发展的最前沿成果之一,HotSpot开发团队赋予它的使命是未来可以替换掉JDK1.5中发布的CMS收集器。

    与CMS收集器相比G1收集器有以下特点:

    (1) 空间整合,G1收集器采用标记整理算法,不会产生内存空间碎片。分配大对象时不会因为无法找到连续空间而提前触发下一次GC。

    (2)可预测停顿,这是G1的另一大优势,降低停顿时间是G1和CMS的共同关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为N毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。

    上面提到的垃圾收集器,收集的范围都是整个新生代或者老年代,而G1不再是这样。使用G1收集器时,Java堆的内存布局与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔阂了,它们都是一部分(可以不连续)Region的集合。

    G1的新生代收集跟ParNew类似,当新生代占用达到一定比例的时候,开始出发收集。

    和CMS类似,G1收集器收集老年代对象会有短暂停顿。

    步骤:

    (1)标记阶段,首先初始标记(Initial-Mark),这个阶段是停顿的(Stop the World Event),并且会触发一次普通Mintor GC。对应GC log:GC pause (young) (inital-mark)

    (2)Root Region Scanning,程序运行过程中会回收survivor区(存活到老年代),这一过程必须在young GC之前完成。

    (3)Concurrent Marking,在整个堆中进行并发标记(和应用程序并发执行),此过程可能被young GC中断。在并发标记阶段,若发现区域对象中的所有对象都是垃圾,那个这个区域会被立即回收(图中打X)。同时,并发标记过程中,会计算每个区域的对象活性(区域中存活对象的比例)。

     

    (4)Remark, 再标记,会有短暂停顿(STW)。再标记阶段是用来收集 并发标记阶段 产生新的垃圾(并发阶段和应用程序一同运行);G1中采用了比CMS更快的初始快照算法:snapshot-at-the-beginning (SATB)。

    (5)Copy/Clean up,多线程清除失活对象,会有STW。G1将回收区域的存活对象拷贝到新区域,清除Remember Sets,并发清空回收区域并把它返回到空闲区域链表中。

     

    (6)复制/清除过程后。回收区域的活性对象已经被集中回收到深蓝色和深绿色区域。

     

    四、finalize()方法详解

    1. finalize的作用

    (1)finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。
    (2)finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性
    (3)不建议用finalize方法完成“非内存资源”的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象);② 作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。其原因可见下文[finalize的问题]


    2. finalize的问题
    (1)一些与finalize相关的方法,由于一些致命的缺陷,已经被废弃了,如System.runFinalizersOnExit()方法、Runtime.runFinalizersOnExit()方法
    (2)System.gc()与System.runFinalization()方法增加了finalize方法执行的机会,但不可盲目依赖它们
    (3)Java语言规范并不保证finalize方法会被及时地执行、而且根本不会保证它们会被执行
    (4)finalize方法可能会带来性能问题。因为JVM通常在单独的低优先级线程中完成finalize的执行
    (5)对象再生问题:finalize方法中,可将待回收对象赋值给GC Roots可达的对象引用,从而达到对象再生的目的
    (6)finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法,但并不影响GC对finalize的行为)

    3. finalize的执行过程(生命周期)

    (1) 首先,大致描述一下finalize流程:当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。
    (2) 具体的finalize流程:
      对象可由两种状态,涉及到两类状态空间,一是终结状态空间 F = {unfinalized, finalizable, finalized};二是可达状态空间 R = {reachable, finalizer-reachable, unreachable}。各状态含义如下:

    • unfinalized: 新建对象会先进入此状态,GC并未准备执行其finalize方法,因为该对象是可达的
    • finalizable: 表示GC可对该对象执行finalize方法,GC已检测到该对象不可达。正如前面所述,GC通过F-Queue队列和一专用线程完成finalize的执行
    • finalized: 表示GC已经对该对象执行过finalize方法
    • reachable: 表示GC Roots引用可达
    • finalizer-reachable(f-reachable):表示不是reachable,但可通过某个finalizable对象可达
    • unreachable:对象不可通过上面两种途径可达

    状态变迁图:

    变迁说明:

      (1)新建对象首先处于[reachable, unfinalized]状态(A)
      (2)随着程序的运行,一些引用关系会消失,导致状态变迁,从reachable状态变迁到f-reachable(B, C, D)或unreachable(E, F)状态
      (3)若JVM检测到处于unfinalized状态的对象变成f-reachable或unreachable,JVM会将其标记为finalizable状态(G,H)。若对象原处于[unreachable, unfinalized]状态,则同时将其标记为f-reachable(H)。
      (4)在某个时刻,JVM取出某个finalizable对象,将其标记为finalized并在某个线程中执行其finalize方法。由于是在活动线程中引用了该对象,该对象将变迁到(reachable, finalized)状态(K或J)。该动作将影响某些其他对象从f-reachable状态重新回到reachable状态(L, M, N)
      (5)处于finalizable状态的对象不能同时是unreahable的,由第4点可知,将对象finalizable对象标记为finalized时会由某个线程执行该对象的finalize方法,致使其变成reachable。这也是图中只有八个状态点的原因
      (6)程序员手动调用finalize方法并不会影响到上述内部标记的变化,因此JVM只会至多调用finalize一次,即使该对象“复活”也是如此。程序员手动调用多少次不影响JVM的行为
      (7)若JVM检测到finalized状态的对象变成unreachable,回收其内存(I)
      (8)若对象并未覆盖finalize方法,JVM会进行优化,直接回收对象(O)
      (9)注:System.runFinalizersOnExit()等方法可以使对象即使处于reachable状态,JVM仍对其执行finalize方法

     

    五、总结

     

    根据GC的工作原理,我们可以通过一些技巧和方式,让GC运行更加有效率,更加符合应用程序的要求。一些关于程序设计的几点建议: 

    1.最基本的建议就是尽早释放无用对象的引用。大多数程序员在使用临时变量的时候,都是让引用变量在退出活动域(scope)后,自动设置为 null.我们在使用这种方式时候,必须特别注意一些复杂的对象图,例如数组,队列,树,图等,这些对象之间有相互引用关系较为复杂。对于这类对象,GC 回收它们一般效率较低。如果程序允许,尽早将不用的引用对象赋为null.这样可以加速GC的工作。 

    2.尽量少用finalize函数。finalize函数是Java提供给程序员一个释放对象或资源的机会。但是,它会加大GC的工作量,因此尽量少采用finalize方式回收资源。 

    3.如果需要使用经常使用的图片,可以使用soft应用类型。它可以尽可能将图片保存在内存中,供程序调用,而不引起OutOfMemory. 

    4.注意集合数据类型,包括数组,树,图,链表等数据结构,这些数据结构对GC来说,回收更为复杂。另外,注意一些全局的变量,以及一些静态变量。这些变量往往容易引起悬挂对象(dangling reference),造成内存浪费。 

    5.当程序有一定的等待时间,程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。使用增量式GC可以缩短Java程序的暂停时间。

    ============================================================

    欢迎关注公众号:程序员面试经验分享(jobbible)

    展开全文
  • Java核心技术卷I》java接口 笔记

    千次阅读 多人点赞 2021-03-03 21:42:27
    写在最前:本笔记全程参考《Java核心技术卷I》,添加了一些个人的思考和整理 接口 1、接口的概念 接口用来描述类应该做什么,而不指定他们应该怎么做。 接口不是类,而是对希望符合这个接口的类的一组需求。不可以...

    写在最前:本笔记全程参考《Java核心技术卷I》,添加了一些个人的思考和整理

    接口

    1、接口的概念

    1. 接口用来描述类应该做什么,而不指定他们应该怎么做
    2. 接口不是类,而是对希望符合这个接口的类的一组需求。不可以实例化(new)一个接口
    3. 一个类可以实现零或多个接口
    4. 接口的所有方法都是public抽象方法,所以可以省略关键字public abstract(例外:默认方法)

    让类实现接口通常需要下面两个步骤:

    1. 使用关键字implements实现接口:
      public class Employee implements Comparable {}
    2. 重写接口中的所有方法。此时要显式声明方法为public

    声明一个接口的关键字是:interface,它用来取代class的位置:public interface 接口名 {}

    2、小插曲:Comparable接口和compareTo方法

    2.1 概述

    Comparable接口中的compareTo方法将返回一个整数。如果两个数不相等,则返回一个正值或者有一个负值(这取决于两个数哪个大,如果调用方小于参数,则返回负值)如果相等,则返回0.

    需要注意:整数的范围不宜过大,避免造成溢出(减去一个负数时会变成加法运算)如果确定参数是非负整数,或者两者的绝对值都不超过(Integer,MAX_VALUE-1)/2,就不会出现问题。否则,可以调用Ingeter.compare方法

    compareTo方法中的相减技巧不适用于浮点类型。因为两者的差值在返回int类型时四舍五入可能会变成0. 可以借助Double.compare方法实现

    2.2 compareTo方法与equals方法

    Comparable接口的文档建议compareTo方法应该与equals方法兼容。也就是说,当x.equals(y)时,x.compareTo(y)就应该返回0. JavaAPI中绝大多数都遵从了这个建议,只有BigDecimal例外:

    x = new DigDecimal("1.0");
    y = new DigDecimal("1.00");
    x.equals(y); // false
    x.compareTo(y); // true 之所以如此可能是由于没有明确的方法来确定这两个数字哪一个更大
    

    2.3 compareTo方法的对称性以及继承中的问题

    如果反转compareTo方法的调用者和参数时,返回的结果也应该翻转(但是具体的值不一定)。

    equals方法一样,在继承中会遇到对称性问题:

    假设现在有父类Employee及其子类Manager,如果Employee实现了Comparable<Employee>,而不是Comparable<Manager>,那么其子类Manager要覆盖compareTo,就必须做好比较经理员工的准备,而绝对不能仅仅将员工强转为经理(因为这么做会违反“对称原则”:当翻转调用者和参数时会出现强转异常!)

    public Manager extends Employee {
        public int compareTo(Employee other) {
            Manager otherManager = (Manager) other; // 不要这么写
            // ...
        }
    }
    

    解决方式:

    • 如果不同子类中比较有不同含义,就应该将属于不同类的对象之间的比较视为非法,并在每个compareTo方法开始时进行getClass检测:

      if (this.getClass() != other.getClass()) throw new ClassCastException();
      
    • 如果存在能够比较子类对象的通用算法,那么可以在超类中提供一个compareTo方法,在一开始使用instanceof检测子类,并将方法声明为final,保证子类不串改语义。

    3、接口的特点

    1. 接口不是类,不可以实例化一个接口。应该通过接口来引用一个实现了这个接口的类对象。

    2. 可以使用instanceof检查一个对象是否实现了某个接口:if (obj instanceof Comparable)

    3. 接口中不能包含实例字段,但可以包含常量,且可以省略public static final

      public interface Powered extend Moveable {
      	double SPEED_LIMIT = 95; // public static final的常量	
      }
      
    4. 任何实现了接口的类都自动地继承了常量,而不必采用类名(应该说是接口名)调用

    5. 一个类可以有多个接口,但是只能继承于一个父类。多接口算是java实现多继承的方式

    6. 一个类除了实现接口之外,还可以去继承其他类

    7. 多个父接口存在同名的抽象方法不会影响程序

    8. 接口可以定义默认方法

    4、接口作用简述

    1. 可以使项目分层,所有的层都面向接口开发,开发效率提高了(例子:回调模式,见下方)

      可以理解为灯泡和灯座,两个不同的工厂做出来的不同的产品可以耦合

    2. 接口可以使代码和代码之间的耦合度降低,就像灯泡和灯座,变得“可插拔”

    接口与回调

    回调(callback)是一种程序设计模式。其可以指定某个特定事件发生时应该采取的操作。

    例如Swing下的Timer类,可以完成定时任务。在构造定时器时,需要设置一个时间间隔,然后告诉定时器要定期做什么事。

    在很多程序设计语言中,可以提供一个函数名来指定要做的事,而在java中采用的是面对对象的方法:我们可以传入某个类的对象,然后让定时器定期调用这个对象的某个方法。怎么确保传入的对象肯定有这个方法呢?只要这个对象的类实现了某个接口,就可以保证它一定实现了这个接口的某个方法。

    5、接口与抽象类

    5.1 接口存在的意义

    之所以要出现接口,而不是让抽象类完成接口的工作,是因为Java的设计者选择了不支持多重继承。其主要原因是多重继承会让语言变得非常复杂,或会降低效率。而接口可以提供多重继承的大多数好处,且可以避免多重继承带来的复杂性和低效性。

    5.2 两者的区别和联系

    5.2.1 区别

    1. 接口的设计目的,是对类的行为进行约束;而抽象类的设计目的,是代码复用。
    2. 接口是对行为的抽象,而抽象类是对根源(类别)的抽象(应该用抽象类,而能游泳应该是接口)。
    3. 一个类只能继承一个直接父类,这个父类可以是具体的类也可是抽象类;但是一个类可以实现多个接口。
    4. 接口里面只能对方法进行声明,抽象类既可以对方法进行声明也可以对方法进行实现(即编写方法的具体代码)。(但是接口可以实现默认方法)

    5.2.2 联系

    1. 抽象类中的抽象方法不能缺省的public
    2. 接口其实是一个特殊的抽象类,特殊在接口是完全抽象的
    3. 一个非抽象的类实现接口,需要将接口中所有的的方法实现(通过方法重写)
    4. 抽象级别(从高到低):接口>抽象类>实现类。

    5.2.3 共同点

    1. 都是上层的抽象层。
    2. 都不能被实例化
    3. 都能包含抽象的方法,这些抽象的方法用于描述类具备的功能,但是不提供具体的实现。

    6、接口的静态方法和私有方法

    Java8开始允许即可中添加静态方法,虽然这没什么毛病,但是有违接口作为抽象规范的初衷。

    通常我们会将静态方法放在工具类中,这些工具了是接口的伴随类。(如标准库中的Collection/CollectionsPath/Paths,但是在Java11中,Path接口实现了与工具类等价的方法,如此看来,Paths伴随类就不是必要的了)

    在Java9中,接口可以定义private的方法。private方法可以是静态方法或非静态方法。

    7、接口的默认方法

    可以为接口的方法提供一个默认实现,使用default修饰符标记:

    public interface Comparable<T> {
        default int compareTo(T other) {
            // ...
        }
    }
    

    对于Comparable接口来说,这可能没什么用,因为每一个子类都会覆盖这个默认实现

    实现接口会继承默认方法

    7.1 接口演化

    默认方法的一个重要用途是“接口演化”。如果对一个接口添加一个新的非默认方法,那么可能会导致以前实现了该接口的类不能编译(因为没有重写接口的新方法)

    7.2 默认方法冲突

    如果现在接口中定义一个默认方法,又在父类或另一个接口中定义同名且相同参数的方法,则会产生冲突,但是并不是错误。Java解决方法冲突的规则如下:

    1. 父类优先。如果父类提供了一个具体方法,那么同名且拥有相同参数的默认方法会被忽略,但不会报错。
    2. 如果两个接口的默认方法冲突,则子类必须覆盖这个方法来解决冲突。需要注意的是,即使两个接口中只有一个接口实现了默认方法,另一个只定义了同名的抽象方法,子类也不会继承前者的默认方法,必须重写方法。

    8、Comparator接口

    我们无法修改java默认的比较规则(无法修改某个类的compareTo方法的实现)

    有些时候我们想要自定义比较标准,而不采用默认的比较方式,此时就需要使用比较器(Comparator)

    比较器是实现了Comparator接口的类的实例。

    当我们想要按照长度比较字符串时,可以定义如下的实现Comparator<String>的类:

    class LengthComparator implements Comparator<String> {
    	public int compare(String first, String second) {
            return first.length() - second.length();
        }
    }
    

    利用lambda表达式可以更简洁的使用Comparator接口

    9、对象克隆与Cloneable接口

    克隆是一种深复制(deep copy),克隆后的对象是一个新对象,新对象与原对象处于不同的内存区域,同时其成员字段也会被深复制,这样,新对象和原对象才没有任何瓜葛。

    9.1 标记接口

    Cloneable是一个标记接口,它不包含任何方法,唯一的作用是用于在类型检查中通过instanceof检查

    9.2 Object的clone()方法与protected

    9.2.1 Object的clone()方法:

    Object类中的clone方法声明为protected,源码如下:

    protected native Object clone() throws CloneNotSupportedException;
    

    java中的native关键字表示这个方法是个本地方法。而且native修饰的方法执行效率比非native修饰的高。

    9.2.2 protected访问权限:

    protected访问权限解释:

    protected访问权限允许字段或方法被同一个包下的类访问。

    此外,对于子类:private限制字段或方法只能在类内部使用,而protected则允许字段或方法能在子类内部使用,但是不允许通过子类的实例在子类外部使用。

    9.2.3 Object的clone()方法与protected的爱恨情仇

    如下方:

    • Object obj1 = obj.clone();会出错,因为此处不是在Object类内部使用,而是在CloneTest类;
    • 也正因此,CloneTest cloneTest1 = (CloneTest) cloneTest.clone();没有问题。
    • MyObject myObj1 = myObj.clone();报错也是同样的道理。如果在MyObject中实现方法,在方法内部调用this.clone(),则编译不会报错,不过clone()方法要求类实现Cloneable接口,没有接口会出现CloneNotSupportedException异常
    class MyObject {
        public void test() throws CloneNotSupportedException {
            // 类内部中调用,编译没有问题,但是:
            // 因为没有实现Cloneable接口,运行时会出现CloneNotSupportedException异常
            Object clone = this.clone();
    	}
    }   
    
    public class CloneTest {	// Object类的子类
    	public static void main(String[] args) throws CloneNotSupportedException {
    		Object obj = new Object();
    
    		// 错误:'clone()' has protected access in 'java.lang.Object'
    		Object obj1 = obj.clone();
    
    		MyObject myObj = new MyObject();
    
    		// 错误:'clone()' has protected access in 'java.lang.Object'
    		MyObject myObj1 = myObj.clone();
    
    		CloneTest cloneTest = new CloneTest();
    		// 没有问题:
    		CloneTest cloneTest1 = (CloneTest) cloneTest.clone();
    	}
    }
    

    9.3 使类能够调用clone()方法

    MyObject类中重写clone()方法,覆盖掉继承自父类的clone()方法,则编译通过,不再有因为protected引起的不可见问题

    class MyObject implements Cloneable{ // 定义一个空类,Object类的子类
    	public void test() throws CloneNotSupportedException {
    		// 子类自身中调用,没有问题
    		Object clone = this.clone();
    	}
    
        // 注意要将权限改成public,否则不在同个包下且非子类的类中是无法调用protected方法的
    	@Override
    	public Object clone() throws CloneNotSupportedException {
    		return super.clone();
    	}
    }
    
    public class CloneTest {
        public static void main(String[] args) throws CloneNotSupportedException {
            MyObject myObj = new MyObject();
      
            // 没有问题
            myObj.test();
            // 没有问题
            MyObject myObj1 = (MyObject) myObj.clone();
        }
    }
    
    展开全文
  • java 性能技巧优化

    千次阅读 2014-03-01 18:32:18
    Java性能优化技巧 文章分类:Java编程 转载:http://blog.csdn.net/kome2000/archive/2010/04/28/5537591.aspx  [size=small]在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身。养成良好...
     
    
    转载:http://blog.csdn.net/kome2000/archive/2010/04/28/5537591.aspx 


    [size=small]在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身。养成良好的编码习惯非常重要,能够显著地提升程序性能。 

    1. 尽量使用final修饰符。 
    带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如 java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高 50%。 

    2.尽量重用对象。 
    特别是String对象的使用中,出现字符串连接情况时应使用StringBuffer代替,由于系统不仅要花时间生成对象,以后可能还需要花时间对这些对象进行垃圾回收和处理。因此生成过多的对象将会给程序的性能带来很大的影响。 

    3. 尽量使用局部变量。 
    调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量,实例变量等,都在堆(Heap)中创建,速度较慢。 

    4.不要重复初始化变量。 
    默认情况下,调用类的构造函数时,java会把变量初始化成确定的值,所有的对象被设置成null,整数变量设置成0,float和double变量设置成0.0,逻辑值设置成false。当一个类从另一个类派生时,这一点尤其应该注意,因为用new关键字创建一个对象时,构造函数链中的所有构造函数都会被自动调用。 
    这里有个注意,给成员变量设置初始值但需要调用其他方法的时候,最好放在一个方法比如initXXX()中,因为直接调用某方法赋值可能会因为类尚未初始化而抛空指针异常,public int state = this.getState(); 

    5.在java+Oracle的应用系统开发中,java中内嵌的SQL语言应尽量使用大写形式,以减少Oracle解析器的解析负担。 

    6.java编程过程中,进行数据库连接,I/O流操作,在使用完毕后,及时关闭以释放资源。因为对这些大对象的操作会造成系统大的开销。 

    7.
    过分的创建对象会消耗系统的大量内存,严重时,会导致内存泄漏,因此,保证过期的对象的及时回收具有重要意义。 
    JVM的GC并非十分智能,因此建议在对象使用完毕后,手动设置成null。 

    8.在使用同步机制时,应尽量使用方法同步代替代码块同步。 

    9.尽量减少对变量的重复计算。
     
    比如 
    for(int i=0;i<list.size();i++) 

    应修改为 
    for(int i=0,len=list.size();i<len;i++)


    10. 采用在需要的时候才开始创建的策略。
     
    例如: 
    String str="abc";
    if(i==1){ list.add(str);}

    应修改为: 
    if(i==1){String str="abc"; list.add(str);}


    11.慎用异常,异常对性能不利。
     
    抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地方法,fillInStackTrace()方法检查栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用栈,因为在处理过程中创建了一个新的对象。 
    异常只能用于错误处理,不应该用来控制程序流程。 

    12.不要在循环中使用Try/Catch语句,应把Try/Catch放在循环最外层。
     
    Error是获取系统错误的类,或者说是虚拟机错误的类。不是所有的错误Exception都能获取到的,虚拟机报错 Exception就获取不到,必须用Error获取。 

    13.通过StringBuffer的构造函数来设定他的初始化容量,可以明显提升性能。 
    StringBuffer的默认容量为16,当StringBuffer的容量达到最大容量时,她会将自身容量增加到当前的2倍+2,也就是2*n+2。无论何时,只要StringBuffer到达她的最大容量,她就不得不创建一个新的对象数组,然后复制旧的对象数组,这会浪费很多时间。所以给StringBuffer设置一个合理的初始化容量值,是很有必要的! 

    14.合理使用java.util.Vector。
     
    Vector 与StringBuffer类似,每次扩展容量时,所有现有元素都要赋值到新的存储空间中。Vector的默认存储能力为10个元素,扩容加倍。 
    vector.add(index,obj) 这个方法可以将元素obj插入到index位置,但index以及之后的元素依次都要向下移动一个位置(将其索引加 1)。 除非必要,否则对性能不利。 
    同样规则适用于remove(int index)方法,移除此向量中指定位置的元素。将所有后续元素左移(将其索引减 1)。返回此向量中移除的元素。所以删除vector最后一个元素要比删除第1个元素开销低很多。删除所有元素最好用 removeAllElements()方法。 
    如果要删除vector里的一个元素可以使用 vector.remove(obj);而不必自己检索元素位置,再删除,如int index = indexOf(obj);vector.remove(index); 

    15.当复制大量数据时,使用 System.arraycopy();
     

    16.代码重构,增加代码的可读性。 

    17.不用new关键字创建对象的实例。 
    用 new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用她的clone() 方法。clone()方法不会调用任何类构造函数。 
    下面是Factory模式的一个典型实现。 
    public static Credit getNewCredit()
    {
        return new Credit();
    }

    改进后的代码使用clone() 方法, 
    private static Credit BaseCredit = new Credit();
    public static Credit getNewCredit()
    {
        return (Credit)BaseCredit.clone();
    }
    

    18. 乘除法如果可以使用位移,应尽量使用位移,但最好加上注释,因为位移操作不直观,难于理解。 

    19.不要将数组声明为:public static final。
     

    20.HaspMap的遍历。
     
    Map<String, String[]> paraMap = new HashMap<String, String[]>();
    for( Entry<String, String[]> entry : paraMap.entrySet() )
    {
        String appFieldDefId = entry.getKey();
        String[] values = entry.getValue();
    }

    利用散列值取出相应的Entry做比较得到结果,取得entry的值之后直接取key和 value。 

    21.array(数组)和ArrayList的使用。 
    array 数组效率最高,但容量固定,无法动态改变,ArrayList容量可以动态增长,但牺牲了效率。 

    22.单线程应尽量使用 HashMap, ArrayList,
    除非必要,否则不推荐使用HashTable,Vector,她们使用了同步机制,而降低了性能。 

    23
    .StringBuffer,StringBuilder 的区别在于:java.lang.StringBuffer 线程安全的可变字符序列。一个类似于String的字符串缓冲区,但不能修改。StringBuilder与该类相比,通常应该优先使用 StringBuilder类,因为她支持所有相同的操作,但由于她不执行同步,所以速度更快。为了获得更好的性能,在构造StringBuffer或 StringBuilder时应尽量指定她的容量。当然如果不超过16个字符时就不用了。 
    相同情况下,使用StringBuilder比使用 StringBuffer仅能获得10%~15%的性能提升,但却要冒多线程不安全的风险。综合考虑还是建议使用StringBuffer。 

    24. 尽量使用基本数据类型代替对象。 

    25.用简单的数值计算代替复杂的函数计算,比如查表方式解决三角函数问题。
     

    26.使用具体类比使用接口效率高,但结构弹性降低了,但现代IDE都可以解决这个问题。 

    27.考虑使用静态方法,
     
    如果你没有必要去访问对象的外部,那么就使你的方法成为静态方法。她会被更快地调用,因为她不需要一个虚拟函数导向表。这同事也是一个很好的实践,因为她告诉你如何区分方法的性质,调用这个方法不会改变对象的状态。 

    28.应尽可能避免使用内在的GET,SET方法。 
    android编程中,虚方法的调用会产生很多代价,比实例属性查询的代价还要多。我们应该在外包调用的时候才使用get,set方法,但在内部调用的时候,应该直接调用。 

    29. 避免枚举,浮点数的使用。 

    30.二维数组比一维数组占用更多的内存空间,大概是10倍计算。 

    31.SQLite数据库读取整张表的全部数据很快,但有条件的查询就要耗时30-50MS,大家做这方面的时候要注意,尽量少用,尤其是嵌套查找! [/size][align=left][/align]
    • 16:39
    展开全文
  • 第10版根据Java SE 8全面更新,同时修正了第9版中的不足,系统全面讲解了Java语言的核心概念、语法、重要特性和开发方法,包含大量案例,实践性强。  本书共14章。第1章概述Java语言与其他程序设计语言不同的性能;...
  • Java 核心技术专题

    千次阅读 2007-09-08 17:11:00
    什么是 Java 核心技术?
     

    什么是 Java 核心技术?
    Java 语言与编程实践
    Java 虚拟机技术
    Java SE 平台技术
    Java 高级编程技术
    IBM Java 运行时与 SDK
    Java 理论与实践



    本专题帮助软件开发人员了解 Java 平台和相关技术中最为基础与核心的内容,如 Java 编程语言、Java 虚拟机、Java SE 平台等;此外我们还讨论了 Java 编程技术中所涉及到的诸多高级主题,如集合、垃圾收集、I/O 编程、本地接口(JNI)等。掌握这些内容,对于每一位专业 Java 程序员来说都十分地关键,对于提高 Java 编程技能也十分地有价值。


    什么是 Java 核心技术?

    Java 技术既是一种高级的面向对象的编程语言,也是一个平台。Java 技术基于 Java 虚拟机(Java virtual machine,JVM)的概念 —— 这是语言与底层软件和硬件之间的一种转换器。Java 语言的所有实现都必须实现 JVM,从而使 Java 程序可以在有 JVM 的任何系统上运行。

    Java 核心技术是广泛的 Java 平台和相关技术中最为基础和核心的部分,包括基础技术,如面向对象的 Java 语言、Java 虚拟机技术、Java 运行时库等,另外也包括 Java 技术中的一些高级特性,如集合、垃圾收集、I/O 编程、本地接口(JNI)、安全性、多线程编程等。



    回页首



    Java 语言与编程实践

    Java 编程基础

    下列文章和教程提供了 Java 语言和编程相关技术的基础和深入介绍:

    Java 5 语言增强

    Java 5(代号为 Tiger)为 Java 语言带了较大的变化,下面内容将聚焦 Java 5 增强的语言特性:

    正则表达式

    Java 1.4 在 java.util.regex 包中加入了对使用正则表达式的模式匹配的支持:

    Java 编程实践

    下列最佳实践节选自由 Addison-Wesley 出版的《Practical Java》一书:



    回页首



    Java 虚拟机技术

     

    类路径与类装入器(ClassLoader)



    回页首



    Java SE 平台技术

    Java SE(Java Platform,Standard Edition)

    Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 包含了支持 Java Web 服务开发的类,并为 Java Platform,Enterprise Edition(Java EE)提供基础。

    • Java SE 6 新特性 专栏将对 Java SE 6 (或“Mustang”)中的新特性进行介绍。

    • 驯服 Tiger 专栏对 Java SE 5 (或“Tiger”)做了精彩的概述。

    • Merlin 的魔力 系列讨论了以前的 Java SE 平台版本,J2SE 1.4 或 “Merlin”。许多现有的 Java 应用程序基于 J2SE 1.4,而且这个系列中的大多数概念是与 Java SE 5 编程相关的。


    回页首



    Java 高级编程技术

    垃圾收集(Garbage Collector,GC)机制

    Java 的一个重要优点就是通过垃圾收集器(Garbage Collection,GC)自动管理内存的回收,程序员不需要通过调用函数来释放内存。下面整理了和之相关的文章资源:

    集合框架(Collections Framework)

    “集合框架”提供了一组精心设计的接口和类,它们以单个单元即集合的形式存储和操作数据组。对于计算机科学数据结构课程中学到的许多抽象数据类型如映射(map)、集(set)、列表(list)、树(tree)、数组(array)、散列表(hashtable)和其它集合来说,该框架提供了一个方便的 API。

    I/O

    下列内容与 Java 输入输出(I/O)编程主题相关:

    Java 动态编程与字节码工具

    “Java 编程的动态性”系列文章研究了执行 Java 应用程序时幕后所发生的事情。

    动态代理工具 是 java.lang.reflect 包的一部分,在 JDK 1.3 版本中添加到 JDK,它允许程序创建 代理对象。

    Classworking 工具箱系列文章演示了如何使用运行时 classworking,来用全速前进的生成代码取代反射代码。



    回页首



    IBM Java 运行时与 SDK

    “Java 技术,IBM 风格”系列:随着 Java™ 5.0 的出现,IBM® 在它的 Java 技术实现方面进行了改进,这个系列主要关注 IBM Developer Kit 5 版本中的变化。

    下面介绍了有关 IBM JVM for Linux 内容:

    下文介绍了 IBM Java 垃圾收集器:



    回页首



    Java 理论与实践

    如何将出色的 Java 理论应用于实践?如何解决实际编程问题?下面的专栏为我们带来了来自 Java 专家的最佳实践:

    • Java 理论与实践 ” 专栏旨在探索设计原则如何满足解决实际问题的需求这一难以捉摸的结合点。我们将探索设计模式、可靠软件设计的原则以及为什么“最佳实践”是最好的,同时也关注如何将它们应用于实际问题。


    回页首


    文档选项
    将此页作为电子邮件发送

    将此页作为电子邮件发送



    热点推荐
    Java TOP 10!
    SOA TOP 10!
    WebSphere TOP 10!
    Rational Edge 电子月刊
    Rational 测试工具包
    WebSphere 技术期刊
    WebSphere 在线用户组
    WebSphere 专区导航
    DB2 Magazine 中文版

    资源中心
    Java 技术文档库
    Java 应用开发源动力
    Java Web 开发资源
    Java 与 DB2
    Java 与 XML
    Java 与 Web 服务
    Eclipse 项目资源
    Geronimo 项目资源
    DB2 9 资源中心
    HelloWorld 系列
    Rational工具可视化系列
    RAD 认证系列
    WAS 专栏
    WAS CE 专栏
    Ajax 技术资源中心
    Web 2.0 开发专区

    更多 Java 站点
    Eclipse.org
    Sun 官方的发展历史
    Java SE
    Java EE
    Java ME
    Java Community Process(JCP)
    Java 认证
    XP.org

      特别推荐
    Java 应用开发源动力
    Rational 软件测试工具包
    SOA 企业架构师免费工具包


     
    展开全文
  • JAVA面试技巧之自我介绍

    万次阅读 多人点赞 2019-01-08 11:09:11
    如果想要在自我介绍的时候就能够打动面试官,吸引面试官对我们的兴趣,那么像我们这种接受过Java培训的程序员的自我介绍当然不能和应届生或者其他非技术岗位一样。如何进行自我介绍比较好?有没有什么套路呢?当然有...
  • 总想对JAVA学习总结出些许经验来让小伙伴们少走点弯路,趁着有空就写吧,权当对自己总结,谈不上经验之谈,还望大家可以互相交流,现在就按照我学习JAVA路线图来谈谈我一些小感受,个人一些小技巧
  • 资源支持,Java核心技术卷1第十版中文。本书共14章.第1章概述Java语言与其他程序设计语言不同的性能:第2章讲解如何下载和安装JDK及本书的程序示例:第3章介绍变量、循环和简单的函数:第4章讲解类和封装;第S章...
  • Java 基础篇 Java 多线程篇 Java JVM篇 Java 进阶篇 Java 新特性篇 Java 工具类篇 Java综合篇 Java基础篇 恕我直言,在座的各位根本写不好Java! 8张图带你轻松温习 Java 知识 ...
  • 欢迎小伙伴订阅我的新专栏“Java高薪面试宝典”,在这里我将和大家分享在Java面试中常见的核心考点和技术,为大家的Java学习之路助一臂之力! 开胃菜谱 1、JDK、JRE、JVM是什么? 2、什么是面向对象 3、Java...
  • 注意: : 优先级警告...使用 Khallware(Java概念验证) 概述 这是一些用Java编写的简单,独立的概念证明。 主题包括: -简单的Java构造,data_types和语言...-各种核心Java技术 -j2ee技术的各种子集 -通用Java
  • Java位运算技巧

    千次阅读 2018-08-23 20:36:53
    位运算作为底层的基本运算操作,往往是和'高效'二字沾边,适当的运用位运算来优化系统的核心代码,会让你的代码变得十分的精妙。以下是我所遇之的一些简单的位运算技巧作为博文记录。 1.获得int型最大值 ...
  • Java2核心技术第7版全两卷.pdf中文高清

    千次下载 热门讨论 2012-09-14 14:22:28
    本资源内有两本书《Java2核心技术卷I:基础知识(第7版)》和《JAVA2核心技术,卷II:高级特性(第7版)》,大小分别为 88MB 和 112 BM,均为 PDF 格式,高清影印版。两本书分别介绍如下: 《Java2核心技术卷I:基础知识...
  • Java核心技术卷1第十版中文(文件过大所以压缩)。本书共14章.第1章概述Java语言与其他程序设计语言不同的性能:第2章讲解如何下载和安装JDK及本书的程序示例:第3章介绍变量、循环和简单的函数:第4章讲解类和封装...
  • java核心技术卷一第一章说的是一些java特性并顺带简单说了一下java和C++的区别,在此不再特别记录第二章写的是环境安装和使用命令行窗口调试运行,并总结了一些调试技巧,在此记录一下,至于环境安装等等非常基础的...
  • JAVA核心知识点--JDK1.8中的日期处理

    万次阅读 多人点赞 2017-12-12 19:22:54
    Java 8中如何处理日期和时间 示例 1、在Java 8中获取今天的日期 示例 2、在Java 8中获取年、月、日信息 示例 3、在Java 8中处理特定日期 示例 4、在Java 8中判断两个日期是否相等 示例 5、在Java 8中检查像...
  • Java核心技术 卷1 基础知识

    万次阅读 2019-04-09 09:31:25
    网站 ...> CiCi岛 下载 电子版仅供预览及学习交流使用,下载后请24小时内删除,支持正版,喜欢的请购买正版书籍 ...购买正版 ... 根据Java SE 8全面更新,系统全面讲解Java语言的核心概念、语法...
  • Java性能优化技巧

    千次阅读 2010-04-28 09:43:00
    Java性能优化技巧参考了些书籍,网络资源整理出来,适合于大多数Java应用在JAVA程序中,性能问题的大部分原因并不在于...在JAVA核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了
  • 书评:Java核心编程卷1——基础

    千次阅读 2013-11-04 23:24:31
    本文来源于我在InfoQ中文站翻译的文章,原文地址是:...那时所有与Java相关的图书基本上都是由Sun公司的几个工程师们所发布的,比如说Arthur Van Hoff et.al所写的“H
  • 阅读线程池的源码有一个小技巧,可以按照线程池执行的顺序进行串连关联阅读,这样更容易理解线程池的实现。 源码阅读流程解读 我们先从线程池的任务提交方法execute()开始阅读,从execute()我们会发现线程池执行...
  • 写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,希望可以给大家一些经验,能让大家更好学习和使用Java。 这次介绍的主要内容是和J2SE相关的部分,另外,会在以后再介绍些J2EE相关的、和Java中...
  • 1.return 一个空的集合,而不是 null 如果一个程序返回一个没有任何值的集合,...Java 的标准库设计者已经在 Collections 类中放了一个空的 List 常量 EMPTY_LIST,除此之外,还有 EMPTY_MAP, EMPTY_SET,真是贴心。
  • Java面试技巧—如何自我介绍

    千次阅读 2020-06-17 12:26:16
    Java面试技巧—如何自我介绍 本文转自:https://www.yoodb.com/quotation/detail/1134 在企业面试环节中“自我介绍”这个老生常谈的话题就不用多说什么了,面试官必定会问的。那么如何在自我介绍的时候就能够...
  • Java 并发核心编程

    万次阅读 热门讨论 2010-11-03 15:41:00
    Java 并发核心编程 内容涉及: 1、关于java并发 2、概念 3、保护共享数据 4、并发集合类 5线程 6、线程协作及其他   1、关于java并发 自从java创建以来就已经支持并发的理念,如线程和锁。这篇指南主要是...
  • 速学Java面试技巧,斩获心仪offer

    千次阅读 2020-06-02 10:40:20
    于是我们决定先从Java面试开始,特别邀请到了拥有8年Java面试官经验的胡书敏老师,给所有Java开发者一次彻底的面试技能提升。 胡老师曾助力600+人拿到心仪offer;那么,正在找工作或者想要跳槽的你,这场直播绝对...
  • 新书推荐《Java核心技术卷Ⅰ:基础知识(原书第11版)》长按二维码了解及购买全新第11版!针对Java SE9、10、11全面更新!Java领域极具影响力和价值的著作之一,与《Java...
  • import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.security.cert.CertificateException; import ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 66,525
精华内容 26,610
关键字:

java核心技巧

java 订阅