Java基础知识总结 - 超详细篇收藏.pdf

所需积分/C币:31 2019-01-09 09:54:47 599KB PDF
55
收藏 收藏
举报

1,JDK:Java Development Kit,java的开发和运行环境,java的开发工具和jre。 2,JRE:Java Runtime Environment,java程序的运行环境,java运行的所需的类库+JVM(java虚拟机)。 3,配置环境变量:让java jdk\bin目录下的工具,可以在任意目录下运行,原因是,将该工具所在目录告诉了系统,当使用该工具时,由系统帮我们去找指定的目录。
a=a+b:a=8: b=a-b;b=3; a=a-b;a=5; 方法二: a =an b: // b=an b: //b=anbb=a a=a^b;∥/a=a^b^a=b 练习:高效的算出2*8=2<<3; 重载的定义是:在一个类中,如果出现了两个或者两个以上的同名函数,只要 它们的参数的个数,或者参数的类型不同,即可称之为该函数重载了 如何区分重载:当函数同名时,只看参数列表。和返回值类型没关系 重写:父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中 定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)o Java内存管理 Java内存管理:深入Java内存区域 Jaa与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面 的人想进去,墙里面的人却想出来。 概述: 对于从事C和C++程序开发的开发人员来说,在内存管理领域,他们既是拥有 最高权力的皇帝,又是从事最基础工作的屴动人民一既拥有每一个对象的"所有 权",又担负着每一个对象生命开始到终结的维护责任 对于Java程序员来说,在虚拟机的自动内存管理机制的帮助下,不再需要为 每一个new操作去写配对的 delete/ree代码,而且不容易出现内存泄漏和内存 溢出问题,看起来由虚拟机管理内存一切都很美好。不过,也正是因为Java 程序员把内存控制的权力交给了Java虚拟机,旦岀现内存泄漏和溢岀方面 的问题,如果不了解虚拟机是怎样使用内存的,那排查错误将会成为一项异常 艰难的工作。 运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同 的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随 着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立 和销毁。根据《Java虚拟机规范(第2版)》的规定,Java虚拟机所管理的 内存将会包括以下儿个运行时数据区域,如下图所小: 程序计数器 程序计数器( Program Counter Register)是一块较小的内存空间,它的 作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型 里(仅是概念模型,各种虚拟机可能会通过一些更髙效的方式去实现),字节 码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码 指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计 数器来完成。由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执 行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理 器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢 复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之 间的计数器互不影响,独立存储,我们称这类内存区域为"线程私有"的内 存。如果线程正在执行的是个Java方法,这个计数器记录的是正在执行的 虚拟机字节码指令的地址;如果正在执行的是№atve方法,这个计数器值则为 空( Undefined)。此内存区域是唯一一个在Java虚拟机规范中没有规定任何 OutofMemory Error情况的区域 Java虚拟机栈 与程序计数器一样,Java虚拟机栈( Java virtua| Machine stacks)也是 线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的 内存模型:每个方法被执行的时候都会同时创建一个栈帧( Stack frame)用 于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用 直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。 经常有人把Java内存区分为堆内存(Heap)和栈内存( Stack),这种分法比 较粗糙,Java内存区域的划分实际上远比这复杂。这种划分方式的流行只能说 明大多数程序员最关注的、与对象内存分配关系最密切的内存区域是这两块。 其中所指的"堆"在后面会专门讲述,而所指的"栈"就是现在讲的虚拟机栈,或者 说是虚拟机栈中的局部变量表部分 局部变量表存放了编译期可知的各种基本数据类型( boolean、byte、char、 short、int、 float、long、 double)、对象引用( reference类型),它不等同于 对象本身,根据不同的虚拟机实现,它可能是一个指向对象起始地址的引用指 针,也可能指向一个代表对象的句或者其他与此对象相关的位置)和 returnAddress类型(指向了一条字节码指令的地址)。 其中64位长度的long和 double类型的数据会占用2个局部变量空间 (Slot),其的数据类型只占用1个。局部变量表所需的内存空间在编译期 间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空 间是完全确定的,在方法运行期间不会改变局部变量表的大小。在Java虚拟 机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟 机所允许的深度,将抛出 StackOverflow Error异常;如果虚拟机栈可以动态扩 展(当前大部分的Java虚拟机都可动态扩展,只不过Jaa虚拟机规范中也允 许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出 OutofMemory Error异常。 本地方法栈 本地方法栈( Native method stacks)与虚拟机栈所发挥的作用是非常相 似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服 务,而木地方法栈则是为虚拟机使用到的 Native方法服务。虚拟机规范中对木 地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具 体的虚拟机可以自由实现它。甚至有的虚拟机(譬如 Sun Hotspot虚拟机)直 会抛出 StackOverflow Error和 OutofMemoryEr异, 接就把本地方法栈和虚拟机栈合二为。与虚拟机栈一样,本地方法栈区域也 Java堆 对于大多数应用来说,Java堆( Java Heap)是Java虚拟机所管理的内 存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时 创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这 里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数 组都要在堆上分配,但是随着JT编译器的发展与逃逸分析技术的逐渐成熟, 栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分 配在堆上也渐渐变得不是那么"绝对"了。 Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做"GC堆" ( Garbage Collected Heap,幸好国内没翻译成"垃圾堆")。如果从内存回收 的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆中还 可以细分为:新生代和老年代;再细致一点的有Eden空间、 From survivor空 间、 To Survivor空间等。如果从内存分配的角度看,线程共享的Java堆中可 能划分出多个线程私有的分配缓冲区( Thread loca| Allocation buffer, TLAB)。不过,无论如何划分,都与存放内容无关,无论哪个区域,存储的都 仍然是对象实例,进一步划分的目的是为了更好地回收内存,或者更快地分配 内存。在本章中,我们仅仅针对内存区域的作用进行讨论,Java堆中的上述各 个区域的分配和回收等细节将会是下一章的主题。 根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间 中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以 实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩 展来实现的(通过-mx和-Xms控制)。如果在堆中没有内存完成实例分配, 并且堆也无法再扩展时,将会抛出 OutofMemory Error异常。 方法区 方法区( Method area)与Java堆一样,是各个线程共享的内存区域,它 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代 码等数据。虽然Java虚拟机规范把方法区摧述为堆的一个逻辑部分,但是它 却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。 对于习惯在 Hotspot虚拟机上开发和部署程序的开发者来说,很多人愿意 把方法区称为"永久代" Permanent generation),本质上两者并不等价,仅仅 是因为 HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说 使用永久代来实现方法区而已。对于其他虚拟机(如 BEA JRockit、IBMJ9 等)来说是不存在永久代的概念的。即使是 Hot spot虚拟机本身,根据官方发 布的路线图信息,现在也有放弁永久代并"搬家"至 Native Memory来实现方法 区的规划了。 Java虚拟机规范对这个区域的限制非常宽松,除了和Java堆一样不需要 连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。 相对而言,垃馺收集行为在这个区域是比较少出现的,但并非数据进入了方法 区就如永久代的名字一样"永久"存在了。这个区域的内存回收目标主要是针对 常量池的回收和对类型的卸载,一般来说这个区域的回"成绩"比较难以令人 满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必 要的。在Sun公司的BUG列表中,曾出现过的石干个严重的BUG就是 由于低版本的 HotSpot虚拟机对此区域未完全回收而导致内存泄漏。根据Java 虚拟机规范的规定,当方法区无法满足内存分配需求时,将拋出 OutofMemoryError异常 运行时常量池 运行时常量池( Runtime constant pool)是方法区的一部分。C|ass文 件中除∫有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常 量池( Constant pool table),用于存放编译期生成的各种字面量和符号引 用,这部分内容将在类加载后存放到方法区的运行时常量池中。Java虚拟机 对 Class文件的每一部分(自然也包括常量池)的格式都有严格的规定,每 个字节用于存储哪种数据都必须符合规范上的要求,这样才会被虚拟机认可、 装载和执行。但对于运行时常量池,Java虚拟机规范没有做仼何细节的要求 不同的提供商实现的虚拟机可以按照自己的需要来实现这个内存区域。不 般来说,除了保存Cass文件中描述的符号引用外,还会把翻译出来的直接 引用也存储在运行时常量池中。运行时常量池相对于 Class文件常量池的另外 个重要特征是具备动态性,Java语言并不要求常量一定只能在编译期产生 也就是并非预置λ Class文件中常量池的内容才能进入方法区运行时常量池 运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便 是 String类的 intern()方法。既然运行时常量池是方法区的一部分,自然会受到 方法区内存的限制,当常量池无法再中请到内存时会抛出 OutOfMemoryError 异常。 对象访问 介绍完Java虚拟机的运行时数据区之后,我们就可以来探讨一个问题: 在Java语言中,对象访问是如何进行的?对象访问在Java语言中无处不在 是最普通的程序行为,但即使是最简单的访问,也会却涉及Java栈、Java 堆、方法区这三个最重要内存区域之间的关联关系,如下面的这句代码 Object obj= new Object(; 假设这句代码出现在方法体中,那" Object obj”这部分的语义将会反映到Java 栈的本地变量表中,作为一个 reference类型数据出现。而" new Object(y"这部 分的语义将会反映到Java堆中,形成一块存储了 Object类型所有实例数据值 ( Instance data,对象中各个实例字段的数据)的结构化内存,根据具体类型 以及虚拟机实现的对象内存布局( Object Memory Layout)的不同,这块内存 的长度是不固定的。另外,在Java堆中还必须包含能查找到此对象类型数据 (如对象类型、父类、实现的接口、方法等)的地址信息,这些类型数据则存 储在方法区中。 由于 reference类型在Java虚拟机规范里面只规定了一个指向对象的引 用,并没有定义这个引用应该通过哪种方式去定位,以及访问到Java堆中的 对象的具体位置,因此不同虚拟机实现的对象访问方式会有所不同,主流的访 问方式有两种:使用句柄和直接指针。如果使用句柄访问方式,Java堆中将 会划分出一块内存来作为句柄池, reference中存储的就是对象的句柄地址, 而句柄中包含了对象实例数据和类型数据各自的具体地址信息,如下图所示 如果使用的是直接指针访问方式,Java堆对象的布局中就必须考虑如何 放置访问类型数据的相关信息, reference中直接存储的就是对象地址,如下 图所示: 这两种对象的访问方式各有优势,使用句柄访问方式的最大好处就是 reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象 是非常普遍的行为)时只会改变句柄中的实例数据指针,而 reference本身不 需要被修改。使用直接指针访问方式的最大好处就是速度更快,它节省了一次 指针定位的时间开销,由于对象的访问在Java中非常频繁,因此这类开销积 少成多后也是一项非常可观的执行成本。就本书讨论的主要虚拟机Sun Hotspot而言,它是使用第二科方式进行对象访问的,但从整个软件开发的范 围来看,各种语言和框架使用勹柄来访问的情况也|分常见。 匿名对象使用场景: 1:当对方法只进行一次调用的时候,可以使用匿名对象 2:当对象对成员进行多次调用时,不能使用匿名对象。必须给对象起名字。 类中怎么没有定义主函数呢? 注意:主函数的存在,仅为该类是否需要独立运行,如果不需要,主函数是不 用定义的。 主函数的解释:保证所在类的独立运行,是程序的入口,被jm调用。 成员变量和局部变量的区别 1:成员变量直接定义在类中。 局部变量定义在方法中,参数上,语句中。 2:成员变量在这个类中有效 局部变量只在自己所属的大括号内有效,大括号结束,局部变量失去作用域。 3:成员变量存在于堆内存中,随着对象的产生而存在,消失而消失。 局部变量存在于栈内存中,随着所属区域的运行而存在,结束而释放 构造函数:用于给对象进行初始化,是给与之对应的对象进行初始化,它具有 针对性,函数中的一种。 特点 1:该函数的名称和所在类的名称相同。 2:不需要定义返回值类型。 3:该函数没有具体的返回值。 记住:所有对象创建时,都需要初始化才可以使用。 注意事项:一个类在定义时,如果没有定义过构造函数,那么该类中会白动生 成一个空参数的构造函数,为了方便该类创建对象,完成初始化。如果在类中 自定义了构造函数,那么默认的构造函数就没有了。 个类中,可以有多个构造函数,因为它们的函数名称都相同,所以只能通过 参数列表来区分。所以,一个类中如果出现多个构造函数。它们的存在是以重 载体现的。 构造代码块和构造函数有什么区别? 构造代码块:是给所有的对象进行初始化,也就是说,所有的对象都会调用 个代码块。只要对象一建立。就会调用这个代码块。 构造函数:是给与之对应的对象进行初始化。它具有针对性。 执行顺序:(优先级从高到低。)静态代码块>mian方法>构造代码块>构造方 法。其中静态代码块只执行一次。构造代码块在每次创建对象是都会执行。 静态代码块的作用:比如我们在调用C语言的动态库时会可把.o文件放在此 处 构造代码块的功能:(可以把不同构造方法中相同的共性的东西写在它里 面)。例如:比如不论任何机型的电脑都有开机这个功能,此时我们就可以把 这个功能定义在构造代码块内。 Person p= new P( arson: 创建一个对象都在内存中做了什么事情? 1:先将硬盘上指定位置的 Person. class文件加载进内存 2:执行main方法时,在栈内存中开辟了man方法的空间(压栈-进栈),然后 在main方法的栈区分配了一个变量p 3:在堆内存中开辟一个实体空间,分配了一个内存首地址值。neW 4:在该实体空间中进行属性的空间分配,并进行了默认初始化 5:对空间中的属性进行显示初始化。 6:进行实体的构造代码块初始化。 7:调用该实体对应的构造函数,进行构造函数初始化。() 8:将首地址赋值给p,p变量就引用了该实体。(指向了该对象) 封装(面向对象特征之一):是指隐臧对象的属性和实现细节,仅对外提供公 共访问方式 好处:将变化隔离;便于使用;提高重用性;安全性。 封装原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方 法对其访问。 this:代表对象。就是所在函数所属对象的引用。 thi到底代表什么呢?哪个对象调用了this所在的函数,this就代表哪个对 象,就是哪个对象的引用。 开发时,什么时候使用this呢? 在定义功能时,如果该功能内部使用到」∫调用该功能的对象,这时就用this来 表示这个对象 ths还可以用于构造函数间的调用。 调用格式:this(实际参数); this对象后面跟上.调用的是成员属性和成员方法(一般方法); this对象后面跟上0)调用的是本类中的对应参数的构造函数。 注意:用this调用构造函数,必须定义在构造函数的第一行。因为构造函数是 用于初始化的,所以初始化动作一定要执行。否则编译失败。 static:★★★关键字,是一个修饰符,用于修饰成员(成员变量和成员函数) 特点: 1、 static变量 按照是否静态的对类成员变量进行分类可分两种:一种是被 static修饰的变 量,叫静态变量或类变量;一种是没有被 static修饰的变量,叫实例变量。 两者的区别是: 对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次 内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方 便),当然也可以通过对象来访问(但是这是不推荐的)。 对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量 可以在内存中有多个拷贝,互不影响(灵活)。 2、静态方法 静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法 中不能用this和 super关键字,不能直接访问所属类的实例变量和实例方法(就 是不带 static的成员变量和成员成员方法),只能访问所属类的静态成员变量和 成员方汯。因为实例成员与特定的对象关联!这个需要去理解,想明白其中的 道理,不是记忆!!! 因为 static方法独立于任何实例,因此 static方法必须被实现,而不能是抽 象的 abstract 3、 static代码块 static代码块也叫静态代码块,是在类中独立于类成员的 static语句块,可以 有多个,位置可以随便放,它不在任何的方法体内,JM加载类吋会执行这些 静态的代码块,如果 static代码块有多个,JVM将按照它们在类中出现的先后 顶序依次执行它们,每个代码块只会被执行一次 4、 static和fna一块用表小什么 static fina用来修饰成员变量和成员方法,可简单理解为"全局常量"! 对于变量,表示一旦给值就不可修改,并且通过类名可以访问。 对于方法,表示不可覆盖,并且可以通过类名直接访问。 备注: 1,有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有 数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静 态时,必须要明确,这个数据是否是被对象所共享的。 2,静态方法只能访问静态成员,不可以访问非静态成员。

...展开详情
试读 33P Java基础知识总结 - 超详细篇收藏.pdf
立即下载 低至0.43元/次 身份认证VIP会员低至7折
一个资源只可评论一次,评论内容不能少于5个字
  • 分享达人

    成功上传6个资源即可获取
关注 私信 TA的资源
上传资源赚积分or赚钱
    最新推荐
    Java基础知识总结 - 超详细篇收藏.pdf 31积分/C币 立即下载
    1/33
    Java基础知识总结 - 超详细篇收藏.pdf第1页
    Java基础知识总结 - 超详细篇收藏.pdf第2页
    Java基础知识总结 - 超详细篇收藏.pdf第3页
    Java基础知识总结 - 超详细篇收藏.pdf第4页
    Java基础知识总结 - 超详细篇收藏.pdf第5页
    Java基础知识总结 - 超详细篇收藏.pdf第6页
    Java基础知识总结 - 超详细篇收藏.pdf第7页

    试读结束, 可继续读3页

    31积分/C币 立即下载 >