精华内容
下载资源
问答
  • 传播智客风清扬JAVA百度云资源,传播智客风清扬JAVA百度云资源
  • 风清扬JAVA教程ppt

    2015-07-21 00:12:23
    风清扬老师的教程课件,包含基础课程讲解,编程入门非常实用
  • 风清扬Java面试题突击100道! https://www.zhihu.com/people/13148848 目录1. 你对面向对象的理解2. JDK/JRE/JVM3. ==和equals的区别4. final关键字5. String,StringBuild,StringBuffer区别6. 接口和抽象类的区别7...

    风清扬Java面试题突击100道!

    https://www.zhihu.com/people/13148848

    1. 你对面向对象的理解

    1. 对比面向对象和面向过程的区别
    • 面向对象:是以组织者角度思考,eg:干什么事,找哪些人来做
    • 面向过程:是以执行者角度思考,eg:到底怎么干
    1. 三大特性
    • 封装
    • 继承
    • 多态

    2. JDK/JRE/JVM

    1. 简述三者的关系

      • JDK:Java开发工具包,提供了Java的开发环境和运行环境JRE
      • JRE:Java运行环境,包括了Java虚拟机和一些基础类库
      • JVM:Java虚拟机,执行字节码文件
    2. Java如何实现跨平台

      • Java源码要编译成class文件,才能被虚拟机执行。一次编译,到处运行
      • 我们在不同的平台安装不同的JVM,使用同一套class文件,这样就实现了跨平台

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2RSnvgqj-1620227111528)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210501135614290.png)]

    3. ==和equals的区别

    1. ==比较的值
      • 基本数据类型(栈、方法区):比较的是数值
      • 引用数据类型(堆):比较的是地址
    2. equals默认比较的也是地址
      • String类重写了Object的equals,实现了比较字面值
    package cn.com.gs.common.test;
    
    public class EqualsTest {
        public static void main(String[] args) {
            // 引用数据类型
            String s11 = new String("zs");
            String s12 = new String("zs");
            System.out.println(s11 == s12);// false
    
            // 基本数据类型,相加时相当于new
            String s21 = "zs";
            String s22 = "zs";
            System.out.println(s21 == s22); // true
    
            String s23 = "zszs";
            String s24 = s21 + s22;// 底层使用new StringBuild创建一个新的对象,再赋值
            System.out.println(s23 == s24); // false
    
            // 常量
            final String s31 = "zs";
            final String s32 = "zs";
            final String s33 = s31 + s32;//
            String s34 = s31 + s32;
            final String s35 = s21 + s22;// 底层使用new StringBuild创建一个新的对象
            System.out.println(s31 == s32); // true
            System.out.println(s23 == s33); // true
            System.out.println(s23 == s34); // true
            System.out.println(s23 == s35); // false
        }
    }
    
    

    4. final关键字

    可以修饰类,变量,方法等。

    • 修饰类:表示类不可继承;eg:String就是常量类

    • 修饰变量:

      • 基本数据类型:表示值不可更改

      • 引用数据类型:表示引用指向不可更改,但是引用的对象里的属性值还是可变的

        final Student student = new Student(1, "Andy");
        student.setAge(18);// 这种是可以的
        
        student = new Student(2, "Andy");// 这种是不可以的
        
    • 修饰方法:表示方法不可重写

    5. String,StringBuild,StringBuffer区别

    StringStringBuildStringBuffer
    是否可变final修饰,每次声明的都是不可变变量final修饰,字符串支持动态修改,append方法final修饰,字符串支持动态修改
    线程安全/线程不安全线程安全,使用synchronized修饰
    性能/

    StringBuild使用:在方法内部使用,处理字符串的拼接,此时不会有多线程安全问题。

    多线程执行add方法时,每个线程都有自己独有的栈区,资源不共享时不会出问题。

    只有多线程访问同一个共享资源时需要考虑安全问题。

    public void add() {
        StringBuild sb = new StringBuild();
        sb.append("zs");
    }
    
    

    6. 接口和抽象类的区别

    1. 接口
      • 类:interface修饰
      • 静态常量:public static final修饰
      • 方法:public abstract修饰的抽象方法,没有方法体(jdk1.8以后,可以有实现的方法,需要在方法上加上default或static)
    2. 抽象类
      • 类:abstract修饰
      • 变量:
      • 构造器:不能被实例化,只能被子类调用
      • 方法:可以有抽象的,也可以有非抽象的
      • 举例:BaseDao

    7. 递归算法笔试:

    求N的阶乘

    公式:N! = (n-1)!*n

    例如:3! = 1 * 2 * 3

    出口:n0 或 n1,return 1;

    求解菲波那切数列的第N个数是几

    数字规律:1,1,2,3,4,8,13,21…

    8.Integer自动拆箱装箱

    // Integer,装箱valueOf方法,数值在-128~127,就返回事前缓存好的数值,其他则new
    Integer i1 = 128;// 自动装箱Integer.valueOf(128),128超出范围,则new Integer(128)
    Integer i2 = 128;
    int i3 = 128;
    System.out.println(i1 == i2);// false
    System.out.println(i1 == i3);// true,自动拆箱valueOf,比较数值
    System.out.println(i2 == i3);// true
    
    Integer i4 = 127;
    Integer i5 = 127;
    System.out.println(i4 == i5);// true
    

    9. 重写和重载

    重写:发生在父子类之间,子类重写父类的方法,同名同参

    重载:发生在同一个类中,同名不同参

    10. list和set

    list:有序,可重复

    set:无序,不可重复。无序指输出顺序!=输入顺序,和排序无关

    11. ArrayList和LinkedList区别

    ArrayListLinkedListVector
    底层结构数组,连续的内存空间;
    长度固定,不够用时自动扩容1.5倍
    双向链表,不连续的内存空间
    速度(不太严谨)查找快:因为地址连续
    删除/插入慢:因为数据要移动
    查找慢:因为需要指针一个个寻找
    删除/插入快:数据不需要移动,只需要改变前后节点的指针指向即可
    线程安全不安全不安全安全,synchronized修饰

    在查找速度上,需要区分场景:

    1. 根据位置查:ArrayList > LinkedList
    2. 根据值查:两者都需遍历,性能不分上下

    在插入速度上,需要区分场景:

    1. 在头部/中间位置插入:LinkedList  > ArrayList
    2. 在末尾插入:不分上下
    

    延伸:

    确定有1000个对象要存储,使用哪个更省内存?

    答:ArrayList更省内存,因为双向链表要存储指针,指针也占内存。

    ​ 初始化时就分配1000的内存,避免扩容;

    ArrayList如何扩容?

    第一次创建一个数组,长度为10;

    当存第11个的时候,就自动创建一个长度是15的数组;

    然后将所有对象迁移到新数组中。

    12. Spring的IOC

    1. 你的理解

      控制反转:将创建对象的动作交给Spring容器

      解析+赋值

    2. 应用场景

    3. 具体怎么实现

      • 配置文件实现

        怎么加载配置文件?

        怎么解析xml? dom4j解析

        <bean></bean>
        
      • 注解实现@Autowired

        什么时候能找到注解?

        答:启动流程:扫描所有包,拿到@controller修饰的类,再找@Autowired修饰的属性,根据类型进行依赖注入

    13. 如何在双向链表A、B之间插入一个C?

    // 先定义C
    C.pre = A
    C.next = A.next;
    // 再从后往前修改指针
    A.next.pre = C;
    A.next = C
    

    14. HashSet存储原理

    HashSet<Object> set = new HashSet<>();
    set.add("a");
    
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    

    add方法底层还是使用的HashMap来存储,值作为key

    延伸:

    为什么使用HashSet?

    答:要保证数据的唯一性,Set可以保证数据不重复;

    怎么保证数据不重复?

    答:使用遍历来比对,效率太低。这时出现了Hash算法。

    根据需要,重写Object的hashCode方法;

    在存储对象时,计算hashCode, 再用hash值和数组长度-1进行位运算,得到要存储的位置。

    如果我们要存的位置没有元素,直接存储;

    如果有元素,计算equals方法,相等即同一对象不存储,不相等则形成链表(???再优化为红黑树)

    为什么采用hash算法?

    答:通过hash算法,确认存储的每个对象唯一。

    hash算法不可逆,输出值为定值,计算时可减小数据量。

    15. ArrayList和Vector

    ArrayList:不安全,效率高;

    Vector:安全,效率低

    16. HashTable&HashMap&ConcurrentHashMap

    HashTable:哈希表,本质是数组,数组的元素是链表

    HashTableHashMapConcurrentHashMap
    本质是数组,数组的元素是链表本质是数组,put/get分段锁
    线程安全安全不安全,多线程操作同一个HashMap,可能出现死锁问题;
    解决方式1.0:Collections.synchronizedMap()方法,但是性能依旧有问题,相当于用了HashTable
    解决方式2.0:jdk提供了并发包concurrent,兼顾了线程和效率的问题

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XB3uqZbo-1620227111530)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210501181206650.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PljfMw5t-1620227111532)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210501181142735.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OVMk9fs9-1620227111533)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210501181012036.png)]

    17. 开发一个自己的栈,你会怎么写?

    栈的特点:底层数组,先进后出

    入栈:arr[arr.length + 1] = object

    出栈:

    • pop():取出并移除
    • peak():取出

    18. 开发一个双向链表的节点类

    public class Node<T> {
    	Node pre;
        Node next;
        T data;
    }
    

    19. IO流

    1. 分类

      • 按方向分类:输入流、输出流
      • 按读取单位分:字节流、字符流
    2. 如何选择字节流和字符流?

      • 字节流:上传下载时,不需要具体解析文件内容时,使用字节流
      • 字符流:需要具体解析文件内容时,使用字符流

    20. serialVersionUID的作用是什么

    1. serialVersionUID什么时候出现?

      答:在对象序列化到磁盘时,会根据当前类的结构生成serialVersionUID。

      如果serialVersionUID由系统生成,可能导致在类更新后,反序列化失败,无法读取以往的版本。

      所以一般情况下,我们会手动在类里面写一个固定的serialVersionUID值。

    2. 有什么作用?

      答:用于反序列化时比对。反序列化时,先根据当前类的结构生成一个版本ID,和磁盘的版本ID进行比对,一致则反序列化成功,否则反序列化失败。

    3. 什么时候需要序列化和反序列化?

      答:序列化:当想要把类信息写入磁盘时;反序列化:要从磁盘读取信息时;

    21. Java的异常

    Throwable:

    • Error:一般是JVM异常,有可能是我们写的有问题
      • StackOverError栈内存溢出
    • Exception:
      • runtimeException运行时异常:编译时无法发现,一般是程序写的并不严谨导致的。
        • 数组下标越界
        • 空指针
        • 类型转换异常
        • 数字格式异常
        • 算法异常
      • 非运行时异常:
        • IOException
        • SQLException
        • FileNotFoundException
        • NoSuchFileException
        • NoSuchMethodException

    22. throw和throws的区别

    throw:作用在方法内,用于主动抛出一个异常

    throws:作用在方法声明上,可以抛出多个异常

    一般我们的异常都是一级一级往上抛,最终通过异常处理机制统一处理。(方便打印日志及响应信息)。

    自定义异常怎么写?

    框架的异常最终为什么要继承RuntimeException?

    答:因为框架制定了一系列规则,我们可能因为不会使用而导致出异常,并不属于逻辑错误。

    23. 创建线程的方式

    • 继承Thread:重写run方法
    • 实现Runnable接口:重写run方法
    • 实现Callable接口(可以获取线程执行之后的返回值):重写call方法

    其实后两种,严格来说是一个可执行的任务,还是需要创建Thread对象来执行,比如new Thread(runnable).start();

    实际开发中,我们一般采用线程池,统一管理,节约资源。

    延伸:

    启动线程的方式

    线程池的使用

    24. main方法,不是一个人在战斗

    main也是一个线程,同时还有一个GC垃圾回收线程

    25. 线程的五大状态

    新建new、就绪runnable、运行runnable、阻塞(blocked、waiting、timed waiting)、死亡terminated

    img

    详述共6种状态:getState()

    new、runnable、blocked、waiting、timed waiting、terminated

    blocked:当线程进入synchronize同步代码块或同步方法,但是没有获取到锁,会进入blocked状态, 直到其他线程释放锁,当前线程拿到锁,进入就绪runnable状态。

    waiting:当线程调用wait()或join()时,线程进入waiting状态,

    ​ 当线程调用notify()/notifyAll(),或者join的线程执行结束后,进入就绪runnable状态。

    timed waiting:当线程调用wait(time)或sleep(time)时,线程进入timed waiting状态,

    ​ 当线程调用notify()/notifyAll(),或者线程休眠结束后,进入就绪runnable状态。

    26. 谈谈你对线程安全的理解

    描述:当多线程访问同一个对象时,如果不用额外的同步控制,就能得到正确的结果,那我们就说这个对象是线程安全的。

    如何做到线程安全?

    答:常见的是使用synchronize加锁,例如StringBuffer

    27. sleep和wait的区别

    sleepwait
    所属属于Thread类,Thread.sleep()属于Object类,o.wait()
    不释放锁,休眠结束自动进入就绪状态释放锁,等待notify()/notifyAll()唤醒
    使用范围任意代码只能放在同步代码块或同步方法

    为什么wait要定义在Object上,而不定义在Thread上?

    答:Java的锁是对象级别的,我们需要对象锁来实现多线程的互斥效果

    为什么wait必须用在同步代码块或同步方法中?

    答:因为wait方法需要被唤醒,需要按照先wait、再唤醒的顺序来执行。用同步来保证顺序。

    如果写在非同步的地方,其他线程提前调用了notify方法,那么当前线程就无法被唤醒。

    28. 谈谈你对ThreadLocal的理解

    ThreadLocal为每个线程创建一个副本,实现在线程的上下文传递对象。

    每个线程都有一个对应的Map区域,存放键值对,键为threadLocal,在线程上下文都可获取到。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fQIE09Qj-1620227111535)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210502171035909.png)]

    29. ThreadLocal的使用

    使用实例:在操作数据库时,service调用两个dao,事务要统一控制。

    每一个dao层的方法,使用同一个connection连接,由底层进行connection的传递。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eAicQxJq-1620227111535)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210502175005881.png)]

    30. 类加载机制

    什么是类加载机制?

    答:JVM使用Java类的流程:

    1. Java源文件—>编辑—>class文件
    2. 类加载器ClassLoader读取class文件,并将其转为java.lang.Class实例。有这个实例,JVM就可以进行创建对象和调用方法等操作了。

    class来源有哪些?

    答:来源有三种

    1. Java自带的核心类库,在$JAVA_HOME/jre/lib下,最著名的rt.jar
    2. Java自带的扩展类,在$JAVA_HOME/jre/lib/ext下
    3. 我们自己开发的类,以及我们用的第三方jar,位于WEB-INF/lib下

    有哪些类加载器?

    答:对于不同来源的class,有不同的加载器:

    1. Java核心类:由BootstrapClassLoader加载。这个加载器被称为“根加载器或引导加载器”;

      ​ BootstrapClassLoader不继承ClassLoader,是JVM内部实现的。

      ​ 我们无法通过Class类的getClassLoader获取。

    2. Java扩展类:由ExtClassLoader加载,被称为“扩展类加载器”;

    3. 自己开发的类和第三方类库:由AppClassLoader加载,被称为“系统类加载器”;

    // BootstrapClassLoader不继承ClassLoader,是JVM内部实现的
    String string = new String();
    System.out.println(string.getClass().getClassLoader());// null
    
    // 我们自己的Student类
    Student student = new Student();
    System.out.println(student.getClass().getClassLoader());// AppClassLoader
    System.out.println(student.getClass().getClassLoader().getParent());// ExtClassLoader
    System.out.println(student.getClass().getClassLoader().getParent().getParent());// null
    

    面试场景:

    我现在编写一个类,类全名为java.lang.String, 我们这个类能否替换掉JDK的String类?

    答:不能。因为类加载的双亲委派机制。双亲是指AppClassLoader还有两个上级。

    在加载class时,AppClassLoader委派给ExtClassLoader,ExtClassLoader又委派给BootstrapClassLoader,BootstrapClassLoader找到该类就使用该类,找不到就让委托人ExtClassLoader自己去找。

    所以我们new String()时,是由BootstrapClassLoader找到了JDK的String,无法找到我们自定义的String。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7x1VjuWf-1620227111536)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210502183953634.png)]

    31. Ajax的工作原理

    异步交互、XMLHttpRequest对象、回调函数

    传统模式和Ajax模式对比:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7fMzfBma-1620227111537)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210502210638895.png)]

    32. JavaScript的原型机制

    JavaScript的原型有一个关键的作用:用来扩展其原有类的特性,从而使框架更易用。

    eg:给String类扩展一个hello方法

    var str = "abc";
    String.prototype.hello = function(){
    	alert("通过原型的方式扩展原有类的方法或属性")
    }
    str.hrllo();
    

    33. JSP和Servlet的区别

    • JSP本质是一个Servlet,JSP—>翻译—>Servlet—>编译—>class文件

    • JSP主要是写HTML页面视图,也支持Java代码;Servlet主要写java逻辑代码

    jsp翻译成java文件,存储路径tomcat/work/Catilina/localhost/examples/org/apache/jsp/…

    34. Servlet生命周期

    Servlet是单例的,只初始化一次,用完销毁。

    生命周期:创建对象—>初始化—>service()—>doGet/doPost()—>销毁

    创建对象的时机

    1. 默认是第一次访问该Servlet时创建
    2. 也可以通过web.xml改变创建时机,比如容器启动时就创建,DispatcherServlet。
    <!--DispatcherServlet:项目启动就创建-->
    <load-on-startup>1</load-on-startup>
    
    <!-- springMVC配置 -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:config/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    

    需要考虑线程安全吗?

    需要:因为Servlet是单例的,被多个线程共享,需要考虑安全问题。

    35. session和cookie的区别

    sessioncookie
    存储位置服务端客户端
    存储格式key-value形式,value存对象key-value形式,value存字符串
    存储大小受服务器内存控制一般来说,最大4k
    生命周期服务器控制,默认30分钟客户端控制,分两种情况:
    1.会话级cookie(默认):随浏览器关闭而消失,例如存储sessionId的cookie;
    2.非会话级cookie:通过有效期控制的失效时间,例如7天免登录功能;setMaxAge来设置有效期

    关闭浏览器后,session会消失吗?

    答:不会,session由服务器控制,与客户端无关。

    为什么会产生session的使用?

    答:因为http是无状态的协议,服务器需要有一种机制来存储用户的登录信息,以此来校验用户访问接口的权限。

    36. 转发和重定向的区别

    转发:发生在服务器端内部的跳转,对于用户来说,只有一次请求;

    重定向:发生在客户端的跳转,对于用户来说,发了两次请求。

    37. 谈谈MVC三层架构

    三层架构:控制层、业务层、数据层。

    • 控制层:负责对外提供接口;SpringMVC
    • 业务层:编写具体的业务逻辑;Spring
    • 数据层:和数据库交互;Mybatis、SpringJdbc

    MVC:将控制层分为模型、视图和控制器。

    • Model:代表一个数据对象;
    • View:代表一个可视化的页面,比如HTML、JSP
    • Controller:控制器作用在模型和视图上,用于接收数据以及返回对应的视图。

    SpringMVC执行流程:
    在这里插入图片描述

    1.springmvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求进行真正的处理工作。

    2.DispatcherServlet查询HandlerMapping,找到处理请求的Controller。

    3.DispatcherServlet将请求提交到目标Controller。

    4.Controller进行业务逻辑处理后,会返回一个ModelAndView。

    5.Dispathcher查询ViewResolver视图解析器,找到ModelAndView对象指定的视图对象。

    6.将页面渲染到浏览器客户端。

    38. JSP九大内置对象

    request、response、session、application

    page、pageContext、config、out、exception

    39. JSP的4大域对象

    作用范围
    HttpServletRequest只能在同一次请求中使用
    HttpSession只能在同一个会话使用
    PageContext只能在当前jsp页面使用
    ServletContext只能在同一个web应用使用

    40. 并发和并行的区别

    并发:同一个CPU执行多个任务,按时间片交替执行

    并行:在多个CPU,同时处理多个任务

    41. 数据库三大范式

    第一范式:列不可分;

    第二范式:要有主键;

    第三范式:不可存在传递依赖;

    ​ 举例:商品表和商品类别表。

    ​ 商品表要关联商品类别,存储一个商品类别ID字段即可;

    ​ 如果此时存储了一个商品类别Name字段,即存在了传递依赖,造成了冗余,违反了第三范式。

    反范式设计:(反第三范式)

    ​ 上例中,违反了第三范式,正贴合了反范式思想。

    ​ 反范式是为了提高查询效率,以冗余换时间,将多表关联转为单表查询,提高查询效率。

    ​ 经典示例:订单表。订单表要存储订单人、订单地址等信息,而不能通过多表关联。

    42. 数据库聚合函数

    count、sum、max、min、avg

    select count(*) from t_student; // 学生总数
    select sum(age) from t_student; // 年龄总和
    select max(age) from t_student; // 年龄最大的学生
    select min(age) from t_student; // 年龄最小的学生
    select avg(age) from t_student; // 平均年龄
    

    count(*)和count(字段)的效率问题

    43. 左连接、右连接、内连接

    左连接(left join):以左表为基础,查询右边满足关联条件的信息,查询结果条数=左表记录数

    右连接(right join):以右表为基础,查询左边满足关联条件的信息,查询结果条数=右表记录数

    内连接(inner join):查询两表满足关联条件的信息,查询结果条数不确定

    44. 如何避免SQL注入

    SQL注入,是指通过字符串拼接的方式,构成了一种特殊的,和预期相悖的查询语句

    常用注入字符 #(Mysql)、–(Oracle)

    # 原语句
    select * from t_user where username = ? and password = ?
    # 用户输入username值为“or 1=1 #”,密码随便输入,即可登录
    # 拼接完的SQL如下
    select * from t_user where username = "or 1=1 #" and password = ?
    相当于
    select * from t_user where username = "or 1=1
    

    解决方案:

    ​ 使用预处理PreparedStatement对象,好处有:

    • 解决SQL注入问题
    • 预先编译,执行效率提高

    MyBatis如何解决注入?

    ​ Mybatis在写语句时,使用#占位可解决注入,而?不行

    45. JDBC如何控制对事务的控制

    JDBC通过Connection来控制事务,代码如下

    try {
    	connection.setAutoCommint(false);
        // dosomeing
        connection.commit();
    } catch(Exception e) {
        connection.rollback();
    }
    

    事务的边界要放在业务层,因为业务层可能会调用多个dao,要用一个事物来控制。

    46. 事务的特点

    原子性:事务中包含的操作要么一起成功,要么一起失败

    一致性:数据库中的数据,在事务操作前后,都应该满足业务规则约束。比如A给B转账,转账前后,A和B的账户总金额应该是一致的。

    隔离性:一个事务的执行,不能受其他事务的干扰。

    持久性:事务一旦提交,结果便是永久性的。即便宕机,依然可以靠事务日志完成数据持久化。

    ​ 事务日志包括回滚日志和重做日志。

    ​ 当我们修改数据时,首先会将数据库变化信息记录到重做日志中,然后再对数据库中的数据进行修改。这样即便数据库崩溃,我们也可以通过重做日志进行数据恢复。

    image-20210503131956990

    47. 事务的4大隔离级别

    • read uncommited读未提交:可能会导致脏读、幻读、不可重复读;
    • read commited读已提交:避免脏读,可能会导致幻读、不可重复读;
    • repeatable read可重复读:避免脏读、不可重复读,可能会导致幻读;
    • serializable串行化:避免脏读,幻读、不可重复读,但性能影响较大;

    Oracle默认隔离级别:读已提交;

    MySQL默认隔离级别:可重复读;

    场景:夫妻两人在不同的地方用同一张卡在消费,老婆看上了一件衣服3000块,查询余额有4000块钱,于是刷卡结账,与此同时丈夫请客吃饭,花了2000块钱,导致老婆结账时失败。

    脏读:

    幻读:

    不可重复读:查询余额4000,但是当真正结账时发现只剩2000了,重复读的数据不一致,这就叫不可重复读。

    48. synchronized和lock的区别

    synchronizedlock
    作用位置作用在代码块、方法作用在代码块
    获取锁机制不需要手动获取锁,进入修饰的代码块、方法自动获取锁需要手动加锁lock()
    释放锁机制发生异常时会自动解锁需要手动解锁unlock(),否则会死锁,一般写在finally里

    synchronized加锁对象:

    • 代码块:可自定义锁住对象,比如synchronized(this){xxx}
    • 静态方法:锁住类
    • 普通方法:锁住对象

    49. TCP和UDP协议

    传输层协议

    TCP建立连接:三次握手

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1hlXTTW9-1620227111539)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503140128851.png)]

    TCP断开连接:四次挥手

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-74PXpTKH-1620227111540)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503143553230.png)]

    50. 什么是死锁?如何避免死锁?

    线程1锁住了资源a,线程2锁住了资源b,这时线程1需要访问资源b,线程2也需要访问资源a,双方都在等待对方释放锁,从而发生死锁。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wDAjLS8q-1620227111541)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503144909567.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nEL8a83s-1620227111542)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503144839932.png)]

    如何避免死锁?

    1. 避免嵌套加锁;
    2. 可以采用tryLock(timeout)的方式,超时后主动退出,避免死锁;
    3. 降低锁的粒度,不要几个功能共用一把锁

    51. 反射

    反射是一种能力,能够在程序运行时,动态的获取当前类的所有属性和所有方法,可以动态执行方法,动态给属性赋值等操作。

    举例:@Autowired根据反射自动实现赋值

    原理:注解解析程序,扫描指定包下哪些属性加了@Autowired注解,加了注解的就去容器中,根据类型找到相应的实现,进行赋值。

    52. 谈谈对Spring的认识

    1. Spring的特性IOC、AOP
      • IOC:解耦
      • AOP:业务增强

    Spring Data和Spring web模块,更方便继承其他主流框架。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XhYi9xui-1620227111542)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503162025948.png)]

    53. Spring的bean作用域

    • bean默认是单例的
    • 原型:每次调用bean的时候,都会创建一个新的对象
    • request:一次请求创建一个对象
    • session:一个会话中bean共享

    bean生命周期

    img

    54. Spring的bean是线程安全的吗

    默认情况下,bean是单例的,在多线程下如果操作对象,就需要考虑线程安全???

    风清扬老师讲:bean是单例的,但是bean无状态,就是没有存储数据,没有通过数据的状态来作为下一步操作的依据,从这点看,是线程安全的。

    不懂

    56. 事务的传播特性和Spring支持的特性

    事务的边界在service层。

    如果一个事务内,调用了另外一个有事务的service方法,此时我们需要把这个事务控制在最外层,就发生了事务的传播。

    Spring支持的特性

    • propagation_required:支持当前事务,如果当前没有事务,就新建一个事务
    • propagation_supports:支持当前事务,如果当前没有事务,就以非事务方式进行
    • propagation_mandatory:支持当前事务,如果当前没有事务,就抛出异常
    • propagation_requires_new:新建事务,如果当前存在事务,就把当前事务挂起
    • propagation_not_supported:以非事务方式执行,如果当前存在事务,就把当前事务挂起
    • propagation_never:以非事务方式执行,如果当前没有事务,就抛出异常

    57. 什么是悲观锁,什么是乐观锁?

    悲观锁:利用数据库本身的锁机制来实现,会锁记录。

    select * from t_table  where id = 1 for update
    

    ​ 举例:synchronized

    乐观锁:不锁记录,采用CAS(compare and swap)模式,采用version字段作为判断依据。

    version字段可以+1,也可采用时间戳

    select *,version from t_table where id = 1
    得到version = 1,以此查询结果作为更新的限定条件,更新时更新version字段
    update t_table set version = version + 1 where id = 1 and version = 1
    

    为什么不采用其他字段呢?

    ​ 首先,我们不能使用业务字段,业务字段有可能出现ABA的情况

    58. Mybatis缓存机制

    缓存,主要作用是为了提高查询效率,减少和数据库的交互,减轻数据库的压力。

    适用于读多写少的场景。

    默认开启一级缓存。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cFuVQXDk-1620227111544)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503171126975.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6K87pF8B-1620227111544)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503171215721.png)]

    一级缓存总结

    • 默认开启
    • 作用域在SqlSession,SqlSession关闭重新打开后,会重新查询数据库
    • 执行过查询条件,就会把结果放进一级缓存
    • 对数据库有任何更新操作,都会清空一级缓存!注意,任何更新操作指增删改。

    二级缓存:默认关闭,图有问题

    • 默认关闭
    • 作用域是SqlSessionFactory
    • sqlsession关闭后,才会将结果放进二级缓存
    • 对数据库有任何更新操作,都会清空二级缓存!注意,任何更新操作指增删改

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7x3w87Rr-1620227111545)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503171950193.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-77VG0HQX-1620227111546)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503172054551.png)]

    代码验证:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qlf4uQOq-1620227111547)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503172257444.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1P0LhJQB-1620227111547)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503172318960.png)]

    发现sqlsession关闭后,才会将结果放进二级缓存。

    59. Mybatis分页方式

    分为物理分页和逻辑分页。

    • 物理分页(正常人都用):从数据库查出指定条数的数据。eg:分页插件PageHelper
    • 逻辑分页:使用Mybatis自带的RowBounds进行分页,一次性查出多条数据,再检索分页中的数据。具体一次性查询多少条数据,受封装jdbc配置的fetch-size决定。

    分页插件能实现的原理:

    • Mybatis提供了一个拦截器接口Interceptor
    • 分页插件实现Interceptor接口,重写intercept()方法
      • 在方法内部,拦截到待执行的SQL,然后根据不同的方言、分页参数,重新生成带分页的SQL,执行重写后的SQL,从而实现分页

    60. 从在浏览器输入地址到响应,都经历了什么?

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oouHLsXe-1620227111548)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503180413159.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ePm07qwc-1620227111549)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503180251904.png)]

    61. Synchronized底层原理

    通过两个指令实现。

    JDK1.6之前:

    JDK1.6之后:提供三种锁,偏向锁、轻量级锁和重量级锁。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P7mBOFna-1620227111549)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503182019858.png)]

    synchronized如何保证可见性?

    可见性指多个线程对共享变量要可见。

    线程工作时,分为本地内存和主内存。获取到锁之后,都从主内存读;当释放锁后,将本地内存的值写到主内存。下一个线程就能从主内存拿到最新的值,从而实现可见性。

    62. synchronized和volatile的区别

    synchronizedvolatile轻量级线程同步机制
    作用位置代码块、方法变量
    作用可以保证变量修改的可见性和原子性,可能会造成线程阻塞。可以保证变量修改的可见性,但无法保证原子性,不会造成线程阻塞

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rMCEQcka-1620227111550)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210503183536238.png)]

    微服务

    63. 什么是微服务?

    64. 为什么要做微服务?

    65. 怎么做服务拆分?

    根据业务边界拆分,一般分为公共服务和业务服务。

    例如:短信服务、邮件服务等

    SpringBoot

    1. 启动流程

    示例代码:重点@SpringBootApplication,SpringApplication.run()

    @SpringBootApplication
    public class Application {
    	public static void main(String[] args) {
    		SpringApplication.run(Application.class, args);
    	}
    }
    

    每个SpringBoot程序都有一个主入口,也就是main方法,main里面调用SpringApplication.run()启动整个spring-boot程序,该方法所在类需要使用@SpringBootApplication注解。

    @SpringBootApplication = (默认属性)@Configuration + @EnableAutoConfiguration + @ComponentScan。

    @ComponentScan:自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。

    • 我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。

    • 所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages。

    • 但是一般满足不了我们的需求,还是需要自己指定扫描包路径

    @EnableAutoConfiguration:开启自动配置。他实现的关键在于引入了AutoConfigurationImportSelector,其核心逻辑为selectImports方法,逻辑大致如下:

    • 从配置文件META-INF/spring.factories加载所有可能用到的自动配置类(spring-boot-autoconfig包);
    • 去重,并将exclude和excludeName属性携带的类排除;
    • 过滤,将满足条件(@Conditional)的自动配置类返回;

    2. Springboot使用JavaConfig整合MVC

    在spring.factories配置文件下,预先写好了WebMvcAutoConfiguration类,

    Spring

    1. JavaConfig技术之web容器启动为什么能够调用Spring框架下的方法呢?

    Servlet3.0以后提供了SPI技术

    规范:需要在项目根目录下WETA-INF/services文件夹下提供一个配置文件,配置文件名为javax.servlet.ServletContainerInitializer,在配置文件中指定实现了ServletContainerInitializer接口的类路径。

    我们用的Spring框架,在spring-web包下已经实现了该规范,如下图所示。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RYnU1E7Y-1620227111550)(C:\Users\Sharm\AppData\Roaming\Typora\typora-user-images\image-20210505213012350.png)]

    SpringServletContainerInitializer.java使用了@HandlesTypes({WebApplicationInitializer.class}),意味着对规范进行了扩展,提供了一个WebApplicationInitializer接口。启动时会自动将WebApplicationInitializer的实现类扫描成一个list,遍历执行各个类的onStartup方法。

    后续我们想写的容器启动就加载的类,实现WebApplicationInitializer接口重写onStartup方法即可。

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package org.springframework.web;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    
    public interface WebApplicationInitializer {
        void onStartup(ServletContext var1) throws ServletException;
    }
    
    

    2. 编程题:使用JavaConfig技术,实现无xml的SSM框架

    展开全文
  • Java中变量的应用比常量的应用要多很多。所以变量也是尤为重要的知识点! 什么是变量?变量是一个内存中的小盒子(小容器),容器是什么?生活中也有很多容器,例如水杯是容器,用来装载水;你家里的大衣柜是容器...

    一.变量运算符

    今日内容介绍
     变量
     运算符

    第1章 变量

    1.1 变量概述

    前面我们已经学习了常量,接下来我们要学习变量。在Java中变量的应用比常量的应用要多很多。所以变量也是尤为重要的知识点!
    什么是变量?变量是一个内存中的小盒子(小容器),容器是什么?生活中也有很多容器,例如水杯是容器,用来装载水;你家里的大衣柜是容器,用来装载衣裤;饭盒是容器,用来装载饭菜。那么变量是装载什么的呢?答案是数据!结论:变量是内存中装载数据的小盒子,你只能用它来存数据和取数据。

    1.2 计算机存储单元

    变量是内存中的小容器,用来存储数据。那么计算机内存是怎么存储数据的呢?无论是内存还是硬盘,计算机存储设备的最小信息单元叫“位(bit)”,我们又称之为“比特位”,通常用小写的字母b表示。而计算机最小的存储单元叫“字节(byte)”,通常用大写字母B表示,字节是由连续的8个位组成。
    当程序需要使用存储空间时,操作系统最小会分派给程序1个字节,而不是1个位。你可能会说,如果程序只需要1个位的空间,系统分派不能只分派1个位吗?答案是不能!这就像你只需要1支烟,你到商店去买烟,商店分派的最小单元是1盒(20支),他不可能卖给你1支烟。
    你可能会

    展开全文
  • 2015年Java传智博客基础视频笔记_风清扬(刘意)
  • (译)8幅图带你了解Java

    2017-07-10 22:29:02
     前言:偶然间发现一个学习java的网站:http://www.programcreek.com/java-tutorials/,虽然是英文的,但是静下心来看并不难懂,很是言简意赅,上面点击量最大的一篇文章:以8幅图阐述八个java基本概念,深刻体会到...

            前言:偶然间发现一个学习java的网站:http://www.programcreek.com/java-tutorials/,虽然是英文的,但是静下心来看并不难懂,很是言简意赅,上面点击量最大的一篇文章:以8幅图阐述八个java基本概念,深刻体会到一幅图胜过千言万语

    本篇文章重点关注以下问题:

    • String对象不可改变的特性
    • hashCode()与equals()方法协作约定
    • Java 异常类层次结构
    • 集合类层次结构关系
    • 锁——Java同步的基本思想
    • Java对象引用处理机制
    • Java 对象在堆中的内存结构
    • JVM 运行时数据区

    1. String对象不可改变的特性

      下面以三幅图展示String的不可变特性:

    1.1 声明一个String类型

    String s = "abcd";

             变量str存储字符串对象的引用,下面的箭头应该被解释为“存储String对象'abcd'的引用”。

    1.2 将一个字符串变量赋值给另一个String变量 

    String s2 = s;

            s2存储与s1相同的引用值(可以理解为地址),因为它是相同的字符串对象。

    1.3 字符串拼接concat

    s = s.concat("ef");

            s现在存储新创建的字符串对象的引用。

    2. hashCode()与equals()方法协作约定

            HashCode(哈希编码,散列码)旨在提高性能。 equals()和hashCode()必须满足:

    1. 如果两个对象相等,则它们必须具有相同的哈希码。
    2. 如果两个对象具有相同的哈希码,则它们可能相同也可能不相等。
      查找顺序:hashcode() -> equals(),都匹配则为同一个对象。

    3. Java异常类层次结构

            红色是受检异常(程序必须检查、处理的异常),此异常必须必须在方法中处理或在方法后面throws,以期待上级处理。

    4. 集合类层次结构 

            注意Collections和Collection之间的区别。


     

     5. Java同步

            Monitor可以视为包含特殊房间的建筑物。 特殊的房间一次只能由一个客户(线程)占用。 房间通常包含一些数据和代码。

       如果客户想要占用特别的房间,他必须先进入走廊排队(Hallway)等待。 调度程序将根据某些标准(例如FIFO)选择一个。 如果他由于某种原因被暂停,他将被送到等候室(wait room),并计划在之后重新进入特别的房间。 如上图所示,这栋楼有3间房间。

           简而言之,Monitor是监视线程访问特殊房间的设施。 它确保只有一个线程可以访问受保护的数据或代码。

     6. Java对象引用处理机制

           别名是指多个引用指向同一个内存地址(对象实际地址,可以理解为这就是对象),甚至这些引用的类型完全不一样。

            a和b指向了同一个物理地址。 在运行时,多态特性根据真实的对象类型决定调用父类还是子类的具体方法,而不是根据引用变量的类型.

    7. Java堆和栈

              该图显示了运行时,方法和对象在内存中的存储位置。

       绝大多数情况下:对象(及其属性域)都保存在堆里面,而方法的参数,局部变量(引用,以及6种基本类型)保存在栈里面。当然,极特殊的情况下(极度优化[对象入栈],常量池[String],静态变量[方法区]等)也会打破这个潜规则。

    8. JVM运行时数据区域

           上图显示了整个JVM运行时数据区域。

     8.1 每个线程的数据区(不共享)

           每个线程的数据区域包括程序计数器JVM堆栈本机方法堆栈。 当创建新线程时,它们都将随之创建,线程销毁,也随之消失。

    • 程序计数器:用于控制每个线程的执行,记录当前线程的执行到哪;
    • JVM堆栈:线程执行就是不断入栈、出栈的过程;如下图所示
    • 本地方法堆栈:用于支持本机方法,即非Java语言方法。

    8.2 所有线程共享的数据区域

           所有线程共享堆和方法区:

    • 堆:堆是我们最常处理的区域。 它存储在JVM启动时创建的数组和对象。 垃圾收集在这方面工作。
    • 方法区:方法区域存储运行时常量池,字段和方法数据,以及方法和构造函数代码。
    • 运行时常量池: 每一个类或者接口,在其编译后生成的.class文件中,有一个部分叫做常量表(constant_pool_table),JVM将class文件加载以后,就解析常量表的内容到运行时常量池。 包括编译时方法中就明确可知的数字值,String值,以及必须在运行时解析的属性域引用(field reference)。

      如上图所示,JVM栈(Stack)由一个个的栈帧(Frame)组成,当一个方法被调用时会自动压入一个栈帧到Stack中, 每个栈帧(frame)由局部变量区(Locol Variable Array),操作数栈(Operated Stack),以及对常量(池)(Reference to Constant Pool)的引用组成.

    展开全文
  • 传智播客刘意老师的 java基础视频,包含视频,代码,笔记,PPT等
  • Java集合笔记

    2019-03-02 14:40:26
    集合 1.集合中的存储的数据都是对象,比如存进一个int类型的数字,则会被自动封装成Interger包装类型。 2.集合存放的对象都是引用,对象实际上还是存在内存中。 3.集合可以存储任意类型,任意长度的数据类型。...

    集合

    1.集合中的存储的数据都是对象,比如存进一个int类型的数字,则会被自动封装成Interger包装类型。
    2.集合存放的对象都是引用,对象实际上还是存在内存中。
    3.集合可以存储任意类型,任意长度的数据类型。
    4.除了Map外,其他的集合都是继承了Iterator接口,Map为独立的接口,Iterator接口有三个方法分别为hasnext(),next(),remove(),而next()方法决定了只能往后遍历,不能往前遍历,遍历过的对象就无法再次遍历,而LinkedIterator在继承了Iterator方法的基础上增加了三个方法,分别为hasPrevious(),previous(),add(),通常无序集合是实现Iterator接口,而有序数组集合则是实现了LinkedIterator接口。
    5.Iterable中封装了Iterable。
    6. Collection接口下有两个子接口,分别为List和Set。
    7. ArrayList底层是数组,特点是查询快,增删慢,线程不安全,效率高。
    8. Vector底层也是数组,特点也是查询快,增删慢,线程安全,效率低,几乎被淘汰了。
    9. LinkedList底层是双向链表,特点是查询慢,增删快,线程不安全,效率高。
    10. HashSet底层是数组加上链表结构,当存储一个对象时,先利用hashCode算出hash值映射的地址,再将对象存在此处,当两个对象的hash值相同时,就会在数组的同一个位置调用equals方法进行,比较假如引用的地址相同则不存入,假如地址不同则在该位置上形成一个链表,新插入的对象是在链表头部。
    11. TreeSet底层采用了红黑树结构,有序不唯一,适合与范围查询
    12. LinkedHashSet底层是链表加哈希表,链表保证了插入的顺序,哈希表保证了数值的唯一。
    13. set接口下的三个集合都是线程不安全的,其中HashSet的效率最高,LinkedHashSet效率低些。
    14. Map集合严格意义上不是集合,而是存储了一种映射关系,因为没有实现Iterable,所以没有for-each方法,遍历map集合有两个方法,一种是getset方法和entryset方法,getset是将map集合转成set集合,再使用get方法取出value值,而entry方法是将整个entry关系取出,所以相比之下是entryset的效率更高
    15. hashmap线程不安全,而hashtable线程安全但是效率较低,是因为hashtable会在修改整个集合的时候加锁,还有个currenthashtable则是分段锁,支持多线程操作,当一个线程修改某段时,其他线程还是能对其他段进行修改
    16. hashmap中的key和value允许为null,而hashtable不允许为null。

    展开全文
  • 为了更清晰的表达如何加锁和释放锁,JDK1.5以后提供了一个新的锁对象Lock Lock: void lock() :获取锁 void unlock() :释放锁 ...java"] public class SellTicket implements Run...
  • 传智播客 刘意_2015年Java基础视频-深入浅出精华版 笔记day01-day27
  • FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java"); // // 调用read()方法读取数据,并把数据显示在控制台 // // 第一次读取 // int by = fis.read(); // System.out.println(by);...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,763
精华内容 1,105
关键字:

风清扬java

java 订阅