java常识
1.jdk是java开发工具包,jre是java运行环境,jvm是java虚拟机,jdk包括jre,jre包括jvm,它们都在操作系统上运行。jdk和jre都可以单独安装,而jvm不能单独安装,假如给客户开发业务,只需要安装jre就可以了,因为jre安装简单迅捷,而且可以运行,客户不需要开发java程序,所以没有必要花时间安装jdk。jdk包含开发和运行组件,而jre是运行组件,开发需要运行来测试,程序最终在jvm上运行。
2.home键和end键可以使光标分别回到头和尾
3.单行注释是ctrl+/,多行注释是ctrl+shift+/
4.计算机只有硬件是无法工作的,需要软件驱动硬件才能工作,软件包括系统软件和应用软件,系统软件是直接与硬件交互的软件,如windows操作系统,Linux操作系统等,应用软件是运行在系统软件之中的
5.DOS命令,在Cmdr中点击鼠标左键,然后选中任意要复制的内容,然后再点击鼠标右键就粘贴好了。Dir列出当前目录下的所有子文件和目录。CD加绝对路径或者相对路径就跳到了这个路径目录下。cls清屏。切换磁盘,C:,D: 即可。CD…回到上级,CD\回到根目录。configure可以查看本机的IP地址,还可以查看网卡的物理地址,这个地址具有全球唯一性,也叫MAC地址,电脑有一个路由器网卡和一个网线网卡,ping www.baidu.com 可以得到百度的ip地址,ping +ip±t可以查看网络是否稳定,ctrl+c可以终止命令
6.JDK是java开发工具包,javase是java基础java标准版,javaee是主攻方向java企业版,javame是java微型版,java底层语言是c++,不是c,java源代码是开放的,java有垃圾自动回收机制,简称GC机制,c++需要手动释放,相当于有一个保洁。内存是运行过程中的临时存储空间,断电之后就消失了,cpu负责运算,主板将各个部件连接起来,硬盘是持久化存储,不会因为断电而丢失数据,对于java内存只能由虚拟机来操作,c或者c++容易导致内存泄漏。
7.java具有可移植性,就是跨平台,比如在windows,Linux上可以完全不修改代码运行,编译一次到处运行,这是因为java有一个jvm虚拟机,jvm是用c++写的,jvm是jdk的一部分,Linux和windows操作系统上下载的jdk是不同的版本,所以jvm也不同,但是相同的java代码通过不同的jvm虚拟机,就可以在不同的操作系统上运行。因此java程序是不能直接运行的,必须通过虚拟机,这就像flash在不同浏览器上需要不同的插件帮助才能运行
8.IP地址相当于计算机在同一个网络中的身份证号,唯一标识。
9.ctrl +y和ctrl+z重做和撤销,光标在末尾shift+home选中这一行,行首按shift+end选中这一行。home回到行首,end回到行尾,ctrl+home回到文件头,ctrl+end回到文件尾,双击选中一个单词,三击选中一行,ctrl+a全选
10.java程序有编译和运行两个阶段,程序员写的是.java的普通文本文件又叫做源代码,不能被Java虚拟机识别,必须通过javac.exe这个编译器先编译成.class的字节码文件,jvm只认识字节码文件。在windows上写的源代码可以在Linux上编译运行,windows上写的源代码编译的字节码也可以在Linux上运行,删除源代码,只要字节码也可以跨平台运行。但是源代码最好不要删除,不然没法修改。jvm其实是一个类加载器,它能识别类文件,即.class文件。注意字节码不是二进制文件,因为操作系统直接打交道的是二进制文件,jvm负责把字节码文件翻译成二进制文件,来被操作系统识别,windows和Linux上的jvm相当于不同的翻译官。编译阶段windows和Linux生成的字节码都是一样的。
11.代码的整个过程
a在硬盘的某个位置,新建一个.java文件
b用idea等工具打开这个.java文件
c在.java文件中编写符合语法规范的源代码
d保存源代码
e javac.exe(编译器)开始对.java文件进行编译,如果符合语法规则就会生成.class字节码文件,并且一个源代码可以生成多个字节码文件,如果不符合语法规则就会报错,并且完全不生成任何字节码文件,编译的实质就是检查语法
f生成字节码文件后,java.exe(运行器)对字节码文件进行运行。
g jvm负责将字节码文件装载进去并进行解释,解释为1010110010110…的二进制文件
h jvm会将二进制文件交给os操作系统,操作系统会执行二进制码和硬件进行交互
12.关于环境变量,配置jdk的bin目录,在bin目录中有javac.exe和java.exe等程序,配置好了环境变量之后windows就可以找到这些命令了。不配置的话操作系统是找不到这些命令的,还可以把javac和java等命令放入系统自带的环境变量system32目录下,只不过这样比较混乱。path环境变量就是为windows操作系统引路的,如果DOS窗口出现命令找不到的时候就可以通过设置环境变量来解决。打游戏可以将游戏启动exe文件设到环境变量中,通过DOS窗口启动游戏(装逼专用),path环境变量可以设置很多个,没什么影响。javac+源文件的路径就可以编译该源文件了,把源文件直接拖进DOS窗口就可以显示出绝对路径了,神操作:点到一个文件夹路径,然后在这个路径窗口输入Cmdr,Cmdr将直接跳到这个窗口。java+类名(不带class后缀)就可以运行了,JavaHome环境变量配置以适应Tomcat web应用,而classpath这个环境变量是为类加载器指路的,以后会用到
13.定义一个class,如果没有main方法psvm,只能编译,不能运行,psvm是程序的入口,类中还能写别的方法,但不是入口,注释:类的{}叫作类体,类体中有方法,其中有一个主方法,方法的{}叫做方法体,方法体中的代码依次逐行执行。java源文件中可以有多个class类,一个class生成一个class文件,一个萝卜一个坑,class不一定加public的类可以没有,但是如果有的话,必须和源文件的名字保持一致,public的类有且只能有一个,一般一个软件的入口只有一个,因此一般只写一个psvm
14.标识符就是程序员可以自己命名的东西,但是main除外,比如类名,方法名,常量,变量等,包含字母数字下划线美元符号不能以数字和其它符号开头,但是可以有汉字等。类名和接口名首字母全部大写,变量名和方法名第一个单词小写,后面首字母大写,常量名首字母全部大写并且单词与单词之间用下划线连接。使用变量之后内存空间就得到了复用。
15.一个字等于两个字节(byte),一个字节等于八位或者八个比特,一个比特就是一个1或者0,变量的数据类型规定死是为了开辟固定的内存空间。变量的三要素是数据类型,变量名和变量值。在java中,变量必须先声明并且赋值才能访问,变量就是一个存储数据的盒子,关于变量的作用域遵循出了大括号就不认识了,局部变量在函数执行完毕之后释放内存
16.数据类型包括基本数据类型和引用数据类型,基本数据类型包括八种int byte short long float double char boolean都是小写,而引用数据类型其实就是一个类名,比如String,byte short int long占用的字节(byte)分别1,2,4,8个,byte就是一个字节。float 和 double分别占用4,8个字节,char占用2个字节,boolean占用1个字节。整型,浮点型,布尔型都比较容易转换为二进制,但是字符型必须有一个编码方式,每个国家不同,字符编码包括编码和解码两个过程。计算机刚开始是为战争设计,不支持文字,后来才有了英语等文字,英文编码方式采用ASCII码,因为英文全是字母,只需要一个字节就够了,即256种就够了,所以英文在计算机方面占有优势,’a’其实对应97,先编码成01100001,再解码成’a’。如果编码和解码采用的不是同一个方式,就是出现乱码,比如utf-8和gbk,gbk是中国标准,utf是全国所有国家的标准,编码和解码一定要按照同一种标准
17.转移字符是\加上一个字母,\t是制表符相当于tab就是空好几个空格,\n是换行,\和\’标识普通的\和’
18.自动类型转换是指小容量可以转换为大容量,反之则不行,大容量要是想要赋值给小容量必须加强制类型转换符,但有的时候可能会损失精度,强制类型转换符是(强转类型)比如(int),加上去就能编译通过,运行可能损失精度,比如long转为int时直接把前面四个字节砍掉,当一个整数没有超过byte,short,char时可以直接赋值给这些类型的变量,超过了需要强转,但是要损失精度,byte,short,char做运算时是先转换成int再进行运算,多种数据类型做混合运算时,最终的结果是最大容量对应的类型,但是除了byte,short,char,它们会先变int再运算。
19.计算机采用二进制,并且是二进制的补码形式,因为这样的效率最高,注意:任何一个浮点型数据都比整型的容量大,复习103课的作业
20.&叫做逻辑与,&&叫做短路与,例如:
int x=10;
int y=11;
System.out.println(x>y&x>y++)
System.out.println(y)
输出为false ,11
int x=10;
int y=11;
System.out.println(x>y&&x>y++)
System.out.println(y)
输出为false ,12
短路与左边已经决定了对错右边就不会执行了,效率要高一些,但是有的场景需要使用逻辑与,或也是一个道理
21.赋值运算符先对等号右边的部分进行运算,再赋值给左边的变量,但是对于x=x+1和x+=1是有区别的,例如:
byte x=7;
x=x+1;
会报错,因为byte与int经行运算时byte会先转换成int,最终的结果是一个int,而把int赋值给一个byte是大范围赋值给小范围必须强转
byte x=7;
x+=1;
是对的,因为x+表示x的类型永远不会变化,总会把右边的转成x本来的类型,相当于x=(byte)(x+1),精度是有可能损失的
注意:有时候字符串的拼接x=”a”+x是不能用x+=”a”的,因为还有一个顺序的问题,所以遇到字符串的时候最好采用普通的写法
22.三目运算符
boolean sex=true;
System.out.println(sex ? “boy”:”girl”);
输出为boy
23.类型转换的六条规则:
a除boolean类型不能相互转换,其它其中基本数据类型都可以互相转换
b如果int型字面量没有超出byte,short,char的取值范围,那么可以直接赋值
c小容量向大容量可以自动转换,排序为:
byte1<short(char)2<int4<long8<float4<double8,char相比short可以表示更大的正数,字节数多不一定容量越大,因为float比long大,因为浮点型里面有比较复杂的幂运算,可以用少的字节表示更大的容量
d大容量转为小容量必须添加强制转换符,并且有可能损失精度
e byte,short,char混合运算时都会先转换成int类型,再做运算
f多种数据混合运算时,先转换成最大的那种数据类型再运算,e规则除外
24.switch在jdk8之后开始支持字符串,之前只支持整型,break用来终止离它最近的循环146到161是阶段回顾
25.判断一个数是不是质数不需要从1取到最后,只需要从2取到这个数减去1看中间有没有把这个数整除的,寻找一个数的因子只需取到这个数的一半,写完代码正确后要考虑有没有优化办法,可以在写题目的时候就写一个优化的标题提醒自己还要优化
26.main方法是代码执行的入口,由jvm虚拟机自动调用,然后自上而下依次逐行地执行,在main方法中可能有其它类和方法,在调用这些类和方法的时候也是自上而下地执行,除了main方法之外的所有方法都需要程序员手动调用,不调用的方法不会执行。方法执行完毕以后的局部变量自动释放内存(如果不释放,比如sum(int x,int y),再传入参数时x,y又被赋值,变量名重复了,这是不符合语法规则的,编译就不会通过),方法定义在类体当中,方法的顺序是没有关系的,方法可以极大的减少重复,c语言中叫函数,java叫方法。
[修饰符列表] 返回值类型 函数名(形式参数列表){
方法体;
}
形参可以任意命名,并且要规定数据类型,这里时int x,int y,传入的数据1,2叫做实参,形参与实参必须数量相同类型相同一一对应,如果一个方法没有返回值,就用void关键字填充,main方法不需要给jvm返回任何结果,return;可以直接终止这个方法。函数的调用方法是类名.方法名,调用自己类中方法时类名可以省略,外部类不能省略,可以用大容量的数据类型接受方法返回的小容量数据类型,自动转换
27.常见的错误,编译器不运行程序,只负责检查语法是否正确,例如:
public static int m(){
boolean flag=true;
if(flag){
return 1;
}
}是错误的因为在没有运行前,并不能保证这个方法就一定又返回值,必须加一个else return 。。。保证一定会有一个分支执行,或者直接在if之后加一个return 。。。还有就是只要return执行了,不管有没有返回值,这个方法都结束了,有时候return下面的某个语句永远无法执行,那么编译报错,一个语句必须要有执行机会,这里用三目运算符return flag?1:0
28.jvm的栈彻底贯彻了逐行执行的法则,栈中存方法和局部变量,main方法最先入栈,执行过程中如果有调用的函数就停下来,把这个调用的函数入栈,调用的函数还有可能调用函数,不停的压栈,直到最后一个方法彻底执行完毕,这个方法就被弹出栈,并且清除局部变量的缓存,方法区存代码,jvm的内存原理非常重要,在后期调错的时候有巨大的作用,详细191
29.java中允许方法名相同,但是参数不能相同,java编译器会通过参数的不同而区分开来,这种机制叫做方法的重载overload,功能相似可以考虑使用重载机制,重载机制需要满足在同一给类中,方法名相同,参数的类型或者顺序或个数不同这三个条件就是方法的重载
注意:public class a{
public static void main(String arg[]){
public static double sum和public static int sum
}函数重复了,编译不通过,也就是说方法的重载只和方法名和参数列表有关,与修饰符列表和返回值类型无关
}
30.递归三要素是结束条件,调用自身,减小规模

31.OOA(Object Oriented Analysis) 面向对象分析,OOD面向对象设计,OOP面向对象编程,这三步是实现软件的过程。PM是项目经理。属性是以数据形式存在的,而数据只能存在变量中,所以属性数一种变量,变量必须先声明,再赋值才能访问,成员变量会赋默认值,对像一定有自己的实例变量,所以说变量是一定要初始话的,只不过成员变量有可能使用默认值作为初始化。堆内存中存储对象以及对象的实例变量,栈中存储方法和局部变量,方法区存储字节码文件类名代码片段,见227,类名加属性是无法直接访问的,因为没有默认值,只有实例化以后才有默认值,方法当中的引用数据类型其实存的是一个地址,指向堆内存,这种方式叫引用
32.系统会自动给类定义一个无参数的构造方法,而这个构造方法被称为缺省构造器,构造方法名必须和类名一致,且修饰符列表统一写public,不能加static,不要任何返回值包括关键字void,构造方法的作用是给类完成属性的初始化,构造方法跟普通方法不一样,构造方法是通过new来实现的,new Student()是一种无参数构造方法,这种方法仅限于类中的构造方法没有定义的时候,当一个类没有定义构造方法时,系统会自动定义一个没有参数的缺省构造器,构造方法也存在重载的机制,见239,没有返回值,编译器会判定该方法是构造方法,发现构造方法与类名不同,编译器就会报错,当在堆内存new对象时才用构造方法设置对象参数,所以最好每次都写一个无参构造方法以确保成员变量都有默认值,无参构造方法虽然什么都没有写,但是实际上是在这个方法体中进行的实例变量默认值初始化,手动定义有参数的构造方法,无参构造方法就会消失,手动定义的有参构造方法如果有的成员变量没有赋值,系统就会自己赋默认值
这个图是构造方法的重载机制,可见new对象时输入什么参数就会使用哪种构造方法,不管使用哪种构造方法,成员变量一定是有值的,要么由new对象括号里设置参数,要么系统自动赋一个默认值,注意:如果手动写了一个有参构造方法,无参构造方法就消失了,就不能使用无参构造方法创建对象,只能使用自己手动写的有参构造方法new对象,这也是为什么要利用重载机制手动写上无参构造方法的原因,构造方法的本质作用是创建对象,还有给对象属性赋值
33.没有static的对象称为实例对象,没有static的方法称为实例方法,实例方法必须先构造实例对象才能通过点的方式调用,有static的方法和变量可以直接通过类名点方法的方式访问,把成员变量设置成私有的private,然后用get和set方法进行访问就可以设置关卡,比如set小于某个值就return,不让赋值,比如设一个输入密码等,set和get方法都是实例方法,不带static。static是类级别的可以修饰成员变量和方法,称为静态变量和静态方法,都是通过类名点的方式访问,没有空指针异常的发生。成员变量分为实例变量和静态变量,实例变量和实例方法都是对象级别的,采用引用点的方式访问堆内存中由构造函数构造的对象,引用赋值null会出现空指针异常,因为它没有地址指向谁。静态变量在类加载时初始化,不需要new对象,静态变量存储在方法区,实例变量一定需要引用.来访问,而静态变量既可以通过类名.来访问,也可以通过引用.来访问,但是不建议这样写,空指针只有空的引用访问实例变量时才会出现,如果一个方法需要实例变量就一般使用实例方法,工具类中的方法一般使用静态方法,静态代码块不常用,了解到258
34.this是一个关键字,全部小写,一个对象一个this,this是一个引用,this保存当前对象的引用地址,指向自身,所以this代表的就是当前对象,this存储在堆内存对象的内部,this永远代表当前对象,是一种泛指,this不能出现在静态方法中,在实例方法中或者构造方法中,为了区分实例变量和局部变量,this.是不能省略的,大部分情况下是可以省略的,this(实际参数列表)是通过一个构造方法去调用另外一个构造方法
35.成员变量分为静态变量和实例变量,静态变量存储在方法区,实例变量存储在堆内存,局部变量存储在栈中,在一个普通类中无法定义静态方法,只能在主类中定义
36.类定义时默认继承Object类,也就是说所有类的父类都是Object,继承一般使用在什么是什么的情况下,System是一个类,out是一个静态变量,类名.+静态变量嘛,而out同时还是一个对象,这个对象有一个方法叫做println,功能是打印出输入的参数,因为重载机制,参数可以数字符串,数字等,JDK写好了很多基础类,当源码中又native关键字时表示底层调用c++写的dll程序,继承的作用是方法复用和造成多态机制,访问权限不能更低只能更高,比如之前方法是public,现在不能是private,重写之后的方法不能比以前抛出更多的异常,只能更少,构造方法不能被继承,所以构造方法不能也不能被覆盖,私有方法无法覆盖,静态方法覆盖没有意义
37.多态具有向上转型和向下转型,无论是向上转型还是转型都需要具有继承关系,向上转型是子到父,向下转型是父到子,可以对比基本数据类型的自动类型转换和强制类型转换,分别对应向上转型和向下转型,什么时候需要向下转型,当需要调用子类特有的方法时。但是向下转型有风险,比如:java.lang.ClassCastException类型转换异常。
还有一个很经典的异常:java.lang.NullPointerException 空指针异常。在向下转型时一定要用instanceof来判断转型是否成功,多态就是多种形态,编译期是静态绑定,运行期是动态绑定,父类型的引用指向子类型的对象,编译器会判断子类型对象是否是父类型的子类对象,如果是编译通过,但是运行时new出来的是子类型对象,调用方法也是子类型,私有方法不能覆盖,静态方法不谈覆盖,覆盖和多态是一起说的,相辅相成
38.软件开发涉及七大原则,其中一条就是OCP原则,开闭原则,对添加开放,对修改关闭,比如对于主人喂养动物,修改主人的喂养方法不允许,因为这是在改源程序,添加宠物允许,因为这是加一个类,因此喂养的参数就设置成Animal,添加动物时就让动物去继承Animal然后编写代码,不需要修改主人的源代码,喂养的参数是Pet pet,传入new Cat(),实际上就是Pet pet=new Cat();父类型引用指向子类型对象,这就是多态在OCP中的应用,运行时用的是Cat,多态可以降低程序的耦合度,提高程序的扩展力
39.super是一个关键字,只能小写,super能出现在实例方法和构造方法中,super不能使用在静态方法中,super和this一样,只能出现在构造方法的第一行,super()的方式出现,通过当前的方法去调用父类的构造方法,目的是代码复用。new A();其实是一个方法,执行的是public A(){}的方法,new对象就是一个执行构造方法存入堆内存的过程,当一个构造方法第一行既没有this又没有super的话,会默认有一个super,表示通过当前子类的构造方法调用了父类的无参构造方法,所以必须保证父类中有无参构造方法,因此在定义类时都要把无参构造方法加上,this和super不能共存
40.final 关键字修饰类时这个类不能被继承,比如String,final修饰的函数无法被覆盖,final修饰的变量只能赋一次值,一旦赋值不能再重新赋值,既然final修饰的变量不会随对象变化而变化,所以final之前基本都要用static修饰,这样的好处是变量上升到类级别,不需要每次创建对象时都为变量在堆内存开辟一个空间,只需要在方法区开辟一份静态变量的空间就可以了,static和final联合修饰的叫做常量,常量名全部大写中间用下划线分隔,常量是一种特殊的静态变量,只是常量不能改变,都是存储在方法区,都是在类加载时初始化,因此常量一般都是公开的,用public修饰,public static final String COUNTRY=”China”;
41.抽象类无法实例化,所以抽象类天生就是为了被继承的,由于final修饰的类无法被继承,而abstract修饰的类无法被实例化,因此这两个词不能同时出现,否则就没有意义了,抽象类虽然不能被实例化,但是抽象类有构造方法供子类使用,对于super()当子类在new对象时,super在父类无法找到无参构造方法就会报错(比如这时父类写了一个有参构造方法,就会把无参构造方法覆盖掉,这也是每个类都要手动写上无参构造方法的原因),抽象方法没有方法体,没有大括号,以分号结尾,修饰符列表中有abstract关键字,抽象类中可以有抽象方法和非抽象方法,但是非抽象类中不能有抽象方法,一个非抽象类继承抽象类的方法必须把方法重写override,不然这个非抽象类就是抽象的,这显然是矛盾的,抽象类引用可以指向非抽象子类,这就是多态,面向抽象编程,这种编程思想符合OCP 原则,向上转型,自动类型转换,抽象类new不了创建不了对象,抽象类中不一定有抽象方法,抽象方法一定出现在抽象类中。
面试题(java语言中凡是没有方法体的方法都是抽象方法,错,因为c++底层代码有native的,就没有方法体,例如public native int hashCode();这个方法是Object调用了c++的动态链接库程序)
42.接口是特殊的抽象类,接口是完全抽象的,接口支持多继承,接口中只包含常量和抽象方法,接口中的public abstract关键字可以去掉,接口中所有的元素都是public修饰,接口中的方法不能有方法体,因为接口中所有的元素都是public的,所以重写方法的时候都要用public,继承机制访问权限只能更高,不能更低,范围只能更大不能更小,接口与接口之间在进行强制类型转换时,没有继承关系,也能强转,最终还是要加instanceof运算符进行判断,继承和实现都可以进行,extends关键词在前,implements关键字在后,接口通常是一种行为动作,接口在开发中的作用类似于多态在开发中的作用,接口是纯抽象的,面向抽象编程,面对接口编程。自己要能写出进阶38的foodMenu的案例,接口与多态的结合。任何一个接口都有调用者和实现者,调用者面向接口调用,实现者面向接口实现,接口将实现者和调用者解耦合,项目组围绕接口开发,这样效率非常高,凡是能用is a表示的用继承,用has a表示的用属性,用like a表示实现关系一般是类实现接口,分别对应A extends B ,A{B b},A implements B
43.java lang包下的类不需要导入,比如String和System,private修饰的变量只能在本类中用,public都可以访问,默认只能在本类或同包下访问,protect只能在本类或同包或子类下访问,访问权限中属性和方法四个都能用,类和接口只能用public和默认,默认类和public类中都可以写静态变量和静态方法,但是运行时只执行public类中的main方法
44.什么是api,应用程序编程接口,整个jkd的类库就是javase的api,每一个api都会配套一套api帮助文档application programming interface,可以判断两个基本数据类型是否相等,但是不能判断引用数据类型是否相等,因为引用数据类型存的是内存地址,所以这个时候就要把equals重写,见进阶56有重写方法,String要用equals,不能用,java.lang包已经把String的equals方法重写了,也就是说java包里的api都有object里面的方法,都进行了重写,sout加引用,这里会自动调用引用的toString方法
45.柱子建议:了解缓存和消息队列,数据库里用索引很重要,读写分离,高性能索引mysql必读,网络基础得熟悉,数据库索引,操作系统原理,jvm结构,垃圾回收,网路主要熟悉三种模型,每层的协议作用,特别是http和tcp,操作系统就死锁,虚拟内存lru,进程线程通信,io原理,内核态,海豹推荐:深入理解java虚拟机,java并发编程的艺术
46.数组是效率最高的索引方式,因为第一个数据的首地址知道,数组的地址是连续的,数据的字节大小知道,想要访问某个数据,只需要首地址加上索引乘上4(int)就可以找到数据,所以不管数据有多少检索效率都是非常高的,不是一个一个找,而是数学计算算出来的,缺点是为了保证数组中的元素的内存地址连续,数组上增加或者删除数据的时候,会涉及到数组元素统一向前或者向后移动的情况,再者数组很难找到一块非常连续的内存,所以数组的容量不能太大,数组包含静态初始化和动态初始化,动态初始化会设置默认值,引用数据类型为null,数组中必须存储相同的数据类型或者引用数据类型的子类,数组要扩容就要新建一个数组,把之前的数组数据拷贝进去,调用System.arraycopy()即可,具体使用方法见进阶81
47.Arrays有两种比较常用的静态方法,sort(数组)排序,binarySearch(关键字,数组),”中国人”.charAt(1)返回国,String.compareTo(String) 是比较字符串的排序,String.contains(String),String.endsWith(String)判断是否以某个字符串结尾类似还有startsWith方法,String.equalsIgnoreCase(String)忽略大小写判断是否相等,String.getBytes()获得一个byte数组值,是字符的ascii值,String.indexOf(Sting)获得字符串的下标索引
注意:判断数组长度是length属性,判断字符串长度是String.length()方法,length()方法可以用来判断字符串是否为空,String s=”abcdabcdab”.replace(“a”,”f”);把a替换成f再赋值给s,”abvdfj-fah-afj”.split(“-”);返回一个拆分数组,Sting.subString(a,b)左闭右开截取,当b不赋值时把a后面的全部截取下来,String.toCharArray()返回一个字符数组,String.toLowerCase() String.toUpperCase();分别转换为小写和大写。String.valueOf(x)是一种静态方法,把x转换为字符串,搜索源码双击shift,查看某个函数的源码按住ctrl用鼠标左键点击要查看的内容,System.out.println方法其实调用了valueOf方法,valueOf又调用了toString方法
48.每一个字符串的创建都需要在方法区中开辟一片空间,这时候需要用StringBuffer,它可以创建一个初始容量为16byte的数组,字符串缓冲区对象,用来拼接字符串,该数组有append方法。这是因为String对象都是final修饰的数组,它的指针不能改变,数组也无法扩容,创建一个就占用一个内存地址,而StringBuffer没有final修饰,指针可以改变,当进行字符串的拼接时重新创建一个数组,然后进行数组扩容,指针指向扩容后的数组,原先的数组被垃圾回收机制回收,因此它不会占用大量的内存,当用到比较大的字符串不想扩容,因为扩容的时间复杂度较大,StringBuffer可以设置容量大小,还有一个StringBuider效果差不多,但是StringBuider是非线程安全的,StringBuffer的方法都是synchronized修饰是线程安全的
49.八种基本数据类型和八种数据类型的包装类,包装类是为了有时候传入对象为Object,基本数据类型不能传入,为了让基本数据类型也能传入,把八种基本数据类型包装起来再传进去
byte java.lang.Byte
short java.lang.Short
int java.lang.Integer
long java.lang.Long
float java.lang.Float
double java.lang.Double
boolean java.lang.Boolean
char java.lang.Character
其中数字型对象,比如Integer i=new Integer(“123”);可以把整型123装箱成为一个整数对象,而i.intValue()和i.floatValue()等具有拆箱功能,把整型对象转换为基本数据类型。在jdk5之后具有自动拆箱和自动封箱的功能,比如Integer i=10;是自动封箱,把10封箱成索引为i的整型对象,int y=i;是自动拆箱,把拆箱赋值给y,当Integer 和int相加的时候会把Integer自动转化为int相加,Integer a=127中127没有超出 byte的取值范围,a会直接指向方法区提前创建好的常量池,如果再创建Integer b=127,b的引用跟a一样,也会指向常量池的127,而Integer c=128会在堆内存new一个Integer对象,如果再Integer d=128,d的引用跟c是不同的,池cache就是缓存,缓存的优点是效率高,缺点是占用内存,硬盘是机械交互,刷磁盘,速度慢,而内存是电流交互,速度快,大型项目都要用缓存,Integer有一个静态方法Integer.ParseInt(“123”);String直接转换为Int,返回一个int值,同理也有Double.ParseDouble(“123”);

50.System总结:
a System.out.println中out是System类的一个静态变量,out其实是PrintStream类,这个类中有一个方法是println。
System.gc();是建议启动垃圾回收机制
System.currentTimeMillis();取自1970年一月一日至系统当前时间的毫秒数
System.exit(0);退出JVM
BigDecimal,DecimalFormat作为了解
51.Random random=new Random();
int num=random.nextInt(bound);
枚举也是一种引用数据类型,枚举中的每一个量都可以看作常量,枚举也会生成class文件
enum Result{
Success,Fail;
}
Result相当于int void Student,且返回值为Result.Success,Result.Fail; 枚举是可以用于switch的,Scanner 接受输入,switch里面放入enum类的valueOf输入,然后case
52.异常在java中以类的形式存在,每当有一个错误发生都会new一个异常对象,JVM执行时会发现异常,异常分为可处理异常exception和不可处理异常error,exception又分为编译时异常和运行时异常,所有的异常都是发生在运行阶段,编译时异常表示如果这种异常不处理,编译阶段就提前报错,Object下有Throwable,Throwable下有error(直接退出jvm)和exception,exception分为编译时异常(exceptionsubclass)和运行时异常(runtimeexception在程序编写阶段可以处理也可以不处理),异常的发生就是new对象,new对象一定是运行阶段发生的,编译时异常发生的概率高,运行时异常发生的概率低,编译时异常相当于下大雨需要提前带伞,发生的概率较高,需要在运行之前就预处理,运行时异常发生的概率很低,没有必要在运行之前处理,如果运行时异常也要编译时处理,那么程序执行的效率就很低了。处理异常有两种方式,在throws关键字,一直往上面抛,如果抛给了main方法,main方法再抛给jvm,jvm最终就会终止程序,第二种方式是try catch语句进行异常的捕捉。比如分母为0这种异常属于运行时异常,这种异常不需要在运行之前处理,但是如果发生了还是会抛出异常

流就是把外部文件的内容读到java运行程序内存中,调用new FileOutputStream()时,idea会报红,这是因为FileOutputStream构造方法有一个声明throws FileNotFoundException,FileNotFoundException的父类是IOException,IOException的父类是Exception,所以FileNotFoundException是编译时异常,编译时异常要求程序员必须进行处理否则就会报错,throws后面可以使用多个异常用逗号隔开,一般不建议在main方法处上抛,因为上抛并不能解决全部问题,一旦发生异常虚拟机会抛出异常终止程序,而try catch的方式即使发生异常程序也会继续执行,

catch中的e实际上就是一个异常对象,就是jvm控制台输出的语句,输出e其实就是调用了e的toString方法,而且e是一个实例对象,里面有真实的错误信息,快速复制文件路径的方法就是点shift加右键,再点复制为路径,连起来就是shift右键加a,异常也是支持多态的,下面的异常可以用上面的异常代替,这样虽然可以用一个exception代替所有异常,但是最好还是一条一条地处理,这样有利于后期的调试和维护,catch可以写多个,而且大的异常一定要写在上面,小的异常写下面,try只用写一个,catch也可以写一个,里面的异常用逻辑或连接,如果希望调用程序的人自己修复异常就用throws,如果希望程序一直执行下去就用try catch自己处理
53.java中异常追踪时采用异步线程的方式打印,throw是抛异常,异常机制提高了程序的健壮性,程序执行不会因为异常而宕机
注意:怎么处理异常信息:一定要看自己的程序报错,不要看api里的错误,api是不会出错的,自己的程序报错一定要先看前面的,前面的会导致后面的错误,只有前面的正确了,后面的才会正确,处理完了前面的再处理后面的。
有的时候必须要用到finally,比如IO流文件打开必须关闭,而一旦出现异常,fs.close()就不会执行了,这时需要finally来保证出现异常也要执行,但是fs如果放在try里面就是局部变量了,所以fs的创建还是要在try的外面作为全局变量,但是close还会有空指针异常的风险,在finally里面还要处理空指针异常,try不能单独使用,但是可以和finally一起使用
54 面试题:final,finally,finalize有什么区别
finalize是垃圾回收机制为java程序员准备的一个时机,是一个方法,类似的还有静态代码块,static{},finalize有点像遗言,在某个对象或变量被回收时再留下一点指令,比如new 一个person对象其应用是a,重写person的finalize方法,因为finalize其实是object自带的方法,重写,输出“垃圾要被回收了”,然后把a指向空指针,person对象就变成了垃圾,这个时候就有可能进行垃圾回收,当然可以通过循环确保垃圾足够多,这就表明垃圾回收时finalize方法执行了,finalize是一个标志符,标志符是程序员写的变量名,方法名,类名,接口名等,jdk自带的api也是标识符,关键字是具有某种功能和限定的单词,比如public,final,static,class,void等,标识符不能与关键字同名
final是关键字,表示变量只能赋值一次,或者类或接口不能被继承,或者方法不能被重写
finally与try一起使用,表示必须执行的代码,除非System.exit(0);退出虚拟机,否则总会执行
55.在实际业务中有时需要自己定义一个异常类,都要继承RuntimeException运行时异常或者Exception编译时异常,然后写一个有参构造方法和一个无参构造方法,其实异常就相当于不符合某个条件然后提示,如果仅仅提示,调用的人不知道这个类有哪些异常,把提示改为编译时异常就可以让调用者处理这个异常,详细见进阶179,
问题:数组元素是object如何开辟空间?
回答:数组开辟空间其实就是开辟一片地址的空间,地址指向对象就,不管这个对象大还是小,都不会影响他们的地址大小,每个地址都是连续的且占用内存相同,因此查找某个索引并不是通过遍历的方式,而是通过第一个数据的内存地址,再通过数学方法计算出所需索引的内存地址,然后通过这个地址找到索引对应的对象,数组应该不能既有引用数据类型又有基本数据类型,因为基本数据类型开辟的空间是不同的。
子类抛出的异常不能比父类的异常更多,”abc”.equals(name)比name.equals(“abc”)好,nullname比namenull好因为不容易写成单等号,输入为字符串也会可能有空指针异常,所以都要在开头判断输入是否为null,null代表不确定的对象。
56.C++:int a=10;在方法体中在栈内存开辟空间,a中直接存放10。在成员变量中在堆内存开辟空间,指针也是一种数据类型,32位系统中所占内存大小为4个字节,64位系统中所占内存为8个字节intp=&a是将a的内存地址赋给p,p是解引用,把a地址中的值找出来,long表示long型指针数据类型,和int一样这样的指针占用内存为32位,可以用(int)把16进制转换为10进制,当p指向null(0)或0到255的地址时,*p不能再赋值,因为这些地址不允许访问,这会发生空指针异常,int p=(int )0x1010这种情况叫野指针,应该尽量避免
问题:一个指针占用4个字节,为什么输出是8个字母或数字,因为本来4个字节是32位的,但是地址是用16进制来表示的,可能是因为2进制位数太多太难看清楚的原因吧,而四位的二进制其实表示一个16进制数,因此32位的二进制用16进制表示出来就是8个字母或数字,32位的系统就是4个字节,64位的系统就是8个字节
57.C++:const int p=&a是常量指针,const修饰p,也就是说
p即地址内的值是不能改变的,但是地址可以改变,int const p=&a是指针常量,const修饰的是p,p是一个地址,所以地址不能改变,但是值可以改变,常量指针const和int的位置是可以交换的const int const
p=&a;指针指向的地址和地址中的值都不能改变,在C++中array代表数组的首地址
58.C++:函数的声明是为了让编译器知道main函数执行时有这个函数,只是函数可能写在了下面,函数的声明不需要方法体,声明可以有多次,但是定义只能有一次,函数形参不是地址时不会改变实参的值,函数形参是参数时可能会改变实参的值

59.java中的集合分为两类,一类是单个方式存储元素,这一类的超级父接口是java.util.Collection,这种方式都是可迭代的。一个是以键值对的方式存储这一类的超级父接口是java.util.Map,

List集合存储元素特点:有序可重复,存进去的元素顺序和取出的顺序相同,每一个元素都有下标,存进去一个1,可以再存进去一个1
Set集合存储元素特点:无序不可重复,存进去的元素顺序和取出的顺序不一定相同,没有下标,存进去一个1,不能再存1
SortedSet(SortedMap)集合存储元素特点:无需不可重复,但是可以按照大小顺序排序,Set其实就是Map的key部分
进阶190要求能画出集合的概念图

集合中不能存基本数据类型,虽然add(5)是可以的,但是这里其实有一个装箱机制,存进去的是Interger对象的内存地址,集合存储的都是内存地址
collection的方法有add(xx)添加元素,size()元素个数,clear()清空元素,contains(xx)是否包含某个元素,返回一个布尔类型,remove删除,toArray转成数组
collection有一个iterator方法可以获得一个迭代器对象,这个对象是一个Iterator类,实例对象有hasNext和Next方法,作用分别是判断下一个元素是否为空,返回下一个元素,collection的contains调用了equals,所以比较的是内容,放在集合里面的元素要重写equal方法,否则contains还是比较的地址,remove也是调用equals方法,先遍历找到equals一样的就进行删除,当集合的结构发生变化时,迭代器必须重新获取
60.ArrayList添加第一个元素以后数组初始化容量为10,size获取的是数组的元素个数,而不是容量,ArrayList扩容为原来的1.5倍,因为扩容的效率很低,所以建议初始化时控制好容量,这里扩容是运用二进制的移位运算,比如一个二进制数向左移动一位就是增大一倍,向右移动一位就是减小一倍,而扩容是本来的加上向右移动一位,所以是1.5倍,移位的符号是>>和<<,例如sout(16>>2)就是4,这里是int有32位,左移可以很多,右移太多会变成0,数组检索效率极高,增删效率很低,但是末尾增删元素效率还是很高的,ArrayList是用的最多的
61.链表的基本单元是Node,每一个节点都有两个属性,一个是存储的数据,一个是下一节点的内存地址,链表的优点是增删效率很高,因为不涉及到大量元素位移,缺点是查询效率较低,因为每一次查找某个元素都需要从头结点开始往下遍历,把非线程安全的ArrayList变成线程安全的,需要用到Collections中的静态方法synchronizedList把arrayList传进去,链表底层都是双向链表,想要单向自己写,集合中默认使用Object,但是这样会导致迭代器对象不好调用类的方法,每次都要转型,因此泛型可以规定集合中的元素是什么类型,泛型这种机制只对编译阶段起作用,泛型的缺点是导致集合中的元素缺乏多样性,钻石表达式说的是泛型在右边可以省略,如ArrayLista=new ArrayList<>();高版本后面可以不写

泛型有一个标识符,写什么都可以,一般写E或T,自己写的类就是这样定义泛型,在new对象的时候定义类型,new对象时不用就是默认Object,增强for循环的缺点是没有下标,在需要使用下标的循环中无法使用,而且需要输出的数据类型相同
62.Set是无序不可重复,指的是add的时候不会增加重复的元素,而且没有下标,因此,遍历的时候顺序是随意的,但是TreeSet会把无序的元素以排序的方式输出,实际上它本身还是无序的,这并不矛盾,类的静态内部类的静态方法,就是内里面有一个静态的类,这个类有静态方法,于是就有class.class.means这种用法,class大写,class大写,means格式是方法,就看出来了,实际上,map.entrySet返回的是一个Set集合,里面装的是Node元素,遍历Set,取Node.getKey和Node.getValue就可以取出键和值,Map. entrySet比起Map.keySet的好处在于entrySet直接得到了map的节点集合,集合中是节点,节点的key和value一次性取得,而keyset先找到key,通过key取遍历map获得value,效率较低,哈希值其实就是key值通过数学计算转换为数组的下标,一般用final int hash表示。
63.重点:
a.hash表的原理:map的底层原理是hash表,map.put(key,value)先把调用hashCode方法得到key的hash值,注意不同的key的hash值可能相同也可能不同,这很好的起到了分流的作用,然后hash值通过hash算法得到一个数组下标,在这个下标所对应的内存地址如果为null就把key,value封装成一个Node放进去。再次map.put(key,value),如果key通过算法算出的下标对应的内存地址已经有一个链表了,就在这个链表上遍历,如果找不到相同的key就把新Node添加到末尾,找到了就把找到的Node值改为新的值
b.map.get(key)还是通过算法找到key对应的下标看,这个效率和数组是一样的,时间复杂度为1,然后遍历链表,寻找与key相同的节点,找到了就输出节点的value,没找到就返回null
c.在查找方面,哈希表直接定位到key所对应的内存地址,而不需要把所有元素都遍历一遍,在小范围类遍历找到对应的key,这个效率比起全部遍历极大提高,删和增都是在链表上操作,所以不会整体移动,充分发挥了链表和数组的优势,事实上,哈希表的查询效率没有数组高,因为它还是要小范围遍历,增删效率也没有链表高,

放在hashMap中的key部分的元素要重写equals和hashCode方法,也可以解释为什么hash表的迭代是无序的,因为加进去一个键值对可能在任意位置,而迭代是按照数组下标,链表顺序输出的,迭代方法就是entrySet,而equals方法保证了hash表的key部分不可重复,而Set是HsahMap的key部分,因此set都是无序且不可重复的,因此hashSet中的元素也需要重写hashCode和equals方法,哈希表上的单向链表的key的hash值都是相等的,key的equals判定一定返回false,如果把hashCode的返回值设为相同的值,那么哈希表就变成了一条单向链表,这种情况被称为散列分布不均匀,如果把hashCode的返回值都设为不同的值,那么哈希 表就变成一个数组了,也是散列分布不均匀,散列分布均匀需要掌握一定的hashCode重写技巧,hashMap在下标百分之75被填充时就会扩容,hashMap初始化容量必须是2的倍数,这样有利于散列均匀。对于equals方法,当下标为null时不会调用equals方法,当下标部位null时得调用equals,而下标跟hashCode方法是关联的,因此想要要equals,重写了equals,就必须重写hashCode方法,并且equals方法返回true,hashCode也必须返回true,直接在idea工具生成就是了,但是要注意业务需求是不是判定同一个变量就是同一个商品,需要自己勾选,如果哈希表的某条链表节点超过8个,就会变成红黑树这种数据结构,其实这也很好的解决了一个疑问,那就是链表很长时,其实链表的增删效率会因为链表的查找效率太低而降低,因此用树结构来解决这个问题,hash值相同一定在同一条链表上,不同也可能在同一条链表,因为这涉及到hash算法,这种情况叫做hash碰撞,hashMap的key可以为null,但只能有一个,hashTable的key和value都不能为null
64.自平衡二叉树是左根右中序遍历,存放的过程就是排序的过程,取出来就是按照大小顺序排列的,遇到TreeSet或者TreeMap想要排序可以采用两种方式,第一种是放在集合中的元素实现java.lang.Comparable接口,第二种是在构造TreeSet或者TreeMap的时候给它传一个比较器对象,当比较规则不会发生改变的时候,或者比较规则只有一个的时候建议选择接口的方式,当比较规则经常改变建议使用使用有参构造比较器对象的方法,java集合的三种集合类型是set集,list列表,map映射,集合可以存放对象的引用,不能存放基本数据类型,具体见homework练习,对于TreeSet和TreeMap来说有两种排序的方式,一种是重写传入对象的Comparable接口,Comparable的泛型必须要与类相同然后重写compareTo方法,一种是在TreeSet创建对象的时候进行有参构造,传入一个匿名内部类,也就是new Comparator{
public int compare(Integer i1,Integer i2){
return i2-i1;
}
},匿名对象其实就是new 类名,匿名内部类其实就是一个对象,首先重写接口中的方法,这就变成了一个类,匿名,然后new这个类成为一个对象,还是匿名的,整个过程有两个匿名的过程,总之匿名内部类就是一个没有名字的对象。这两种方式会先用比较器,比较器的优先级更高,因此用比较器可以实现逆序排列,而重写排序方法就不行,因为有的类有final修饰,是无法继承修改的,如果不用匿名内部类还要专门写一个类来继承Comparator接口,new对象,很麻烦,所以匿名内部类作用还是很大的,注意Map是没有迭代器的,因为Map不是Iterator老祖宗的子类,Map必须通过keySet或者entrySet分别获得key集合或者Node集合才可以遍历,但是entrySet必需在迭代器生成的时候加一个泛型,因为Object类没有getKey,getValue方法,必须将Object改写为Map.entrySet<>泛型
65.
有的流是按照字节的方式读取数据的,一次读取一个字节byte,等同于一次读取八个二进制位,这种流是万能的。
有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,这种流不能读取声音视频图片等等,只能读取文本文件,连word都无法读取,比如汉字占用两个字节,字节读取方式就是一半一半的读,注意,在windows系统中char占用两个字节,在java中char占用一个字节,java中以stream结尾的都是字节流,以reader,writer结尾的都是字符流
65.java.io 有四大家族:
java.io.InputStream,java.io.OutputStream,java.io.Reader,java.io.Writer
它们都是抽象类,都实现了Closeable接口,都是可关闭的,都有close方法,流是硬盘和内存之间的管道,用完之后一定要关闭,而输出流都有flushable接口实现flush方法,作用是将管道剩余未输出的数据强行输出完,刷新的作用就是清空管道,否则可能会导致数据丢失

idea中当前默认路径是工程的根,这里会用到字符串的一些方法,复习前面的,硬盘的文件复制到另外一个文件,需要把文件中的数据以流的方式读入到内存中,然后再通过内存写入到另一个磁盘,中间的指挥是cpu的指令,也就是我们编写的代码,读和写是同时进行的
当一个流的构造参数是另外一个流时,这个负责包装的流就叫做包装流,这个传进来的流叫做节点流,节点流会自动关闭,包装流需要自己关闭,File类和四大家族没什么关系,是用来操作文件的。
66.一个进程就是一个应用程序,线程是进程的执行单元,一个进程可以启动多个线程,比如jvm进程中就有main方法和垃圾回收至少两个线程,堆内存和方法区是共存的,栈内存是独立的,使用多线程有,多线程有两种方式,一种是写类的时候继承Thread,一种是继承Runnable接口,然后要用的时候把继承接口的类传入线程的构造方法中,两者都要重写run方法,但是在执行的时候用start方法,实现接口比较好用,因为第一种方式不能继承别的类,第二种方式更灵活,第二种方式采用匿名内部类的方式代码更简洁,匿名内部类就是通过一个没有名字的类new出来的对象,start之后线程就具有了对cpu的抢占权,线程在就绪和运行之间频繁切换,当一个线程遇到阻塞状态,比如接受用户输入或者sleep方法,此线程就会放弃之前占有的cpu时间片

67.一个线程有五个状态:
a 新建状态 b 就绪状态 c 运行状态 d 阻塞状态 e 死亡状态
thread有一个静态方法,sleep让当前线程进入休眠,哪怕是new对象的sleep方法也会转换为类名的sleep方法,让当前线程进入休眠,当不能抛出异常不能用throws时多半是父类没有抛出异常,子类不能比父类抛出更多的异常,所以只能用try catch,而run方法在父类中没有抛出异常,所以子类中也无法抛出异常,方法重写时子类是不能抛出更多异常的,在JAVA中子类覆盖父类方法时,可以不抛出异常,如果抛出异常,只能抛出父类异常的子类。如果父类没有抛出异常子类也不能抛出异常,但是可以try,catch。还有就是方法重写时权限不能更低,比如toString重写时,父类都是public,子类只能是public,线程调度模型分为抢占式和均分式两种,抢占式最低优先级是1,默认优先级是5,最高优先级是10
68.重点:什么时候会存在安全问题a多线程并发b有共享数据c共享数据有增删改的行为。
在多线程并发的情况下,有共享数据,并且这个数据还会被修改,此时就存在线程安全问题。这时候需要线程排队执行,这种机制被称为线程同步机制,异步就是并发,同步就是排队
注意:要想保证两个线程共享同一个对象,操作这个对象,就要把这个对象作为有参构造传入到这个线程的类中,
具体见mythreadseven
synchronized关键字修饰共享对象,这个共享对象可以是常量池中的字符串,也可以是共享对象的某个属性,总之这个共享对象一定是要唯一的,这个共享对象是你想要排队的线程所共享的,总之因为共享所以才会排队,java中有三大变量,局部变量,全局变量,静态变量,其中永远不会存在线程安全的是局部变量,因为局部变量存在于栈中,栈中的东西不共享,实例变量在堆中,静态变量在方法区,都只有一个,有可能共享,synchronized修饰的范围越小,效率就越高。
成员变量包括静态变量和局部变量,线程安全主要是保护成员变量的安全,局部变量和常量没有线程安全问题,symchronized出现在实例方法上,表示整个方法体都需要同步,可能会无故扩大同步的范围,导致程序的执行效率降低,故这种方式不常用,使用局部变量的话,局部变量没有线程安全问题,使用StringBuilder而不是StringBuffer
具体见317面试题,对象锁有多少个对象就有几把说,类锁不管创建多少个对象都只有一把锁

symchronized在开发中最好不要嵌套使用,不然会出现死锁
69.怎么解决线程安全问题,在不得已的情况下再使用symchronized。
a.尽量使用局部变量和静态变量代替静态变量和实例变量
b.如果必须是实例变量,可以考虑创建多个对象,这样,实例变量就不同步了
线程其它知识:
a.守护线程:java中线程分为两大类,一类是用户线程,一类是守护线程,垃圾回收机制就是一个守护线程,守护线程一般是一个死循环,用户线程只要结束,守护线程就会结束,main方法是一个用户线程,只需要把线程调用setDaemon即可
b.定时器:每天00:00备份数据,这个需要用到定时器,并且可以将定时器设置为守护线程,一直在那里看着,所有的用户线程都结束了,守护线程也就结束了
c.实现线程的第三种方式:FutureTask方式,实现Callable接口
d.关于Object中的wait和notify方法,生产者和消费者模式
70.反射机制重要的类:
a.java.lang.Class 代表整个字节码,代表一个类型,代表整个类
b.java.lang.reflect.Method代表字节码中的方法字节码
c.java.lang.reflect.Constructor代表字节码中的构造方法字节码
d.java.lang.reflect.Field代表字节码中的属性字节码
获取到的对象需要可以调用newInstance方法创建对象,但是必须保证有无参构造方法
反射机制的灵活性,在不改变java源代码的基础上,可以通过只修改配置文件就获得不同的java对象,符合ocp原则,ssm,ssh等框架都是使用了反射机制,用Class.forName()静态代码块执行一次,且不需要new对象,如果只需要执行静态代码块不需要执行其它代码时考虑这种方式,如果使用的是相对路径,在代码移植时可能会出现一些问题,src是类的根路径,资源绑定器ResourceBoudle只能绑定properties文件,properties必须放置在类文件下
71.反射机制的作用有反编译(见348可以做一个反编译器),执行静态代码块,执行无参构造方法(必须有无参构造),

int…arg就是可变长度参数,比如输入10可以,10,20也可以,不输入也可以,可变长度参数只能有一个,且一定出现在最后一个,这里的arg可以看成是一个数组,遍历他。Modifier类有一个静态方法toString可以把修饰符列表值转换为对应的修饰符

反射机制可以调用配置文件的对象,如果想改变对象,只需要改配置文件就可以了,不需要修改源码
72.注解是给编译器看的,常用注解有Deprecated,不鼓励使用这样的注解,通常它很危险或者有更好的选择Override表示一个方法准备重写,元注解有Target和Retention,元注解是标注注解的注解。Target标注被标注的注解可以出现在哪些地方
73.jdbc操作六部:
a注册驱动(表明使用哪种数据库)
b获取连接(打开数据库和java的通道)
c获取操作对象(获取数据库对象才能操作,不解释)
d执行语句(crud)
e处理查询结果集(只有r需要)
f释放资源(基本操作)
jdbc:mysql://localhost:3306/bjpowernode
这里jdbc:mysql是网络协议也叫通信协议,通信协议是通信之前就提前定好的数据传输格式,数据包怎么传数据,相当于http,localhost是本机的ip地址,3306是软件代号,数据库端口号,这里对应的是mysql软件,bjpowernode是软件资源

这是Driver类的静态代码块,本来是要先获得驱动new Driver()再注册,即静态代码块里的东西,但是运用反射机制可以在获取反射对象的时候直接执行静态代码块,这种方式常用,因为参数是一个字符串,可以写到配置文件中,java的Driver是一个接口,而jdbc的Driver是已经实现好的Driver,是javaDriver的子类,可以用多态机制接受jdbc的Driver,然后注册驱动,当然也可以直接用jdbc的Driver的静态方法,注册驱动
net start mysql,net stop mysql分别是打开和关闭mysql
74.“select *from t_user where id=’” + id + “‘and name=’” + name + “’”;
字符串连接变量的格式是’”+变量名+”’,在这个sql语句中,如果把id写为2,name写为ff’or ‘1’=’1整条语句就变成了
“select *from t_user where id='2’and name=‘ff’or ‘1’=’1’”;
这个话中or后面是正确的判定,故这句话一定会select所有,而不需要管密码是否正确
75.注解可以出现在类上,方法上,属性上,变量上,甚至是注解上

java常识(小细节)相关推荐

  1. 学习Java,容易被你忽略的小细节(2)

    昨天心情真的太糟糕了,写完<学习Java,值得注意你注意的问题(1)>之后,迎来些许的支持以后就是一片片的谴责.我的主页上涌现出许许多多Java方面的牛人,谴责我水平太低,写的问题太初级. ...

  2. java小细节_为什么我喜欢Java的细节

    java小细节 他们说,Java太冗长了. 您可以找到Hello World程序的比较,这些程序在ruby中使用2行,在Java中使用10行,而要读取文件,您需要使用Java 20行和php中1行. ...

  3. java怎么让多个方法循环运行下去_35 个小细节,提升 Java 代码的运行效率!你知道几个?...

    原标题:35 个小细节,提升 Java 代码的运行效率!你知道几个? 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个 ...

  4. java图片上传并解析,详解SpringMVC实现图片上传以及该注意的小细节

    本篇文章主要介绍了详解SpringMVC实现图片上传以及该注意的小细节,具有一定的参考价值,感兴趣的小伙伴们可以参考一下. 先附上图片上传的代码 jsp代码如下: ![](${path}/mall/i ...

  5. java离职证明模板_离职证明的一个小细节,差点让我「背调」over

    终于拿下了鹅厂的offer. 久战职场,深知诚信的重要性,不管是简历还是面试表述,都不敢有任何的弄虚作假,在等待背调结果的几天里,虽然有一些莫名的小紧张,整体上也是满满的坦荡自信:随便调查吧,我没什么 ...

  6. java 性能优化小细节

    代码 优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用,但 ...

  7. 【Java常识】10.0 基本数据类型的自动装箱、拆箱、正则表达式

    1.0 基本数据类型有专门的包,这算是很常识了.但是有个小知识点,就是涉及自动装箱拆箱. 代码演示如下: package edp.com.learn1;public class Demo {publi ...

  8. 如何用C语言改变宏定义的大小,C语言中宏定义使用的小细节

    C语言中宏定义使用的小细节 #pragma#pragma 预处理指令详解 在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#p ...

  9. final关键字的这8个小细节,你get到几个?

    前言 大家好,我是狂聊君. 今天来聊 final 关键字,因为最近在看的几本书都讲到了 final 关键字,发现好多小细节自己都忽视了,抽空总结了一下,分享给大家. 正文 final关键字是一个常用的 ...

  10. 学长的求职经验 记录【就业创业信息网、求职流程、求职小细节】

    目录 1.就业创业信息网 2.求职流程 3.求职小细节 4.毕业设计 1.就业创业信息网 郑州轻工业大学 就业创业信息网:http://job.zzuli.edu.cn/   郑州大学 就业创业信息网 ...

最新文章

  1. c语言把地址用%d输出字符串,C语言必须要记住的经典程序
  2. 以游戏演绎1200多年前的古诗——《画境长恨歌》叙事设计思路分享
  3. Java创新型模式_java设计模式--创建型模式(一)
  4. em算法 实例 正态分布_EM算法解GMM
  5. 电脑没网络设备dns服务器没检测到响应,设备或资源dns没检测到有响应 网络无法连接...
  6. leetcode —— 206. 反转链表
  7. 退出域不能够重新加入域,郁闷呀
  8. ElasticSearch API实现CRUD
  9. Springboot启动扩展点超详细总结,再也不怕面试官问了
  10. SAP NetWeaver 平台介绍
  11. css中的滤镜,CSS中的filter(滤镜)属性
  12. 机器学习项目实战----信用卡欺诈检测(二)
  13. centos6.5解决方案-1
  14. 企业图纸共享办公系统哪个好
  15. 线性拟合(回归)的小结
  16. [51Nod 1035 最长的循环节] 循环小数的性质
  17. 怎么把wav文件改成mp3?
  18. Bmob后端云——Android再也不担心没有后台了
  19. 什么是PACS系统? 其特点是什么? PACS系统应该具有哪些功能?
  20. docker安装ElasticSearch8.1.0错误curl: (52) Empty reply from server的处理方法

热门文章

  1. 05Oracle P6培训系列:05创建项目
  2. mp4编码为hevc无法在浏览器播放的问题(java进行转码为h264)
  3. 考勤机信息同步不到服务器,考勤机实时同步功能上线啦
  4. Java_Dubbo视频教程-雷丰阳-专题视频课程
  5. ISO常见的17大体系介绍
  6. Oracle JDE 系统架构总结..
  7. SoapUI接口测试——添加新的API接口——new rest service from uri
  8. SpringBoot项目解决 log4j2 核弹漏洞
  9. 邮件小技巧:让同一个收件人地址同时显示在收件人和抄送人栏中
  10. 录屏软件电脑版哪个好?4个电脑免费录屏软件推荐