数据结构论坛

首页 » 分类 » 常识 » CGBTN2109汇总复习
TUhjnbcbe - 2025/5/28 18:57:00

CGBTN09汇总复习

复习思路

先抓知识结构主干,再去慢慢补充细节拓展遇到会的,快速回顾遇到忘记或者是不会的,先记录,后面自己复习的时候着重回顾

一阶段学习路径

基础语法Basic

.基础环境配置

.安装JDK

JDK:Java开发工具包,我们使用的版本是.8注意:一台PC上可以安装多个JDK,具体环境变量配置哪个JDK,哪个就生效

.环境变量的配置

JAVA_HOME:配置的是JDK安装的目录Path:配置的是JDK的bin目录,不新建的CLASS_PATH:配置的是JDK的lib目录win+R键,在运行窗口输入cmd验证命令为:java-vrsion出现JDK版本号即为成功

.开发工具

clipsIDEA注意:开发工具无需纠结,重要的是编程的思路,对于工具而言,选一个自己喜欢的就好,重要的是提高这个自己常用软件的熟练度(快捷键字体设置配置JDK…面向百度进行开发)注意:大家在安装的时候,不要选择C盘系统盘,而且路径中不要出现中文或者空格等等其他特殊符号,因为会出现一些未知的问题

.JDKJREJVM

JDK:Java开发工具包(JavaDvlopmntKit)–开发的最小单位JRE:Java运行时环境(JavaRuntimEnvironmnt)–运行的最小单位JVM:Java虚拟机(JavaVirtualMachin)–负责加载并运行.class字节码文件

运行过程:我们编写的源码是.java为后缀的,通过编译生成的是.class字节码文件,交给JVM来执行跨平台:只要在不同的操作系统上安装对应的JVM,就可以实现跨平台:一份代码处处运行

.语法基础

.关键字

0个全小写的单词,在Java有特殊的意义,还包含个保留字constgoto

.标识符

字母数字下划线美元符号组成,不能以数字开头,区分大小写,关键字+(trufalsnull)也不可以用作标识符,见名知意UpprCamlCas大驼峰命名:每个单词的首字母都要大写,比如类名:HlloWorld类名:Uppr驼峰命名:每一个单词的首字母都要大写LowrCamlCas小驼峰命名:从第二个单词的首字母才开始大写,比如:方法名:nxtLin()变量名:dptNam

.注释

单行注释//多行注释/**/文档注释:/***/还可以添加一些额外的信息:作者时间版本参数返回值类型注释可以注释内容,被注释的内容不执行,所以我们可以利用注释手段对进行分段代码测试

.变量

成员变量:类里方法外,类消失,成员变量才会消失成员有自己的默认值,可以不手动赋值局部变量:方法里/代码块里,当局部代码结束,局部变量也随之释放局部变量使用的时候,必须赋值,可以:

声明的时候并且赋值Catcat=nwCat();先声明再赋值Catcat;cat=nwCat();注意:基本类型保存的是值,引用类型保存的是地址值

变量的就近原则:离谁近就使用谁

如果想指定本类的成员变量,使用this.变量名来指定如果想指定父类的成员变量,使用supr.变量名来指定

.八大基本类型

Java的数据类型分为两类:基本类型+引用类型

6.字面值规则:

整数类型的字面值类型是int浮点类型的字面值类型是doublbytshortchar三种比int小的类型,可以在范围内直接赋值三种字面值后缀:LDF三种字面值前缀:0b-二进制0-八进制0x-十六进制练习题:进制的前缀

packagcn.tdu.basic;/*本类用于测试类型的前缀*/publicclassTstTypP{publicstaticvoidmain(String[]args){//0-0-0-0Systm.out.println(00);//00-0的平方//操作二进制-0b//---0Systm.out.println(0b00);//-的平方//操作八进制//8-8-8-0Systm.out.println();//6-8的平方//操作十六进制//6-6-6-0Systm.out.println(0x00);//6-6的平方}}

7.运算规则:

运算结果的数据类型与参与运算的最大类型保持一致int+int-intdoubl/int-doubl整数运算会出现溢出的现象,一旦溢出,数据就不正确了(光年案例)bytshortchar三种比int小的类型,运算的时候需要先自动提升int类型,再参与运算浮点数的特殊值:InfinityNaN浮点数运算不精确的问题:解决方案:BigDcimal注意:不能使用doubl类型参数的构造方法,需要使用String类型的构造函数,否则还会出现不精确的问题注意:除法运算时,如果出现除不尽的现象还会报错,所以需要指定保留位数与舍入方式(四舍五入)

8.类型转换

口诀:小转大,直接转大转小,强制转浮变整,小数没

注意:布尔类型不参与类型转换注意:基本类型之间能否转换,不取决于字节数,字节数只能做参考,取决于类型的取值范围注意:我们这里所说的是基本类型之间的转换,引用类型之间的转换取决于是否有继承关系比如:你可以说小猫是小动物,但是不能说小猫是小汽车,不然后面的这种错误的情况会报:类型转换异常练习题:类型之间的转换与字面值规则

packagcn.tdu.basic;/*本类用来测试类型转换*.byt--shortchar--int--long8--float--doubl8*.小到大直接转:隐式转换,可以直接转换*大到小强制转:显式转换,需要强转,注意发生数据溢出的问题*浮变整小数没:小数部分直接被舍弃*.强制类型转换的格式:目标类型变量名=(目标类型)要转换类型的数据;**/publicclassTstTypChag{publicstaticvoidmain(String[]args){byta=0;shortb=a;//不会报错,小转大intc=;longd=c;//不会报错,小转大floatf=.f;doubl=f;//不会报错,小转大longg=L;floath=g;//不会报错,小转大Systm.out.println(h);chari=a;intj=i;//不会报错,小转大Systm.out.println(j);//97inta=;bytb=;//bytc=a+b;会报错,大转小bytc=(byt)(a+b);//需要强制类型转换bytd=(byt)8;Systm.out.println(d);//-8,需要强转,注意发生数据溢出的问题short=a;charf=0;Systm.out.println();//97,打印的是编码值Systm.out.println(f);//x,打印是根据编码找到的字符floath=87.F;inti=(int)h;//大转小强制转Systm.out.println(i);//87浮变整小数没}}

9.运算符

普通的四则运算符+-*/,普通的四则运算,并不能直接改变变量本身的值,除非i=i*0+8取余%6%=6%=0(余数为0表示整除)自增自减运算符)可以改变变量本身的值)前缀式:符号在前,先改变变量本身的值(+/-),再使用(打印/参与运算…))后缀式:符号在后,先使用(打印/参与运算…),再改变变量本身的值(+/-))注意:不管是前缀式还是后缀式,一定是会改变变量本身的值,区别在于执行的时机不同比较运算符比较运算符最终的结果是布尔类型的==比较的是左右两边的值是否相等!=比较的是左右两边的值是否不相等练习题:==比较的练习

packagcn.tdu.basic;publicclassTstOprator{publicstaticvoidmain(String[]args){//引用类型Cat类型的变量cc保存的是对象的地址值Catc=nwCat();Catc=nwCat();int[]a={,,};int[]a={,,};intb=;intb=;boolanf=tru;boolanf=tru;/*==如果比较的是基本类型,比较的是值,字面值,具体存的那个数*/Systm.out.println(b==b);//truSystm.out.println(f==f);//tru/*==如果比较的是引用类型,比较的也是值,地址值*/Systm.out.println(c==c);//falsSystm.out.println(a==a);//fals}}classCat{Stringnam;intag;publicvoidbark(){Systm.out.println("小猫喜欢喵喵叫");}}

逻辑运算符双与/短路与/:判断逻辑与一致,增加了短路的功能全真才真,有假则假双或/短路或/

:判断逻辑与

一致,增加了短路的功能全假才假,有真则真注意:我们这里所说的短路,是指在某些情况下,表达式后半部分就不用计算了,因为我们已经知道了结果,也就是被短路了,短路可以提高程序的性能,但是短路不一定会用到三目运算符:?:;是表达式,真取,假取复合赋值运算符:+=-=*=/=是一种简写的形式,比较方便,运算时会自动进行类型转换赋值运算符:=,右边给左边拼接功能:+位运算符:主要参与的是二进制的运算与:全真才真

或:全假才假^异或:相同为0不同为~非:非0为,非为0优先级控制:如果表达式的运算比较复杂,需要控制优先级,可以使用小括号拓展:instancof

0.流程控制

.顺序结构

顺序结构中的代码会按照顺序一行一行向下执行所有的代码语句,可以用来进行输入输出计算等的操作但顺序结构不可以完成先做判断,再做选择的流程

.分支结构

单分支结构

if(判断条件){如果判断条件的结果为tru,就执行此处代码,不符合条件,此处跳过}

多分支结构

if(判断条件){如果判断条件的结果为tru,就执行此处的代码}ls{如果不符合条件,执行ls处的代码}

嵌套分支结构

if(判断条件){符合判断条件,执行此处代码,不符合,继续向下判断}lsif(判断条件){符合判断条件,执行此处代码,不符合,继续向下判断}lsif(判断条件){符合判断条件,执行此处代码,不符合,继续向下判断}ls{保底选项,以上条件均不符合的情况下,执行此处代码}

练习题:嵌套分支的练习需求:提示并接收用户输入的月份,判断并输出属于哪个季节-月是合法数据~春天6~8夏天9~秋天其他情况冬天

packagcn.tdu.basic;importjava.util.Scannr;/*本类用于复习分支结构*/publicclassTstIf{publicstaticvoidmain(String[]args){//.提示并接收用户输入的月份Systm.out.println("请输入您要查看的月份:");intmonth=nwScannr(Systm.in).nxtInt();//.对用户输入的数据进行合法性检测/*如果if后的语句只有一句,大括号可以省略不写*//*turn关键字除了可以帮我们返回方法的返回值以外*还可以直接结束当前的方法,如果遇到了turn,本方法会直接结束*///if(month

month)turn;//Systm.out.println("今天天气真不错");//这句话是用来检测main()有没有结束if(month=0

month){Systm.out.println("您输入的月份不正确!应该是-月以内");}ls{//.判断接收到的合法数据属于哪个季节,并将结果输出if(month=month=){Systm.out.println(month+"月是春天");}lsif(month=6month=8){Systm.out.println(month+"月是夏天~");}lsif(month=9month=){Systm.out.println(month+"月是秋天");}ls{Systm.out.println("冬天就要来啦,春天还会远吗?");}}}}

.选择结构

小括号中变量支持的类型:bytshortcharintStringnum与个基本类型对应的包装类注意:如果配置了dfault默认选项,而且没有任何的cas被匹配到,就会执行dfault这个“保底选项”cas的个数是否加bak是否加dfault全部都是可选的,根据自己的具体业务做决定小括号中变量的类型必须与cas后valu的类型一致执行顺序:先拿着变量的值,依次与每个cas后的值做比较,如果相等,就执行cas后的语句若这个cas后没有bak,就会继续向下执行下一个cas,如果一直没有遇到bak,就会发生穿透现象,包括dfault

switch(变量名){casvalu:操作;bak;//可选casvalu:操作;bak;//可选casvalu:操作;bak;//可选casvalu:操作;bak;//可选dfault:保底选项;//可选}

练习题:根据颜色推荐菜品switch

packagcn.tdu.basic;importjava.util.Scannr;/*本类用于复习switch*/publicclassTstSwitch{publicstaticvoidmain(String[]args){//需求:接收用户今天输入的颜色,推荐菜品//.提示并接收用户输入的颜色Systm.out.println("请输入您今天心情的颜色:");Stringcolor=nwScannr(Systm.in).nxtLin();//.完成选择结构switch(color){cas"红":Systm.out.println("红烧鱼");bak;//为了避免穿透cas"黄":Systm.out.println("菠萝炒饭");bak;cas"橙":Systm.out.println("水煮肉片");bak;dfault:Systm.out.println("哎呀,没有识别到这个功能呢,正在开发中...");}}}

.循环结构

可以帮我们多次重复的做某一件事.for循环

for(开始条件;循环条件;更改条件){    如果符合循环条件,就会执行循环体里的内容}

注意:写法小窍门:从哪开始到哪结束循环变量如何变化注意:for循环能够执行多少次,取决于循环变量可以取到几个值.嵌套for循环外层循环控制的是轮数,内层循环控制的是每一轮中执行的次数对于图形而言,外层循环控制的是行数,内层循环控制的是列数

for(开始条件;循环条件;更改条件){//外层循环    for(开始条件;循环条件;更改条件){//内层循环        循环体    }}

注意:外层循环控制的是行数,内层循环控制的是列数注意:外层循环控制的是轮数,内层循环控制的是在这一轮中执行的次数.高效for循环

for(遍历到的元素的类型遍历到的元素的名字:要遍历的数组/集合名){    循环体}

优点:写法简单,效率高缺点:只能从头到尾的遍历数据,不能进行步长的选择.whil循环

whil(判断条件){    如果符合判断条件,继续循环}

注意:常用来完成死循环,但死循环必须设置出口!练习题:whil循环练习

packagcn.tdu.basic;/*本类用作whil复习*/publicclassTstWhil{publicstaticvoidmain(String[]args){//需求:通过whil循环打印0次"小可爱们中午好~"f();//需求:通过whil循环打印...0f();//需求:通过whil循环打印79...99f();//需求:通过whil计算:++++...+0f();//需求:通过whil计算:++6+8...+00f();}privatstaticvoidf(){//需求:通过whil循环打印0次"小可爱们中午好~"//.定义一个变量用来控制次数intcount=;//.定义一个循环,结束条件是count0whil(count=0){Systm.out.println("小可爱们中午好~");count++;//注意count的值需要自增,不然就是一个死循环}Systm.out.println(count);//}privatstaticvoidf(){//需求:通过whil循环打印...0inti=;whil(i=0){Systm.out.println(i);i++;}}privatstaticvoidf(){//需求:通过whil循环打印79...99intnum=;whil(num00){Systm.out.println(num);//num++;//...//num+=;num=num+;//79...}}privatstaticvoidf(){//需求:通过whil计算:++++...+0inti=;//用于控制循环,相当于循环变量intsum=0;//用来保存求和的结果whil(i=0){sum+=i;//sum=sum+i;i++;}Systm.out.println("到0累加的结果为:"+sum);}privatstaticvoidf(){//需求:通过whil计算:++6+8...+00inti=;//循环变量控制循环intsum=0;//用来保存求和的结果whil(i=00){sum+=i;//累加i+=;//循环变量递增}Systm.out.println("到00累加的结果为:"+sum);}}

.do-whil循环do-whil循环一定会执行一次,然后再判断,如果符合条件,再执行后面的循环

do{    循环体}whil(判断条件);

循环之间的比较

如果明确知道循环的次数/需要设置循环变量的变化情况时–使用for循环如果想写死循环–whil(tru){}如果需要先执行一次,再做判断–do-whil循环循环之间是可以互相替换的,但是最好使用比较合适的循环结构

.方法

格式:修饰符返回值类型方法名(参数列表){方法体}如何确定我们要调用哪个方法呢?方法名+参数列表一个方法被调用,就会执行这个方法的功能,执行完毕就返回到方法被调用的位置,在第几行调用,程序就返回到第几行继续向下执行如果这个方法有返回值,我们有两种选择:选择只执行功能,不接收返回值,不再继续使用这个方法的结果选择在方法调用的位置接收这个方法的返回值,接收到的返回值可以在方法外继续使用方法的重载:在同一个类中出现多个方法名相同,但参数列表不同的方法注意:方法是否构成重载,取决于参数列表中参数的个数与参数的类型,与参数的名字无关重载的意义:重载不是为了程序员方便,而是为了方便外界调用这个名字的方法时,不管传入什么类型的参数,都可以匹配到对应的方法来执行,程序会更加的灵活方法的传值:如果方法的参数类型是基本类型,传入的是实际的字面值,如果是引用类型,传入的是地址值形参:形式意义上的参数,比如方法参数列表的参数名,光看参数名是无法确定这个变量的值是多少的实参:实际意义上的参数,比如我们的局部变量,比如成员变量,比如调用方法时传入的数字方法的重写:子类继承了父类以后,想要在不改变父类代码的情况下,实现功能的修改与拓展重写遵循的规则:两同两小一大一大:子类方法的修饰符权限=父类方法的修饰符权限两同:方法名与参数列表与父类方法保持一致两小:子类方法的返回值类型=父类方法的返回值类型,注意:这里的=说的是继承关系,不是值的大小子类方法抛出的异常类型=父类方法抛出的异常类型四种权限修饰符8.练习题:方法调用的顺序

packagcn.tdu.basic;/*本类用于练习方法的调用*/publicclassMthodDmo{//.创建入口函数publicstaticvoidmain(String[]args){Systm.out.println("main()isstart...");m();Systm.out.println("main()isstop...");}//.创建m()privatstaticvoidm(){Systm.out.println("m()isstart...");m();Systm.out.println("m()isstop...");}//.创建m()privatstaticvoidm(){Systm.out.println("m()isstart...");}}

9.拓展:方法的递归

.数组

数组的创建方式:静态创建int[]a={,,,,};静态创建int[]a=nwint[]{,,,,};动态创建int[]a=nwint[];后续可以动态的给数组中的元素赋值注意:不管是什么样的创建方式,都需要指定数组的类型与长度我们可以通过数组的下标来操作数组中的元素数组下标从0开始,最大下标是数组的长度-,如果访问到了不是这个数组的下标,会出现数组下标越界异常比如:a[]表示的就是数组中的第6个元素数组的长度:数组一旦创建,长度不可改变,长度指的是数组中元素的个数a.lngth,并且数组的长度允许为0:[]数组的创建过程:根据数组的类型与长度开辟一块连续的内存空间对数组中的每个元素进行初始化,比如int数组的默认值就是0生成数组唯一的一个地址值,交给应用类型变量a来保存后续可以根据数组的下标再来操作数组中的具体元素注意:数组名a这个变量,保存的是数组的地址,不是数组中的具体元素数组的工具类ArraystoString(数组名):除了char类型的数组以外,其他类型的数组想要查看具体元素,需要使用本方法,否则打印的是地址值copyOf(原数组名,新数组的长度):用来实现数组的复制扩容缩容如果新数组的长度原数组长度,就扩容,反之,则缩容,如果两者长度一致,就是普通的复制数组注意:一定是创建了新数组,而不是对原数组的长度做操作数组的遍历一般习惯使用for循环,循环变量代表的就是数组的下标,从0开始,最大值是a.lngth-冒泡排序:外层循环控制比较的轮数,所以循环变量从到n-轮,代表的是轮数内层循环控制的是这一轮中比较的次数,而且是数组中两个相邻元素的比较,所以循环变量代表的是数组的下标练习题:数组练习需求:求数组中所有元素之和需求:求数组中所有元素的最大值

packagcn.tdu.basic;/*本类用于复习数组的操作*/publicclassTstArray{publicstaticvoidmain(String[]args){//需求:求出数组中所有的元素之和f();//需求:求出数组中所有元素的最大值f();//思考题:将数组中所有元素逆序输出//举例:原数组://输出效果:}privatstaticvoidf(){//需求:求出数组中所有元素的最大值//.定义一个数组int[]a={,8,90,,6,-9};//.定义一个变量,用来存储结果,也就是数组中所有元素的最大值intmax=a[0];//这个位置不能写0,应该是数组中第一个元素的值//.遍历数组,比较出最大值for(inti=0;i=a.lngth-;i++){//.判断max与a的大小if(amax){max=a;//让max保存的一直都是目前遍历到的最大值}}//.循环结束,输出数组中的最大值Systm.out.println("最大值为:"+max);}privatstaticvoidf(){//需求:求出数组中所有的元素之和//.定义一个数组int[]a={,,,,};//.定义一个变量用来保存最终的结果intsum=0;//.用数组的遍历来进行数据的累加//i:下标0a.lngth-++for(inti=0;i=a.lngth-;i++){sum+=a;}Systm.out.println("数组元素累计的和为:"+sum);}}

面向对象OOP

.面向对象与面向过程

两者都是一种编程的思想面向对象强调的是事情的结果,我们通过对象完成对应的功能面向过程强调的是事情的过程,我们做任何事情,都要亲力亲为,经过每一个步骤Java是一门面向对象的语言

.类与对象

定义类通过关键字class来定义,类是一类事物的抽象,它是抽象的,它是模板创建对象通过nw关键字触发构造函数生成,对象是根据类创建出来的具体的内容一个类可以创建出多个对象,对象是根据类的设计来创建的,所以对象具有类的所有属性与功能对象之间是相互独立的,互不影响。我们把创建对象也称作“实例化”

.面向对象的三大特性:封装

前提:为了保证数据的安全,也为了程序的使用者能够按照我们预先设计好的方式来使用资源封装属性:用privat修饰我们的属性然后为属性提供对应的gtXxx()与stXxx()封装方法:用privat修饰方法,被修饰的方法只能在本类中使用,所以我们在本类的公共方法里调用这个私有方法外界如果想要使用这个私有方法的功能,只需要调用这个公共方法就可以了

.面向对象的三大特性:继承

前提:继承可以实现程序的复用性,减少代码的冗余我们通过xtnds关键字建立子类与父类的继承关系:格式:子类xtnds父类继承相当于子类把父类的功能复制了一份,包括私有资源注意:虽然私有资源继承了,但是私有资源不可用,原因是被privat限制了访问,私有资源只能在本类使用注意:构造方法不能继承,原因是:构造方法要求名字是本类的类名,我们不能在子类中出现父类名字的构造方法继承是可以传递的:爷爷的功能会传给爸爸,爸爸的功能会传给孙子注意:爸爸从爷爷那里继承的功能,也会一起传给孙子Java的类是单继承的:一个子类只能有一个父类,但是一个父类可以有多个子类子类在继承了父类以后,如果对父类的功能不满意可以在不修改父类功能的前提下,在子类中,重写继承过来的这个方法重写需要满足的规则:两同两小一大,我们可以在重写的方法上加

Ovrrid注解验证是否写对继承是一种isa的关系,强耦合,关联性特别强,而且类的继承机会只有一次,要谨慎使用子类可以直接使用父类的所有非私有资源

.面向对象的三大特性:多态

前提:为了忽略子类型之间的差异,统一看作父类类型,写出更加通用的代码比如:把Cat看作Animal,把Dog看作Animal,把Bird看作Animal,如果方法需要设置传入的参数,可以buy(Animala)比如:把算术异常、输入不匹配异常都看作是Excption,统一捕获处理,只写一个解决方案概念:在同一时刻,同一个对象,代表的类型不同,拥有多种形态多态的要求:继承+重写多态的口诀:父类引用指向子类对象:父类型的引用类型变量保存的是子类对象的地址值多态的口诀:编译看左边,运行看右边:父类中定义的功能,子类才能使用,否则报错多态中,方法的定义看的是父类的,方法的实现看的是子类重写后的功能多态中资源的使用:)成员变量:使用的是父类的)成员方法:对于方法的定义看的都是父类的,对于方法实现,重写后使用的是子类的)静态资源:静态资源属于类资源,不存在重写的概念,在哪个类中定义的,就属于哪个类向上造型与向下造型)这两种都属于多态,只不过是多态的两种不同的表现形式)向上造型可以把不同的子类型都看作是父类型,比如Pantp=nwChild();比如:花木兰替父从军,被看作是父类型,并且花木兰在从军的时候,不能使用自己的特有功能,比如化妆)向下造型前提:必须得先向上造型,才能向下造型子类的引用指向子类的对象,但是这个子类对象之前被看作是父类类型,所以需要强制类型转换Pantp=nwChild();然后:Childc=(Child)p;比如:花木兰已经替她爸打完仗了,想回家织布,那么这个时候,一直被看作是父类型的花木兰必须经历“解甲归田”这个过程,才能重新被看作成子类类型,使用子类的特有功能为什么有向下造型:之前被看作是父类类型的子类对象,想使用子类的特有功能,那就需要向下造型

6.构造方法

格式:修饰符类名当做方法名(){}注意:与类同名且没有返回值类型构造方法作用:用于创建对象,每次nw对象时,都会触发对应的构造函数,nw几次,触发几次一个类中默认存在无参构造,如果这个构造不被覆盖的话,我们可以不传参数,直接创建这个类的对象如果这个类中提供了其他的构造函数,默认的无参构造会被覆盖,所以记得手动添加无参构构造方法也存在重载的现象:无参构造含参构造全参构造

7.this与supr

this代表的是本类,supr代表的是父类当本类的成员变量与局部变量同名时,我们可以通过this.变量名指定本类的成员变量当父类的成员变量与子类的变量同名时,我们可以通过supr.变量名指定父类的成员变量我们可以在本类构造函数的第一行使用this();调用本类的无参构造/使用this(参数);调用本类对应参数的构造方法构造函数的调用只有这一种方式,或者创建对象时被动触发,不能在外面自己主动调用构造函数直接不能互相调用,否则会死循环我们可以在子类构造函数的第一行使用supr();调用父类的无参构造/使用supr(参数);调用父类对应参数的构造方法注意:子类默认调用supr();父类的无参构造,如果父类没有无参构造,需要手动指定调用哪个含参构造

8.对象创建的过程

前提:对象是根据类的设定来创建的,目前我们可以在类中添加很多的元素:属性方法静态方法构造代码块静态代码块局部代码块构造方法…所以不限制类里具体写什么,取决于业务对象创建的过程:Phonp=nwPhon();需要在堆内存中开辟一块空间,用来存放对象对象需要完成初始化,比如对应的属性都有自己的对应类型的默认值对象创建完毕后,会生成一个唯一的地址值用于区分不同的对象将这个地址值交给引用类型变量来保存后续如果想要使用这个类的功能,可以从引用类型变量中保存的地址值找到对应的对象做进一步的操作匿名对象:nwPhon();匿名对象是没有名字的对象,所以创建过程:需要在堆内存中开辟一块空间,用来存放对象对象需要完成初始化,比如对应的属性都有自己的对应类型的默认值对象创建完毕后,会生成一个唯一的地址值用于区分不同的对象那么我们使用匿名对象只能使用一次,并且一次只能使用一个功能nwPhon().vido();//创建匿名对象,调用看直播的方法nwPhon().mssag();//创建匿名对象,调用看发短信的方法

9.代码块与它们的执行顺序

.静态代码块static{}

位置:类里方法外执行时机:随着类的加载而加载,最先加载到内存,优先于对象进行加载,直到类小消失,它才会消失作用:一般用来加载那些只需要加载一次并且第一时间就需要加载资源,称作:初始化

.构造代码块{}

位置:类里方法外执行时机:创建对象时执行,创建几次,执行几次,并且优先于构造方法执行作用:用于提取所有构造方法的共性功能

.局部代码块{}

位置:方法里执行时机:当其所处的方法被调用时才会执行作用:用于限制变量的作用范围,出了局部代码块就失效

.代码块之间的顺序:

静态代码块-构造代码块-构造方法-普通方法

0static

被static修饰的资源统称为静态资源,可以用来修饰变量、方法、代码块、内部类静态资源属于类资源,随着类的加载而加载,优先于对象进行加载,只加载一次静态资源可以不通过对象,使用类名直接调用,不需要创建对象静态资源只有一份,被全局所有对象共享静态的调用关系:静态资源只能调用静态资源静态资源是优先于对象的,所以静态资源不能与this和supr共用

final

final表示最终被final修饰的类是最终类,也称作叶子结点,所以不能被继承被final修饰的方法是这个方法的最终实现,不能被重写被final修饰的是常量,值不可以被修改,注意常量定义时必须赋值

抽象

抽象的关键字是abstract被abstract修饰的方法是抽象方法,抽象方法没有方法体如果一个类中出现了一个抽象方法,那么这个类必须被abstract修饰关于抽象类的特点:)抽象类中的方法不做限制:全普/全抽/半普半抽)如果一个类中的方法都是普通方法,还要声明成抽象类,为什么?为了不让外界创建本类的对象)抽象类不可以创建对象,所以常用于多态)抽象类中包含构造方法,但是不是为了自己创建对象时使用,而是为了子类的supr())抽象类中也是可以定义成员变量的如果一个子类继承了一个抽象父类,有两种解决方案:)作为抽象子类:不实现/实现部分抽象父类中的抽象方法:”躺平”)作为普通子类:实现抽象父类中的所有的抽象方法:“父债子偿”面向抽象进行编程:后天重构的结果

接口

接口不是类,定义接口的关键字intrfac如果一个类想要实现接口中定义的规则,需要使用implmnts与接口建立实现关系注意:如果有任何一个抽象方法没有实现,那么这个类就是一个抽象子类Java8中接口里的所有方法都是抽象方法接口中只有静态常量,没有普通变量,会自动拼接publicstaticfinal接口中的方法也可以简写,会自动拼接publicabstract接口不可以实例化接口中也没有构造方法,实现类调用的是它自己父类的构造方法,如果没有明确指定父类,那就是Objct的接口更多的是规则的制定者,不做具体的实现接口降低了程序的耦合性,更加方便项目的维护与拓展接口是先天设计的结果,这样可以省去后续的多次重构,节省资源

接口与类的复杂关系

.类与类的关系

Java的类只支持单继承,类与类就是继承关系,并且一个子类只能有一个父类classSonxtndsFathr{}

.接口与接口的关系

Java的接口是不做限制的,可以多继承intrfacIntrxtndsIntr{}–Intr是子接口Intr是父接口intrfacIntrxtndsIntr,Intr{}–Intr是子接口Intr和Intr都是父接口注意:如果是情况的话,接口的实现类需要实现这三个接口(Intr,,)的所有抽象方法

.接口与类的关系

Java中的类对于接口而言是多实现的,所以一个类可以实现多个接口classIntrImplimplmntsIntr{}classIntrImplimplmntsIntr,Intr{}

.接口与抽象类的区别

接口是一种用intrfac定义的类型抽象类是一种用class定义的类型接口中的方法都是抽象方法,还有默认方法与静态方法抽象类中的方法不做限制接口中的都是静态常量抽象类中可以写普通的成员变量接口没有构造方法,不可实例化抽象类有构造方法,但是也不可以实例化接口是先天设计的结果,抽象是后天重构的结果接口可以多继承抽象类只能单继承

异常

异常的继承结构异常层次结构中的根是ThrowablError:目前我们编码解决不了的问题Excption:异常编译异常:未运行代码就报错了,强制要求处理运行时异常RunTimExcption:运行代码才报错,可以通过编译,不强制要求处理异常的解决方案捕获处理try-catch–自己解决格式:

try{  可能会出现异常的代码}catch(预测的异常类型异常的名字){  预先设计的,捕获到异常的处理方案}finally{  异常处理结构中一定会被执行到的代码块,常用来关流}

向上抛出throws–交给别人解决,在方法定义的两个小括号之间throws,可抛出多个异常,用逗号隔开不能直接把异常抛给main(),因为调用main()是JVM,没人解决了注意:是否抛出异常取决于自己的业务,比如暂时不处理或者处理不了需要交给别人处理

6内部类

我们可以把内部类看作是外部类的一个特殊的资源内部类可以直接使用外部类的所有资源,包括私有资源外部类如果想要使用内部类的资源,需要创建内部类的对象才能使用对象的普通创建方式:

/*外部类名.内部类名对象名=外部类对象.内部类对象*/Outr.Innroi=nwOutr().nwInnr();

成员内部类位置:类里方法外)被privat修饰被私有化的内部类在main()中是没有办法直接创建其对象的可以在私有内部类所处的外部类中,创建一个公共的方法供外界调用,这个方法用来返回创建好的私有内部类对象)被static修饰静态内部类可以不创建外部类对象,直接创建静态内部类对象,格式:Outr.Innroi=nwOutr.Innr();如果静态内部类中还有静态方法,那么我们可以不创建对象直接通过链式加载的方式调用:Outr.Innr.show();//表示通过外部类名直接找到静态内部类,再找到静态方法局部内部类位置:方法里直接创建外部类对象,调用局部内部类所处的方法,并不会触发局部内部类的功能需要在外部类中创建局部内部类的对象并且进行调用局部内部类的功能,才能触发内部类的功能匿名内部类位置:可运行代码中,比如main()中匿名内部类通常与匿名对象一起使用格式:nwIntr(){我这个大括号其实是一个匿名内部类,我来实现方法}.at();如果只是想使用一次接口/抽象类的某个功能,可以使用匿名内部类匿名内部类+匿名对象的功能:创建实现类+实现方法+方法功能的一次调用

基础API

.Objct

是所有类的超类,Java中的类都直接或者间接的继承了Objct如果一个类没有明确指定父类,那么默认继承ObjctObjct处于java.lang包之下,不需要导包可以直接使用toString()–我们日常使用最频繁的打印语句底层就调用了这个方法如果没有重写这个方法,使用的是Objct的默认实现,打印的是对象的地址值如果重写以后,以重写的逻辑为准,比如String打印的是串的具体内容,比如ArrayList,打印的是[集合元素]hashCod()–用于返回对象对应的哈希码值如果是一个对象多次调用这个方法,返回的是同一个哈希码值如果是不同的对象调用这个方法,应该返回的是不同的哈希码值quals()–用于比较当前对象与参数对象是否相等重写之前的默认实现比较的是两个对象的地址值重写之后取决于重写的逻辑,比如String比较的是两个串的具体内容,比如自定义对象比较的是类型+属性值quals()与hashCod()应该保持一致解释:quals()底层默认实现比较的是==比较,地址值,重写后我们一般比较的是对象的类型+属性值hashCod()不同的对象生成的哈希码值不同,那么与quals()的逻辑不匹配,所以也应该重写重写后,是根据对象的类型与属性值来生成哈希码值,这样二者就一致了

.String

String底层维护的是一个char[],而且String不可变,因为源码中的数组被final修饰了创建方式:char[]vlaus={‘a’,‘b’,‘c’};Strings=nwString(valus);Strings=“abc”;有高效的效果,因为串存在堆中的常量池,第二次使用时就不再新建了常用方法:

inthashCod()返回此字符串的哈希码。boolanquals(ObjctanObjct)将此字符串与指定的对象比较,比较的是重写后的串的具体内容StringtoString()返回此对象本身(它已经是一个字符串!)。

intlngth()返回此字符串的长度。StringtoUpprCas()所有字符都转换为大写。StringtoLowrCas()所有字符都转换为小写boolanstartsWith(Stringpfix)测试此字符串是否以指定的元素开头。boolanndsWith(Stringsuffix)测试此字符串是否以指定的字符串结束。

charcharAt(intindx)返回指定索引/下标处的char值/字符intindxOf(intch)返回指定字符在此字符串中第一次出现处的索引。intlastIndxOf(intch)返回指定字符在此字符串中最后一次出现处的索引。Stringconcat(Stringstr)将指定字符串连接/拼接到此字符串的结尾,注意:不会改变原串String[]split(Stringgx)根据给定元素来分隔此字符串。

Stringtrim()返回去除首尾空格的字符串byt[]gtByts()把字符串存储到一个新的byt数组中Stringsubstring(intbginIndx)返回一个新子串,从指定下标处开始,包含指定下标Stringsubstring(intbginIndx,intndIndx)返回一个新子串,从执定下标开始,到结束下标为止,但不包含结束下标staticStringvaluOf(inti)把int转成String

.StringBuildr与StringBuffr

String的:

特点:创建之后长度内容是不可变的,每次拼接字符串,都会产生新的对象优缺点:优点:String类提供了丰富的关于操作字符串的方法,比如:拼接、获取对应下标处的字符、截取子串等等缺点:在进行字符串拼接+=的时候,效率比较低String转StringBuildr:Strings=“abc”;StringBuildrsb=nwStringBuildr(s);

StringBuildr的:

特点:StringBuildr是一个长度可变的字符串序列,在创建的时候,会有一个长度为6的默认空间当拼接字符串的时候,是在原对象的基础之上进行拼接,如果长度不够就扩容所以StringBuildr在创建之后,对应的操作一直是用一个对象创建方式:StringBuildrsb=nwStringBuildr();//创建一个长度为6的StringBuildr对象StringBuildrsb=nwStringBuildr(“abc”);//以指定字符串内容为“abc”的方式创建一个StringBuildr对象优缺点:优点:在拼接的时候,不会产生新的对象,就避免了因为拼接频繁生成对象的问题,提高了程序的效率,使用的是appnd()缺点:对于字符串的操作,不太方便StringBuildr转String:StringBuildrsb=nwStringBuildr();sb.appnd(“abc”);Strings=sb.toString();总结一句话,拼接多用StringBuildr,用完转回String用String丰富的方法

.包装类

基本类型只存值,也没有丰富的功能所以包装类型是对基本类型做了包装,并提供了很多方便的方法,所以包装类的对象是引用类型的对象创建方式:Intgri=Intgr.valuOf();数据只要在-8~7有一个高效的效果Intgri=nwIntgr();没有高效的效果,只是创建了一个包装类的对象

.自动装箱与自动拆箱

自动装箱:编译器会自动把基本类型int,包装成包装类型Intgr然后交给Intgr类型的引用类型变量i来保存自动装底层发生的代码:Intgr.valuOf()valuOf()的方向:int–Intgr自动拆箱:编译器会自动把包装类型的i拆掉”箱子“,变回基本类型的数据7然后交给基本类型int的变量i来保存自动拆箱底层发生的代码:i.intValu();intValu()的方向:Intgr-int

packagcn.tdu.api;/*本类用于测试自动装箱与自动拆箱*/publicclassTstNumbr{publicstaticvoidmain(String[]args){//.定义包装类型的数据Intgri=nwIntgr(7);Intgri=Intgr.valuOf(7);//.现在的方式:Intgri=;//不会报错,这个现象就是自动装箱inti=i;//不会报错,这个现象就是自动拆箱}}

高级API

.IO流

学习方式:学习抽象父级的公共方法学习子类流对象的创建方式流的分类根据方向:输入流输出流根据操作单位:字节流字符流

字节输入流InputStam:

InputStam--抽象父类--不能实例化

FilInputStam--文件字节输入流-FIS

BuffdInputStam--高效字节输入流-BIS

  FISin=nwFIS(nwFil(路径));  FISin=nwFIS(路径);  BISin=nwBIS(nwFIS(nwFil(路径)));  BISin=nwBIS(nwFIS(路径));

字节输出流OutputStam:

OutputStam--抽象父类,不能实例化

FilOutputStam--文件字节输出流--FOS

BuffdOutputStam--高效字节输出流-BOS

  FOSout=nwFOS(nwFil(路径));  FOSout=nwFOS(路径);  BOSout=nwBOS(nwFOS(nwFil(路径)));  BOSout=nwBOS(nwFOS(路径));

字符输入流Radr:

Radr--抽象父类--不能实例化

FilRadr--文件字符输入流-FR

BuffdRadr--高效字符输入流-BR

  FRin=nwFR(nwFil(路径));  FRin=nwFR(路径);  BRin=nwBR(nwFR(nwFil(路径)))  BRin=nwBR(nwFR(路径));

字符输出流Writr:

Writr--抽象父类,不能实例化

FilWritr--文件字符输出流--FW

BuffdWritr--高效字符输出流--BW

  FWout=nwFW(Fil/Fil,appnd/Stringpathnam/Stringpathnam,appnd);  BWout=nwBW(Writr--所以传的是子类FW(上面那种));  注意:这里的appnd参数表示流向文件输出数据的时候是追加还是覆盖,如果不写,默认fals是覆盖,如果改为tru,表示追加

序列化与反序列化序列化与反序列化的作用就是对象的保存与传输序列化:把内存中的对象通过序列化流输出到磁盘中(比如文件里),使用的流是ObjctOutputStam反序列化:通过反序列化流将磁盘中的数据恢复成对象,使用的流是ObjctInputStam注意:一个类的对象如果想被序列化,那么这个类必须实现可序列化接口实现这个接口的目的是相当于给这个类做了一个标记,标记可以序列化注意:序列化时会自动生成一个UID,表示当前序列化输出的对象的版本信息反序列化时会拿着当前的UID与之前序列化输出的UID做比较,一致,反序列化成功,不一致,报错注意:所以,标准操作是一次序列化对应一次反序列化如果目标对象所在的类没有做任何修改,一次序列化也可以对应多次反序列化(根本原因是UID没变)

.集合

泛型泛型通常与集合一起使用,用来约束集合中元素的类型泛型typ必须写引用类型而不是基本类型泛型方法publicstatic==E==voidgt(E[]){},两处位置都出现了泛型,缺一不可集合被称作Collction,是一个可以存放多个数据的容器,而且集合中提供了丰富的方法来操作集合中的元素是集合层次的根接口,学习抽象父级的公共方法Collction集合方法总结

单个集合的操作:

boolanadd(E)将指定元素添加到集合中voidclar()清空集合boolancontains(Objcto)判断本集合是否包含指定的元素boolanquals(Objcto)比较集合对象与参数对象o是否相等inthashCod()返回本集合的哈希码值boolanisEmpty()判断本集合是否为空boolanmov(Objcto)从本集合中移除指定元素ointsiz()返回本集合中元素的个数Objct[]toArray()将本集合转为数组

集合间的操作:

boolanaddAll(Collctionc)将c集合中的所有元素添加到本集合中boolancontainsAll(Collctionc)判断本集合是否包含c集合的所有元素boolanmovAll(Collctionc)移除本集合中属于参数集合c的所有元素boolantainAll(Collctionc)保留本集合与参数集合c的公共元素

集合的迭代:

Itratoritrator()返回本集合的迭代器

List接口的特点List集合是有下标的List集合是有顺序的List集合可以存放重复的数据

单个集合的操作:

voidadd(intindx,Elmnt)在集合的指定下标indx处插入指定元素lmntEgt(intindx)返回本集合中指定下标indx处的元素Emov(intindx)移除本集合中指定下标indx处的元素Est(intindx,Elmnt)用参数元素lmnt替换集合中指定下标indx处的元素intindxOf(Objcto)判断指定元素o在本集合中第一次出现的下标,如果不存在,返回-intlastIndxOf(Objcto)判断指定元素o在本集合中最后一次出现的下标,如果不存在,返回-ListsubList(intfromIndx,inttoIndx)截取子集合,包含formidx处的元素,不包含toIndx处的元素

集合间的操作与集合的迭代

boolanaddAll(intindx,Collctionc)将参数集合c中的所有元素,插入到本集合中指定的下标indx处ListItratorlistItrator()返回此列表元素的迭代器,这个是List自己的,不太常用,可以逆序迭代

List接口的两个常用实现类ArrayList的特点:)底层的数据结构是数组,内存空间是连续的)元素有下标,通常可以根据下标进行操作)增删操作比较慢,查询操作比较快LinkdList的特点:)底层的数据结构是链表,内存空间是不连续的)元素有下标,但是通常首尾节点操作比较多)增删操作比较快,查询操作比较慢注意:LinkdList查询慢也不是都慢,首尾操作还是比较快的

简单方法:

voidaddFirst(E)添加首元素voidaddLast(E)添加尾元素EmovFirst()删除首元素EmovLast()删除尾元素EgtFirst()获取首元素EgtLast()获取尾元素Elmnt()获取首元素

功能一致但是名字不太好记的方法:

boolanoffr(E)添加尾元素boolanoffrFirst(E)添加首元素boolanoffrLast(E)添加尾元素Epk()获取首元素EpkFirst()获取首元素EpkLast()获取尾元素Epoll()返回并移除头元素EpollFirst()返回并移除头元素EpollLast()返回并移除尾元素

Map接口Map接口的特点map集合的结构是:键值对、KEY与VALUE、Map.EntryK,V的映射关系map中ky值不允许重复,如果重复,对应的valu会被覆盖map中的映射关系是无序的map没有自己的迭代器,所以迭代时通常需要转成st集合来迭代

简单方法:

voidclar()清空集合boolanquals(Objcto)判断集合对象与参数o是否相等inthashCod()返回本集合的哈希码值boolanisEmpty()判断集合是否为空intsiz()返回本集合中键值对的个数

map单个集合间的操作

boolancontainsKy(Objctky)判断map中是否包含指定的kyboolancontainsValu(Objctvalu)判断map中是否包含指定的valuVgt(Objctky)根据指定的ky返回对应的valu,如果不存在,返回nullVmov(Objctky)删除本集合中参数ky对应的键值对Vput(Kky,Vvalu)向集合中添加映射关系(键值对)voidputAll(Mapm)向本集合中添加m集合的所有映射关系(键值对)

map的迭代

Collctionvalus()把本map中的Valu值取出放入一个Collction中并返回这个CollctionStkySt()把本map中的Ky值取出放入一个St集合中并返回这个St集合StMap.EntryK,VntrySt()把本map中的每一对KV都看成是一个Entry,把所有的Entry取出放入一个St集合中并返回这个St集合

St接口St接口的特点st集合没有重复的元素st集合的元素是无序的st集合可以存null值,并且null最多有一个我们自定义对象如果想去重,需要在自定义类中添加重写的quals()与hashCod()集合学习的方法学习父级的公共方法,学习子类的创建方式,学习各种集合的特点关于List大多都是与下标有关的操作关于St通常都是去重的操作关于map通常都是映射关系,也就是键值对API要常练习,方法互相之间没有任何关系,用哪个,查哪个

.进程与线程

程序:数据与指令的集合,而且程序是静态的

进程:运行中的程序,给程序加入了时间的概念,不同时间进程有不同的状态,进程是动态的,代表OS中正在运行的程序进程有独立性,动态性,并发性

并行:相对来说资源比较充足,多个CPU同时并发处理多个不同的进程

串行:相对来说资源不太充足,多个资源同时抢占公共资源,比如CPU

线程:线程是OS能够进行运算调度的最小单位一个进程可以拥有多个线程,当然,也可以只拥有一个线程,只有一个线程的进程称作单线程程序注意:每个线程也有自己独立的内存空间,当然也有一部分共享区域用来保存共享的数据

线程的几种状态以及线程状态之间的切换)新建状态:创建线程对象,申请PCB,对应的是nw线程对象)就绪状态/可运行状态:万事俱备,只欠CPU,刚刚创建好的线程对象所有资源已经准备好,并且加入到了就绪队列之中唯有等待操作系统的调度,只要分配了CPU,也就是时间片,当前线程可立即执行,对应的是start()注意:调用start()并不会立即执行线程对象,这个是由OS的调度规则决定的。我们控制不了)执行/运行状态:就绪队列中的线程对象被OS选中,分配了时间片,正在执行注意:只有就绪状态才能变成运行状态)阻塞状态:线程在执行过程中遇到了问题,比如锁阻塞、休眠阻塞、等待阻塞…注意:我们的阻塞状态,等问题解决了以后/获取了临界资源后是加入到就绪队列中的,转为就绪状态,而不是转为运行状态直接执行)终止状态:线程成功执行完毕,释放资源,归还PCB6)线程的挂起:正在运行中的线程,由于CPU分配的时间片已经用完,所以需要冻结当前线程运行的状态与各项信息把它插入到就绪队列中,直到下次这个线程被调度执行时,重新恢复现场,继续执行

多线程编程实现方案一:xtndsThad继承方式)自定义一个多线程类用来继承Thad类)重写run()里的业务)创建线程对象)通过刚刚创建好的自定义线程类对象调用start()注意:不能调用run(),因为这样调用只会把run()看作一个普通的方法,并不会以多线程的方式启动程序而且调用start()时,底层JVM会自动调用run(),执行我们自定义的业务注意:我们除了可以调用默认的父类无参构造以外,还可以调用Thad(Stringnam),给自定义的线程对象起名字,相当于supr(nam);

多线程编程实现方案二:implmntsRunnabl实现方式)自定义一个类实现接口Runnabl)实现接口中唯一一个抽象方法run())创建接口实现类的对象,这个对象是作为我们的目标业务对象)创建Thad类线程对象,调用的构造函数是Thad(Runnabltargt))通过创建好的Thad类线程对象调用start(),以多线程的方式启动同一个业务targt注意:由于Runnabl是一个接口,无法创建对象,所以我们传入的目标业务类,也就是接口实现类的对象注意:只有调用start()才能把线程对象加入到就绪队列中,以多线程的方式启动,但是:接口实现类与接口都没有这个start(),所以我们需要创建Thad类的对象来调用start(),并把接口实现类对象交给Thad(targt);大家可以理解成“抱大腿”,创建的是Thad类的线程对象,我们只需要把业务告诉Thad类的对象就好啦使用方式二的优势:)耦合性不强,没有继承,后续仍然可以继承别的类)采用的是实现接口的方式,后续仍然可以实现别的接口)可以给所有的线程对象统一业务,业务是保持一致的)面向接口编程,有利于我们写出更加优雅的代码

多线程编程实现方案三:Excutors创建线程池的方式)创建线程池的工具类:Excutors.nwFixdThadPool(intn);可以创建包含最多n个线程的线程池对象)创建好的线程池对象:ExcutorSrvic使用pool.xcut()来讲线程池中的线程以多线程的方式启动,每次调用都会将一个线程对象加入到就绪队列之中这个线程池对象负责:新建/启动/关闭线程,而我们主要负责的是自定义的业务注意:线程池是不关闭的,实现的效果就是线程池中线程对象的随取随用,这样就避免了频繁的创建与销毁线程,不会造成资源浪费)合理利用线程池可以拥有的优势:.降低系统的资源消耗:减少系统创建与销毁线程对象的次数,每个线程都可以重复利用,执行多次任务.提高响应速度:当任务到达时,任务可以不用等待线程创建就能立即执行.提高线程的可管理性:可以根据系统的承受能力,调整线程池中线程的数目防止因为创建多个线程消耗过多的内存导致服务器的崩溃

多线程数据安全隐患的解决方案)出现数据安全问题的原因:多线程程序+多个线程拥有共享数据+多条语句操作共享数据)解决:加锁synchronizd同步关键字.同步方法,格式:在方法的定义上加synchronizd.同步代码块,格式:

    synchronizd(唯一的锁对象){        可能会出现数据不安全问题的所有代码    }

注意:锁对象必须唯一!!!比如:如果是实现接口的方式,只需要创建一个接口实现类对象。而这个对象当做的是目标业务对象,类中定义的锁对象自然也只有一个比如:如果是继承Thad类的方式,我们需要创建多个子类对象作为线程对象那这个时候不同的线程对象间应该共享同一把锁,所以需要把锁设置为静态,被全局所有对象共享而且建议,此种方式使用的锁对象是本类的字节码对象:类名.class注意:加锁时,同步代码块的范围需要考虑,不能太大,太大效率太低;也不能太小,太小锁不住注意:加锁时,锁对象的类型不做限制,只要保证锁对象唯一即可

同步与异步异步:是多个线程抢占资源的效果,不排队,所以效率高,但是数据不安全同步:每次只有一个线程独占资源,排队,所以效率低,但是安全,为了安全必要应该牺牲一部分资源

.注解

JDK自带的注解(个)要求大家掌握的是

Ovrrid注解,这个注解可以加在方法上,用来表示这是一个重写的方法元注解个元注解是用来定义其他注解的注解,也就是说,注解的语法与JAVA不同,是靠注解来定义的定义注解的格式:

intrfac注解名可以根据元注解对注解进行设置:表示被描述的注解可以使用的位置:值可以多选

Targt({ElmntTyp.TYPE,ElmntTyp.FIELD,ElmntTyp.METHOD})表示被描述的注解的声明周期:注意值只能选

Rtntion(RntionPolicy.RUNTIME/SOURCE/CLASS)自定义注解我们也可以根据自己的需求来定义个性化的注解:使用

intrfac注解名来定义的,主要使用的就是上面的两个元注解除此之外,我们还可以给注解加功能,比如注解的属性:格式:属性类型属性名();比如:intag();注意:定义了注解的普通属性以后,使用注解时必须给属性赋值,格式:

Ric(ag=0)如果给属性设置了默认值,那么使用注解时就不需要给属性赋值了,格式:intag()dfault0;我们还可以给注解添加特殊的属性valu,注意这个属性名字必须是valu,类型不作限制注意:特殊属性如果不设置默认值,使用注解时也需要赋值,不过赋值可以简写,比如

Ric(“appl”)特殊属性赋予默认值后,就可以直接使用注解了,赋予默认值的格式:Stringvalu()dfault“appl”;注意:如果有多个属性,并且都没有赋予默认值,那么使用注解时的格式:

Ric(valu=“appl”,ag=0)

.设计模式

概念:是一些前人总结出来的值得学习的编程“套路”,设计模式一共有种单例设计模式:确保代码中本类的实例只有一个实现思路:方案一:饿汉式)把本类的构造方法私有化–为了不让外界调用构造函数来创建对象)通过本类的构造方法创建对象,并把这个对象也私有化,为了防止外界调用)提供公共的全局访问点向外界返回本类的唯一的一个对象注意:公共方法需要设置成静态–需要跳过对象,通过类名直接调用这个返回本类对象的公共方法对象也需要设置成静态的–这个对象需要在静态方法中被返回,而静态只能调用静态方案二:懒汉式==延迟加载的思想:==我们有的时候有些资源并不是需要第一时间就创建出来,所以需要延迟到需要时再创建,这样既可以提升性能,又可以节省资源)把本类的构造方法私有化–为了不让外界调用构造函数来创建对象)创建了一个本类类型的引用类型变量)提供公共的全局访问点向外界返回本类的唯一的一个对象注意:这个公共的方法里,需要做判断如果引用类型的变量值为null,说明:之前没有创建过本类对象–创建后再赋值给引用类型变量,并把它返回如果引用类型的变量值不为null,说明:之前有创建过本类对象,这个引用类型变量保存就是地址值,本次不再新建对象,直接返回

6.反射

反射的概念反射是Java这门语言中比较有特点的一个特征,反射非常强大,我们可以通过反射获取目标类当中的资源,甚至是私有资源不仅仅如此,我们甚至还可以使用资源,并且创建对象,所以反射是一个经常被使用到的技术开发过程中,我们有的时候并不能拿到源代码,但是又需要使用资源,那这个时候反射的出现就很有必要了反射需要用到的API

获取字节码对象Class.forNam(“类的全路径”);注意:传入的是类的全路径名,包含包名.类名,而且会抛出异常类名.class注意:这个写法需要自己手动接一下获取到的字节码对象,不能用快捷方式的对象.gtClass();注意:经常与匿名对象一起使用获取包名类名clazz.gtPackag().gtNam()//包名clazz.gtSimplNam()//类名clazz.gtNam()//完整类名获取成员变量定义信息gtFilds()//获取所有公开的成员变量,包括继承变量gtDcladFilds()//获取本类定义的成员变量,包括私有,但不包括继承的变量gtFild(变量名)gtDcladFild(变量名)获取构造方法定义信息gtConstructor(参数类型列表)//获取公开的构造方法gtConstructors()//获取所有的公开的构造方法gtDcladConstructors()//获取所有的构造方法,包括私有gtDcladConstructor(int.class,String.class)获取方法定义信息gtMthods()//获取所有可见的方法,包括继承的方法gtMthod(方法名,参数类型列表)gtDcladMthods()//获取本类定义的的方法,包括私有,不包括继承的方法gtDcladMthod(方法名,int.class,String.class)反射新建实例clazz.nwInstanc();//执行无参构造创建对象clazz.gtConstructor(int.class,String.class)//要先获取构造方法c.nwInstanc(,”海绵宝宝”);//通过获取到的构造函数对象,创建目标类对象反射调用成员变量clazz.gtDcladFild(变量名);//获取变量fild.stAccssibl(tru);//使私有成员允许访问fild.st(实例,值);//为指定实例的变量赋值,静态变量,第一参数给nullfild.gt(实例);//访问指定实例变量的值,静态变量,第一参数给null反射调用成员方法Mthodm=Clazz.gtDcladMthod(方法名,参数类型列表);m.stAccssibl(tru);//使私有方法允许被调用m.invok(实例,参数数据);//让指定实例来执行该方法

关于反射的学习方式如果能够直接操作源码,就不需要使用反射反射经常用于源码与三大框架底层之中,熟练掌握有助于编程思想的提高反射的思路与正常使用略有区别,所以需要多练习,掌握这些写法重点参考笔记中的8个单元测试方法

反射技术详细笔记

,

1
查看完整版本: CGBTN2109汇总复习