1.接口和抽象类之间的区别
解析:接口是一种特殊形式的抽象类,使用接口完全有可能实现与抽象类相同的操作,但一般而言,抽象类多用于在同类事物中有无法具体描述的的方法的场景,所以当父类和子类之间存在逻辑上的层次结构时,推荐使用抽象类,而接口多用于不同类之间,定义不同类之间的通信规则,所以当希望支持差别较大的两个或者更多对象之间的特定交互行为时,应该使用接口。使用接口能大大降低软件系统的耦合度。
重要重要重要!!!:
接口和抽象类是支持抽象类定义的两种机制,接口表示一个实体,抽象类表示一个概念。
接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法和私有变量的,如果一个类中包含抽象方法,这个类就是抽象类。使用abstract来表示一个类是抽象类。接口就是指一个方法的集合,接口中所有的方法都没有方法体(jdk1.8以后可以有方法体!!!!)。
包含一个或多个抽象方法的类必须被声明为抽象类,抽象类可以声明方法的存在而不去实现它,被声明为抽象的方法不能包含方法体!!!。在抽象类的子类中,实现方法必须含有相同的或者更低的访问级别。抽象类在使用的过程中不能被实例化,但是可以创建一个对象使其指向具体子类的一个实例。抽象类的子类为父类中所有的抽象方法提供具体的实现,否则,他们也是抽象类。接口可以被看作抽象类的实体,接口中的方法都是抽象的,可以通过接口来间接地实现多重继承。接口中的成员变量都是static final类型。
共同点:
-
都不能被实例化
-
接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能被实例化
区别:
-
接口只有定义,不能有方法的实现;抽象类可以有方法的定义和实现,即其方法可以在抽象类中实现
-
一个类可以实现多个接口,但是只能继承一个抽象类
-
接口强调特定功能的实现,设计理念“has-a”聚合关系,抽象类强调所属关系,设计理念“is-a”继承关系
-
接口中定义的成员变量默认为public static final,只能够有静态的不能被修改的数据成员,而且,必须给其赋初值,其所有的成员方法都是public/abstract的,而且只能被这两个关键字修饰。
-
抽象类可以有自己的数据成员变量,也可以有非抽象的成员方法,抽象类中的成员默认为default,也可以被定义为private/protected/public,这些变量可以在子类中重新被定义,也可以重新赋值。抽象类中的抽象方法(必须有abstract修饰)不能有private/static/synchronized/native等访问修饰符修饰,同时方法必须以分号结尾,不能有方法体。有功能需要累积的时候使用抽象类;不需要累积的时候使用接口。
-
接口被运用于实现比较常用的功能,便于日后维护或者添加删除方法,抽象类更倾向于充当公共类的角色,不便日后的维护和修改。
实际使用的时候,接口可以继承接口,抽象类可以实现接口,抽象类也可以继承具体类。
2.覆写是指派生类方法覆盖基类方法,覆盖一个方法对其重写,以起到不同的作用。
需要注意以下几点:
-
派生类中的覆盖方法必须要和基类中被覆盖方法有相同的函数名和参数
-
派生类中的覆盖方法的返回值必须和基类中被覆盖方法的返回值相同
-
基类中被覆盖方法不能为private,否则,其子类只是定义了另外一个方法,并没有对其覆盖
-
子类方法不能缩小父类方法的访问权限
-
子类方法不能比父类方法抛出更多的异常
3.Java代码整体结构
package是Java中特有的内容,它的作用就是把若干类按包结构进行分类管理,最重要的用途就是为了解决同名但作用不同的类同时存在的问题
在java语言中,package语句必须作为Java源文件的第一条语句,指明该文件中定义的类所在的包。
Java类或接口有这样的命名规则:被public修饰的类或者接口必须与文件名相同(因为一个java文件中只能有一个public修饰的类)
4.Java运行环境
Java程序被编译后并不是生成能在硬件平台上可执行的代码,而是生成了一个中间代码,不同的硬件平台上会安装有不同的JVM,由JVM来负责把中间代码翻译成硬件平台能执行的代码。
运行顺序:java程序-->JRE/JVM-->操作系统-->硬件
5.接口的理解
Java接口是一系列方法的声明,是一些方法特征的集合。一个接口只有方法的声明,但没有方法的实现,因此,这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同行为(功能)。通常,接口中定义的成员变量默认为public static final,只能够有静态的不能被修改的数据成员,而且,必须给其赋初始值,其所有的成员方法都是public,abstarct的,只能被这个两个关键字修饰
6.String中没有char方法,使用char方法编译会失败
7.访问控制修饰符作用的范围
修饰符 |
对象本身 |
同一个包下 |
子类 |
其他包 |
public |
√ |
√ |
√ |
√ |
protected |
√ |
√ |
√ |
× |
default |
√ |
√ |
× |
× |
private |
√ |
× |
× |
× |
允许作为类以及类成员的访问控制符的是public protected private
8.重载
是在一个类中多态的表现,是指在一个类中定义了多个同名的方法,他们或有不同的参数个数,或有不同的参数类型。在使用重载时需要注意:
-
重载是通过不同的方法参数来区分的,例如,不同的参数个数、不同的参数类型、不同的参数顺序
-
不能通过方法的访问权限、返回值类型和抛出的异常类型来进行重载
Java不支持返回类型不同的重载,也就是重载的方法必须具有相同的返回值
如果使用返回值进行重载的话,会使得程序产生二义性。
例如public int f(int a, int b) public float f(int a, int b),Test test = new Test(),test.f(1,2),程序不知道该使用哪一个方法
9.继承
继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并扩展新的能力,子类能继承父类的公有(public)和受保护(protected)的方法和属性,但是不能继承私有方法和属性。
继承情况下的构造方法的使用:
-
在创建子类对象的时候,必定会首先调用父类的构造方法,然后再调用子类的构造方法
-
构造方法是不能被继承的
-
当子类没有显式的调用构造方法的时候,编译器会自动的调用父类的无参数的构造方法,子类不可以通过super()调用父类的构造方法
子类通过继承可以继承父类的所有成员,私有的可以通过反射获得(注意是私有属性通过反射获取)
覆写:
-
派生类中的覆盖方法必须和基类中被覆盖的方法有相同的方法名或参数
-
派生类中的覆盖方法的返回值必须和被覆盖方法的返回值相同
-
基类中被覆盖方法不能用private修饰,否则子类只是定义了一个方法,并没有对其覆盖。
-
子类不能缩小父类的访问权限
-
子类不能抛出比父类更多的异常
10.面向对象的基础知识
-
类可以被理解为变量和方法的集合体
-
类成员数据可以是公有的,也可以是私有的,封装的时候就是私有
11.8种基本类型的字节大小
byte |
1 |
short |
2 |
int |
4 |
long |
8 |
boolean |
1 |
char |
2 |
float |
4 |
double |
8 |
12.Java代码的初始化顺序
父类静态变量->父类静态代码块->子类静态变量->子类静态代码块->父类非静态变量->父类非静态代码块->父类构造方法->子类非静态变量->子类非静态代码块->子类构造方法
13.面向对象的基本特征
-
抽象:就是忽略一个主题中与当前目标无关的那些方面,以便更充分的注意与当前目标有关的方面,抽象并不打算了解全部问题,而只是选择其中一部分,暂时不用关注细节。抽象有两个方面内容:1、过程抽象 2、数据抽象
-
继承:
-
封装:指将客观事物抽象成类,每个类对自身的数据和方法实行保护,类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐蔽
-
多态:指允许不同类的对象对同一消息做出响应。多态包括参数化多态和包含多态。多态性语言具有灵活、抽象、行为共享和代码共享的优势,很好的解决了应用程序方法同名的问题
14.ArrayList、Vector、LinkedList区别
背!背!背!
首先都是可伸缩的数组,可以动态的改变长度的数组
ArrayList和Vector都是基于存储元素的Object[] array来实现的,他们会在内存中开辟一块连续的空间来存储,由于数据存储是连续的,因此他们支持用序号来访问元素,同时索引数据的速度比较快。但是在插入元素的时候需要移动容器中的元素,对于数据的插入操作执行速度比较慢。他们两都有一个初始化的容量大小,当里面的存储的元素超过这个大小的时候,就需要动态的扩充他们的存储空间。
ArrayList和Vector最大的区别就是synchronized(同步)的使用,没有一个ArrayList是同步的,而Vector绝大多数的方法都是直接或者间接同步的,所以Vector是线程安全的,ArrayList不是线程安全的,正是由于Vector提供了线程安全的机制,使其性能也要略逊于ArrayList
LinkedList采用双向列表机制来实现的,对数据的索引需要从列表头开始遍历,因此随机访问的效率比较低,但是插入元素的时候不需要对数据进行移动,故插入效率较高。同时LinkedList不是线程安全的。
当对数据的主要操作为索引或只在集合的末端增加、删除元素,使用ArrayList或Vector效率比较高。当对数据的操作主要为指定位置插入或删除元素,使用LinkedList效率比较高。当在多线程中使用容器时,选用Vector较为安全。
创建ArrayList对象的时候可以不指定其大小空间,在这种情况下,列表默认大小为10,在后面的使用过程中,如果发现列表的大小不够用,此时会扩充为原来的1.5倍大小。
15.HashMap和Hashtable的区别
HashMap是一个最常用的Map,它根据键的Hashcode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap和Hashtable都采用了Hash方法进行索引。
区别如下:
-
HashMap是Hashtable轻量级的实现(非线程安全的实现),它们都实现了Map接口,主要区别在于HashMap允许空的键值(null->key)(但需要注意的是,HashMap最多只允许一条记录为null,不允许多条记录为null),而Hashtable不允许空键值
-
Hashtable的方法是线程安全的,而HashMap由于不支持线程的同步,所以不是线程安全的。多线程访问的情况下,Hashtable自行同步,HashMap需要提供额外的同步机制。
-
Hashtable使用Enumeration进行遍历,HashMap使用Iterator进行遍历
-
Hashtable中Hash数组默认大小是11,增加的方式是old*2+1。在HashMap中,Hash数组默认大小为16,而且一定是2的指数
16.&和&&的区别
&是按位与操作符,a&b是将a/b装换成二进制数以后,然后再按位与操作。
&&是逻辑与操作符,a&&b是a/b都为true就为true,否则为false,有短路的功能,第一个为false就不会计算第二个的值,第一个为true才会计算第二个的值。
17.Collection和Collections的区别
-
Collection是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。实现该接口的类主要有List和Set,该接口的设计目标是为各种具体的集合提供最大化的统一的操作方式。
-
Collections是针对集合类的一个包装类,它提供了一系列的静态方法实现对各种集合的搜索、排序以及线程安全化等操作,其中大多数方法都是用于处理线性表。Collections不能实例化,如同一个工具类,服务于Collection框架。
18.设计模式?
设计模式(Design Pattern)是一套被反复利用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式的目的是为了代码重用,避免程序大量修改,同时使代码更容易被他人理解,并且保证代码的可靠性,设计模式使得代码编制真正的工程化,设计模式可以说是软件工程的基石。
常用的设计模式有工厂模式、单例模式、适配器模式、享元模式、观察者模式。
19.SpringMVC、IOC、AOP
SpringMVC是在Spring框架上发展起来的框架,它提供了构建web应用程序的全功能MVC模块,使用了Spring可插入的MVC架构,可以自由的选择各个模块所使用的架构,非常灵活。SpringMVC把控制器、模型、分派器以及处理程序对象的角色进行了分离,因此,SpringMVC具有很好的可定制性。
IOC控制反转,将用户主动创建对象实例的过程转交给Spring容器负责,Spring容器会控制程序之间的关系,而不是由调用者的程序代码直接控制,控制权由调用者转移到Spring容器,控制权发生了反转。即IOC(通过依赖注入DI实现)
Spring容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它所依赖的实例,即DI,依赖注入
AOP面向切面编程,是对面向对象开发的一种补充,允许开发人员在不改变原来模型的基础上动态的修改模型从而满足新的需求。
20.static关键字知识
在java中,方法名称、成员变量都可以使用static修饰,但是局部变量不能使用static修饰,即方法体中的变量是不能使用static修饰的。
作用:
-
第一,为某特定数据类型或对象分配单一的存储空间,而与创建的对象个数无关。
-
第二,希望某个方法或属性与类而不是对象关联在一起,即在不创建对象的情况下通过类直接调用方法或使用类的属性。
具体实现:
-
通过static实现全局的效果,定义static变量。
-
static成员方法
-
static代码块
-
static内部类
21.Servlet的工作方式。
Servlet是采用Java语言编写的服务器端程序,它运行于Web服务器中的Servlet容器中,其主要功能就是提供请求/响应的Web服务模式,可以生成动态的Web内容,Servlet工作原理如下:
-
用户通过单击一个链接来向Servlet发起请求
-
Web服务器接收到该请求后,会把该请求提交给响应的容器负责,当容器发现这是对Servlet发起的请求后,容器此时就会创建两个对象:HttpServletResponse/HttpServletRequest.
-
容器可以根据请求消息中的URL消息找到对应的Servlet,然后针对该请求创建一个单独的线程,同时将2中创建的两个对象以参数的形式传递到新创建的线程中去。
-
容器调用Servlet的service()方法来完成对用户请求的响应,service()方法会调用doPost()方法或者doGet()方法来完成具体的响应任务,同时把生成的动态页面返回给容器。
-
容器把响应消息组装成HTTP格式返回给客户端,此时,这个线程结束运行,同时删除2中创建的两个对象。
Servlet的生命周期:
Servlet的生命周期可以分为加载、创建、初始化、处理客户请求、卸载五个阶段
-
加载:容器通过类加载器使用Servlet类对应的文件来加载Servlet
-
创建:通过调用Servlet的构造方法来创建完成一个Servlet实例
-
初始化:通过调用Servlet的init()方法来完成初始化工作,这个方法是在Servlet已被创建但向客户提供服务之前调用的,需要注意的是,init()方法只会被调用一次。
-
处理客户请求:Servlet一旦被创建后,就可以为客户端提供服务了。具体时间就是容器判断,处理请求,构建新的线程,调用service方法,采取不同的方法处理。
-
卸载:容器在卸载Servlet之前需要使用destroy()方法,让Servlet自己释放占用的系统资源,一旦destroy被调用,容器就不会再向这个Servlet发送任何请求消息了。如果再需要这个Servlet,就重新创建并初始化。destroy也是被调用一次。
22.JDBC访问数据库的流程:
-
加载JDBC驱动器。将数据库的JDBC驱动加载到classpath中,在基于JavaEE的web开发过程中,一般是将JDBC驱动赋值到WEB-INF/lib下
-
加载JDBC驱动,并将其注册到DriverManager中,一般使用反射机制Class.forName(String driverName)
-
建立数据库连接,取得connection对象。
-
建立Statement对象或者PreparedStatement对象。
-
通过Statement或者PreparedStatement对象执行SQL语句。
-
访问结果集ResultSet对象
-
将上述使用的对象关闭,释放资源。
23.Java中的引用知识
指针和引用的区别:指针指向一块内存,它的内容是所指内存的地址;引用时候某块内存的别名。(引用底层是通过指针实现的,但是两者不能等同。指针可以进行比较运算和整数加减运算,引用不能)
引用本身存储的对象的地址信息,而这个地址信息是存储在栈中的,在声明后就会立刻在栈上分配存储空间。在方法调用传递引用的时候,对形参的引用的值本身所做的修改对实参不可见。从本质上说,引用也是原始数据类型(Primitive)
24.sleep()和wait()的区别
sleep()是线程暂停执行一段时间的方法,wait()也是一种线程暂停执行的方法。
区别:
-
原理不同。sleep是Thread类的静态方法,是线程来控制自身流程的,它会使此线程暂停执行指定时间,而把执行机会让给其他线程,等到计时时间到,此线程会自动苏醒。而wait是Object类的方法,用于线程间的通信,这个方法会使当前拥有该对象锁的进程等待,直到其他线程调用notify()或者notifyAll()方法才醒来。
-
对锁的处理机制不同。由于sleep方法的主要作用是让线程休眠指定的一段时间,到时间自动恢复,不涉及线程间的通信。因此使用sleep并不会释放锁。wait方法则不同,当调用wait方法后,线程会是释放掉它所占用的锁,从而使线程所在对象的其他synchronized数据可被其他线程使用。
-
使用区域不同,sleep可以在任何地方用,wait方法必须放在同步控制方法或者同步语句块中使用。
-
sleep不释放锁,容易导致“死锁”现象产生,建议使用wait
25.内部类
-
静态内部类
-
被指明为static的内部类,它可以不依赖外部类实例而被实例化,而通常的内部类需要在外部类实例化之后才能实例化。静态内部类不能与外部类有相同的名字,不能访问外部类的普通的成员变量,只能访问外部类中的静态成员和静态方法(包括私有类型)
-
-
成员内部类
-
静态内部类去掉static之后就是成员内部类,成员内部类为非静态内部类,可以自由的引用外部类的属性和方法,无论方法是静态的还是非静态的。只有外部类被实例化后,内部类才能被实例化。注意:非静态内部类中不能有静态成员
-
-
局部内部类
-
定义在一个代码块中的类,作用范围为其所在的代码块,用的最少。局部内部类像局部变量一样,不能被public/private/protected/static修饰,只能访问方法中定义为final类型的局部变量
-
-
匿名内部类
-
没有类名的内部类,不使用关键字class/extends/implements,没有构造方法,它必须继承其他类或其他接口。
-
26.Java提供了三种实现同步机制的方法
-
synchronized方法后synchronized块
-
wait和notify
-
Lock(ReentrantLock重入锁)
27.filter的作用?
在Servlet运行之前之中之后提供相应的处理,确保响应后的需求满足请求者的需要。
filter的组成:
-
在Servlet被调用之前截获
-
在Servlet被调用之前检查Servlet Request
-
根据需要修改Request头和Request数据
-
根据需要修改Response头和Response数据
-
在Servlet被调用之后截获
28.forward和redirect的区别?
forward(请求转发)是服务器内部的重定向,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,而客户端并不知道,因此在客户端浏览器的地址栏中不会显示转向后的地址,还是原来的地址。由于在整个定向的过程中用的是同一个Request,因此forward会将Request的信息带到被定向的JSP或Servlet中使用
redirect(重定向)则是客户端定向,是完全的跳转,即客户端浏览器会利用跳转后的地址,然后重新发送请求,因此浏览器或显示跳转后的地址。同时由于这种方式比forward多了一次请求,所以forward效率更高。注意,客户端重定向可以通过设置特定的HTTP头或者写JavaScript脚本实现。
29.Java中二维数组的声明的方法
-
type ArrayName[][]
-
type[][] ArrayName
-
tyep[] ArrayName[]
需要注意在声明二维数组的时候,其中方括号的内容必须为空!
30.可变参数知识
在Java语言中,可以使用省略号...来实现可变参数,可变参数的几个特点如下:
-
只能作为最后一个参数出现。如果参数个数不定,当其后面还有相同类型的参数时,Java无法区分传入的参数属于前一个可变参数还是后面的参数,所以只能让可变参数位于最后一项。
-
只能位于变量的类型和变量名之间,类似int...a String...b
-
编译器为可变参数隐含创建一个数组,在调用的时候,可以用数组的形式来访问可变参数。
31.volatile的作用
volatile用于保证数据的同步,也就是可见性
由于在系统忙的不可开交的时候,数据没有办法很好的同步,造成程序执行不对,使用volatile可以使得系统通知对应变量修改参数,保证数据的同步
32.如何查看Java程序使用内存的情况?
public static void main(String[] args) { //得到JVM中的空闲内存量(单位字节) System.out.println(Runtime.getRuntime().freeMemory()); //得到JVM的内存总量(单位字节) System.out.println(Runtime.getRuntime().totalMemory()); //JVM试图使用的最大内存量(单位字节) System.out.println(Runtime.getRuntime().maxMemory()); //可用处理器的数目 System.out.println(Runtime.getRuntime().availableProcessors()); } |
33.a=a+b与a+=b的区别?
在Java中,当参与运算的两个数是byte、short或者int时,他们首先都会被转换成int类型,在进行计算。然后把计算的结果赋值给用来存储结果的变量。如果用来存储结果变量的类型是byte或者short,这意味着需要把int类型转换为byte或short类型。a+=b会隐式地把运算结果转换为a的类型,而a=a+b不会把运算结果的类型隐式的转化为a的类型。
34.会话跟踪技术
会话:指的是从客户端打开与服务器的连接并发出请求到服务器响应客户端请求的全过程。
会话跟踪:对同一个用户对服务器的连接的请求和接受响应的监视,由于客户端与服务器之间是通过HTTP协议进行通信的,而HTTP协议本身是无状态协议,不能保存客户的信息。
会话跟踪技术四种:
-
page代表与一个页面相关的对象和属性。一个页面由一个编译好的Java Servlet类表示。
-
request代表与Web客户端发送的一个请求相关的对象和属性,一个请求可能跨越多个页面,设计多个web组件
-
sessioin代表与用于某个Web客户端的一个用户体验相关的对象和属性,一个web会话经常会跨越多个客户端请求
-
application代表与整个web程序相关的独享和属性。实质是跨越多个web应用程序,包括多个页面、请求和会话的一个全局作用域。
34.使用多线程注意事项。
如何避免死锁,提高多线程情况下的并发量是很重要的。
-
如果使用volatile代替synchronized,尽可能用volatile。因为被synchronized修饰的方法或者代码块在同一时间允许一个线程访问,而volatile没有这个限制,因此使用synchronized会降低并发量,由于volatile无法保证原子操作,因此在多线程的情况下,只有对变量的操作为非原子操作时才可以使用volatile
-
尽可能减少使用synchronized块内的代码,只把临界区的代码放到synchronized块中,尽量避免使用synchronized来修饰整个方法。
-
尽可能给每个线程都定义一个线程的名字,不要使用匿名线程,有利于调试
-
尽可能使用concurrent容器(ConcurrentHashMap)来代替synchronized容器(Hashtable),因为synchronized容器使用synchronized关键字通过对整个容器加锁实现多线程安全的,性能比较低,而concurrent采用了更加细粒度的锁,支持更高的并发量。
-
使用线程池来控制多线程的执行
35.异常的继承关系
36.Java类加载器加载问题与结构
类的加载方式分为隐式装载和显式装载两种。隐式装载指的是程序在使用new等方式创建对象时,会隐式的调用类的加载器将对应的类加载到JVM中,显式装载值得是通过直接调用Class.forName()方法将所需要的类加载到JVM中。
类加载的主要步骤:
-
装载:根据查找路径找到相对应的class文件,然后导入
-
链接:
-
检查:检查待加载的class文件的正确性
-
准备:给类中的静态变量分配存储空间
-
解析::将符号引用转换为直接引用
-
-
初始化:对静态变量和静态代码块执行初始化工作
37.序列化Serializable的理解
在分布式的环境下,当进行远程通信的时候,无论是何种类型的数据,都会以二进制序列的形式在网络上传送。序列化是一种将对象转换成字节序列的过程,用于解决在对对象流进行读写操作时所引发的问题。序列化可以将对象的状态写在流里进行网络传输,或者保存到文件、数据库等系统中,并在需要的时候把该流读取出来重新构造成一个相同的对象。
序列化的特点:
-
如果一个类能被序列化,那么他的子类也能被序列化
-
由于static代表类的成员,transient代表对象的临时数据,因此被声明为这两种类型的数据成员是不能够被序列化的
-
子类实现了serializable接口,父类没有,父类中的属性不能序列化,子类中的属性可以序列化
38.在Java语言中,Socket的连接和建立的原理是什么?
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路一端称为一个Socket,套接字,用来实现不同的虚拟机之间或不同计算机之间的通信。在Java语言中,Socket分为TCP(Transmission Controll Protocol)和UDP(User Datagram Protocol)两种,任何一个Socket都是由IP地址和端口号唯一确定。
基于TCP:Server端监听指定的某个端口是否有连接请求,Client向Server端发出Connect,然后Server端向Client发回Accept消息,连接建立起来,就可以send和Wirte了。
建立连接,收发数据,关闭Socket
39.事务的四个属性:ACID
atomicity consistency isolation durability
-
原子性:数据修改,要么全部执行,要不都不执行,不允许执行一部分。
-
一致性:事务执行前后,数据库数据必须保持一致状态。
-
隔离性:独立性,当两个或两个以上事务并发执行的时候,为了保证数据的安全性,将一个事务内部的操作隔离起来,不被其他的正在进行的事务看到。
-
持久性:永久性,事务完成以后,DBMS保证它对数据库中的数据的修改时永久的,系统或介质发生故障时,该修改也是永久的,一般通过数据库备份与恢复来保证。
事务隔离级别:
-
TRANSACTION_NONE JDB:不支持事务
-
TRANSACTION_READ_UNCOMMITTED:未提交读,说明在提交前一个事务可以看见另一个事务的变化。这样脏数据,不可重复读,和虚读都是允许的
-
TRANSACTION_READ_COMMITTED:已提交读。说明读取未提交的数据是不允许的。这个级别仍然允许不可重复读和虚读的chansh
-
TRANSACTION_REPEATABLE_READ:可重复读,说明事务保证能够再次读取相同的数据而不会失败,但虚读仍然会出现
-
TRANSACTION_SERIALIZABLE:可序列化。它是最高的事务级别,可以防止读脏数据、不可重复读、虚读
脏读:指的是一个事务读取了另一个事务尚未提交的数据(主要是A读取到B未提交的内容,然后B回滚了)
不可重复读:指的是一个事务的操作导致另外一个事务前后两次读取到不同的数据。(B读取数据之后,A修改了数据,然后B在读,发现数据不同了)
虚读:指的是一个事务的操作导致另外一个事务前后两次查询的结果数据量不同。(A修改了B的数据,导致B前后两次读到的数据不一致,A存入银行100元未提交,银行报表查询账户200,然后A提交了,这时银行统计时候账户300)
40.fail-fast和fail-safe区别
fail-safe允许在遍历的过程中对容器中的数据进行修改,而fail-fast则不允许。
fail-fast:直接在容器上遍历,在遍历的过程中,一旦发现容器中的数据被修改了(增删改查),会立刻抛出ConcurrentModificationException异常导致遍历失败,常见的使用fail-fast方式的容器有HashMap和ArrayList等
fail-safe:这种遍历基于容器的一个克隆,因此对容器中内容的修改不影响遍历。常见的使用fail-safe方式遍历的容器有ConcurrentHashMap和CopyOnWriteArrayList
41.Java语言的特点
SUN公司对Java的描述:“Java is simple, Object-oriented, distributed, interpreted, robust, secure, architecture, neutral, portable, high-performance, multithreded, and dynamic language”
42.向数据表中插入一列
alter table_name add column_name dataType
43.终止当前线程的方式
-
抛出一个异常
-
当前线程调用sleep方法
-
优先级高的线程进入就绪状态
44.乐观锁和悲观锁
悲观锁:很悲观,每次去拿数据都认为别人会更改数据,每次拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞block,直到它拿到锁为止。
乐观锁:很乐观,每次去拿数据都认为别人不会更改数据,所以不会上锁,但是在更新的时候会判断一下在此期间有没有人去更新这个数据,可以使用版本号等机制。
45.进程和线程的关系
-
一个线程只能属于一个进程,而一个进程可以拥有多个线程,至少一个
-
资源分配给进程,同一进程的所有线程共享该进程的资源
-
处理器分给线程,即真正在处理机上运行的是线程
-
线程在执行过程中,需要协作同步,不同进程的线程间要利用消息通信的办法实现同步。线程是进程内的一个执行单元,也是进程内的可调度实体
两者的相同点:
-
二者都具有ID、一组寄存器、状态、优先级以及所要遵循的调度策略
-
每个进程都有一个进程控制块,线程也拥有一个线程控制块
-
线程和子线程共享父线程的资源;线程和子线程独立于他们的父进程,竞争使用处理器资源;线程和子进程的创建者可以在线程和子进程上实施某些控制
两者的不同点:
-
线程是进程的一部分,一个没有线程的进程是可以被看做单线程的,如果一个进程内拥有多个线程,进程的执行过程不是一条线的,而是多条线程共同完成
-
启动一个线程的所花费的空间远远小于启动一个进程所花费的空间。
-
系统运行时候会为进程分配内存空间,但是不会为线程分配内存空间
多线程的优点
-
无须跨越进程边界
-
程序逻辑控制方式简单
-
所有线程可以直接共享内存和变量
46.Java内存区域的分布
-
程序计数器:线程所执行的字节码行号指示器,用于指示程序应该执行哪一行,线程私有
-
虚拟机栈:局部变量表、操作数栈、动态链接、方法出口等,线程私有(局部)
-
本地方法栈:同上,不过执行的是本地的方法
-
堆:用于存放对象实例(包括数组),线程共享
-
方法区:类信息、常量、静态变量、即时编译后的代码等,线程共享
-
运行时常量池:方法区的一部分,存放编译期生成的各种字面量和符号引用。
47.多态
引用多态:
父类引用可以指向子类
父类引用可以指向自身
方法多态:
父类调用自己的方法
父类调用子类的方法