构造器总结:
类中有缺省构造器,不一定要定义构造器
构造器不能被继承,因此不能被重写,但可以被重载
方法可以和类同名,和构造器区别在于必须要有返回值类型
一个类可以定义多个参数列表不同的构造器,实现构造器重载
在调用子类构造器之前,会先调用父类构造器
当子类构造器中没有使用"super(参数或无参数)"指定调用父类构造器时,是默认调用父类的无参构造器
如果父类中包含有参构造器,却没有无参构造器,则在子类构造器中一定要使用“super(参数)”指定调用父类的有参构造器,不然就会报错。
抽象类和接口的区别:
- 抽象类体现继承关系,一个类只能单继承。接口体现实现关系,一个类可以多实现。
- 抽象类中可以定义非抽象方法和抽象方法,子类继承后可以直接使用非抽象方法;接口的方法都是抽象的,必须由子类实现。接口中的成员都有固定的修饰符
- 抽象类由构造方法,用于给子类对象初始化;接口没有构造方法
- 抽象类不可以实例化,即不能用new创建对象。抽象类必须由子类覆盖了所有的抽象方法后,该子类才可以实例化,否则,这个子类也是抽象类。
- 抽象类关键字abstract不能和final,static,private关键字共存
- 接口中声明变量必须是final,public,static的,接口中定义的方法都是abstract,public的。接口里的数据成员必须初始化,且全是常量,不是变量
- 接口也可以通过关键字extengs来继承其他接口
DBMS事务:
四大特性:原子性,一致性,持久性,隔离性
只有存在并发数据访问时才需要事务
原子性:事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败
一致性:事务结束后系统状态是一致的
隔离性:并发执行的事务彼此无法看到对方的中间状态
持久性:事务完成后所做的改动都会被持久化
原子性实现事务管理子系统
一致性实现完整子系统
持久性实现恢复管理子系统
隔离性实现安全控制管理子系统
脏读:a事务读取b事务尚未提交的数据,并在此基础上操作,而b事务执行回滚,那么a读到的数据就是脏数据
不可重复读:事务a重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务b修改过了
幻读:事务a重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务b提交的行
丢失更新1:事务a撤销时,把已经提交的事务b的更新数据覆盖了
丢失更新2:事务a覆盖b已经提交的数据,造成事务b所做的操作丢失
Java内存:
Java把内存分为两种,一种是栈内存,一种是堆内存
在函数中定义的一些基本数据的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码中定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。
堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就会变成数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或对象,引用对象相当于为数组或对象起的一个别名,或者代号。
引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候(引用变量x=null),才会变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。
总结:在jdk1.7中,将常量池放入堆内存。
栈存放引用,堆存放new对象和数组,常量池存放常量。
方法区:方法中的局部变量,存放在方法运行时临时建立的方法栈中,其随着栈的销毁而结束
基本数据类型栈中的值就是实际存储的值,引用类型栈中的值就是指向堆中的地址
Java垃圾回收机制:
Java提供了一个系统级的线程,即垃圾回收器线程。用来对每个分配出去的内存空间进行跟踪。当JVM空闲时,自动回收每块可能被回收的内存,gc是完全自动的,不能被强制执行。但是可以通过system.gc()或runtime.getRuntime().gc()来建议执行垃圾回收器,垃圾回收的时间和顺序是无法预知的。
在jvm垃圾收集器收集一个对象之前,一半要求程序调用适当的方法释放资源,但在没有明确释放资源的情况下,Java提供了默认机制终止该对象来释放资源,这个方法就是finalize()。它的原型为protected void finalize() throws Throwable。在finalize()方法返回之后,对象消失,垃圾收集开始执行。原型中的throws Throwable表示它可以抛出任何类型的异常。
当对象的引用变量被赋值为null,可能被当成垃圾
局部变量存放在栈上,栈上的垃圾回收,由finalize()来实现,gc用于堆。
Java中的垃圾收集器相对于以前的语言的优势是:
C语言要求成需要显示的分配内存,释放内存。程序在需要时分配内存,不需要时释放内存。但是这种做法常常引起内存泄漏,即由于某种原因使分配的内存始终没有得到释放。如果该任务不断地重复,程序最终会耗尽内存并异常终止,至少无法继续运行。相比之下,Java不要求程序员显示地分配内存和释放内存,避免了很多潜在问题。Java在创建对象时会自动分配内存,并当该对象的引用不存在时释放这块内存。
在Java语言中,判断一块空间是否符合垃圾收集器收集标准的标准:
1) 给对象赋予了控制null,以后再没有调用过
2) 给对象赋予了新值,即重新分配了内存空间
但是,一块内存空间符合了垃圾收集器的收集标准,并不意味着这块内存空间就一定会被垃圾收集器收集。
Java异常处理机制:
try-catch-throw-throws-finally
- try语句:用大括号{ }指定了一段代码,该代码可能会抛出一个或多个例外
- catch语句:Java运行时系统从上到下分别对每个catch语句处理的例外类型进行检测,直到找到类型相匹配的catch语句为止。因此catch语句的排列顺序应该是从特殊到一般。
- finally语句:try所限定的代码中,当抛弃一个例外时,后面的代码不会被执行。通过finally语句可以指定一块代码。无论try所指定的程序块中是否会抛弃例外,也无论catch语句中的例外类型是否与所抛弃例外的类型一致,finally所指定的代码都会被执行,它提供了统一的出口。通常在finally语句中可以进行资源的清除工作。
- throws语句:总是出现在一个函数头中,用来标明该成员函数可能抛出的各种异常。对大多数exception子类来说,Java编译器会强迫你声明在一个成员函数中抛出异常的类型。如果异常的类型是error或runtimeexception,或它们的子类,这个规则不起作用,因为这在程序中的正常部分中是不期待出现的。如果你想明确抛出一个runtimeexception,你必须用throws语句来声明它的类型。
- throw语句:总是出现在函数体中,用来抛出一个异常。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中从里到外寻求含有与其匹配的catch子句的try块
try-catch-finally 规则( 异常处理语句的语法规则 ):
- 必须在 try 之后添加 catch 或 finally 块。try 块后可同时接 catch 和 finally 块,但至少有一个块。
- 必须遵循块顺序:若代码同时使用 catch 和 finally 块,则必须将 catch 块放在 try 块之后。
- catch 块与相应的异常类的类型相关。
- 一个 try 块可能有多个 catch 块。若如此,则执行第一个匹配块。即Java虚拟机会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或 其子类的实例,就执行这个catch代码块,不会再执行其他的 catch代码块
- 可嵌套 try-catch-finally 结构。
- 在 try-catch-finally 结构中,可重新抛出异常。
- 除了下列情况,总将执行 finally 做为结束:
JVM 过早终止(调用 System.exit(int));在 finally 块中抛出一个未处理的异常;计算机断电、失火、或遭遇病毒攻击
catch只会匹配一个,因为只要匹配了一个,虚拟机就会使整个语句退出
throws和throw的区别:
throws:写在方法声明之后,表示方法可能抛出异常,调用者需要处理这个异常
throw:写在在方法体中,表示方法一定会抛出一个异常,要么try…catch处理,要么throws抛出
throw是语句抛出一个异常
throws是方法抛出一个异常
throw要么和try-catch-finally语句配套使用,要么与throws配套使用。但是throws可以单独使用,然后再由处理异常的方法捕获。Throws a,b,c只是告诉程序这个方法可能会抛出这些个异常,方法的调用者可能要处理这些异常,而这些异常可能是该函数体产生的;而throw是明确这个地方要抛出这个异常
Java监视器机制:
监视器:用于监控与调度多个线程如何进入特殊房间的基础设备,确保只有一个线程访问受保护的数据或代码
实现:在Java虚拟机(JVM)中,每一个对象(Object)和每一个类(Class)都在逻辑上与某一个监视器(monitor)关联在一起。为了实现所有的这些监视器(monitors)之间的相互排斥能力,每一个对象(Object)和每一个类(Class)都具有一个锁(lock, 也称互斥锁(mutex))。如果一个线性获得了某些数据上的一个锁(lock),那么,直到该线程释放该锁之前,其他的线程都无法获取该锁。为了声明一个监控区域,该监控区域最多只允许一个客户(线程)访问,Java提供了同步语句(synchronization statements) 和 同步方法(synchronization methods) 两种便利机制。一旦某个代码块被 synchronized 关键词包围,该代码块就变成了一个监控区域。
在一个程序当中代码段访问了同一个对象从单独的并发的线程当中,那么这个代码段叫“临界区”
解决方法:使用同步的机制对临界区进行保护
同步的两种方式:同步语句和同步方法
对于同步来说,都是使用synchronized方法
每个对象都有一个监视器,或者叫做锁
Java用监视器机制实现了进程之间的异步执行
MySQL最左前缀原则:
最左前缀:组合索引的第一个字段必须出现在查询组句中,这个索引才会被用到。
只要组合索引最左边第一个字段出现在Where中,那么不管后面的字段出现与否或者出现顺序如何,MySQL引擎都会自动调用索引来优化查询效率。
根据最左匹配原则可以知道B-Tree建立索引的过程,比如假设有一个3列索引(col1,col2,col3),那么MySQL只会会建立三个索引(col1),(col1,col2),(col1,col2,col3)。
Httpservlet容器响应web客户请求流程:
- web客户向servlet容器发出http请求
- servlet容器解析web客户的http请求
- servlet容器创建一个httprequest对象,在这个对象中封装http请求信息
- servlet容器创建一个httpresponse对象
- servlet容器调用httpservlet的service方法,这个方法中会根据request的method来判断具体是执行doGet还是doPost,把HttpRequest和HttpResponse对象作为service方法的参数传给HttpServlet对象
- HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息
- HttpServlet调用HttpResponse的有关方法,生成响应数据
- Servlet容器把HttpServlet的响应结果传给Web客户。 doGet() 或 doPost() 是创建HttpServlet时需要覆盖的方法.
log4j
打印日志的组件,支持按分钟/年为间隔生成新的日志文件,不可以在运行时重新设置
log4j的组成:
日志记录器(Loggers):控制要禁用哪些日志记录语句,并对日志信息进行级别限制
输出端(Appenders):指定了日志将打印到控制台还是文件中
日志格式化器(Layout):控制日志信息的显示格式
Logger对象的获得或创建:Logger被指定为实体,由一个String类的名字识别
Logger logger =Logger.getLogger(Class clazz)
日志级别:每个Lgger都被指定了一个日志级别,用来控制日志信息的输出
- error:指出虽然发生错误事件,但仍然不影响系统的继续运行
- warn:表现会出现潜在的错误情形
- info:强调应用程序的运行全程
- debug:对调试应用程序有帮助
.logger.setLevel(Level.INFO);logger.info(“…”);
JVM内存模型:
Java虚拟机运行时数据区域:
程序计数器
是一块较小的内存空间,可以看作当前线程所执行的字节码行号指示器
- 线程私有,各线程之间不影响
- 在任何一个确定的时刻,一个处理器都只会执行一条线程中的指令
- 字节码解释器工作就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖计数器来完成
- 如果正在执行Java方法,计数器记录的是正在执行的虚拟机字节码指令地址
- 如果是native方法,则计数器值为空(native方法:指的是Java程序调用了非Java代码,是一种引入其他语言程序的接口)
- 程序计数器也是在Java虚拟机中唯一没有规定r任何OutOfMemeoryError异常情况的区域
Java虚拟机栈:
- 线程私有,生命周期与线程相同
- 虚拟机栈是执行Java方法的内存模型(字节码)服务:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表,操作数栈,方法链接,方法出口等信息
- 每个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程
局部变量表:32位变量槽,存放了编译期可知的各种基本数据类型,对象引用,returnAddress类型
操作数栈:基于栈的执行引擎,虚拟机把操作数栈作为它的工作区,大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈
动态链接:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用。持有这个引用是为了只支持方法调用过程中的动态链接。Class文件的常量池中有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用为参数。这些符号引用一部分会在类加载阶段或第一次引用的时候转化为直接引用,这种转化称为静态解析。另一部分将在每一次的运行期间转化为直接引用,这部分称为动态链接。
方法出口:返回方法被调用的位置,恢复上层方法的局部变量和操作数栈。如果无返回值,则把它压入调用者的操作数栈
本地方法栈
为虚拟机使用的native方法服务
Java堆
Java虚拟机所管理的内存中最大的一块
- 线程共享,在虚拟机启动时创建
- 唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存
- Java堆是垃圾收集器管理的主要区域,也称“GC堆”
- 从内存回收角度看,Java堆分为:新生代、老生代(再细分:Eden空间、From Survivor空间、To Survivor空间等)
- 从内存分配的角度看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer , TLAB)
- Survivor空间等Java堆可以处在物理上不连续的内存空间中,只要逻辑上是连续的即可
- 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常
方法区
- 线程共享,用于储存已被虚拟机加载的类信息、常量、静态变量,即编译器编译后的代码、,方法区也成为持久代
- 方法区主要存放Java类定义信息,与垃圾回收关系不大,可以选择不实现垃圾回收,但不是没有垃圾回收
- 方法区域的内存回收主要是针对常量池的回收和对类型的卸载
- 运行时常量池,也是方法区的一部分,虚拟机加载class后把常量池中的数据放入运行时常量池
运行时常量池
常量池:常量池数据编译期被确定,是class文件中的一部分,存储了类、方法、接口等中的常量,当然也包括字符串常量
字符串常量池:常量池的一部分,存储编译期类中产生的字符串类型数据
运行时常量池:线程共享。方法区的一部分。虚拟机加载class后把常量池中数据放入到运行时常量池。相对于class文件常量池的另一个重要特性是具备动态性
JDK1.6之前字符串常量池位于方法区
JDK1.7字符串常量池被放在堆中
直接内存
是虚拟机运行时数据区的一部分,也不是JAVA虚拟机规范中定义的内存区域,但是这一部分内存被频繁使用,也可能导致OUTOFMEMORYERROR异常出现。