面试题知识点学习与总结第一章

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38120325/article/details/82788693

一些面试中会问到的以及自己学习的知识点

1.什么时候使用视图?
    -视图是虚拟的,物理上是不存在的,只是存储了数据的集合,其中的数据是根据基表的变化而变化的,不可以删除视图
    -简化数据操作,实现定制数据(主要是字段多少)
2.MyBatis和Hibernate对比
    -Mybatis容易上手,Hibernate比较难上手;
    -Mybatis需要手动编写sql,Hibernate有良好的映射机制;
    -Hibernate查询不能控制查询字段,高级查询使用Mybatis更方便;
    -Hibernate有完整的对象关系映射解决方案,开发者不需要理会数据库底层实现和sql执行
    -Hibernate的缓存
        Hibernate一级缓存是Session缓存,利用好一级缓存就需要对Session的生命周期进行管理好。
        Hibernate二级缓存是SessionFactory级的缓存。 SessionFactory的缓存分为内置缓存和外置缓存。内置缓存中存放的是SessionFactory对象的一些集合属性包含的数据(映射元素据及预定SQL语句等),对于应用程序来说,它是只读的。外置缓存中存放的是数据库数据的副本,其作用和一级缓存类似.二级缓存除了以内存作为存储介质外,还可以选用硬盘等外部存储设备。二级缓存称为进程级缓存或SessionFactory级缓存,它可以被所有session共享,它的生命周期伴随着SessionFactory的生命周期存在和消亡。
    -MyBatis的缓存:Mybatis的二级缓存除了采用系统默认的缓存机制外,都可以通过实现你自己的缓存或为其他第三方缓存方案,创建适配器来完全覆盖缓存行为。
    缓存比较:
        =相同点:Hibernate和Mybatis的二级缓存除了采用系统默认的缓存机制外,都可以通过实现你自己的缓存或为其他第三方缓存方案,创建适配器来完全覆盖缓存行为。    =不同点:Hibernate的二级缓存配置在SessionFactory生成的配置文件中进行详细配置,然后再在具体的表-对象映射中配置是那种缓存。MyBatis的二级缓存配置都是在每个具体的表-对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。    =两者比较:因为Hibernate对查询对象有着良好的管理机制,用户无需关心SQL。所以在使用二级缓存时如果出现脏数据,系统会报出错误并提示。而MyBatis在这一方面,使用二级缓存时需要特别小心。如果不能完全确定数据更新操作的波及范围,避免Cache的盲目使用。否则,脏数据的出现会给系统的正常运行带来很大的隐患。    
    -Hibernate和MyBatis都支持JDBC和JTA事务处理。
    -Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
    -Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
    -Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
    -Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。

3.JPA,ORM,Hibernate之间的关系: 
    -ORM是一种思想,JPA是这种思想的规范约束,Hibernate是这种思想和规范的具体实现;
4.在Java5以前,switch(expr)中,expr只能是byte、short、char、int。从Java5开始,Java中引入了枚举类型,expr也可以是enum类型,从Java7开始,expr还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。
5.Java对于eqauls方法和hashCode方法是这样规定的:
    (1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;
    (2)如果两个对象的hashCode相同,它们并不一定相同。
6.Hash算法解决冲突的方法:
    -开放定址法:一旦发生冲突,去寻找下一个空的散列地址,只要列表足够大,一定能找到空的散列地址;
    -再Hash法:有多个不同的Hash函数,当发生冲突时,使用其他的,依次Hash直到不冲突为止;
    -链地址法:每个Hash表节点都是一个链表的存储结构,当Hash值相同时添加到列表的下一个指针;
    -建立公共溢出区:将Hash表分为正式表和溢出表,如果发生冲突,填入溢出表中;
7.可重入锁
    -重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者clas),这样的锁就叫做可重入锁。ReentrantLock和synchronized都是可重入锁。
8.Volatile关键字
    -保证不同线程对这个变量进行操作时的可见性,一个线程改变某个变量之后会立即写入主内存,
    -禁止了进行指令排序,可以保证有序性;
    -不能保证原子性
    -使用volatile必须具备以下2个条件:
  1)对变量的写操作不依赖于当前值
  2)该变量没有包含在具有其他变量的不变式中
9.Java内存模型具备一些先天的“有序性”,即不需要通过任何手段就能够得到保证的有序性,这个通常也称为happens-before原则。如果两个操作的执行次序无法从happens-before原则推导出来,那么它们就不能保证它们的有序性,虚拟机可以随意地对它们进行重排序。
  下面就来具体介绍下happens-before原则(先行发生原则):
------程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
------锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作
------volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
------传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
------线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作
------线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
------线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
------对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始
10.lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:
  1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
  2)它会强制将对缓存的修改操作立即写入主存;
  3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
11.Java如何调用C或者C++;
    -编写java代码,定义native修饰的方法(可以使用别的语言来完成,但是不能再使用abstract修饰)
    -利用javah生成native方法的.h  C++文件。
    -使用c/c++来进行native方法的实现
12.回调函数的原理;
    -类A调用类B的方法,B执行完之后主动调用类A的CallBack方法
13.Java中的方法调用-解析与分派
    -所有方法调用中的目标方法在Class文件里面都是一个常量池中的符号引用,在类加载的解析阶段,会将其中一部分符号引用转化为直接引用,这种解析能成立的前提是:方法在程序真正运行之前就有一个可以确定的调用版本,且在运行期不可变.
    -java虚拟机中提供了5条方法调用字节码指令,分别如下:
        invokestatic:调用静态方法
        invokespecial:调用实力构造器<init>方法,私有方法和父类方法
        invokevirtual:调用所有的虚方法
        invokeinterface:调用接口方法,会在运行时再确定一个实现此接口的对象
        invokedynamic:先在运行时动态解析出调用点限定符所引用的方法,然后再执行该方法,在此之前的四条调用指令,分派逻辑是固化在java虚拟机内部的,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的
    -静态分派 发生在编译阶段
    -动态分派 运行期根据方法接收者的实际类型来选择方法。
    解析与分派不是排他关系,而是在不同层次上去筛选,确定目标方法的过程。
14.使用Semaphore控制方法的并发访问个数
    Semaphore两个重要的方法就是
        semaphore.acquire() 请求一个信号量,这时候的信号量个数-1
        semaphore.release() 释放一个信号量,此时信号量个数+1
15.类加载机制:
    加载:将所有的类变成.class文件;
    验证:确保.class文件中的字节流的信息都符合虚拟机的安全
    准备:正式为类变量分配内存并设置初始值
    解析:虚拟机将常量池中的符号引用变为直接引用                     
        -符号引用与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。
        -直接引用可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在。
    初始化:初始化阶段是执行类构造器<client>方法的过程。<client>方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证<client>方法执行之前,父类的<client>方法已经执行完毕。
        -注意以下几种情况不会执行类初始化:
            通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。
            定义对象数组,不会触发该类的初始化。
            常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。
            通过类名获取Class对象,不会触发类的初始化。
            通过Class.forName加载指定类时,如果指定参数initialize为false时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。
            通过ClassLoader默认的loadClass方法,也不会触发初始化动作。
   

持续更新.......

猜你喜欢

转载自blog.csdn.net/m0_38120325/article/details/82788693