java笔记

Java基础笔记

Java概述

1.java在1995年由Sun Microsystems推出经过23年迭代,至今发展到JDK11的版本。
2.java的特点是面向对象、简单、跨平台。
3.将源文件编译成字节码文件(.class)再交与不同平台进行解释执行。
4.JVM虚拟机、JRE运行环境、JDK开发环境。
5.Windows下的DOS命令:windows+R、d:、cd xxx、cd…、dir、exit。
6.开发步骤
a)创建.java结尾的源文件。
b)编写程序(class、main、逻辑代码)
c)编译:javac 文件名.java (文件名.后缀名 )
d)运行:java 类名 (无后缀)
7.同一个源文件中可以定义多个类
a)编译后,每个类都会生成独立的 .class文件。
b)一个类中,只能由一个主函数,每个类都可以有自己的主函数。
c)public 修饰的类称为公开类,要求类名必须与文件名称完全相同,包括大小写。
d)一个源文件中,只能有一个公开类。
8.通过package关键字在源文件的首行进行包的定义
a)带包编译:java -d .xxx.java
b) 带包运行:java xxx.xxx.xxxClass
c) 经验:域名倒置
9.层级之间必须缩进,一行只写一句代码。
10.单行注释 // 多行注释 /* / 文档注释 /* */
11.javadoc -d . xxx.java
12.类名:每个单词的首字母大写
13.函数名、变量名,首字母小写,拼接词首字母大写
14.包名全小写
15.常量全大写,使用“_”进行分割。

前置知识

1.什么是内存?
内存是瞬时状态下的存储空间,造假高、工业上的设计瓶颈。
Java虚拟机(java程序)默认分配到的物理内存是1/8。
bit-> Byte->KB->MB->GB->TB->PB->EB->ZB->YB->BB->NB->DB
2.变量:
a)概念:计算机内存中一块存储空间,也是存储数据的基本单元。
b)组成:数据类型、变量名、值。
c)定义:先声明、再赋值。(声明并赋值、同时声明多个同类型变量)
d)注意:变量需要先赋值,再使用;否则:错误,尚未初始化。
3.数据类型:
a)二进制表现形式 byte==8bit
b)二进制与十进制的转换
c)扩展:程序运行过程中,瞬时空间(局部变量表 -Slot 槽)
d)整数:
byte 1个字节 short 2个字节
int 4个字节 long 8个字节
e)小数:
float 4个字节 单精度 将小数存入float类型变量中时,追加F
double 8个字节 双精度
近似值:
float 32bit 1bit 符号位 8bits指数位 23bits尾数位
double 64bit 1bit 符号位 11bits指数位 52bits尾数位
f)boolean:
取值:ture/false
除了直接赋值true或false,还可以赋予比较后的表达式的结果
g)character
英文对应的ASCCI编码,中文或其他国家语言对应的Unicode编码。
每个字符都有对应的整数表现形式。
赋值: char c1 = ‘A’;或者 char c2 = 65;或者 char c3 = ‘\u0041’;
4.选择结构、分支结构、循环结构
a)是否使用循环,及使用的步骤!
明确是否需要使用循环。
分析循环条件和循环操作是什么。 操作:相加求和:条件: 1~100
循环结构的选型。循环结构的选型。 循环次数是否明确、首次是否需要入口条件
b)while 与 do while 的对比:
首次即有入口条件,先判断,再执行。适用于循环次数明确的场景。
首次没有入口条件,先执行,再判断。适用于循环次数不明确的场景。
c)for(初始;条件;迭代) {操作;}
d)流程控制关键字
break 跳出整个循环
continue 跳出一次(本次)循环
e)基本if选择结构:if(条件){操作}
if else选择结构:if(条件){操作}else{操作} 只执行其中一个
多重if选择结构:if(条件){操作}
else if(条件){操作}
else if(条件){操作}
else{操作}
注意:相互排斥,有一个执行,其他均不执行,适用于区间判断。
嵌套if选择结构: if(外层){
if(内层){ }
else{ }
}else{ 外层}
注意:外层条件满足时,再判断内层,嵌套格式正确下,支持任意组合。
f)分支结构 switch(变量|表达式){
case 值1:逻辑代码1;break;

case 值n:逻辑代码n;break;
default:未满足时的逻辑代码;
}
可判断类型:byte、short、int、char、string(JDK7+)
变量中的值等于n,则执行逻辑代码n
如果变量中的值没有匹配的case值时,执行default中的逻辑代码。
当匹配的case被执行后,并不会自动退出整个结构,break关键字可以在匹配的case执行后,直接跳出整个结构。
g)局部变量
概念: 声明在函数内部的变量必须先赋值再使用。
作用范围:定义行开始到所在的代码块结束。
注意:多个变量,在重合的作用范围内,不可出现重名(命名冲突)

函数

概念:实现特定功能的一段代码,可反复使用。
定义语法:public static void 函数名( ){
//函数主体
}
经验:将需要在多个位置重复使用的一组代码,定义在函数内。
定义的位置:函数定义在类的内部,与main函数并列。
函数的调用:在需要执行函数代码的位置,通过函数名称进行调用。
注意:调用函数时,会优先执行函数内部的代码,结束后,返回到函数调用处,继续向下执行。
函数的参数:函数与调用者之间需要数据的交互,调用者必须提供必要的数据,才能使函数完成相应的功能。调用函数时,所传入的数据被称为“参数”。
形参:等价于局部变量的声明
实参:等价于局部变量的赋值
返回值与返回值类型:public static 返回值类型 函数名称(参数列表){
//函数主题
return value;//返回值
}
调用语法:变量 = 函数名称( );变量类型与返回值类型一致。
注意: 一个函数只能有一个返回值。return 结束当前函数直接返回。

数组

概念:一组连续的储存空间,存储多个相同的数据类型。
特点:类型相同、长度固定。
数组的使用:数组中的每个数据格被称为“数组元素”。对每个元素进行赋值或取值的操作被称为“元素的访问”。访问元素时,需要使用“下标”(从0开始,依次+1,自动生成)。访问的语法:数组名【下标】;
下标范围:有效下标范围:0~数组长度-1.访问无效下标,会导致数组下标越界。
数组遍历:数组名.length 可动态获得数组长度。使用循环变量i充当下标逐一访问数组元素
数组的默认值:整数:0、小数:0.0、字符:’\u0000’、布尔:false、其他:null
数组创建语法:
1)先声明再分配:数组类型【】数组名;数组名 = new 数据类型【长度】;
2)声明并分配空间:数据类型【】 数组名 = new 数据类型【长度】;
3) 声明并赋值(繁):数据类型【】数组名 = new 数据类型【】{value1,value2,value3};
4)声明并赋值(简):数组类型【】数组名 = {value1,value2,value3};//显式初始化,注意:不可换行
数组的扩容:
创建数组时,必须显示指定长度,并在创建之后不可更改长度。
扩容的思路:1.创建大于原数组长度的新数组。2.将原数组中的元素依次复制到新数组中。
复制的方式;
1)循环将原数组中所有元素逐一赋值给新数组。
2)System.arraycopy(原数组,原数组起始,新数组,新数组起始,长度);
3)java.util.Arrays.copyOf(原数组,新长度);//返回带有原值的新数组。
地址的替换:
数组作为引用类型之一,其变量中存储的是数组的地址。
完成元素复制后,需要将新数组地址,赋值给原变量进行替换。
数组类型的参数:在定义一个函数时定义一个数组形参,在方法调用时,将实参nums中的地址赋值给形参,此时二者指向同一个数组。
数组类型的返回值:在定义函数时定义相应的返回值类型,例如传入int【】类型的数组,对数组进行扩容,那么需要返回一个新数组,新数组中保留原有数据。
可变长参数:
概念:可接受多个同类型实参,个数不限,使用方式与数组相同。
语法:函数名(数据类型… 形参名)//必须定义在形参列表的最后面,且只能有一个。
数组的排序:
1)冒泡排序:相邻两个数值比较大小,互换位置。
2)选择排序:固定值与其他值依次比较大小,互换位置。
3)JDK排序:java.util.Arrays.sort(数组名);//JDK提供(升序)
二维数组:
概念:一维数组中的一维数组;数组中的元素,还是数组。
当查找某个元素时需要两个下标,前一个代表行(高维下标),后一个代表列(低维下标)。二维数组相当于一个多行多列的表格。
高维数组中的每一个元素,保存了低维数组的地址。例如:array【】【】访问array【0】等于访问OX000342
访问低维长度:array【0】.length首个低维数组的长度。array【0】【0】首个低维数组的首个元素。
二维数组创建语法:
1)先声明再分配空间:数据类型【】【】 数组名;数组名 = new 数据类型【高维长度】【低维长度】;
2)声明并分配空间:
数据类型【】【】 数组名= new 数据类型【高维长度】【低维长度】;
3)声明并赋值(繁)
数据类型【】【】数组名=new 数据类型【高维长度】【】//不规则数组,自行new低维数组
4)声明并赋值(简)
数据类型【】【】数组名={ {v1,v2,v3},{v4,v5},(v6) }//显示初始化

面向对象

什么是程序:程序是为了模拟现实世界,解决现实问题而使用计算机语言编写的指令集合。
什么是对象:面向对象思想
一切客观存在的事物都是对象,万物皆对象。
任何对象,一定具有自己的特征和行为。
对象:1.特征:称为属性,一般为名词,代表对象有什么。
2.行为:称为方法,一般为动词,代表对象能做什么。
程序中的对象:如何使用程序模拟现实世界,解决现实问题?
1.首先,在程序当中,必须具有和现实中相同的对象,用以模拟现实世界。
2.然后,使用程序中的对象代表现实中的对象,并执行操作,进而解决现实问题。
现实中的对象多数来源于”模板“,程序中的对象也应该具有”模板“叫类。
类的定义:1.属性:通过变量表示,又称为实例变量。
2.语法:数据类型 属性名;
3.位置:类的内部,方法的外部。
方法:通过函数表示,又称实例方法。
语法:public 返回值类型 方法名(形参){
//方法的主体
}
对象的创建:
1.将对象保存在相同类型的变量中,此变量称为”对象名“或”引用名“
2.访问属性:对象名.属性名=值;//赋值
3.访问属性:对象名.属性名;//取值
4.调用方法:对象名.方法名();
类与对象的关系:
类:模板(一个)--------》创建 对象【实例】多个
类:定义了对象应具有的特征和行为,类是对象的模板。
对象:拥有多个特征和行为的实体,对象是类的实例。
实例变量与局部变量的区别:
局部变量:
定义位置:方法或方法的结构当中
默认值:无默认值
使用范围:从定义行到包含其结构结束
命名冲突:不允许重名
成员变量:
定义位置:类的内部,方法的外部
默认值:字面值(与数组相同)
使用范围:本类有效
命名冲突:可与局部变量重名,局部变量优先
实例方法:
对象的实例方法包含两部分:方法的声明和方法的实现。
方法的声明:代表对象能做什么。组成:修饰符 返回值类型 方法名(形参列表)
方法的实现:代表对象怎么做:即如何实现对应的功能。组成:{}

方法重载:
重载:一个类中定义多个相同名称的方法。
要求:1.方法名称相同。
2.参数列表不同(类型、个数、顺序)。
3.与访问修饰符、访问类型无关。
调用带有重载的方法时,需要根据传入的实参去找到与之匹配的方法。
好处:屏蔽使用差异,灵活、方便。
注意:只是参数名称不同,并不能构成方法的重载。
构造方法:类中的特殊方法,主要用于创建对象。
特点:名称与类名完全相同
没有返回值类型。
创建对象时,触发构造方法的调用,不可通过句点手动调用。
注意:如果没有在类中显式定义构造方法,则编译器默认提供无参构造方法。如已手动添加有参构造方法,则无参构造方法不在默认提供,可根据需求自行添加。
对象创建过程: 通过new关键字 触发对象创建
1.内存中开辟对象空间
2.为各个属性赋予初始值
3.执行构造方法中的代码
4.【将对象的地址赋值给变量】
对象的的内存分配:
存储对象的变量s(引用)中保存对象的地址,通过变量中的地址访问对象的属性和方法。
构造方法重载:构造方法也可以重载,遵循重载规则。创建对象时,根据传入参数,匹配对应的构造方法。
构造方法为属性赋值:
创建对象的同时,将值传入构造方法,由构造方法为各个属性赋值
this关键字:类是模板,可服务于此类的所有对象;this是类中的默认引用,代表当前实例;当类服务于某个对象时,this则指向这个对象。
this第一种用法:调用实例属性、实例方法。
当实例变量和局部变量重名时,优先访问局部变量;此时,如需要访问实例变量,需要增加this.前缀。不存在重名时,则可省略this。
this第二种用法:调用本类中的其他构造方法。
在构造方法中,调用本类的其他构造方法,即可复用构造方法中的逻辑代码。this():调用无参构造。this(实参):调用有参构造。注意:必须在构造方法的首行。

三大特性

一、封装
封装的必要性:在对象的外部,为对象的属性赋值,可能存在非法的数据录入。
什么是封装:
概念:尽可能的隐藏对象的内部实现细节,控制对象的修改及访问的权限。
访问修饰符:private(可将属性修饰为私有,仅本类可见)
公共访问方法:以访问方法的形式,进而完成赋值与取值操作。但依然没有解决到非法数据录入。
过滤有效数据:在公共的访问方法内部,添加逻辑判断,进而过滤非法数据,以保证数据安全。
get/set方法是外界访问对象私有属性的唯一通道,方法内部可对数据进行检测和过滤。
二、继承
程序中的继承:
程序中的继承,是类与类之间特征和行为的一种赠与或获取。
两个类之间的继承关系,必须满足“is a”的关系。例如:Dog is an Animal。
父类的抽取:
在一组相同或类似的类中,抽取出共性的特征和行为,定义在父类中,实现重用。
继承:
语法:class 子类 entends 父类{ }//定义子类时,显示继承父类
应用:产生继承关系之后,子类可以使用父类中的属性和方法,也可定义子类独有的属性和方法。
好处:既提高代码的复用性,又提高代码的可扩展性。
继承的特点:Java为单继承,一个类只能有一个直接父类,但可以多级继承,属性和方法逐级叠加。
不可继承:
构造方法:类中的构造方法,只负责创建本类对象,不可继承。
private修饰的属性和方法:访问修饰符的一种,仅本类可见。
父子类不在同一个package中时,default修饰的属性和方法:访问修饰符的一种,仅同包可见。
java笔记_第1张图片
方法的覆盖:
方法覆盖原则:方法名称、参数列表、返回值类型必须与父类相同
访问修饰符可与父类相同或是比父类更宽泛。
方法覆盖执行:子类覆盖父类方法后,调用时优先执行子类覆盖后的方法。
super关键字:
在子类中,可直接访问从父类继承到的属性和方法,但如果父子类的属性或方法存在重名(属性遮蔽、方法覆盖)时,需要加以区分,才可专项访问。
super关键字可在子类中访问父类的方法。使用super. 的形式访问父类的方法,进而完成在子类中的复用;再叠加额外的功能代码,组成新的功能。
父子类的同名属性不存在覆盖关系,两块空间同时存在(子类遮蔽父类属性),需要使用不同的前缀进行访问。
继承中的对象创建:
在具有继承关系的对象创建中,构造子类对象会先构造父类对象。
由父类的共性内容,叠加子类的独有内容,组合成完整的子类对象。
java笔记_第2张图片
super调用父类无参构造:
super():表示调用父类无参构造方法,如果没有显示书写,隐式存在于子类构造方法的首行
super(实参):表示调用父类有参构造方法。
this或super使用在构造方法中时,都要求在首行。当子类构造中使用了this()或 this(实参),既不可再同时书写super()或 super(实参),会由this()指向的构造方法完成super()的调用。即同一个子类构造方法中super() this()不可同时存在。
三、多态
程序中的多态:
概念:父类引用指向子类对象,从而产生多种形态。
二者具有直接或间接的继承关系时,父类引用可指向子类对象,即形成多态。
父类引用仅可调用父类所声名的属性和方法,不可调用子类独有的属性和方法。
多态中的方法覆盖:
如子类覆盖了父类中的方法,以父类引用调用此方法时,优先执行子类中的覆盖后的方法,否则执行父类中的方法。
多态的应用:
场景一:使用父类作为方法形参实现多态,使方法参数的类型更为宽泛。
场景二: 使用父类作为方法的返回值实现多态,使方法可以返回不同子类对象。
向上转型(装箱)
父类引用中保存真实子类对象,称为向上转型(即多态核心概念)
注意:仅可调用父类中所声明的属性和方法
向下转型(拆箱)
将父类引用中的真实子类对象,强行转回子类本身类型,称为向下转型。
注意:只有转回子类真实类型,才可调用子类独有的属性和方法。
类型转换异常:
向下转型时,如果父类引用中的子类对象类型和目标类型不匹配,则会发生类型转换异常。
instanceof关键字:
向下转型前,应判断引用中的对象真实类型,保证类型转换的正确性。
语法:引用 instanceof 类型 //返回值boolean类型结果

三个修饰符

一、static
实例属性:实例属性是每个对象各自持有的独立的空间(多份),对象单方面修改,不会影响其他对象。
静态属性是整个类公共持有的共享空间(一份),任何对象修改,都会影响其他对象。
什么是静态:
静态可以修饰属性和方法。
称为静态属性(类属性)、静态方法(类方法)。
静态成员是全类所有的对象共享的成员。
在全类中只有一份,不因创建多个对象而产生多份。
不必创建对象,可直接通过类名访问。
静态方法允许直接访问静态成员。
静态方法不能直接访问非静态成员
静态方法中不允许使用this或是super关键字。
静态方法可以继承,不能覆盖,没有多态。
动态代码块:
创建对象时,触发动态代码块的执行,执行地位:初始化属性之后、构造方法代码之前。作用:可为实例属性赋值,或必要的初始行为。
类加载:
JVM首次使用某个类时,需要通过CLASSPATH查找该类的.class文件。
将.class文件中对类的描述信息加载到内存中,进行保存。如:包名、类名、父类、属性、方法、构造方法…
加载时机:
创建对象、创建子类对象、访问静态属性、调用静态方法、Class.forName(“全限定名”)
静态代码块:
类加载时,触发静态代码块的执行(仅一次)。执行地位:静态属性初始化之后。作用:可为静态属性赋值,或必要的初始行为。
注意:方法只有被调用才会被执行。
带有继承的对象创建过程:
父类静态属性、父类静态代码块、子类静态属性、子类静态代码块、父类实例属性、父类动态代码块、父类构造方法、子类实例属性、子类动态代码块、子类构造方法
二、abstract
不该被创建的对象:Animal仅是一种会吃会睡的对象,再无其他行为,不够具体、不够完整。程序是用来模拟现实世界、解决现实问题的,现实世界中存在的都是“动物”具体的子类对象,并不存在“动物”对象,所以Animal不应该被独立创建成对象。
抽象类:
应用:abstract修饰的类,此类不能new对象。抽象类意为不完整的类、不够具体的类。
作用:可被子类继承,提供共性属性和方法。可声明为引用,强制使用多态。
经验:抽象父类,可作为子类的组成部分,依附于子类对象存在,由父类共性+子类独有,组成完整的子类对象。
不该被实现的方法:
狗的吃方法应该输出:狗在吃骨头
猫的吃方法应该输出:猫在吃鱼
父类提供的方法很难满足子类不同的需求,如不定义,则表示所有动物不会吃、睡。如定义,略显多余,多数会被子类覆盖。
注意:方法的声明必要,方法的实现多余。
抽象方法:
被abstract修饰的方法,称为抽象方法,只有方法声明,没有方法实现({}的部分)。意为不完整的方法,必须包含在抽象类中。
产生继承关系后,子类必须覆盖父类中所有的抽象方法,否则子类还是抽象类。
三、final

什么是最终:最后的,不可更改的
final可修饰的内容:
类(最终类)、方法(最终方法)、变量(最终变量)
final修饰的类:此类不能被继承。
String、Math、System均为final修饰的类,不能被继承。
final修饰的方法:此方法不能被覆盖。
意为最终方法,不支持子类以覆盖的形式修改。
final变量:
final修饰的变量:此变量值不能被改变(常量)。所有的final修饰的变量只能赋值一次,值不允许改变。
实例常量:final String name;
实例常量不再提供默认值,必须手动赋予初始值。赋予时机:显式初始化、动态代码块、构造方法
注意:如果在构造方法中为实例常量赋值,必须保证所有的构造方法都能对其正确赋值。
静态常量:static final String name;
静态常量不再提供默认值,必须手动赋予初始值。赋予时机:显式初始化、静态代码块。
对象常量:final int num = 100;
final Student s = new Student();
final修饰基本类型:值不可变
final修饰引用类型:地址不可变

接口

接口的语法:
接口相当于特殊的抽象类,定义方式、组成部分与抽象类类似。
使用interface关键字定义接口,没有构造方法,不能创建对象,只能定义:公开静态常量、公开抽象方法。
interface MyInterface{
public static final String FIELD=“value”;
public abstract void method();}

与抽象类的异同:
相同:可编译成字节码文件。
不能创建对象
可以作为引用类型
具备Object类所定义的方法
不同:所有属性都是公开静态常量,隐式使用public static final 修饰。
所有方法都是公开抽象方法,隐式使用public abstract修饰。
没有构造方法、动态代码块、静态代码块。
什么是接口:
微观概念:接口是一种能力和约束
接口的定义:代表某种能力
方法的定义:能力的具体要求
经验:Java为单继承,当父类的方法无法满足子类需求时,可实现接口扩充子类能力。
接口支持多实现,可为类扩充多种能力。
接口的规范:
任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类为抽象类。
实现接口中的抽象方法时,访问修饰符必须是public。
接口引用:
同父类一样,接口也可声明为引用,并指向实现类对象。
注意:
仅可调用接口中所声明的方法,不可调用实现类中的独有方法。(多态)
可强转回实现类本身类型,进行独有方法调用。
什么是接口:
宏观概念:接口是一种标准。
回调原理:
程序员(工具的调用者)—》接口的使用者(工具)—》接口(标准)—》程序员(接口的实现者)

常用类

一、内部类:
内部类分为:成员内部类、静态内部类、局部内部类、匿名内部类
什么是内部类:在一个类的内部再定义一个完整的类。
特点:编译之后可生成独立的字节码文件。
内部类可直接访问外部类的私有成员,而不破坏封装。
可为外部类提供必要的内部功能组件。
成员内部类:在类的内部定义,与实例变量、实例方法同级别的类。
外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象。
Outer out = new Outer();
Inner in = out.new Inner();
当外部类、内部类存在重名属性时,会优先访问内部类属性。
成员内部类不能定义静态成员。
静态内部类:
不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。
只能直接访问外部类的静态成员(实例成员需实例化外部类对象)
Outer.Inner inner = new Outer.Inner();
Outer.Inner.show();
局部内部类:
定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。
局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final。
限制类的使用范围。
匿名内部类:
没有类名的局部内部类(一切特征都与局部内部类相同)
必须继承一个父类或者实现一个接口。
定义类、实现类、创建对象的语法合并,只能创建一个该类的对象。
优点:减少代码量。
缺点:可读性较差
二、Object类
超类、基类,所有的类的直接或间接父类。位于继承树的最顶层。
任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承。
Object类中所定义的方法,是所有对象都具有的方法。
Object类型可以存储任何对象。作为参数,可接受任何对象。作为返回值,可返回任何对象。
getClass()方法:
public final Class getClass(){}
返回引用中存储的实际对象类型。
应用:通常用于判断两个引用中实际存储对象类型是否一致。
hashCode()方法
public int hashCode(){}
返回该对象的十六进制的哈希码值
哈希算法根据对象的地址或字符串或数字计算出来的int类型的数值
哈希码并不唯一,可保证相同对象返回相同的哈希码,尽量保证不同对象返回不同的哈希码。
toString()方法:
public String toString(){}
返回该对象的字符串表示(表现形式)。
可以根据程序需求覆盖该方法,如:展示对象各个属性值。
equals()方法:
public boolean equals (Object obj){}
默认实现为(this == obj),比较两个对象地址是否相同。
可进行覆盖,比较两个对象的内容是否相同。
equals()方法覆盖步骤:
比较两个引用是否指向同一个对象。
判断obj是否为null
判断两个引用指向的实际对象类型是否一致。
强制类型转换
依次比较各个属性是否相同
finalize()方法:
当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列。
垃圾对象:没有有效引用指向此对象时,为垃圾对象
垃圾回收:由GC销毁垃圾对象,释放数据存储空间。
自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象。
手动回收机制:使用System。gc();通知JVM执行垃圾回收。
三、包装类
什么是包装类?
基本数据类型所对应的引用数据类型。
Object可统一所有数据,包装类的默认值是null
Byte、Short、integer、Long、Float、Double、Boolean、Character
byte、short、int、long、float、double、boolean、char
类型转换与装箱、拆箱:
8种包装类提供不同类型间的转换方式:
Number父类中提供的6个共性方法。
parseXXX()静态方法
valueOf()静态方法。
注意:需保证类型兼容,否则抛出NumberFormatException异常。
JDK 5.0之后,自动装箱、拆箱。基本数据类型和包装类自动转换
整数缓冲区:java预先创建了256个常用的整数包装类型对象。在实际应用当中,对已创建的对象进行复用。
四、String类
字符串是常量,创建之后不可改变。
字符串字面值存储在字符串池中,可以共享。
String s =“hello”;产生一个对象,字符串池中存储。
String s = new String(“hello”);//产生两个对象,堆、池各存储一个。
可变字符串:
StringBuffer:可变长字符串,JDK1.0提供,运行效率慢、线程安全
StringBuilder:可变长字符串,JDK5.0提供,运行效率快、线程不安全
BigDecimal:
很多实际应用中需要精确运算,而double是近似值存储,不在符合要求,需要借助BigDecimal
位置:Java.math包中。
作用:精确计算浮点数。
创建方式:Big Decimal bd=new BigDecimal(“1.0”);
进行除法运算时,如果不能准确的计算出结果时需要指定保留的位数和取舍方式。
除法:BigDecimal(BigDecimal bd,int scal ,RoundingMode mode)
参数sca:指定精确到小数点后几位。
参数mode:指定小数部分的取舍模式,通常采用四舍五入的模式。取值为BigDecimal.ROUND_HALF_UP

集合

概念:对象的容器,存储对象的对象,可代替数组。
特点:容器的工具类,定义了对多个对象进行操作的常用方法。
位置:Java.util.*;
Collection体系集合:
该体系结构的根接口,代表一组对象,称为”集合“。
List接口的特点:有序、有下标、元素可重复
Set接口的特点:无序、无下标、元素不能重复
Collection父接口:
特点:代表一组任意类型的对象,无序、无下标。
一、List集合
List子接口:有序、有下标、元素可以重复。
List实现类:
ArrayList:数据结构实现,查询快、增删慢;JDK1.2版本,运行效率快、线程不安全。必须开辟连续空间。
Vector:数组结构实现,查询快、增删慢;JDK1.0版本,运行效率慢、线程安全。
LinkdList:链表结构实现,增删快,查询慢。无需开辟连续空间。
泛型集合:
概念:参数化类型,类型安全的集合,强制集合元素必须一致。
特点:编译时即可检查,而非运行时抛出异常
访问时,不必类型转换(拆箱)。
不同泛型之间引用不能相互赋值,泛型不存在多态。
Colletions工具类:
概念:集合工具类,定义了除了存取以外的集合常用方法。
二、Set集合:
Set子接口:无序、无下标、元素不可重复。
方法:全部继承自Collection中的方法。
Set实现类:
HashSet:基于HashCode实现元素不重复。当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入。
TreeSet:基于排列顺序实现元素不重复。实现了SortedSet接口,对集合元素自动排序。元素对象的类别必须实现Comparable接口,指定排序规则。通过CompareTo方法确定是否为重复元素。
三、Map体系集合
Map结构:
Map接口的特点:
1.用于存储任意键值对
2.键:无序、无下标、不允许重复(唯一)
3.值:无序、无下标、允许重复
Map父接口:
特点:存储一对数据,无序、无下标,键不可重复,值可重复。key重复则覆盖原值。
Map集合的实现类:
HashMap:JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value。
Hashtable:JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value
Properties:Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。
TreeMap:实现了SortedMap接口(是Map的子接口),可以对key自动排序。

异常

什么是异常:
概念:程序在运行过程中出现的特殊情况。
异常处理的必要性:
任何程序都可能存在大量的未知问题、错误;如果不对这些问题进行正确处理,则可能导致程序的中断,造成不必要的损失。
异常的分类:
Throwable:可抛出的,一切错误或异常的父类,位于Java.lang包中。
Error:JVM、硬件、执行逻辑错误,不能手动处理
Exception:程序在运行和配置中产生的问题,可处理。
Runtim}eException:运行时异常,可处理,可不处理。
CheckedException:受查异常,必须处理。
异常的产生:
自动抛出异常:当程序在运行时遇到不符合规范的代码或结果时,会产生异常。
手动抛出异常:语法:thow new 异常类型(”实际参数“)
产生异常结果:相当于遇到return语句,导致程序因异常而终止。
异常的传递:
按照方法的调用链反向传递,如始终没有处理异常,最终会由JVM进行默认异常处理(打印堆栈跟踪信息)
受查异常:throws声明异常,修饰在方法参数列表后端。
运行时异常:因可处理可不处理,无需声明异常
常见异常处理结构:
1.try{} cath{}
2.try{} cath{} catch{}
3.try{} cath{} finally{}
4.try{} cath{} cath{} finally{ }
5.try{ } finally{ }
注:多重catch,遵循从子(小)到父(大)的顺序,父类异常在最后。
自定义异常:
需继承自Exception或Exception的子类,常用RuntimeException。
必要提供的构造方法:
无参数构造方法、String message无参的构造方法
方法覆盖:
带有异常声明的方法覆盖:
方法名、参数列表、返回值类型必须和父类相同。
子类的访问修饰符和父类相同或是比父类更宽
子类中的方法,不能抛出比父类更多、更宽的异常。

多线程

什么是进程:
程序是静止的,只有真正运行时的程序,才被称为进程。单核CPU在任何时间点上,只能运行一个进程;宏观并行、微观串行。
什么是线程:
被称为轻量级进程。程序中的一个顺序控制流程,同时也是CPU的基本调度单位。进程由多个线程组成,彼此间完成不同的工作,交替执行,称为多线程。
迅雷是一个进程,当中的多个下载任务即是多个线程。
Java虚拟机是一个进程,当中默认包含主线程(Main),可通过代码创建多个独立线程,与Main并发执行。
线程的组成:
任何一个线程都具有基本的组成部分:
1.CPU时间片:操作系统(iOS)会为每个线程分配执行时间。
2.运行数据:
堆空间:存储线程需使用的对象,多个线程可以共享堆中的对象。
栈空间:存储线程需要使用的局部变量,每个线程都拥有独立的栈。
3.线程的逻辑代码
创建线程(1)
创建一个类继承Thread类,覆run()方法、创建子类对象、调用start()方法
MyThread t1 = new MyThread();t1.start();
创建线程(2)
创建一个类实现Runnable接口、覆盖run()方法、创建实现类对象、创建线程对象、调用start()方法
MyRunnable mr = new MyRunnable();Thread ft2 = new Thread(mr);t2.start();
线程常见方法:
休眠:suleep(long millis) 当前线程主动休眠millis毫秒。
放弃:yield()当前线程主动放弃时间片、回到就绪状态,竞争下一次时间片。
结合:join()允许其他线程加入到当前线程中。
线程的状态:
1.初始状态(New):线程对象被创建,即为初始状态。只在堆中开辟内存,与常规对象无异。
2.就绪状态:调用start()之后,进入就绪状态。等待OS选中,并分配时间片。
3.Running运行状态:获得时间片之后,进入运行状态,如果时间片到期,则回到就绪状态。
4.期限等待:在运行状态调用sleep方法或其他方法后进入,到期之后进入就绪状态。
5.无限期等待:在运行状态调用join方法或其他方法后进入,当满足一定的条件时再进入就绪状态。
6.阻塞状态:在运行状态中执行synchronized
7.终止状态:线程结束,并释放持有的时间片。
d 注:JDK5之后就绪、运行统称Runnable
线程不安全问题:
1.当多线程并发访问临界资源时,如果破坏原子操作,可能会造成数据不一致。
2.临界资源:共享资源(同一对象),一次仅允许一个线程使用,才可保证其正确性。
3.原子操作:不可分割的多步操作,被视为一个整体,其顺序和步骤不可打扰或缺省。
同步方式(1):
同步代码块:synchronized(临界资源对象){
//对临界资源对象加锁
//代码(原子操作)}
注:每个对象都有一个互斥锁标记,用来分配给线程的。
只有拥有对象互斥锁标记的线程,才能进入对该对象加锁的同步代码块。
线程退出同步代码块时,会释放相应的互斥锁标记。
同步方式(2):
同步方法:synchronized 返回值类型 方法名称(形参列表){//对当前对象(this)加锁
//代码 (原子操作)}
注:只有拥有对象互斥锁标记的线程,才能进入该对象加锁的同步方法中。
线程退出同步方法时,会释放相应的互斥锁标记。
同步规则:
注意:1.只有在调用包含同步代码块的方法,或者同步方法时,才需要对象的锁标记。
2.如调用不包含同步代码块的方法,或普通方法时,则不需要锁标记,可直接调用。
已知JDK中线程安全的类:
StringBuffer、Vector、Hashtable、这些类中的公开方法,均为synchonized修饰的同步方法。
经典问题:1.死锁 2.生产者与消费者
线程通信:
等待:wait()
必须在对obj加锁的同步代码块中。在一个线程中,调用obj.wait()时,此线程会释放其拥有的所有锁标记。同时此线程阻塞在o的等待队列中。释放锁,进入等待队列。
通知:notify( )notifyAll( )
必须在对obj加锁的同步代码块中。从obj的waiting中释放一个或全部线程。对自身没有任何影响。

高级多线程

线程池概念:
现有问题:线程是宝贵的内存资源、单个线程约占1MB空间,过多分配易造成内存溢出。
频繁的创建及销毁线程会增加虚拟机回收频率、资源开销,造成程序性能下降。
线程池:线程容器,可设定程分配的数量上限。
将预先创建的线程对象存入池中,并重用线程池中的线程对象。
避免频繁的创建和销毁。
线程池原理:将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程。
获取线程池:常用的线程池接口和类(所在包Java.util.concurrent)
Executor:线程池的顶级接口。
ExecutorService:线程池接口,可通过submit(Runnable task)提交任务代码。
Executors工厂类:通过此类可获得一个线程池。
通过newFixedThreadPoll(int nThreads)获取固定数量的线程池。参数:指定线程池中线程的数量。
通过newCachedThreadPool()获得动态数量的线程池,如不够则创建新的,没有上限。
aCallable接口:
JDK5加入,与Runnable接口类似,实现之后代表一个线程任务。
Callable具有泛型返回值、可以声明异常。
Future接口:
概念:异步接收ExecutorService.submit()所返回的状态结果,当中包含了call()的返回值。
方法:V get( )以阻塞形式等待Future中的异步处理结果(call的返回值)
线程的同步:
形容一次方法的调用,同步一旦开始,调用者必须等待该方法返回,才能继续。
注:单条执行路径。
线程的异步:
形容一次方法调用,异步一旦开始,像是一次消息传递,调用者告知之后立即返回。二者竞争时间片,并发执行。
注:多条执行路径
Lock接口:
JDK5加入,与synchronized比较,显式定义,结构更灵活。
提供更多实用方法,功能更强大、性能更优越。
常用方法:lock()/ /获取锁,如锁被占用,则等待
tryLock()/ /尝试获取锁,成功返回true。失败返回false,不阻塞
unlock()/ / 释放锁
重入锁:
ReentrantLock:Lock接口的实现类,与synchronized一样具有互斥锁功能。
对写锁:ReentrantReadWriteLock
一种支持一写多读的同步锁,读写分离,可分别分配读锁、写锁。
支持多次分配读锁,使多个读操作可以并发执行。
互斥规则:写写:互斥,阻塞。读写:互斥,读读。读读:不互斥、不阻塞
在读操作远远高于写操作的环境中,可在保障线程安全的情况下,提高运行效率。
Collections中的工具方法:
提供了多个可获得线程安全集合的方法。
public static listsynchronizedList(Listlist)
JDK1.2提供,接口统一、维护性高,但性能没有提升,均以synchonized实现。
CopyOnWriteArrayList:
线程安全的ArrayList,加强版读写分离。
写有锁,读无锁,读写之间不阻塞,优于读写锁
写入时,先copy一个容器副本、再添加新元素,最后替换引用。
使用方式与ArrayList无异
CopyOnWriteArraySet:
线程安全的Set,底层使用CopyOnWriteArrayList实现。
唯一不同在于,使用addIfAbsent()添加元素,会遍历数组
如添加的元素已存在,则不添加(丢掉副本)
ConcurrentHashMap:
初始容量默认为16段(Segment),使用分段锁设计,不对整个Map加锁,而是为每个Segment加锁。当多个对象存入同一个Segment时,才需要互斥。最理想状态为16个对象分别存入16个Segment,并行数量16.使用方式与HashMap无异。
ConcurrentLinkedQueue:
线程安全、可高效率读写的队列,高并发下性能最好的队列。无锁、CAS比较交换算法,修改的方法包含三个核心参数(V,E,N)V:要更新的变量、E:预期值、N:新值。只有当V= =E时,V=N;否则表示已更新过,则取消当前操作。

I/O框架

什么是流:内存与存储设备之间传输数据的通道。水借助管道传输;数据借助流传递。
流的分类:
按方向:输入流:将《存储设备》中的内容读入到《内存》中。
输出流:将《内存》中的内容写入到《存储设备》中。
按单位:字节流:以字节为单位,可以读写所有数据。
字符流:以字符为单位,只能读写文本数据。
按功能:节点流:具有实际传输数据的读写功能
过滤流:在节点流的基础之上增强功能。

字节流的父类(抽象类):InputStream:字节输入流 OutputStream:字节输入流
字节节点流:FileOutputStream:write(byte【】b)/ /一次写多个字节,将b数组中所有字节,写入输出流。
FileInputStream:read(byte【】b)/ /从流中读出多个字节,讲读到内容存入b数组,返回实际读到的字节数,如达到文件的尾部,则返回-1
字节过滤流:缓冲流:BufferedOutputStream/BufferedInputStream
提高IO效率,减少访问磁盘的次数;数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close。
字节过滤流:
对象流:ObjectOutputStream/ObjectInputStream
增强了缓冲区功能,增强了读写8种基本数据类型和字符串功能,增强了读写对象的功能readObject()从流中读取一个对象,writeObject(Object obj)向流中写入一个对象
注:使用流传输对象的过程称为序列化、反序列化。
对象序列化的细节:
必须实现Serializable接口,必须保证其所有属性均可序列化,transient修饰为临时属性,不参与序列化。读取到文件尾部的标志:java.io.EOFException.
字符编码:
ISO-8859-1 收录除ASCII外,还包括西欧、希腊语、阿拉伯语、希伯来语对应的文字符号。
UTF-8 针对Unicode的可变长度字符编码
GB2312 简体中文 GBK 简体中文、扩充 BIG5 台湾,繁体中文
注意:当编码方式与解码方式不一致时,会出现乱码。
字符流:
字符流的父类(抽象类):Reader(字符输入流) Writer(字符输出流)
字符节点流:
File Writer:writer(String str)/ /一次写入多个字符,将b数组中所有字符,写入输出流。
FileReader: read(char【】c)// 从流中读取多个字符,将读到内容存入c数组,返回实际读到的字符数;如果达到文件的尾部,则返回-1
字符过滤流:
缓冲流:BufferedWriter/BufferedReader 支持输入换行符,可一次写一行、读一行。
PrintWriter:封装了print()/ println()方法,支持写入后换行。
字符节点流:
桥转换流:Input StreamReader / Output StreamWriter
可将字节l流转换为字符流。可设置字符的编码方式。
使用步骤:
创建节点流、【创建过滤流 设置字符编码集】、封装过滤流、读写数据、关闭流
File类:
概念:代表物理盘符中的一个文件或者文件夹。
方法:createNewFile()、Mkdir()、Delete()、getNme()等
FileFilter接口:
当调用File类中的listFiles()方法时,支持传入FileFilter接口接口实现类,对获取文件进行过滤,只有满足条件的才可以出现在listFiles()的返回值中。

网络编程

什么是网络:由点和线构成,表示诸多对象间的相互联系。
什么是计算机网络:为实现资源共享和信息传递,通过通信线路连接起来的若干主机。
互联网:点与点相连 万维网:端与端相连
物联网:物与物相连 网络编程:让计算机与计算机建立连接、进行通信。
TCP/IP模型:一组用于实现网络互联的通信协议,将协议分成4个层次。
应用层、传输层、网络层、网络接口层
TCP协议:传输控制协议
是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据大小无限制,建立连接的过程需要三次握手,断开连接的过程需要四次挥手。
UDP协议:用户数据报协议
是一种无连接的传输层协议,提供面向事务的简单不可靠信息传递服务,每个包的大小64KB
IP协议:互联网协议地址/网络协议地址,分配给互联网设备的数字标签(唯一标识)
IPV4的应用分类:
回环地址:127.0.0.1 指本机,一般用于测试使用。
Port:端口号:在通信实体上进行网络通信的程序的唯一标识。
端口分类:公认端口:0~1023 注册端口:1024~4915 动态或私有端口:49152~65535
常用端口:MySql :3306 Oracle:1521 Tomcat :8080
InetAddress类:
表示互联网协议(IP)地址对象,封装了与该IP地址相关的所有信息,并提供获取信息的常用方法。
基于TCP的网络编程:
Socket编程:Socket(套接字)是网络中的一个通信节点。分为客户端Socket与服务器ServerSocket,通信要求:IP地址+端口号
开发步骤:
创建通信连接(会话):
创建ServerSocket,指定端口号,调用accept等待客户端接入
客户端请求服务器:
创建Socket,指定服务器IP + 端口号,使用输出流,发送请求数据给服务器,使用输入流,接收响应数据到客户端(等待)
服务器响应客户端:
使用输入流,接受请求数据到服务器(等待),使用输出流发送响应数据给客户端。

反射

什么是类对象:
类的对象:基于某个类new出来的对象,也被称为实例对象。
类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)
获取类对象:
1.通过类的对象,获取类对象
Student s = new Student();Class c = s.getClass();
2.通过类名获取类对象
Class c = 类名.class
3.通过静态方法获取类对象
Class c=Class.forName("包名.类名”);
工厂设计模式:
开发中有一个非常重要的原则“开闭原则”,对拓展开放、修改关闭。工厂模式主要负责对象创建的问题。可通过反射进行工厂模式的设计,完成动态的对象创建。
单例模式:只允许创建一个该类的对象。
方式1:饿汉式(类加载时创建,天生线程安全)
class Singleton{
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}}
方式2:懒汉式(使用时创建,线程不安全,加同步)
class Singleton{
private static Singleton instance = null;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(instance == null) instance = new Singleton();
return instance;
}}
方式3:懒汉式(使用时创建,线程安全)
class Singleton{
private Singleton() {}
private static class Holder{
static Singleton s = new Singleton();
}
public static Singleton instance(){
return Holder.s;
}
}

你可能感兴趣的:(java笔记)