四川禹慕科技有限公司2019面试题

面试时间: 2019-4-1

1. Java 面向对象的特征有哪些,请详细阐述

  • 对象的编程语言有封装、继承 、抽象、多态等4个主要的特征
  • 面向对象编程有三大特性:封装、继承、多态

封装: 封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,面向对象的编程语言中,对象是封装的最基本单位,面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个“模块”中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同一个对象中的属性
抽象: 抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处
继承: 在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性,因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,这就是多态性
多态: 多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定

2. abstract class和interface的区别

抽象类:

  • 抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象
  • 抽象类要被子类继承,接口要被类实现。
  • 抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
  • 抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果
  • 抽象类里可以没有抽象方法
  • 如果一个类里有抽象方法,那么这个类只能是抽象类
  • 抽象方法要被实现,所以不能是静态的,也不能是私有的。
    接口:
  • 接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现。
  • 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
  • 接口可继承接口,并可多继承接口,但类只能单根继承。

3. Java中Heap和Stack的区别

stack:

  • 定义:每个应用运行时都有自己的一段内存空间,用于存放临时变量、参数传递、函数调用时的PC值以及对象的引用,这叫stack
  • 优点:存取速度比堆快,仅次于CPU中的寄存器。另外,
  • 缺点:存在栈中的数据的大小与生存期必须是确定的,所以缺乏灵活性。
    heap:
  • 定义:堆是JVM的内存数据区。Heap的管理很复杂,每次分配不定长的内存空间专门用来保存对象的实例(实际上是保存对象实例的属性值,属性的类型和对象本身的类型标志等),并不保存对象的方法(方法是指令,保存在栈中)。
  • 优点:堆是一个运行时的数据区,它的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,java的垃圾收集器会自动收走这些不再使用的数据。
  • 缺点:由于在运行时动态分配内存,存取速度比较慢。

4. 编程题:写一个 Singleton 出来

懒汉式单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class LazySingleton {
// 私有静态对象,加载时候不做初始化
private static LazySingleton singleton =null;
// 私有构造方法,避免外部创建实例
private LazySingleton(){

}
/**
* 静态工厂方法,返回此类的唯一实例.
* 当发现实例没有初始化的时候,才初始化.
* @return LazySingleton
*/
public static synchronized LazySingleton getInstance(){
if(singleton ==null){
singleton =new LazySingleton();
}
return singleton;
}
}

饿汉式单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class EagerSingleton {
// 私有的唯一实例成员,在类加载的时候就创建好了单例对象
private static final EagerSingleton SINGLETON = new EagerSingleton();
//私有构造方法,避免外部创建实例
private EagerSingleton() {

}
/**
* 静态工厂方法,返回此类的唯一实例.
*
* @return EagerSingleton
*/
public static EagerSingleton getInstance() {
return SINGLETON;
}
}

5. Jvm加载class文件的原理机制

  1. 装载: 查找并加载类的二进制数据;
  2. 链接:
  • 验证:确保被加载类的正确性;
  • 准备:为类的静态变量分配内存,并将其初始化为默认值;
  • 解析:把类中的符号引用转换为直接引用;
  1. 初始化: 为类的静态变量赋予正确的初始值;

    6.

    执行结果:2413
  • 先初始化父类,父类中static依次初始化
  • 子类中static依次初始化
  • 父类变量、代码块依次初始化,再执行父类构造
  • 子类变量、代码块依次初始化,再执行子类构造
    1
    2
    3
    4
    5
    6
    7
    8
    public class A {
    public A() {
    System.out.print(1);
    }
    static {
    System.out.print(2);
    }
    }
1
2
3
4
5
6
7
8
9
public class B extends A {
public B() {
System.out.print(3);
}

static {
System.out.print(4);
}
}
1
2
3
4
5
public class C {
public static void main(String[] args) {
new B();
}
}

注意: 静态代码块只执行一次,而代码块每次都执行
// 245163
// 5163

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class A {
public A() {
System.out.print(1);
}
static {
System.out.print(2);
}
{
System.out.print(5);
}
}

class B extends A {
public B() {
System.out.print(3);
}

static {
System.out.print(4);
}
{
System.out.print(6);
}
}
public class C {
public static void main(String[] args) {
new B();
System.out.println();
new B();
}
}

7. 什么是AJAX,你常用的AJAX方式是什么,请具体描述其实现原理

AJAX:

  • AJAX不是新的编程语言,而是一种使用现有标准的新方法
  • 优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容
  • 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行
  • 常用方式:
    $.ajax()、$.get()、$.post()、load()
  • 原理: Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面

    8. JSP中静态include和动态include的区别

    静态include是编译阶段的代码拼接,动态include是编译后的servlet的运行结果的拼接

    9.什么是SSH框架,并具体描述其中应用的技术的主要功能及其实现原理?

  • SSH是JavaEE中三种框架(Struts+Spring+Hibernate)的集成框架,是目前比较流行的一种Java Web开源框架

原理:

  • 在表示层中,首先通过JSP页面实现交互界面,负责传送请求(Request)和接收响应(Response),然后Struts根据配置文件(struts-config.xml)将ActionServlet接收到的Request委派给相应的Action处理。
  • 在业务层中,管理服务组件的Spring IoC容器负责向Action提供业务模型(Model)组件和该组件的协作对象数据处理(DAO)组件完成业务逻辑,并提供事务处理、缓冲池等容器组件以提升系统性能和保证数据的完整性。
  • 在持久层中,则依赖于Hibernate的对象化映射和数据库交互,处理DAO组件请求的数据,并返回处理结果。

    10.

    原理:
  • 在第一步执行完毕后,整个方法的返回值就已经确定了,
  • 由于还要执行finally代码块,因此程序会将返回值暂存在局部变量区,腾出操作数栈用来执行finally语句块中代码,
  • 等finally执行完毕,再将暂存的返回值又复制回操作数栈顶。
  • 所以无论finally语句块中执行了什么操作,都无法影响返回值,
  • 所以试图在finally语句块中修改返回值是徒劳的。
  • 因此,finally语句块设计出来的目的只是为了让方法执行一些重要的收尾工作,而不是用来计算返回值的。
  • 注意:在finally或者cathch中出现了return就有可能更改返回值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class A {
    public static void main(String[] args) {
    A a = new A();
    System.out.println(a.getA());
    }

    public int getA() {
    int a = 0;
    try {
    return a;
    } finally {
    a = 2;
    }

    }
    }

11. 有如下一段html,请编写css定义,使div1居左,宽度200px;是div2居右,宽度100px,背景颜色为红色

1
2
3
4
5
6
7
8
9
10
11
12
#div1 {
width: 200px;
/*居左*/
float: left
}

#div2 {
width: 100px;
/*居右*/
float: right;
background-color: red;
}
1
2
3
4
<div id="thediv">
<div id="div1">hrer is left</div>
<div id="div2">hrer is right</div>
</div>

12.有如下一段html,请用javascript编写change()方法,实现选择不同的tab,只显示对应的div

1
2
3
4
5
6
7
8
9
10
11
function change(sel) {
// 先让所有div全部隐藏
var tabs = document.getElementsByTagName("div");
for (var i = 0; i < tabs.length; i++) {
tabs[i].setAttribute("style", "display: none");
}
// 再选择显示的div
var id = sel.options[sel.selectedIndex].value;
var tab = document.getElementById(id);
tab.setAttribute("style", "display:block");
}
1
2
3
4
5
6
7
8
<select onchange="change(this)">
<option value="tab1">tab1</option>
<option value="tab2">tab2</option>
<option value="tab3">tab3</option>
</select>
<div id="tab1" style="display: none">here is tab1</div>
<div id="tab2" style="display: none">here is tab2</div>
<div id="tab3" style="display: none">here is tab3</div>

13. 在一张ORACLE下简历的雇员数据表 t_employee,其结果如下

字段名称 类型 说明
f_id number 员工编号(唯一)
f_name varchar(64) 名字
o_dep_id number 所在部门编号
f_join_date date 加入公司时间
o_dep_id number 上司编号(对应员工编号,0表示无上司)

方式一

1
SELECT t.f_name as 名字,IFNULL((SELECT emp.f_name FROM t_employee emp WHERE emp.f_id=t.o_manager_id),'无') as 上司 FROM t_employee t WHERE t.f_name LIKE "李%" and t.f_join_date>"2000-09-01";

方式二

1
2
SELECT t_emp.f_name as 名字,IFNULL( emp.f_name,"无") as 上司 from  (SELECT t.f_name,t.o_manager_id FROM t_employee t WHERE t.f_name LIKE "李%" and t.f_join_date>"2000-09-01") as t_emp
LEFT JOIN t_employee emp ON t_emp.o_manager_id=emp.f_id;

14. 请编写通过JDBC操作(如查询)数据库的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class Jdbc {
private static Connection CONNECTION;

static {
try {
// 不需要使用 Class.forName(),因为DriverManager初始化时会自动注册驱动
// 驱动加载路径:jdbc驱动包中的META-INF.services.java.sql.Driver这个文件中有声明
Properties pro = new Properties();
pro.setProperty("user", "root");
pro.setProperty("password", "root");
CONNECTION = DriverManager.getConnection("jdbc:mysql://localhost:3306/cas_redis?useSSL=false&serverTimezone=UTC", pro);
} catch (SQLException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
String sql = "select id,`name`,gender,age,telphone,register_mode,third_party_id from user_info where id=?";
PreparedStatement preStatement = null;
try {
preStatement = CONNECTION.prepareStatement(sql);
preStatement.setInt(1, 1);
ResultSet resultSet = preStatement.executeQuery();
while (resultSet.next()) {
System.out.printf("%s ", resultSet.getObject("id"));
System.out.printf("%s ", resultSet.getObject("name"));
System.out.printf("%s ", resultSet.getObject("gender"));
System.out.printf("%s ", resultSet.getObject("age"));
System.out.printf("%s ", resultSet.getObject("telphone"));
System.out.printf("%s ", resultSet.getObject("register_mode"));
System.out.printf("%s ", resultSet.getObject("third_party_id"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (preStatement != null) {
preStatement.close();
}
if (CONNECTION != null) {
CONNECTION.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}