一篇带你入门Java垃圾回收器

目录
  • 1 垃圾回收算法
    • 1-1 标记清除算法
      • 算法思想
    • 1-2 标记整理算法
    • 1-3 复制算法
  • 2 JVM分代回收算法
    • 2-1 概述
    • 2-2 分代垃圾回收示例
    • 2-3 分代垃圾回收的总结
      • 对象首先分配在伊甸园区域
    • 2-5 垃圾回收案例分析
  • 2 垃圾回收器
    • 2-1 垃圾回收器概述
    • 2-2 串行垃圾回收器
    • 2-3 吞吐量优先的垃圾回收器
    • 2-4 响应时间优先的垃圾回收器(CMS垃圾回收器)
  • 总结:

第一阶段:串行垃圾回收器:jdk1.3.1之前Java虚拟机仅仅只支持Serial收集器

第二阶段:并行垃圾回收器:随着多核的出现,Java引入了并行垃圾回收器,充分利用多核性能提升垃圾回收效率

第三阶段:并发标记清理回收器CMS:垃圾回收器可以和应用程序同时运行,降低暂停用户线程执行的时间

第四阶段:G1(并发)回收器:初衷是在清理非常大的堆空间的时候能满足特定的暂停应用程序的时间,与CMS相比会有更少的内存碎片

1 垃圾回收算法

1-1 标记清除算法

算法概述

优点:回收速度快

缺点:造成内存碎片,无法分配大的连续空间。

算法思想

在Java9之前,Java默认使用的垃圾回收器是ParallelGC,从Java9开始G1作为了默认的垃圾回收器

  • step1: 第一次扫描,通过GC root对象判断堆内存中哪些对象可以进行垃圾回收,进行标记。
  • step2: 第二次扫描, 将那些标记的GC root对象进行垃圾回收,只需要将起始内存地址与终止内存地址放入空闲内存区就行。

1-2 标记整理算法

第一个依旧是标记,第二步会进行一个空间整理,从而不产生碎片。

优点:避免了内存碎片

缺点:对空间的整理使得效率比较低下。

1-3 复制算法

特点

将管理的内存分为2块区域,from区域与to区域,将那些不需要回收的对象从from区域拷贝到to区域。复制的过程中完成内存区域的整理。之后交换from和to的指向。

优点:不会产生内存碎片

缺点:需要双倍的内存空间,内存利用率不高,而且拷贝也需要时间。



1-4 三种垃圾回收算法总结

垃圾回收算法 优点 缺点
标记清除算法(Mark Sweep) 速度较快 产生内存碎片
标记整理算法(Mark Compact) 没有内存碎片 速度慢
复制算法(Copy) 没有内存碎片 需要占用双倍内存空间

注意:实际的JVM垃圾回收算法中上面的三种算法是综合使用的。

2 JVM分代回收算法

2-1 概述

Garden of Eden:伊甸园 garbage:垃圾

新生代主要由三部分内容组成,分别是Eden区,幸存区from,幸存区to。 通常情况下只有Eden区与幸存区from会存放数目,幸存区to只有垃圾回收时,复制对象会用到。堆内存的新生代进行一次垃圾回收(Minor GC),大部分对象都会都会被回收。

老年代通常存放一些经常被使用的对象,一个对象如果经历多次垃圾回收仍然幸存,那么该对象会从新生代放入老年代。只有新生代内存不足并且老年代内存也不足的时候才会触发full GC对老年代的对象进行垃圾回收。

为什么需要进行划分?

实际环境中,对象的生命周期是不同的,老年代的对象生命周期比较长,可能很长时间才进行一次垃圾回收。新生代的对象生命周期比较短,垃圾回收比较频繁。这种分区法方便采用不同的垃圾回收算法更加有效的进行垃圾回收。

2-2 分代垃圾回收示例

step1:程序刚刚开始运行,产生的对象先放入Eden区,当Eden区放不下的时候。

step2:对Eden区进行Minor GC,并将没有被垃圾回收的对象复制的幸存区To,然后交换幸存区To和幸存区From,第一次垃圾回收的最终的效果如下图所示:

step3: 第一次Minor GC, Eden区又有空间可以分配给新的对象使用,经过一段时间Eden又不够用了,触发第二次Minor GC, 这次垃圾会检查Eden区以及幸存区From哪些对象可以存活,并将这些对象复制到幸存区To,然后交换幸存区To和幸存区From,这个时候Eden区又空了出来,可以放置新的对象。

实际垃圾回收过程中,JVM会对每个对象经过垃圾回收幸存下来的次数进行记录,比如上图中,幸存区的2个对象经过垃圾回收的次数分别是1和2。

step4: 当一些对象经过垃圾回收的次数仍然幸存的次数达到一个阈值(说明这个对象价值比较高),那么这个对象会被移动到老年代。

极端情况考虑:Eden区,from区,老年区都已经满了?

此时会触发Full GC(优先Minor GC,Minor GC依旧内存不够)

2-3 分代垃圾回收的总结

对象首先分配在伊甸园区域

新生代空间不足时,触发 minor gc,伊甸园和 from 存活的对象使用 copy复制到 to 中,存活的对象年龄加 1并且交换from to

minor gc 会引发stop the world,暂停其它用户的线程,等垃圾回收结束,用户线程才恢复运行暂停时间较短,由于新生代大部分对象都是垃圾,复制的对象很少,所以效率较高

当对象寿命超过阈值时,会晋升至老年代,最大寿命是15(4bit,对象头存储)

当老年代空间不足,会先尝试触发 minor gc,如果之后空间仍不足,那么触发full gc,STW的时间更长

Full GC 的stop the world的时间要比MInor GC时间长,老年代存活对象较多加上空间整理时间,所以停止时间会较长。如果Full GC后,空间仍然不足会触发内存不足的异常。

2-4 垃圾回收相关的虚拟机参数

垃圾回收器概述

参数含义 参数 备注
堆初始大小 -Xms
堆最大大小 -Xmx 或 -XX:MaxHeapSize=size
新生代大小 -Xmn 或 (-XX:NewSize=size + -XX:MaxNewSize=size ) NewSize是初始大小,MaxNewSize是最大大小。
幸存区比例(动态) -XX:InitialSurvivorRatio=ratio 和 -XX:+UseAdaptiveSizePolicy 幸存区的比例,默认是8,假设新生代10M内存,8M划分给Eden区,剩下的二等分,一份from,一份to。
幸存区比例 -XX:SurvivorRatio=ratio 动态调整幸存区比例
晋升阈值 -XX:MaxTenuringThreshold=threshold 用于动态调整幸存区比例
晋升详情 -XX:+PrintTenuringDistribution 用于动态调整幸存区比例
GC详情 -XX:+PrintGCDetails -verbose:gc 打印详情信息
FullGC 前 MinorGC -XX:+ScavengeBeforeFullGC 默认在Full GC 前进行一次Minor GC

2-5 垃圾回收案例分析

情况1:什么都不放的情况

new generation:新生代 tenured generation:老年代

package cn.itcast.jvm.t2;
import java.util.ArrayList;
/**
 *  演示内存的分配策略
 */
public class Demo2_1 {
    private static final int _512KB = 512 * 1024;
    private static final int _1MB = 1024 * 1024;
    private static final int _6MB = 6 * 1024 * 1024;
    private static final int _7MB = 7 * 1024 * 1024;
    private static final int _8MB = 8 * 1024 * 1024;
//加入Java开发交流君样:756584822一起吹水聊天
    // -Xms20M -Xmx20M -Xmn10M : 堆初始与最大大小都是20M,新生代的大小为10M.
    // -XX:+UseSerialGC : 为了学习方便,采用这个垃圾回收器,默认的垃圾回收器并不是这个。
    // -XX:+PrintGCDetails -verbose:gc :打印详细信息
    // -XX:-ScavengeBeforeFullGC :在Full GC 前进行 Minor GC.
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            ArrayList<byte[]> list = new ArrayList<>();
            list.add(new byte[_8MB]);
            list.add(new byte[_8MB]);
        }).start();
        System.out.println("sleep....");
        Thread.sleep(1000L);
    }
}

情况1执行结果

可以看到即使用户没有创建对象,系统对象也要占据一部分堆内存空间。

Heap
 def new generation   total 9216K, used 2341K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
// 新生代的空间总的大小为9216K,这里没有把To空间给计算进去,系统任务To的空间是分配是不可用的,所以不是10M,已经使用了2341K,[]内部则是内存地址范围。
  eden space 8192K,  28% used [0x00000000fec00000, 0x00000000fee49420, 0x00000000ff400000)
//
  from space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
  to   space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
 tenured generation   total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
// 老年代大小为10M,可以看到没有任何空间使用
                                          //加入Java开发交流君样:756584822一起吹水聊天
   the space 10240K,   0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000)
 Metaspace       used 3394K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 378K, capacity 388K, committed 512K, reserved 1048576K

Java的内存对象都是分配在堆上吗

情况2:新生代堆空间放满,触发GC

    public static void main(String[] args) throws InterruptedException {
        ArrayList<byte[]> list = new ArrayList<>();
        list.add(new byte[_7MB]);      // 系统类占用2341K,加上new的7MB触发垃圾回收
    }

情况2执行结果

[GC (Allocation Failure) [DefNew: 2342K->696K(9216K), 0.0029193 secs] 2342K->696K(19456K), 0.0029867 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
// GC:minor GC(新生代垃圾回收)    FUll GC  (老年代垃圾回收)
// [Times: user=0.00 sys=0.00, real=0.00 secs] 垃圾回收执行时间
Heap
 def new generation   total 9216K, used 8110K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,  90% used [0x00000000fec00000, 0x00000000ff33d8c0, 0x00000000ff400000)
  from space 1024K,  67% used [0x00000000ff500000, 0x00000000ff5ae100, 0x00000000ff600000)
  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
 tenured generation   total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,   0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000)
 Metaspace       used 3539K, capacity 4536K, committed 4864K, reserved 1056768K
 //加入Java开发交流君样:756584822一起吹水聊天
  class space    used 395K, capacity 428K, committed 512K, reserved 1048576K

情况三: 新生代内存随着对象的增多放不下了

    public static void main(String[] args) throws InterruptedException {
        ArrayList<byte[]> list = new ArrayList<>();
        list.add(new byte[_7MB]);
        list.add(new byte[_512KB]);
        list.add(new byte[_512KB]);
    }

执行结果

新生代放不下,将新生代的对象放置到老年代。

[GC (Allocation Failure) [DefNew: 2342K->670K(9216K), 0.0022591 secs] 2342K->670K(19456K), 0.0023131 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 8678K->538K(9216K), 0.0061246 secs] 8678K->8354K(19456K), 0.0061637 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
 def new generation   total 9216K, used 1132K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,   7% used [0x00000000fec00000, 0x00000000fec94930, 0x00000000ff400000)
  from space 1024K,  52% used [0x00000000ff400000, 0x00000000ff486a00, 0x00000000ff500000)
  to   space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
 tenured generation   total 10240K, used 7815K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,  76% used [0x00000000ff600000, 0x00000000ffda1f80, 0x00000000ffda2000, 0x0000000100000000)
 Metaspace       used 3539K, capacity 4536K, committed 4864K, reserved 1056768K
 //加入Java开发交流君样:756584822一起吹水聊天
  class space    used 395K, capacity 428K, committed 512K, reserveed 1048576K

情况四:一开始直接分配大于新生代的内存,如果老年代放的下,则直接放到老年代

    public static void main(String[] args) throws InterruptedException {
        ArrayList<byte[]> list = new ArrayList<>();
        list.add(new byte[_8MB]);
    }

执行结果

Heap
 def new generation   total 9216K, used 2507K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,  30% used [0x00000000fec00000, 0x00000000fee72ca8, 0x00000000ff400000)
  from space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
  to   space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
 tenured generation   total 10240K, used 8192K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,  80% used [0x00000000ff600000, 0x00000000ffe00010, 0x00000000ffe00200, 0x0000000100000000)
 Metaspace       used 3539K, capacity 4536K, committed 4864K, reserved 1056768K
  class space    used 395K, capacity 428K, committed 512K, reserved 1048576K

小结

当内存比较紧张的时候,即新生代内存放不下的时候,有时候会直接将对象分配到老年代,或者直接在回收次数较少(未达到15次)的情况下,直接将新生代对象弄到老年代。【资料获取】

2 垃圾回收器

2-1 垃圾回收器概述

名称 特点 适合场景 目标 新生代 老年代
串行垃圾回收器 单线程 堆内存小,适合个人电脑(cpu个数) 采用复制的垃圾回收算法 采用标记+整理的垃圾回收算法
吞吐量优先垃圾回收器 多线程 堆内存大,多核CPU 并行,让单位时间内STW的时间最短 复制算法 标记+拷贝
响应时间优先的垃圾回收器(简称CMS) 多线程 堆内存大,多核CPU 并发,尽可能让单次STW最短 复制算法 标记清除算法产生内存碎片需要退化成单线程的垃圾整理回收器

CMS垃圾回收器后来被G1垃圾回收器取代。

2-2 串行垃圾回收器

开启串行垃圾回收器的JVM参数

-XX:+UseSerialGC    = Serial + SerialOld
// Serial:工作在新生代,采用复制的垃圾回收算法
// SerialOld:工作在老生代,采用标记+整理的垃圾回收算法

总结:触发垃圾回收时,让多个线程在一个安全点停下来,然后使用单线程的垃圾回收器去进行垃圾回收,垃圾回收完成后,再让其他线程运行。

2-3 吞吐量优先的垃圾回收器

开启吞吐量优先的垃圾回收器的JVM参数

开启/关闭的参数

默认的多线程垃圾回收器,前者是开启新生代回收器,采用复制算法,后者是开启老年代回收器,采用标记+拷贝算法。下面选项只要开启一个,那么另外一个也会开启。

-XX:+UseParallelGC , -XX:+UseParallelOldGC

开启自适应动态调整新生代的大小,晋升阈值

-XX:+UseAdaptiveSizePolicy

二个指标调整的参数(ParallelGC会根据设定的指标去调整堆的大小到达下面期望设定的目标)
指标1)1/(1+ratio) = 垃圾回收的时间/总的运行时间

ratio默认值时99,即垃圾回收的时间不超过总时间1%。但一般设为19。【资料获取】
如果达不到目标,ParallelGC会调整堆内存大小来达到这个目标,通常是调大,这样垃圾回收的次数会减少,从而提高吞吐量

-XX:GCTimeRatio=ratio

指标2)每次垃圾回收的时间限制( 最大暂停的毫秒数)

默认值是200ms
显然将堆内存空间变小有助于减少每次垃圾回收的时间

-XX:MaxGCPauseMillis=ms

总结:显然指标1)与指标2)是有冲突的。

-XX:ParallelGCThreads=n //垃圾回收并行的线程数目

小结

采用多线程方式进行垃圾回收,垃圾回收的线程数目通常根据CPU的核数进行设置。在垃圾回收阶段,并行的垃圾回收线程会充分占用CPU。在非垃圾回收阶段,用户线程会充分利用CPU资源。

2-4 响应时间优先的垃圾回收器(CMS垃圾回收器)

缺点:采用的标记清除算法产生内存碎片需要退化成单线程的垃圾整理回收器,造成响应时间变长。

开启的JVM参数

注意这个是并发的采用标记清除算法的垃圾回收,这里区别于之前的垃圾回收器,该垃圾回收器能够在进行垃圾回收的同时运行其他非垃圾回收线程(也存在时间阶段需要停止,但不是所有阶段停止)。

老年代并发的垃圾回收器会出现失败的情况,这时老年代垃圾回收器会退化成单线程的垃圾回收器(SerialOld)

-XX:+UseConcMarkSweepGC // use concurrent mark sweep(会产生垃圾碎片) 工作在老年代的垃圾回收器
-XX:+UseParNewGC        // 工作在新生代的垃圾回收器

重要的初始参数

-XX:ParallelGCThreads=n        // 并行的垃圾回收线程数,通常等于CPU的核心数(垃圾回收并行阶段)
-XX:ConcGCThreads=threads      // 并发的线程数目,通常设为并行垃圾回收线程数的1/4(垃圾回收并发阶段)

其他参数

-XX:CMSInitiatingOccupancyFraction=percent // 执行垃圾回收的内存占比,预留空间给浮动垃圾
-XX:+CMSScavengeBeforeRemark
// 在重新标记前,对新生代进行垃圾回收,减少并发清理的垃圾对象,+开启,-关闭

浮动垃圾是指并发清理过程中用户线程新产生的垃圾,需要等待下次并发清理。

并发工作流程概述:

  • step1:老年代发生内存不存的现象。
  • step2:ConcMarkSweepGC会进行一个初始标记动作(初始标记需要STW即阻塞非垃圾回收线程),初始标记只标记根对象,所以速度非常快,暂停时间也非常短。
  • step3:完成初始标记后,之前阻塞的线程又可以运行了,这个时候垃圾回收线程进行并发标记。
  • step4:并发标记结束后,需要再次阻塞非垃圾回收线程,进行一个所谓的重新标记,
  • step5:重新标记完成后,阻塞的线程又可以运行了。垃圾回收线程也并发的清理垃圾对象。

总结:

初始标记与重新标记需要阻塞线程。 在并发阶段,由于垃圾回收线程占用资源,所以系统的吞吐量会受到一定的影响,但是系统的响应速度由于并发执行不会受到垃圾回收的明显影响(相比较其他垃圾回收器,STW时间只需要进行初始标记与重新标记,并且能够不阻塞其他线程进行垃圾的标记与清除)。

最后,祝大家早日学有所成,拿到满意offer,快速升职加薪,也请多多关注我们的其他文章!

(0)

相关推荐

  • SpringBoot项目调优及垃圾回收器的比较详解

    一.SpringBoot项目在外部Tomcat启动时加载两次 如下所示,spring标志出现两次(截取部分代码) . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|=====

  • spring启动后保证创建的对象不被垃圾回收器回收

    一.可达性分析(根搜索)算法 JVM通过可达性分析来判定对象是否存活.这个算法的基本思路就是通过一系列称为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的.如下图中对象object1.object2.object3.object4是可用的对象,object5.object6.object7虽然互相关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象. 在Java

  • 垃圾回收器的相关知识点总结

    垃圾回收器是一把十足的双刃剑.其好处是可以大幅简化程序的内存管理代码,因为内存管理无需程序员来操作,由此也减少了(但没有根除)长时间运转的程序的内存泄漏.对于某些程序员来说,它甚至能够提升代码的性能. 另一方面,选择垃圾回收器也就意味着程序当中无法完全掌控内存,而这正是移动终端开发的症结.对于JavaScript,程序中没有任何内存管理的可能--ECMAScript标准中没有暴露任何垃圾回收器的接口.网页应用既没有办法管理内存,也没办法给垃圾回收器进行提示. 严格来讲,使用垃圾回收器的语言在性能

  • JVM的7种垃圾回收器(小结)

    垃圾回收算法和垃圾回收器 对于JVM的垃圾回收算法有复制算法.标记清除.标记整理. 用阳哥的话就是:这些算法只是天上飞的理念,是一种方法论,但是真正的垃圾回收还需要有落地实现,所以垃圾回收器应运而生. JVM回收的区域包括方法区和堆,jvm对于不同区域不同的特点采用分代收集算法,比如因为所有的对象都是在Eden区进行分配,并且大部分对象的存活时间都不长,都是"朝生夕死"的,每次新生代存活的对象都不多,所以新采取复制算法:而jvm默认是新生代的对象熬过15次GC才能进入老年代,所以老年代

  • 一篇带你入门Java垃圾回收器

    目录 1 垃圾回收算法 1-1 标记清除算法 算法思想 1-2 标记整理算法 1-3 复制算法 2 JVM分代回收算法 2-1 概述 2-2 分代垃圾回收示例 2-3 分代垃圾回收的总结 对象首先分配在伊甸园区域 2-5 垃圾回收案例分析 2 垃圾回收器 2-1 垃圾回收器概述 2-2 串行垃圾回收器 2-3 吞吐量优先的垃圾回收器 2-4 响应时间优先的垃圾回收器(CMS垃圾回收器) 总结: 第一阶段:串行垃圾回收器:jdk1.3.1之前Java虚拟机仅仅只支持Serial收集器 第二阶段:并

  • 简单了解Java垃圾回收器的种类

    在这篇教程中我们将学习几种现有的垃圾回收器.在Java中,垃圾回收是一个自动的进程可以替代程序员进行内存的分配与回收这些复杂的工作.这篇是垃圾回 收教程系列的第三篇,在前面的第2部分我们看到了在Java中垃圾回收是如何工作的,那是篇有意思的文章,我推荐你去看一下.第一部分介绍了Java的垃圾回收,主要有JVM体系结构,堆内存模型和一些Java术语. Java有四种类型的垃圾回收器: 串行垃圾回收器(Serial Garbage Collector) 并行垃圾回收器(Parallel Garbag

  • Java垃圾回收器的方法和原理总结

    什么是Java垃圾回收器 Java垃圾回收器是Java虚拟机(JVM)的三个重要模块(另外两个是解释器和多线程机制)之一,为应用程序提供内存的自动分配(Memory Allocation).自动回收(Garbage Collect)功能,这两个操作都发生在Java堆上(一段内存快).某一个时点,一个对象如果有一个以上的引用(Rreference)指向它,那么该对象就为活着的(Live),否则死亡(Dead),视为垃圾,可被垃圾回收器回收再利用.垃圾回收操作需要消耗CPU.线程.时间等资源,所以容

  • 带你入门Java的类与对象

    目录 类和对象 类的属性 成员方法 形参和实参 局部变量 可变参数 构造方法 this关键字 this.属性名 this.方法名 static关键字 静态变量 1)静态变量 2)实例变量 静态方法 静态代码块 对象的创建 显式创建对象 方法隐含创建对象 总结 匿名对象 总结 类和对象 在面向对象中,类和对象是最基本.最重要的组成单元.类实际上是表示一个客观世界某类群体的一些基本特征抽象.对象就是表示一个个具体的东西.所以说类是对象的抽象,对象是类的具体. "人类"只是一个抽象的概念,它

  • 带你入门Java的集合

    目录 java集合 集合分类---Set.List.Map三种大体系 Set HashSet HashCode()方法 TreeSet 自然排序 List List与ArrayList ArrayList和Vector Map TreeMap 操作集合的工具类:Collections 查找.替换 同步控制 泛型 为什么要有泛型 枚举类 Annotation(注解)概述 基本的Annotation 自定义Annotation 总结 java集合 java集合类存放于java.util包中,是一个用

  • 一篇文章带你入门Java修饰符

    目录 定义 分类 访问控制修饰符 非访问控制修饰符 修饰符的使用说明 修饰类 修饰方法 访问控制修饰符 非访问控制修饰符 修饰变量 总结 定义 Java修饰符:修饰符用来定义类.方法或者变量,通常放在语句的最前端. 分类 主要分为2类: 访问控制修饰符 非访问控制修饰符 访问控制修饰符 可以使用访问控制符来保护对类.变量.方法和构造方法的访问.分为以下4中权限:private,default,protected,public. 权限说明: 修饰符 当前类 同包 子类(不同包) 不同包(其他类)

  • 一篇文章带你入门Java字面量和常量

    目录 引言 概念 字面量 字面量的分类 常量 总结 引言 ♀ 小AD:哥,前两天我没有闪现到刺客脸上了吧 ♂ 明世隐:在这方面做的有进步. ♀ 小AD:明哥教的好,通过学习Java关键字,游戏水平也得到了提升,一举两得,舒服. ♂ 明世隐:可是你看到残血还是上头啊,是了多少次,你说? ♀ 小AD:5.6次吧 ♂ 明世隐:岂止5.6,起码10次. ♀ 小AD:这不是看到200金币,经不住诱惑吗 ♂ 明世隐:关爱残血,你学哪里去了,游戏中就不能多一些人间的关爱吗?你就不能关爱一下放暑假的小弟弟小妹妹

  • 带你入门Java的泛型

    目录 泛型 1.简单泛型 (1)元组 (2)堆栈 2.泛型接口 3.泛型方法 (1)类型推断 (2)通用的Generator (3)Set实用工具实现数学方法 4.擦除 (1)迁移兼容性 (2)擦除的问题 5.擦除的补偿 (1)由于擦除原因,无法通过instanceof比较类型.如果引入类型标签,就可以转而使用动态的isInstance(). (2)创建类型实例 (3)泛型数组 6.边界 7.通配符 (1)List<? extends Fruit>协变 (2)List<? super F

  • 带你入门Java的方法

    目录 什么是方法 方法的定义 方法的使用 总结 什么是方法 例如:System.out.println(); 其结构为-->类.对象.方法: 其含义为-->调用系统类System中的标准输出对象out中的println方法. java方法是语句的集合,它们在一起执行一个功能. 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 方法的本意是功能块,就是实现某个功能的语句块的集合. 原子性:就是一个方法只完成一个功能,这样利于我们后期的拓展. 方法的命

  • 带你入门Java的数组

    目录 数组的定义 数组的声明和创建 1.动态初始化 2.静态初始化 3.数组的默认初始化 数组的四个基本特点 数组边界 数组的使用 Arrays类 总结 数组的定义 数组是相同类型数据的有序集合 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们. 数组的声明和创建 首先必须声明数组变量,才能在程序中使用数组.下面是声明数组变量的语法: dataType[] arrayRefVar;//首选方法 或 data

随机推荐