第一阶段考试
1. 选择题(每题2分,共40分)
1) 输出结果是:(A)
public static void swap(int a, int b) {
int c = a;
a = b;
b = c;
}
public static void main(String[] args) {
int a = 23;
int b = 47;
System.out.println("Before, a:" + a + " b:"+ b);
swap(a,b);
System.out.println("After, a:" + a + " b:"+ b);
}
A.
Before, a:23 b:47
After, a:23 b:47
B.
Before, a:23 b:47
After, a:47 b:23
2) 输出结果是:(A)
public static void swap(Integer a, Integer b) {
Integer c = a;
a = b;
b = c;
}
public static void main(String[] args) {
Integer a = new Integer(23);
Integer b = new Integer(47);
System.out.println("Before, a:" + a + " b:"+ b);
swap(a,b);
System.out.println("After, a:" + a + " b:"+ b);
}
A.
Before, a:23 b:47
After, a:23 b:47
B.
Before, a:23 b:47
After, a:47 b:23
3) 输出结果是:(A)
public static void swap(String a, String b) {
String c = a;
a = b;
b = c;
}
public static void main(String[] args) {
String a = "23";
String b = "47";
System.out.println("Before, a:" + a + " b:"+ b);
swap(a,b);
System.out.println("After, a:" + a + " b:"+ b);
}
A.
Before, a:23 b:47
After, a:23 b:47
B.
Before, a:23 b:47
After, a:47 b:23
4) 输出结果是:(B)
int a = 10;
int b = 5;
int c = 3;
if( a < b & c++ > 1) {
}
System.out.println(c++);
A. 3
B. 4
C. 5
D. 6
5) 输出结果是:(C)
int a = 10;
int b = a++ + ++a + a-- + a--;
System.out.println("a:" + a + " b:" + b);
A. a:10 b:41
B. a:10 b:43
C. a:10 b:45
D. a:10 b:40
6) 以下结果返回true的是(多选 )(ABCE)
A. "hello" == "hello"
B. "hello".equals(new String("hello"))
C. final String a = "he";
a + "llo" == "hello";
D. String a = "he";
a + "llo" == "hello";
E. "he" + "llo" == "hello";
7) 在主方法执行new B()
,代码执行顺序正确的是:(C)
class C {
public C(String str) {
System.out.print(str);
}
}
class A{
static C c1 = new C("1");
C c2 = new C("2");
static {
new C("3");
}
public A(){
new C("4");
}
}
class B extends A{
static C c5 = new C("5");
C c6 = new C("6");
static {
new C("7");
}
public B(){
new C("8");
}
}
A. 12345678
B. 15372468
C. 13572468
D. 13572648
8) 执行完下述代码,遍历集合,打印结果为:(D)
TreeSet set = new TreeSet<>();
set.add("10");
set.add("11");
set.add("10");
set.add("9");
A. 9,10,11
B. 9,10,10,11
C. 10,11,10,9
D. 10,11,9
9) 执行完下述代码,遍历集合,打印value,结果为:(C)
Map<String, String> map = new HashMap<>();
map.put("xi'an", "西安");
map.put("beijing", "北京");
map.put("beijing", "北京市");
map.remove("西安");
A. 西安 北京 北京市
B. 西安 北京市
C. 北京市 西安
D. 北京市
10) 执行完下述代码,遍历集合,结果为:(D)
List<String> list = new ArrayList();
list.add("jerry");
list.add("tom");
list.add("elizabeth");
list.add("smith");
list.add("scott");
list.sort((a, b) -> {
int alen = a.length();
int blen = b.length();
return alen != blen ? blen - alen : a.compareTo(b);
});
A. jerry, tom, elizabeth, smith, scott
B. tom, jerry, scott, smith, elizabeth
C. elizabeth, smith, scott, jerry, tom
D. elizabeth, jerry, scott, smith, tom
11) 下列程序的运行结果是:(D)
class Cat {
void mi() throws NullPointerException {
System.out.println("Cat mi mi ..");
}
}
class SmallCat extends Cat {
int i = 8;
void mi() throws Exception {
System.out.println("SmallCat mi mi ..");
}
public static void main(String[] a) throws Exception {
Cat cat = new SmallCat();
cat.mi();
}
}
A. 运行错误
B. SmallCat mi mi ..
C. Cat mi mi ..
D. 编译错误
12) 说明以下代码的运行结果(A)
public class TestException{
public static void main(String args[]){
System.out.println( ma() );
}
public static int ma(){
int n;
try{
n = 10/0;
}catch(Exception e){
}
return n;
}
}
A. 编译不通过
B. 编译通过,输出-1
C. 编译通过,输出 0
D. 抛出算术异常
13) 下面代码的执行结果(A)
public class TestException {
public static void main(String args[]) {
System.out.println(ma());
}
public static int ma() {
int b = 10;
try {
return b;
} finally {
for (int i = 0; i < 10; i++) {
b++;
}
System.out.print("In Finally! ");
}
}
}
A. In Finally! 10
B. In Finally! 20
C. 10
D. 20
14) 说法正确的是:(C)
public class Example implements Runnable {
public void run() {
while (true) {
}
}
public static void main(String args[]) {
Example ex1 = new Example();
Example ex2 = new Example();
Example ex3 = new Example();
ex1.run();
ex2.run();
ex3.run();
}
}
A. 代码编译失败,不能直接调用run方法
B. 代码编译成功,存在3 个可运行的线程
C. 代码编译成功,存在1 个可运行的线程
15) 输出结果为:(B)
class Number{
public synchronized void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public void c() {
System.out.println(3);
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.c(); }).start();
}
A. 等待1秒,输出1,输出3
B. 输出3,等待1秒,输出1
C. A.B.两种情况都有可能
16) 输出结果为:(B)
class Number{
public synchronized void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public synchronized void b() {
System.out.println(2);
}
}
public static void main(String[] args) {
Number n1 = new Number();
Number n2 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n2.b(); }).start();
}
A. 等待1秒,输出1,输出2
B. 输出2,等待1秒,输出1
C. A.B.两种情况都有可能
17) 输出结果为:(C)
class Number{
public synchronized static void a() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(1);
}
public synchronized static void b() {
System.out.println(2);
}
}
public static void main(String[] args) {
Number n1 = new Number();
new Thread(()->{ n1.a(); }).start();
new Thread(()->{ n1.b(); }).start();
}
A. 等待1秒,输出1,输出2
B. 输出2,等待1秒,输出1
C. A.B.两种情况都有可能
18) 下列属于字符流的有(多选 ):(ABE)
A. BufferedReader
B. FileInputStream
C. ObjectInputStream
D. InputStreamReader
E. FileReader
F. ByteArrayInputStream
19) http协议属于哪一层( ),tcp协议属于哪一层( )(两个空 )?(AB)
A. 应用层
B. 传输层
C. 网络层
D. 链路层
20) 下列说法正确的是(多选 ):(ABCD)
A. UDP协议属于无连接、不可靠的协议
B. TCP协议属于有连接、可靠的协议
C. TCP协议要建立连接需要经过三次握手
D. java中通过ServerSocket、Socket等类来完成TCP编程
2. 问答题(每题2分,共20分)
1) 请描述String、StringBuffer、StringBuilder的特点、是否线程安全,以及它们适用场景?
之前的博客里面有
2) 抽象类和接口有哪些区别,接口中能不能定义方法实现?
3) 解释一下Overload和Override,父子类的静态同名同参数方法算不算Override如何证明?
4) 对于常见的集合List,Set,Map,在什么场合下用什么集合?
5) 请说出异常继承体系中的重要父类,它们的继承关系?另外从语法角度可以把异常分为几类?
6) sleep与wait方法有什么区别?
7) 用什么可以检测线程死锁
8) DML语句有哪些?DDL语句有哪些?
9) 事务的四大特性是指什么?
ACID:
原子性(Atomicity)
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)
10) MySQL数据库的数据导入导出可以用什么命令
导入:mysql> source *.sql
导出:mysqldump -u... -p... 库名 > 导出文件.sql
每题3分
11) 你都知道哪些设计模式,请介绍,并能举出jdk中的体现例子(加分选做)
单例 – 让对象只有一个实例
享元 – 重用对象, 线程池, 连接池, 字符串池…
装饰者 – 不使用继承的情况下,对类的功能增强
例如BufferedReader, InputStreamReader
生产者消费者 – 线程编程时的模式,不属于23种
使用队列解耦生产者、消费者
原型模式 – 不通过new来创建对象,俗称克隆
模板模式 – jdbc中,增删改方法几乎一样,
把这些方法相同的步骤和代码留在方法内部
不同的部分(sql语句、需要的参数值) 通过方法参数传递过来
对于查询方法,需要把多条代码通过方法参数传递过来,必须借助接口
迭代器 – for 遍历集合时,不知道集合的内部结构时,以一种一致的方式遍历集合12) 你所知道的线程安全的类有哪些,哪些是较新的,推荐使用的?(加分选做)
Hashtable ConcurrentHashMap
Vector CopyOnWriteArrayList
StringBuffer
String
13) 什么是悲观锁、乐观锁,java中哪里体现了?(加分选做)
悲观锁:
在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发控制的方法。它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作都某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。
悲观并发控制主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。
悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度(悲观),因此,在整个数据处理过程中,将数据处于锁定状态。 悲观锁的实现,往往依靠数据库提供的锁机制 (也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)
在数据库中,悲观锁的流程如下:
在对任意记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)。
如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。 具体响应方式由开发者根据实际需要决定。
如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。
其间如果有其他对该记录做修改或加排他锁的操作,都会等待我们解锁或直接抛出异常。
MySQL InnoDB中使用悲观锁
要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。set autocommit=0;
//0.开始事务
begin;/begin work;/start transaction; (三者选一就可以)
//1.查询出商品信息
select status from t_goods where id=1 for update;
//2.根据商品信息生成订单
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status为2
update t_goods set status=2;
//4.提交事务
commit;/commit work;
上面的查询语句中,我们使用了select…for update的方式,这样就通过开启排他锁的方式实现了悲观锁。此时在t_goods表中,id为1的 那条数据就被我们锁定了,其它的事务必须等本次事务提交之后才能执行。这样我们可以保证当前的数据不会被其它事务修改。
上面我们提到,使用select…for update会把数据给锁住,不过我们需要注意一些锁的级别,MySQL InnoDB默认行级锁。行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁把整张表锁住,这点需要注意。
优点与不足
悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;另外,在只读型事务处理中由于不会产生冲突,也没必要使用锁,这样做只能增加系统负载;还有会降低了并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数
乐观锁:
在关系数据库管理系统里,乐观并发控制(又名“乐观锁”,Optimistic Concurrency Control,缩写“OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。乐观事务控制最早是由孔祥重(H.T.Kung)教授提出。
乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。
相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。
数据版本,为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据。
实现数据版本有两种方式,第一种是使用版本号,第二种是使用时间戳。
使用版本号实现乐观锁
使用版本号时,可以在数据初始化时指定一个版本号,每次对数据的更新操作都对版本号执行+1操作。并判断当前版本号是不是该数据的最新的版本号。
1.查询出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根据商品信息生成订单
3.修改商品status为2
update t_goods
set status=2,version=version+1
where id=#{id} and version=#{version};
优点与不足
乐观并发控制相信事务之间的数据竞争(data race)的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。但如果直接简单这么做,还是有可能会遇到不可预期的结果,例如两个事务都读取了数据库的某一行,经过修改以后写回数据库,这时就遇到了问题。
14) 你知道哪些排序算法,java中Arrays.sort用的是哪一种?(加分选做)
冒泡,选择,插入,快速,希尔,归并merge,TimSort
对基本类型 双基准点快速排序
对引用类型 TimSort
3. SQL题目(每题2.5分,共10分)
员工表EMP,部门表DEPT,连接字段均名为deptno
1.找出没有员工的部门信息
// 利用not in
select * from dept where deptno not in(select deptno from emp);
// 利用表连接
select a.* from dept a left join emp b on a.deptno=b.deptno
where b.empno is null;
2.找出员工个数大于5人的部门信息
解法1:(in)
select deptno from emp group by deptno having count(*)>3;
select * from dept where deptno in(select deptno from emp group by deptno having count(*)>3);
解法2:(表连接)
(select deptno, count(*) from emp group by deptno having count(*)>3) a
select * from
(select deptno, count(*) from emp group by deptno having count(*)>3) a
inner join dept b on a.deptno=b.deptno;
3.找到工资最高的前五名员工信息
select * from emp order by sal desc limit 5;
4.找到每个部门中比本部门平均工资高的员工信息
// 平均工资
(select deptno, avg(sal) asal from emp group by deptno) a
select * from (select deptno, avg(sal) asal from emp group by deptno) a
inner join emp b on a.deptno=b.deptno and b.sal > a.asal;
4. 编程题
- 用递归方法求一个整数的阶乘(5分)
自己实现,很简单 - 用自己掌握的排序算法对一个整数数组排序(不能用jdk自带的)(5分)
冒泡排序
相邻两个元素比较,如果前一个比后一个大,交换顺序
int[] arr = {5, 4, 3, 2, 1};
// 相邻两个元素比较,如果前一个比后一个大,交换顺序
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length -i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
}
3.写一个类实现单例模式(只需要一种写法)(5分)
4.IO,jdbc综合题目
* 根据output.txt的文件结构,创建合适的数据库表,将文件内容通过输入流读取进来并插入至数据库(5分)
* 写一个查询方法,从数据库表中查询出武力最高的3名武将信息,并打印(5分)
* 写一个查询方法,从数据库表中查询出每个地区的平均年龄,并打印(5分)
import org.junit.Test;
import org.westos.working.mysql.utils.JDBCUtils;
import java.io.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* *************************************
* Copyright (c) 2018 feiyan.com
* All rights reserved.
* *************************************
* *************************************
*
* @Author: think
* @Project: JavaSE
* @Date: Created in 2018/8/25 18:52
* @Since: JDK 1.8
* @Version: 1.0
* @Modified By:
* @Description:
*/
public class TestExam {
@Test
public void testWriteDataToDatabase() throws SQLException {
BufferedReader bufferedReader = null;
Connection connection = JDBCUtils.getConnection();
PreparedStatement preparedStatement = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(
"src/org/westos/working/mysql/output.txt"), "utf-8"));
String sql = "insert into hero(hid,hname,place,sex,birth,death,forceValue) values(?,?,?,?,?,?,?)";
preparedStatement = connection.prepareStatement(sql);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
// 1 阿会喃 云南 男 190 225 74
String[] split = line.split("\t");
// 给? 占位符赋值
preparedStatement.setInt(1, Integer.parseInt(split[0]));
preparedStatement.setString(2, split[1]);
preparedStatement.setString(3, split[2]);
preparedStatement.setString(4, split[3]);
preparedStatement.setInt(5, Integer.parseInt(split[4]));
preparedStatement.setInt(6, Integer.parseInt(split[5]));
preparedStatement.setInt(7, Integer.parseInt(split[6]));
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(preparedStatement, connection);
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testQuery1() {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
stmt = conn.prepareStatement("select * from hero order by forceValue desc limit ?");
stmt.setInt(1, 3);
rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getInt("hid") + "\t" +
rs.getString("hname") + "\t" +
rs.getString("place") + "\t" +
rs.getString("sex") + "\t" +
rs.getInt("birth") + "\t" +
rs.getInt("death") + "\t" +
rs.getInt("forceValue") + "\t");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, stmt, conn);
}
}
@Test
public void testQuery2() {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
stmt = conn.prepareStatement("select place,avg(death - birth) age from hero group by place");
rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("place") +"\t" +rs.getDouble("age"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, stmt, conn);
}
}
}