面试题_20180829001

目录

String、StringBuffer、StringBuilder之间的区别
  • Java 平台提供了两种类型的字符串:String 和StringBuffer/StringBuilder,它们都可以储存和操作字符串,区别如下
  • 1)String 是只读字符串,也就意味着 String引用的字符串内容是不能被改变的。初学者可能会有这样的误解:

1. String str = "abc";
2. str = "bcd";

  • 如上,字符串 str 明明是可以改变的呀!其实不然,str仅仅是一个引用对象,它指向一个字符串对象“abc”。第二行代码的含义是让 str重新指向了一个新的字符串“bcd”对象,而“abc”对象并没有任何改变,只不过该对象已经成为一个不可及对象罢了
  • 2)StringBuffer/StringBuilder 表示的字符串对象可以直接进行修改
  • 3)StringBuilder 是 Java5 中引入的,它和 StringBuffer 的方法完全相同,区别在于它是在单线程环境下使用的,
    因为它的所有方法都没有被 synchronized 修饰,因此它的效率理论上也比 StringBuffer 要高
==与Equals的区别
  • equals 和== 最大的区别是一个是方法一个是运算符。
  • ==:如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象
    的地址值是否相等。
  • equals():用来比较方法两个对象的内容是否相等。
  • 注意:equals 方法不能用于基本数据类型的变量,如果没有对 equals 方法进行重写,则比较的是引用类型的变
    量所指向的对象的地址。
servlet的生命周期
  • Servlet的运行原理

Servlet的运行原理

Servlet生命周期定义了一个Servlet如何被加载、初始化,以及它怎样接收请求、响应请求,提供服务。在讨论Servlet生命周期之前,先让我们来看一下这几个方法:
  • 1.init()方法
    • 在Servlet的生命周期中,仅执行一次init()方法,它是在服务器装入Servlet时执行的,可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init()
  • 2.service()方法
    • 它是Servlet的核心,每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能
  • 3.destroy()方法
    • 仅执行一次,在服务器端停止且卸载Servlet时执行该方法,有点类似于C++的delete方法。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。
  • 下面来谈谈Servlet的生命周期,Servlet的生命周期是由Servlet容器来控制的,它始于装入Web服务器的内存时,并在终止或重新装入Servlet时结束。这项操作一般是动态执行的。然而,Server通常会提供一个管理的选项,用于在Server启动时强制装载和初始化特定的Servlet。
  • 在代码中,Servlet生命周期由接口javax.servlet.Servlet定义。所有的Java Servlet 必须直接或间接地实现javax.servlet.Servlet接口,这样才能在Servlet Engine上运行。javax.servlet.Servlet接口定义了一些方法,在Servlet 的生命周期中,这些方法会在特定时间按照一定的顺序被调用

Servlet的生命周期

Servlet生命周期
  • 加载和实例化Servlet

  • 我们来看一下Tomcat是如何加载的:

    • 1.如果已配置自动装入选项,则在启动时自动载入。
    • 2.在服务器启动时,客户机首次向Servlet发出请求。
    • 3.重新装入Servlet时。
    • 当启动Servlet容器时,容器首先查找一个配置文件web.xml,这个文件中记录了可以提供服务的Servlet。每个Servlet被指定一个Servlet名,也就是这个Servlet实际对应的Java的完整class文件名。Servlet容器会为每个自动装入选项的Servlet创建一个实例。所以,每个Servlet类必须有一个公共的无参数的构造器。
  • 初始化

    • 当Servlet被实例化后,Servlet容器将调用每个Servlet的init方法来实例化每个实例,执行完init方法之后,Servlet处于“已初始化”状态。所以说,一旦Servlet被实例化,那么必将调用init方法。通过Servlet在启动后不立即初始化,而是收到请求后进行。在web.xml文件中用 …… 对Servlet进行预先初始化。
    • 初始化失败后,执行init()方法抛出ServletException异常,Servlet对象将会被垃圾回收器回收,当客户端第一次访问服务器时加载Servlet实现类,创建对象并执行初始化方法。
  • 请求处理

    • Servlet 被初始化以后,就处于能响应请求的就绪状态。每个对Servlet 的请求由一个Servlet Request 对象代表。Servlet 给客户端的响应由一个Servlet Response对象代表。对于到达客户机的请求,服务器创建特定于请求的一个“请求”对象和一个“响应”对象。调用service方法,这个方法可以调用其他方法来处理请求。
    • Service方法会在服务器被访问时调用,Servlet对象的生命周期中service方法可能被多次调用,由于web-server启动后,服务器中公开的部分资源将处于网络中,当网络中的不同主机(客户端)并发访问服务器中的同一资源,服务器将开设多个线程处理不同的请求,多线程同时处理同一对象时,有可能出现数据并发访问的错误。
    • 另外注意,多线程难免同时处理同一变量时(如:对同一文件进行写操作),且有读写操作时,必须考虑是否加上同步,同步添加时,不要添加范围过大,有可能使程序变为纯粹的单线程,大大削弱了系统性能;只需要做到多个线程安全的访问相同的对象就可以了
  • 卸载Servlet
    • 当服务器不再需要Servlet实例或重新装入时,会调用destroy方法,使用这个方法,Servlet可以释放掉所有在init方法申请的资源。一个Servlet实例一旦终止,就不允许再次被调用,只能等待被卸载。
    • Servlet一旦终止,Servlet实例即可被垃圾回收,处于“卸载”状态,如果Servlet容器被关闭,Servlet也会被卸载,一个Servlet实例只能初始化一次,但可以创建多个相同的Servlet实例。如相同的Servlet可以在根据不同的配置参数连接不同的数据库时创建多个实例
你朋友对你的评价,说一下你的优缺点
你的期望薪资是怎样的
HashMap和HashTable的区别?
  • 1.两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些,我们平时使用时若无特殊需求建议使用HashMap,在多线程环境下若使用HashMap需要使用Collections.synchronizedMap()方法来获取一个线程安全的集合(Collections.synchronizedMap()实现原理是Collections定义了一个SynchronizedMap的内部类,这个类实现了Map接口,在调用方法时使用synchronized来保证线程同步,当然了实际上操作的还是我们传入的HashMap实例,简单的说就是Collections.synchronizedMap()方法帮我们在操作HashMap时自动添加了synchronized来实现线程同步,类似的其它Collections.synchronizedXX方法也是类似原理
  • 2.HashMap可以使用null作为key,不过建议还是尽量避免这样使用。HashMap以null作为key时,总是存储在table数组的第一个节点上。而Hashtable则不允许null作为key
  • 3.HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75
  • 4.HashMap扩容时是当前容量翻倍即:capacity*2,Hashtable扩容时是容量翻倍+1即:capacity*2+1
  • 5.HashMap和Hashtable的底层实现都是数组+链表结构实现
  • 6.两者计算hash的方法不同

//Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模:
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;

//HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸:
static int hash(int h) {
     h ^= (h >>> 20) ^ (h >>> 12);
     return h ^ (h >>> 7) ^ (h >>> 4);
 }

static int indexFor(int h, int length) {
     return h & (length-1);
 }

  • 8.判断是否含有某个键
    • 在HashMap 中,null 可以作为键,这样的键只有一个;可以有一个或多个键所对
      应的值为null。当get()方法返回null 值时,既可以表示HashMap 中没有该键,也可
      以表示该键所对应的值为null。因此,在HashMap 中不能用get()方法来判断HashMap 中是否存在某个键,而应该用containsKey()方法来判断。Hashtable 的键值都不能
      为null,所以可以用get()方法来判断是否含有某个键
重载和重写的区别
  • 方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态
    性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为
    重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方
    法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求
  • 方法重载的规则:
    • 1.方法名一致,参数列表中参数的顺序,类型,个数不同。
    • 2.重载与方法的返回值无关,存在于父类和子类,同类中。
    • 3.可以抛出不同的异常,可以有不同修饰符
  • 方法重写的规则:
    • 1.参数列表必须完全与被重写方法的一致,返回类型必须完全与被重写方法的返回类型一致。
    • 2.构造方法不能被重写,声明为 final 的方法不能被重写,声明为 static 的方法不能被重写,但是能够被再次
      声明。
    • 3.访问权限不能比父类中被重写的方法的访问权限更低。
    • 4.重写的方法能够抛出任何非强制异常(UncheckedException,也叫非运行时异常),无论被重写的方法是
      否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则
      可以。
如何确保接口的安全性
  • 首先,什么是接口?
    • 接口无非有两种,一种是内部接口,一种调用对外包装的接口
    • 内部接口:方法与方法之间,模块与模块之间的交互,程序内部抛出的接口,例如下订单,首先你需要登录,然后调用下订单接口,两个模块有交互那么相互之间的调用,就属于内部接口
    • 对外包装的接口:例如A部门做一个买车服务,它卖两种车一是二手,二是新车,那么它要卖二手车,是不是直接可以调用二手车部门共享的数据进行包装,从而是不是达到数据的共享等等,就不一一举例子.
  • 常用接口采用方式:
    • 1、webService接口:是走soap协议通过http传输,请求报文和返回报文都是xml格式的,我们在测试的时候都用通过工具才能进行调用,测试。可以使用的工具有SoapUI、jmeter、loadrunner等;
    • 2、http api接口:是走http协议,通过路径来区分调用的方法,请求报文都是key-value形式的,返回报文一般都是json串,有get和
      post等方法,这也是最常用的两种请求方式。可以使用的工具有postman、RESTClient、jmeter、loadrunner等;
    • 3.https并非是应用层的一种新协议,只是http通信接口部分用SSL(Secure socket Layer)和TLS(Transport Layer Security)协议代替而已
  • 确保接口的安全性方法
    • Token机制
      • 开放接口时最基本需要考虑到接口不应该被别人随意访问,而我也不能随意访问到其他用户的数据,从而保证用户与用户之间的数据隔离。这个时候我们就有必要引入Token机制了。具体的做法: 在用户成功登录时,系统可以返回客户端一个Token,后续客户端调用服务端的接口,都需要带上Token,而服务端需要校验客户端Token的合法性。Token不一致的情况下,服务端需要拦截该请求
    • 对数据进行校验
      • 服务端从某种层面来说需要验证接受到数据是否和客户端发来的数据是否一致,要验证数据在传输过程中有没有被注入攻击。这时候客户端和服务端就有必要做签名和验签。具体做法:** 客户端对所有请求服务端接口参数做加密生成签名,并将签名作为请求参数一并传到服务端,服务端接受到请求同时要做验签的操作,对称加密对请求参数生成签名,并与客户端传过来的签名进行比对,如签名不一致,服务端需要拦截该请求
    • 过载保护
      • 服务端仍然需要识别一些恶意请求,防止接口被一些丧心病狂的人玩坏。对接口访问频率设置一定阈值,对超过阈值的请求进行屏蔽及预警
    • 异常封装
      • 服务端需要构建异常统一处理框架,将服务可能出现的异常做统一封装,返回固定的code与msg,防止程序堆栈信息暴露
    • HTTPS
      • HTTPS能够有效防止中间人攻击,有效保证接口不被劫持,对数据窃取篡改做了安全防范。但HTTP升级HTTPS会带来更多的握手,而握手中的运算会带来更多的性能消耗。这也是不得不考虑的问题
谈谈你对加班的看法
还有什么想了解的
TCP和UDP的区别和优缺点
TCP与UDP区别总结:
  • 1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
  • 2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付,TCP通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
  • 3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
  • 4.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
  • 5、TCP对系统资源要求较多,UDP对系统资源要求较少。
为什么UDP有时比TCP更有优势?
  • UDP以其简单、传输快的优势,在越来越多场景下取代了TCP,如实时游戏。
  • (1)网速的提升给UDP的稳定性提供可靠网络保障,丢包率很低,如果使用应用层重传,能够确保传输的可靠性。
  • (2)TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程,由于TCP内置的系统协议栈中,极难对其进行改进。
  • 采用TCP,一旦发生丢包,TCP会将后续的包缓存起来,等前面的包重传并接收到后再继续发送,延时会越来越大,基于UDP对实时性要求较为严格的情况下,采用自定义重传机制,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成影响。
ArrayList和LinkedList的区别
  • ArrayList 和 Vector 使用了数组的实现,可以认为 ArrayList 或者 Vector 封装了对内部数组的操作,比如向数组中添加,删除,插入新的元素或者数据的扩展和重定向
  • ArrayList查询快,增删慢,线程不安全,效率高.LinkedList查询慢,增删快,线程不安全,效率高
  • LinkedList 使用了循环双向链表数据结构。与基于数组的 ArrayList 相比,这是两种截然不同的实现技术,这也决
    定了它们将适用于完全不同的工作场景。
  • LinkedList 链表由一系列表项连接而成。一个表项总是包含 3 个部分:元素内容,前驱表和后驱表,如图所示:

表项的三个组成部分

  • 在下图展示了一个包含 3 个元素的 LinkedList 的各个表项间的连接关系。在 JDK 的实现中,无论 LikedList 是否
    为空,链表内部都有一个 header 表项,它既表示链表的开始,也表示链表的结尾。表项 header 的后驱表项便是链表
    中第一个元素,表项 header 的前驱表项便是链表中最后一个元素

一个包含 3 个元素的LinkedList的各个表项间的连接关系

JDBC的开发流程
  • 第一步:Class.forName()加载数据库连接驱动;
  • 第二步:DriverManager.getConnection()获取数据连接对象;
  • 第三步:根据 SQL 获取 sql 会话对象,有 2 种方式 Statement、PreparedStatement ;
  • 第四步:执行 SQL 处理结果集,执行 SQL 前如果有参数值就设置参数值 setXXX();
  • 第五步:关闭结果集、关闭会话、关闭连接
你担任的角色主要负责什么工作
你对于我们公司了解多少
JDBC、Hibernate的区别
相同点
  • 1)两者都是 java 数据库操作的中间件、
  • 2)两者对数据库进行直接操作的对象都是线程不安全的,都需要及时关闭。
  • 3)两者都可对数据库的更新操作进行显式的事务处理
不同点
  • JDBC 是 SUN 公司提供一套操作数据库的规范,使用 java 代码操作数据库。Hibernate 是一个基于 jdbc 的主流
    持久化框架,对 JDBC 访问数据库的代码做了封装。
  • 使用的 SQL 语言不同:JDBC 使用的是基于关系型数据库的标准 SQL 语言,Hibernate 使用的是 HQL(Hibernate
    query language)语言。
  • 操作的对象不同:JDBC 操作的是数据,将数据通过 SQL 语句直接传送到数据库中执行,Hibernate 操作的是持
    久化对象,由底层持久化对象的数据更新到数据库中。
  • 数据状态不同:JDBC 操作的数据是“瞬时”的,变量的值无法与数据库中的值保持一致,而 Hibernate 操作的数
    据是可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的
线程的创建,同步
线程创建的方式
  • 1.继承Thread,然后重写run()方法
  • 例如:

public class ThreadOne extends Thread {
    @Override
    public void run() {
        Log.i("TAG","创建线程方式1");
    }
}

//启动线程方式start
ThreadOne one = new ThreadOne();
one.start();

  • 2.实现runnable接口
  • 例如:

public class ThreadTwo implements Runnable {
    @Override
    public void run() {
        Log.i("TAG","创建线程方式2");
    }
}

Thread thread = new Thread(new ThreadTwo());
thread.start();

3.通过Callable和Future创建线程

public class FetureThread implements Callable<Integer> {
    int a = 0;


    @Override
    public Integer call() throws Exception {
        for(int i = 0 ; i < 8; i++ ){
            a++;
        }
        return a;
    }
}

public class Future {
    FetureThread fetureThread = new FetureThread();
    FutureTask<Integer> task = new FutureTask<Integer>(fetureThread);
    public void run(){
      Thread t = new Thread(task);
        t.start();
    }
    public Integer getResult(){
        try {
            return  task.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return 0;
    }
}

Future future = new Future();
future.run();
Log.i("HomeActivity 线程执行结果",future.getResult()+"");

以上三种创建线程的方式比较:
  • 使用继承Thread类的方式创建多线程时优势是:
    • 编写简单,如果需要访问当前线程
    • 线程类已经继承了Thread类,所以不能再继承其他父类
  • 采用实现Runnable、Callable接口的方式创见多线程时,优势是:
    • 线程类只是实现了Runnable接口或Callable接口,还可以继承其他类,同时使用Callable
      还可以获取线程执行的结果
线程的同步方式
同步方法
  • 即有synchronized关键字修饰的方法。
  • 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,
  • 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。

 //代码如: 
 public synchronized void save(){

 }

  • 注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类
同步代码块
  • 即有synchronized关键字修饰的语句块。
  • 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步

//代码如: 
synchronized(object){ 

}

  • 注:同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。
使用特殊域变量(volatile)实现线程同步
  • volatile关键字为域变量的访问提供了一种免锁机制,
  • 使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,
  • 因此每次使用该域就要重新计算,而不是使用寄存器中的值
  • volatile不会提供任何原子操作,它也不能用来修饰final类型的变量

class Bank {
    //需要同步的变量加上volatile
    private volatile int account = 100;

    public int getAccount() {
        return account;
    }
    //这里不再需要synchronized 
    public void save(int money) {
        account += money;
    }
}

  • 注:多线程中的非同步问题主要出现在对域的读写上,如果让域自身避免这个问题,则就不需要修改操作该域的方法。 用final域,有锁保护的域和volatile域可以避免非同步的问题
使用重入锁实现线程同步
  • 在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。
  • ReentrantLock类是可重入、互斥、实现了Lock接口的锁,
  • 它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力

//ReenreantLock类的常用方法有:
ReentrantLock() //创建一个ReentrantLock实例 
lock()          //获得锁 
unlock()        //释放锁 

//注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用

class Bank {
    private int account = 100;
    //需要声明这个锁
    private Lock lock = new ReentrantLock();
    public int getAccount() {
        return account;
    }
    //这里不再需要synchronized 
    public void save(int money) {
        lock.lock();
        try{
            account += money;
        }finally{
            lock.unlock();
        }

    }
}

  • 注意事项: 关于Lock对象和synchronized关键字的选择:
    • 最好两个都不用,使用一种java.util.concurrent包提供的机制,能够帮助用户处理所有与锁相关的代码。
    • 如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码
    • 如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁
使用局部变量实现线程同步
  • 如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,
    副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。

//ThreadLocal 类的常用方法
ThreadLocal()       //创建一个线程本地变量 
get()               //返回此线程局部变量的当前线程副本中的值 
initialValue()      //返回此线程局部变量的当前线程的"初始值" 
set(T value)        //将此线程局部变量的当前线程副本中的值设置为value

public class Bank{
    //使用ThreadLocal类管理共享变量account
    private static ThreadLocal<Integer> account = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue(){
            return 100;
        }
    };
    public void save(int money){
        account.set(account.get()+money);
    }
    public int getAccount(){
        return account.get();
    }
}

  • 注:ThreadLocal与同步机制
    • ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题。
    • 前者采用以”空间换时间”的方法,后者采用以”时间换空间”的方式
使用阻塞队列实现线程同步
  • 前面5种同步方式都是在底层实现的线程同步,但是我们在实际开发当中,应当尽量远离底层结构。 使用javaSE5.0版本中新增的java.util.concurrent包将有助于简化开发。
  • 本小节主要是使用LinkedBlockingQueue来实现线程的同步
  • LinkedBlockingQueue是一个基于已连接节点的,范围任意的blocking queue。
  • 队列是先进先出的顺序(FIFO)

//LinkedBlockingQueue 类常用方法 
LinkedBlockingQueue()   //创建一个容量为Integer.MAX_VALUE的LinkedBlockingQueue 
put(E e)    //在队尾添加一个元素,如果队列满则阻塞 
size()      //返回队列中的元素个数 
take()      //移除并返回队头元素,如果队列空则阻塞 

  • 注:BlockingQueue定义了阻塞队列的常用方法,尤其是三种添加元素的方法,我们要多加注意,当队列满时:
    • add()方法会抛出异常
        - offer()方法返回false
        - put()方法会阻塞
使用原子变量实现线程同步
  • 需要使用线程同步的根本原因在于对普通变量的操作不是原子的。
  • 那么什么是原子操作呢?
  • 原子操作就是指将读取变量值、修改变量值、保存变量值看成一个整体来操作,即这几种行为要么同时完成,要么都不完成。
  • 在java的util.concurrent.atomic包中提供了创建了原子类型变量的工具类,
  • 使用该类可以简化线程同步。
  • 其中AtomicInteger 表可以用原子方式更新int的值,可用在应用程序中(如以原子方式增加的计数器),但不能用于替换Integer;可扩展Number,允许那些处理机遇数字类的工具和实用工具进行统一访问

//AtomicInteger类常用方法:
AtomicInteger(int initialValue)     //创建具有给定初始值的新的AtomicInteger
addAddGet(int dalta)    //以原子方式将给定值与当前值相加
get()   //获取当前值

class Bank {
    private AtomicInteger account = new AtomicInteger(100);

    public AtomicInteger getAccount() {
        return account;
    }

    public void save(int money) {
        account.addAndGet(money);
    }
} 

什么是事务?事务的特性
事务
  • 事务(Transaction),是指访问并可能更新数据库中各种数据项的一个程序执行单元(Unit),通俗点也就是指针对数据库中形形色色的数据,我们进行一些存取操作。
  • 事务通常是由用户编写的程序执行所引起的,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。例如:在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序
事务的特性
  • 数据库事务 transanction 正确执行的四个基本要素。ACID,原子性(Atomicity)、一致性(Correspondence)、隔离
    性(Isolation)、持久性(Durability)。
  • (1)原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执
    行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • (2)一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
  • (3)隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相
    同的时间内,执行 相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称
    为串行化,为了防止事务操作间的混淆, 必须串行化或序列化请 求,使得在同一时间仅有一个请求用于同一数据。
  • (4)持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚
你上家公司的规模,人员组成
工作中遇到的问题怎么解决
谈谈mybaits的优缺点
  • MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录
一、MyBatis框架的优点:
  • 1.与JDBC相比,减少了50%以上的代码量。
  • 2.MyBatis是最简单的持久化框架,小巧并且简单易学。
  • 3.MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用。
  • 4.提供XML标签,支持编写动态SQL语句。
  • 5.提供映射标签,支持对象与数据库的ORM字段关系映射
二、MyBatis框架的缺点:
  • 1.SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求。
  • 2.SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库
三、MyBatis框架适用场合:
  • MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。
  • 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择
阐述 final、finally、finalize 的区别
JSP 和 Servlet 区别
  • final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,被其修饰的类不可继承。
  • finally:异常处理语句结构的一部分,表示总是执行。
  • finalize:Object 类的一个方法,在垃圾回收器执行的时候会调用被回收对象的此方法,可以覆盖此方法
    提供垃圾收集时的其他资源回收,例如关闭文件等。该方法更像是一个对象生命周期的临终方法,当该方法
    被系统调用则代表该对象即将“死亡”,但是需要注意的是,我们主动行为上去调用该方法并不会导致该对
    象“死亡”,这是一个被动的方法(其实就是回调方法),不需要我们调用
如果录用你,你怎样开展工作
上家公司的工资是多少?你的薪资组成是怎么样的
java的基本数据类型有哪些
第一类:逻辑型boolean
  • 1.boolean类型只存在true(真),false(假)两种形式
  • 例:boolean a=true; boolean b=false;
第二类:文本型char
  • 字符常量通常用单引号括起来(可以是中文)java采用unicode编码,每个字符占两个字节,
  • 例:char a=’a’;char b=’你’;
第三类:整数型(byte、short、int、long)
  • byte:8 位,用于表示最小数据单位,如文件中数据,-128~127
  • short: 16 位,很少用 从-32768到32767
  • int:32 位、最常用,-2^31-1~2^31 (21 亿) 从-2147483648,到2147483647共10位
  • long:64 位、次常用 从-9223372036854775808到9223372036854775807共19位
第四类:浮点型(float、double)
  • float:32 位,后缀 F 或 f,1 位符号位,8 位指数,23 位有效尾数。
  • double:64 位,最常用,后缀 D 或 d,1 位符号位,11 位指数,52 位有效尾
  • 注意:在数学中0到1有无数个浮点数;而计算机是离散的,所以表示的时候有误差,
    计算机用精度(小数点后几位来表示正确),比较浮点数时a\==0.1是不合适的,
    应该a-0.1\==0;如果a是0.1,则即使有误差 a-0.1==0因为a和0.1都被表示为一个有误差的计算机二进制
请求转发和重定向的区别
  • 本质区别:转发是服务器行为,重定向是客户端行为。
  • 重定向特点:两次请求,浏览器地址发生变化,可以访问自己 web 之外的资源,传输的数据会丢失。
  • 请求转发特点:一次强求,浏览器地址不变,访问的是自己本身的 web 资源,传输的数据不会丢失。
cookie和session的区别
  • Cookie 是 web 服务器发送给浏览器的一块信息,浏览器会在本地一个文件中给每个 web 服务器存储 cookie。
    以后浏览器再给特定的 web 服务器发送请求时,同时会发送所有为该服务器存储的 cookie。
  • Session 是存储在 web 服务器端的一块信息。session 对象存储特定用户会话所需的属性及配置信息。当用户在
    应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去
  • 1、无论客户端做怎样的设置,session 都能够正常工作。当客户端禁用 cookie 时将无法使用 cookie。
  • 2、在存储的数据量方面:session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象
对跳槽的看法?为什么要离职
你能为公司带来什么
jsp和servlet的区别和联系
  • 1.jsp经编译后就变成了Servlet.
    (JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)
  • 2.jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.
  • 3.Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到.
    Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。
    而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。
联系
  • JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。
  • Servlet和JSP最主要的不同点在于:
    • Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。
    • 而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。
    • JSP侧重于视图,Servlet主要用于控制逻辑
    • Servlet更多的是类似于一个Controller,用来做控制
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值