试题(49)、(50) 若系统中的某子模块需要为其他模块提供访问不同数据库系统的功能,这些数据库系统提供的访问接口有一定的差异,但访问过程却都是相同的,例如,先连接数据库,再打开数据库,最后对数据进行查询。针对上述需求,可以采用____(49)____设计模式抽象出相同的数据库访问过程,该设计模式____(50)____。
A.外观
B.装饰
C.桥接
D.享元
正确答案
A
答案解析
试题(49)、(50)分析 外观(facade)模式是对象的结构模式,要求外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
用户A从CA处获取了用户B的数字证书,用户A通过______可以确认该数字证书的有效性。
A.用户B的公钥
B.用户B的私钥
C.CA的公钥
D.用户A的私钥
正确答案
C
答案解析
[分析] 用户B的数字证书中包含了CA的签名,因此用CA的公钥可验证数字证书的有效性。
设有两个数据库表,父表和子表之间是一对多的联系,为控制子表和父表的关联,可以设置“参照完整性规则”,为此要求这两个表______。
A.在父表连接字段上建立普通索引,在子表连接字段上建立主索引
B.在父表连接字段上建立主索引,在子表连接字段上建立普通索引
C.在父表连接字段上不需要建立任何索引,在子表连接字段上建立普通索引
D.在父表和子表的连接字段上都要建立主索引
正确答案
B
答案解析
[知识点] 数据库的一致性和完整性:实体完整性、域完整性、参照完整性[评析] 参照完整性是指当插入、删除或修改一个表中的数据时,通过参照引用相互关联的另一个表中的数据,来检查对表的数据操作是否正确。 当有两个数据库表,父表和子表之间是一对多的联系,可以通过设置“参照完整性规则”来控制父表和子表的关联。在关系数据库中是通过连接字段来体现和表示联系。连接字段要在父表中做为主关键字,在子表中是外部关键字,为此要求这两个表在父表连接字段上建立主索引,在子表连接字段上只要建立普通索引就可以了。
41)下面关于Spring管理Bean的说法正确的是(B )
A)Bean在Spring容器中有两种管理方式,工厂模式和单例模式
B)Bean在 Spring容器中有两种管理方式,原型模式和单例模式
C)Spring默认的利用工厂模式管理Bean
D)Spring默认利用原型模式管理Bean
要校验xml的内容 使用正则表达式XML的校验是通过XML Schema(XSD) 或DTD文件的语法规范来校验的。DTD现在越来越不受欢迎了,在此选用XSD来校验。
今天在开发中遇到js对象操作问题,做了以下总结:
对象定义
var obj = new Object();
或
var obj = {};
添加属性
obj.name = 'tom';
obj.ses='man';
添加方法
obj.say = function(){
alert('22222');
}
调用 obj.say();
修改属性
obj.name='jack';
删除属性
obj.name = undefined;
obj.say = undefined;
其name、say属性仍存在obj对象中,怎样才能在obj中移除name属性呢?
delete obj.name;
在添加、修改或者删除属性时,和引用属性相同,也可以采用方括号([])语法:
obj[“name”]=”tom”;
使用这种方式还有一个额外的特点,就是可以使用非标识符字符串作为属性名称,例如
标识符中不允许以数字开头或者出现空格,但在方括号([])语法中却可以使用:
obj[“my name”]=”tom”;
需要注意,在使用这种非标识符作为名称的属性时,仍然要用方括号语法来引用:
alert(obj[“my name”]);
而不能写为:
alert(user.my name);
利用对象的这种性质,甚至可以很容易实现一个简单的哈希表,在本书的后面将会看到
其应用。此可见,JavaScript中的每个对象都是动态可变的,这给编程带来了很大的灵活性。
java图像用户界面swing、awt、swt
数据库必须具备的四个特性
1:原子性:事务包含的所有操作要么全部成功,要么全部失败回滚;成功必须要完全应用到数据库,失败则不能对数据库产生影响;
2:一致性:事务执行前和执行后必须处于一致性状态,
例:用户A和用户B的前加起来一共是5000; 无论AB用户之间是如何相互转换的,事务结束后两个用户的钱加起来还是5000,这就是事务的一致性。
3:隔离性:当多个用户并发访问数据库时,数据库为每一个用户开启的事务,不被其他事务的操作所干扰,多个并发事务之间要相互隔离;
4:持久性:一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便在数据库系统遇到故障的情况下也不会丢失事物的操作。
隔离性:当多个线程都开启事务来操作数据库中的数据时,数据库系统要进行隔离操作,以保证各个线程获取数据的准确性。 不考虑事务的隔离性,会产生的几种问题:
01:脏读
是指一个事务处理过程里读取了另一个未提交的事务中的数据,然后使用了这个数据;
例:用户A向用户B转账100元,A通知B查看账户,B发现前确实已到账,而之后无论第二条SQL是否执行,只要该事务部提交,则所有操作都将回滚,当B再次查看账户时就会发现前其实并没有到账。
02:不可重复读
不可重复读是指在一个事务内,多次读取同一个数据,在这个事务还没有结束 ,另一个事务也访问该同一数据,但是由于第二个事务的修改,那么第一个事务两次读取的数据可能不一样,因此称为不可重复读;即同一个事务中原始数据读取不可重复。 注:不可重复读和脏读的区别,脏读是某一个事务读取另一个事务未提交的脏数据; 不可重复读则是读取前一事务提
03:幻读:
当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行修改,这种数据涉及到表中的全部数据行,同时,第二个事务也对这个表数据进行修改,这个修改是对表中新增/删除一条数据,那么操作第一个事务的用户发现表中的数据还没有修改的数据行,就好像发生了幻觉一样,这就是发生了幻读。
注:幻读和不可重复读都读取另一条已经提交的事务,所不同的是不可重复读查询的都是同一数据项,而幻读针对的是一批数据整体。
数据库提供的四种隔离级别:
01:Read uncommitted(读未提交):最低级别,任何情况都会发生。
02:Read Committed(读已提交):可避免脏读的发生。
03:Repeatable read(可重复读):可避免脏读、不可重复读的发生。
04:Serializable(串行化):避免脏读、不可重复读,幻读的发生。
注: 四种隔离级别最高:Seralizable级别,最低的是Read uncommitted级别; 级别越高,执行效率就越低; 隔离级别的设置只对当前链接有效,对JDBC操作数据库来说,一个Connection对象相当于一个链接,只对该Connection对象设置的隔离级别只对该connection对象有效,与其它链接connection对象无关。
01:Mysql的默认隔离级别是:可重复读:Repeatable read;
02:oracle数据库中,只支持seralizable(串行化)级别和Read committed();默认的是Read committed级别;
下面就四种隔离级别进行场景设计:
01: Read uncommitted 读未提交; 公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有2000元,singo空欢喜一场。
02:Read committed 读已提交; singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为何......
03:Repeatable read 重复读 当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。
04:重复读可能出现幻读: singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额(select sum(amount) from transaction where month = 本月)为80元,而singo此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction ... ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出现了幻觉,幻读就这样产生了。
Serializabale:最高的事务隔离级别,代价花费最高,性能很低,很少使用,在此级别下,事务顺序执行,避免上述产生的情况。
Spring IOC三种注入方式:
1. 接口注入
2. getter,setter方式注入
3. 构造器注入
对象与对象之间的关系可以简单的理解为对象之间的依赖关系:
A类需要B类的一个实例来进行某些操作,比如在A类的方法中需要调用B类的方法来完成功能,叫做A类依赖于B类.控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术,由容器控制程序之间的关系,而不是由代码直接控制.
1.接口注入
public class ClassA {
private InterfaceB clzB;
public void doSomething() {
Ojbect obj = Class.forName(Config.BImplementation).newInstance();
clzB = (InterfaceB)obj;
clzB.doIt();
}
……
}
上面代码中,ClassA依赖于InterfaceB的实现,如何获得InterfaceB实现类的实例?传统的方法是在代码中创建 InterfaceB实现类的实例,并将赋予clzB.这样一来,ClassA在编译期即依赖于InterfaceB的实现.为了将调用者与实现者在编译 期分离,于是有了上面的代码.我们根据预先在配置文件中设定的实现类的类名(Config.BImplementation),动态加载实现类,并通过InterfaceB强制转型后为ClassA所用,这就是接口注入的一个最原始的雏形.
public class ClassA {
private InterfaceB clzB;
public Object doSomething(InterfaceB b) {
clzB = b;
return clzB.doIt();
}
……
}
上面代码中,加载接口实现并创建其实例的工作由容器完成.在运行期,InterfaceB实例将由容器提供.即使在IOC的概念尚未确立时,这样的方法也已经频繁出现在我们的代码中.
public class MyServlet extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
……
}
}
HttpServletRequest和HttpServletResponse实例由Servlet Container在运行期动态注入.
2.Setter设置注入基于设置模式的依赖注入机制更加直观,也更加自然.
public class ClassA {
private InterfaceB clzB;
public void setClzB(InterfaceB clzB) {
this.clzB = clzB;
}
……
}
3.构造器注入
public class DIByConstructor {
private final DataSource dataSource;
public DIByConstructor(DataSource ds) {
this.dataSource = ds;
}
……
}
构造器注入,即通过构造函数完成依赖关系的设定,容器通过调用类的构造方法将其所需的依赖关系注入其中.
三种注入方式比较:
接口注入:
接口注入模式因为具备侵入性,它要求组件必须与特定的接口相关联,因此并不被看好,实际使用有限。
Setter 注入:
对于习惯了传统 javabean 开发的程序员,通过 setter 方法设定依赖关系更加直观。
如果依赖关系较为复杂,那么构造子注入模式的构造函数也会相当庞大,而此时设值注入模式则更为简洁。
如果用到了第三方类库,可能要求我们的组件提供一个默认的构造函数,此时构造子注入模式也不适用。
构造器注入:
在构造期间完成一个完整的、合法的对象。
所有依赖关系在构造函数中集中呈现。
依赖关系在构造时由容器一次性设定,组件被创建之后一直处于相对“不变”的稳定状态。
只有组件的创建者关心其内部依赖关系,对调用者而言,该依赖关系处于“黑盒”之中。
总结
Spring使用注入方式,为什么使用注入方式,这系列问题实际归结起来就是一句话,Spring的注入和IoC(本人关于IoC的阐述)反转控制是一回事。
理论上:第三种注入方式(构造函数注入)在符合java使用原则上更加合理,第二种注入方式(setter注入)作为补充。
实际上:我个人认为第二种注入方式(setter注入)可以取得更加直观的效果,在使用工作上有不可比拟的优势,所以setter注入依赖关系应用更加广泛。
Object s="a";if(s instanceof String){
System.out.println("是String实例");}else{
System.out.println("不是String实例");}
//方式三:SELECT COUNT(*) FROM (SQL)方式String newSQL = "SELECT COUNT(1) AS CT FROM (" + selectSQL + ")";
Statement stmt = cn.createStatement();
ResultSet rs = stmt.executeQuery(newSQL);
rs.next();
logger.info("SELECT COUNT(1) AS CT FROM (SQL)方式:" + rs.getInt(1));
rs.close();
stmt.close();
import java.io.*;
import java.util.*;
public class ReadFileAndPrintFirstLine {
public static void main(String[] args) throws Exception {
String filePath = "你的文件路径";
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(filePath)));
String firstLine = reader.readLine();
System.out.println("第一行:" + firstLine);
reader.close();
}
}
两个线程,一个打印100内的奇数一个打印100内的偶数,交替执行。
//要打印的资源
public class Num {
int i=1;
boolean flag = false; //两个线程,交替执行的一个标志
}
//打印奇数的线程
public class PrintQi implements Runnable{
Num num ;
public PrintQi(Num num)
{
this.num = num;
}
public void run()
{
while(num.i<= 100)
{
synchronized (num) {
if(num.flag)
{
try {
num.wait();
} catch (Exception e) {
}
}
else {
System.out.println("奇数"+num.i);
num.i++;
num.flag = true;
num.notify();
}
}
}
}
}
//打印偶数的线程
public class PrintOu implements Runnable{
Num num;
public PrintOu(Num num) {
this.num = num;
}
public void run()
{
while(num.i<=100)
{
synchronized (num)/* 必须要用一把锁对象,这个对象是num*/ {
if(!num.flag)
{
try
{
num.wait(); //操作wait()函数的必须和锁是同一个
} catch (Exception e)
{}
}
else {
System.out.println("oushu-----"+num.i);
num.i++;
num.flag = false;
num.notify();
}
}
}
}
}
//主函数
public class main {
public static void main(String[] args) {
Num num = new Num(); //声明一个资源
PrintQi pQi = new PrintQi(num);
PrintOu pOu = new PrintOu(num);
Thread aThread = new Thread(pQi);
Thread bThread = new Thread(pOu);
aThread.start();
bThread.start();
}
}
---------------------
ArrayList
Vector
推出时间
JDK1.2版本以后
JDK1.0版本就有
线程安全性
非线程安全(不支持多线程)
线程安全
效率
相对较低
效率高
输出方法
for,Iterator
for,Iterator
(Vector的相关例子就不在赘述了)
3.LinkedList类
(底层是双向链表)
(与ArrayList的用法也基本一致,这里也之强调一下两者之间的区别,LinkedList的相关方法见API文 档即可)
ArrayList类
LinkedList类
底层是Object数组
底层是双向链表
经常用于查询操作
经常用于频繁的增加或删除操作
(List特点:存入顺序和取出顺序一致,存储的元素可以重复)
(Set特点:元素的顺序无序且唯一,即无序性和唯一性)
ArrayList是一个可改变大小的数组.当更多的元素加入到ArrayList中时,其大小将会动态地增长。内部的元素可以直接通过get与set方法进行访问,因为ArrayList本质上就是一个数组。
List arrayList = new ArrayList();
如果像上面这样使用默认的构造方法,初始容量被设置为10。当ArrayList中的元素超过10个以后,会重新分配内存空间,使数组的大小增长到16。可以通过调试看到动态增长的数量变化:10->16->25->38->58->88->…(增长幅度为:len/2 + 1)
LinkedList是一个双链表,在添加和删除元素时具有比ArrayList更好的性能.但在get与set方面弱于ArrayList。
当然,这些对比都是指数据量很大或者操作很频繁的情况下的对比,如果数据和运算量很小,那么对比将失去意义。
Vector和ArrayList类似,但属于强同步类。如果你的程序本身是线程安全的(thread-safe,没有在多个线程之间共享同一个集合/对象),那么使用ArrayList是更好的选择。
Vector和ArrayList在更多元素添加进来时会请求更大的空间。Vector每次请求其大小的双倍空间,而ArrayList每次对size增长50%。而LinkedList还实现了Queue接口,该接口比List提供了更多的方法,包括
offer(),peek(),poll()等。