Java基础知识总结01

JVM:是运行java字节码的虚拟机
JDK :是功能齐全的Java SDK。它拥有JRE所拥有的一切,还有编译器和工具。它能够创建和编译程序
JRE :是java运行时的环境,但是不能用于创建新程序

Java的内存划分

​ 由于Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分。
​ 补充:首先Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。在整个程序执行过程中,JVM会用一段空间来存储程序执行期间需要用到的数据和相关信息,这段空间一般被称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存。因此,在Java中我们常常说到的内存管理就是针对这段空间进行管理(如何分配和回收内存空间)。

1.程序计数器(Program Counter Register)也有称作为PC寄存器:(线程私有)
程序计数器是指CPU中的寄存器。保存的是下一条指令的所在存储单元的地址,当CPU需要执行指令时,需要从程序计数器中得到当前需要执行的指令所在存储单元的地址,然后根据得到的地址获取到指令,在得到指令之后,程序计数器便自动加1或者根据转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令。
Java是支持多线程的,程序先去执行A线程,执行到一半然后去执行B线程,然后又跑去接着执行A线程,那程序是怎么记住A线程已经执行到哪里了呢?这就需要程序计数器了。因此,为了线程切换后能够恢复到正确执行的位置,每条线程都有一个独立的程序计数器,这块属于“线程私有”的内存。

2.Java虚拟机栈(线程私有)
Java栈是Java方法执行的内存模型。每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。
当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。当方法执行完毕之后,便会将栈帧出栈。因此可知,线程当前执行的方法所对应的栈帧必定位于Java栈的顶部。
由于每个线程正在执行的方法可能不同,因此每个线程都会有一个自己的Java栈,互不干扰。

3.本地方法栈:
本地方法栈是为虚拟机执行本地方法服务的

4.Java堆:堆内存
Java 堆是虚拟机所管理的内存中最大的一块,是被所有线程共享的一块内存区域,在虚拟机启动时创建.此内存区域的唯一作用就是存放对象实例,几乎所有的对象实例都是在这里分配的。当类加载器读取了类文件后,需要把类、方法、常量、变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行。
凡是new出来的东西,都在堆当中;堆内存里面的东西都有一个地址值:16进制;堆内存里面的数据,都有默认值。
Java 堆是 GC 回收的主要区域,因此很多时候也被称为 GC 堆。为了优化GC性能,堆在逻辑上分为三个区域:新生区、养老区和元空间,GC只需要在小范围的区域中(新生区)搜集垃圾。

5.方法区(线程共享)
它与堆一样,是被线程共享的区域。用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码数据。
方法区中有一个非常重要的部分就是运行时常量池,它是每一个类或接口的常量池的运行时表示形式,在类和接口被加载到JVM后,对应的运行时常量池就被创建出来。运行时常量池受到方法区内存的限制,当常量池无法再申请到内存时就会抛出OutOfMemoryError异常。

Java垃圾回收(GC)机制详解

​ 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收,所以,垃圾回收是必须的

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

如何判断对象存活 :
引用计数算法:给对象添加一个引用计数器,每当有一个地方引用它时计数器加1,引用释放时计数减1,当计数器为0时可以回收。(Java虚拟机中没有使用该方法,主要是因为无法解决对象相互循环引用的问题);
可达性分析算法:基本思想是通过一系列称为“GC Root”的对象(如系统类加载器、栈中的对象、处于激活状态的线程等)作为起点,基于对象引用关系,开始向下搜索,所走过的路径称为引用链,当一个对象到GC Root没有任何引用链相连,证明对象是不可用的。

Java GC都用了哪些算法?分别应用在什么地方?
标记清除(Mark-Sweep)算法,包含“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象;(一个是效率问题,标记和清除过程的效率都不高;另外是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作);
复制(Copying)算法:将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当一块内存用完了,就将还存活着的对象复制到另外一块上,然后清理掉前一块。(缺点:将内存缩小为一半,性价比低,持续复制长生存期的对象则导致效率低下)JVM堆中新生代便采用复制算法,对象每经历一次复制,年龄加1,达到晋升年龄阈值后,转移到老年代。
标记整理(Mark-Compact)算法:标记过程与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。堆中老年代采用的算法
分代收集算法:将Java的堆内存逻辑上分成两块,新生代和老年代,针对不同存活周期、不同大小的对象采取不同的垃圾回收策略。

成员变量和局部变量的区别

  1. 位置:成员变量在方法以外,类里面,局部变量在方法里面
  2. 存放内存位置:成员变量存放在堆内存中,局部变量存放在栈内存
  3. 生命周期:成员变量随着对象的创建而存在,随着没有对象指向该内存被 GC而消失,随着方法的调用或者代码块的执行而存在,随着方法的调用完毕或者代码块的执行完毕而消失
  4. 作用范围:成员变量作用在整个类中,局部变量只能作用在该方法中
  5. 初始值:成员变量有默认初始值,局部变量没有默认初始值,使用之前需要赋值,否则编译器会报错

类与对象

类:具有共同属性和行为的一类事物的概述。

 public class 类名{   类中的属性和行为   } 

对象:从类中抽取出来的实际存在的个体称为对象。

类名 对象名 = new 类名();

static静态关键字

//修饰变量:
static 数据类型 变量名
//静态变量,在类的加载过程中,JVM为静态变量分配一次内存空间,它将不再是跟随对象的创建而存在于堆内存中了,而是存在方法区中的静态区;所有的对象共享一个变量及变量值。中途不要随意修改该属性值,一修改全部修改。
//修饰方法:
【访问权限修饰符】 static 方法返回值 方法名(参数列表)
//静态方法,不属于任何实例对象的,那么就是说在静态方法内部是不能使用this
  1. 在静态方法中没有this关键字因为静态是随着类的加载而加载,而this是随着对象的创建而存在的。静态比对象优先存在。
  2. 静态可以访问静态的,但是静态不能访问非静态的。非静态的可以去访问静态的。
  3. 多了一种调用方式:类名.属性名 / 类名.方法();

this关键字

  1. 当成员变量和局部变量同名的时候,用来区分成员变量和局部变量,带this.为成员变量。
  2. 本质上来说,是一个对象。谁调用这个方法,那么这个this就代表那个对象。
  3. this关键字不能在静态方法中使用,原因是this本质上是一个对象,而静态随着类的加载而加载,优先于对象存在了

super关键字

    • 子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用的父类构造方法,后执行子类构造方法
    • 子类构造可以通过super关键字来调用父类重载构造。
    • super的父类构造调用,必须是子类构造方法的第一个语句,不能一个子类构造调用多次super关键词。
    • 在子类的成员方法中,访问父类的成员变量,成员方法
    • 在子类的构造方法中,访问父类的构造方法

abstract抽象关键字

  • abstract修饰方法:抽象方法
  1. 抽象方法只有方法的声明,没有方法体
  2. 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
  3. 若子类重写了父类中的所有的抽象方法后,此子类方可实例化
  4. 若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
  • abstract修饰类:抽象类
  1. 此类不能实例化
  2. 抽象类中一定有构造方法,便于子类实例化时调用

interface接口

接口(interface)是抽象方法和常量值的定义的集合

  • 接口中的所有成员变量都默认是由public static final修饰的。
  • 接口中的所有方法都默认是由public abstract修饰的。
  • 接口没有构造方法。构造方法用于创建对象
  • 实现接口的类中必须提供接口中所有方法的具体实现内容。
  • 多个无关的类可以实现同一个接口,一个类可以实现多个无关的接口
  • 与继承关系类似,接口与实现类之间存在多态性
  • 接口也可以继承另一个接口,使用extends关键字

函数的重载

在同一个类中,允许存在一个以上的同名函数,(参数类型不同,参数个数不同,参数 类型的顺序不同)满足其一

final关键字

用来修饰一个引用:
引用为基本数据类型,则该引用为常量,该值无法修改;
引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改
引用为类的成员变量,则必须当场赋值,否则编译会报错。

用来修饰一个方法:当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承

用来修饰类 :当用final修改类时,该类成为最终类,无法被继承(比如常用的String类就是最终类)

面向对象的三大特性

封装: 将实现的细节进行隐藏,不向外暴露,只向外面提供共有访问方法或者接口

继承:目的:子类继承父类中的全部非私有属性和行为,不能选择性的继承。子类可在此基础上添加新的属性和行为来满足需求
好处:提高代码的复用性和扩展性,向上抽取为父类,再分别继承即可。Java 只支持单继承

多态:多态是同一个行为具有多个不同表现形式或形态的能力
三个必要条件:继承、重写、父类引用指向子类对象 父类 对象名=new 子类( );

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值