脚本之家(jb51.cc)Java面试题栏目主要收集Java工程师面试题,Java人员面试专属面试题。
聊聊SpringBoot和传统的SSM的区别? SpringBoot是Spring的扩展,在Spring的基础上,简化了传统的SSM开发繁琐的配置; 在部署上,SpringBoot内置了Tomcat,
在面试当中,有时候会问到你在项目中用过多线程么? 对于普通的应届生或者工作时间不长的初级开发 ???—— crud仔流下了没有技术的眼泪。 博主这里整理了项目中用到了多线程的一个简单的实例,希望能对你
@ 介绍一下你做的某些模块,有些什么比较复杂的地方? 略。 你们的文件怎么存储的? 我们的文件是存储在MongoDB中的。 MongoDB单个文档的存储限制是16M,如果要存储大于16M的文件,就要用
1. Java线程的创建方式 (1)继承thread类 thread类本质是实现了runnable接口的一个实例,代表线程的一个实例。启动线程的方式start方法。start是一个本地方法,
1. SpringBoot简介 SpringBoot是简化Spring应用开发的一个框架。他整合了Spring的技术栈,提供各种标准化的默认配置。使得我们可以快速开发Spring项目,免掉x
1. List List 是有序的 Collection。Java List 一共三个实现类: 分别是 ArrayList、Vector 和 LinkedList ArrayList Arr
面向对象编程的基本理念与核心设计思想解释下多态性(polymorphism),封装性(encapsulation),内聚(cohesion)以及耦合(coupling)。继承(Inheritance)与聚合(Aggregation)的区别在哪里。你是如何理解干净的代码(Clean Code)与技术负载(Technical Debt)的。描述下常用的重构技巧。阐述下 SOLID 原则。其他的譬如 KISS,DRY,YAGNI 等原则又是什么含义。什么是设计模式(Design Patterns)?你知道哪些设计模式?你有了解过存在哪些反模式(Anti-Patterns)吗?你会如何设计登陆舰/数学表达式计算程序/一条龙?你知道哪些基本的排序算法,它们的计算复杂度如何?在给定数据的情况下你会倾向于使用哪种算法呢?尝试编写如下代码:计算指定数字的阶乘开发 Fizz Buzz 小游戏倒转句子中的单词回文字符串检测枚举给定字符串的所有排列组合Java 核心概念equals 与 hashCode 的异同点在哪里?Java 的集合中又是如何使用它们的。描述下 Java 中集合(Collections),接口(Interfaces),实现(Implementations)的概念。LinkedList 与 ArrayList 的区别是什么?基础类型(Primitives)与封装类型(Wrappers)的区别在哪里?final 与 static 关键字可以用于哪里?它们的作用是什么?阐述下 Java 中的访问描述符(Access Modifiers)。描述下 String,StringBuilder 以及 StringBuffer 区别。接口(Interface)与抽象类(Abstract Class)的区别在哪里。覆盖(Overriding)与重载(OverLoading)的区别在哪里。异常分为哪几种类型?以及所谓的handle or declare原则应该如何理解?简述垃圾回收器的工作原理。你是如何处理内存泄露或者栈溢出问题的?如何构建不可变的类结构?关键点在哪里?什么是 JIT 编译?Java 8 / Java 7 为我们提供了什么新功能?即将到来的 Java 9 又带来了怎样的新功能?Hibernate / 数据库请解释下 ORM。简述下 Hibernate 的优劣特性。Hibernate 与 JPA 区别在哪?Hibernate 最新版提供了哪些特性?什么是懒加载(Lazy Loading)?什么是 N+1 难题?介绍一些熟悉的 Hibernate 注释。简介下 Hibernate Session 与 SessionFactory。Entity Beans 的状态有哪些。Hibernate 中的缓存分为几层。Hibernate 中事务的支持分为几级?什么是乐观锁(Optimistic Locking)?简述下 ACID 原则。简述下数据库正则化(Normalizations)。请介绍下你日常工作中优化慢查询(Slow Query)的策略。Spring新版的 Spring 中有哪些新特性?介绍下 Spring 的优势与缺陷。什么是控制反转(Inversion of Control)与依赖注入(Dependency Injection)?你用过哪些 Spring 的模块?Spring 中是如何使用依赖注入的?Spring 中提供了几种自动注入的机制?介绍下 Spring MVC。Spring 中 Scopes 有哪些?Spring 中 Bean 的生命周期包含哪些步骤?Spring Bean 与 EJB Bean 的区别在哪里?其他主题介绍下切面编程(Aspect Oriented Programming)。概述下 GET 与 POST 的区别。Web Server、Web Container 与 Application Server 的区别是什么?简要介绍下从浏览器输入 URL 开始到获取到请求界面之后 Java Web 应用中发生了什么。什么是 N 层架构?微服务(MicroServices)与巨石型应用(Monolithic Applications)之间的区别在哪里?你知道哪些商业级设计模式?你是如何测试一个应用的?知道哪些测试框架?你是如何测试单个方法的?在你的职业生涯中,算得上最困难的技术挑战是什么?什么是领域驱动开发(Domain Driven Development)?介绍下一些你最爱的 IDE 的常用插件。除了 IDE 之外,你的日常工作中还会用到哪些工具?你使用什么版本管理工具?分支(Branch)与标签(Tag)之间的区别在哪里?你常用的持续集成(Continuous Integration)、静态代码分析(Static Code Analysis)工具有哪些?
基础篇一、基本功面向对象特征封装,继承,多态和抽象1. 封装封装给对象提供了隐藏内部特性和行为的能力。对象提供一些能被其他对象访问的方法来改变它内部的数据。在 Java 当中,有 3 种修饰符: public, private 和 protected。每一种修饰符给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。下面列出了使用封装的一些好处:通过隐藏对象的属性来保护对象内部的状态。提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。禁止对象之间的不良交互提高模块化2. 继承继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用行,也可以在不修改类的情况下给现存的类添加新特性。3. 多态多态是编程语言给不同的底层数据类型做相同的接口展示的一种能力。一个多态类型上的操作可以应用到其他类型的值上面。4. 抽象抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细节来创建类。 Java 支持创建只暴漏接口而不包含方法实现的抽象的类。这种抽象技术的主要目的是把类的行为和实现细节分离开。final, finally, finalize 的区别1. final修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。2. finally在异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。3. finalize方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。int 和 Integer 有什么区别int 是基本数据类型Integer是其包装类,注意是一个类。为什么要提供包装类呢???一是为了在各种类型间转化,通过各种方法的调用。否则 你无法直接通过变量转化。比如,现在int要转为Stringint a=0;String result=Integer.toString(a);在java中包装类,比较多的用途是用在于各种数据类型的转化中。我写几个demo//通过包装类来实现转化的int num=Integer.valueOf("12");int num2=Integer.parseInt("12");double num3=Double.valueOf("12.2");double num4=Double.parseDouble("12.2");//其他的类似。通过基本数据类型的包装来的valueOf和parseXX来实现String转为XXString a=String.valueOf("1234");//这里括号中几乎可以是任何类型String b=String.valueOf(true);String c=new Integer(12).toString();//通过包装类的toString()也可以String d=new Double(2.3).toString();再举例下。比如我现在要用泛型List<Integer> nums;这里<>需要类。如果你用int。它会报错的。重载和重写的区别override(重写)1. 方法名、参数、返回值相同。2. 子类方法不能缩小父类方法的访问权限。3. 子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。4. 存在于父类和子类之间。5. 方法被定义为final不能被重写。overload(重载)1. 参数类型、个数、顺序至少有一个不相同。2. 不能重载只有返回值不同的方法名。3. 存在于父类和子类、同类中。抽象类和接口有什么区别接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的,另外,实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。还有,接口可以实现多重继承,而一个类只能继承一个超类,但可以通过继承多个接口实现多重继承,接口还有标识(里面没有任何方法,如Remote接口)和数据共享(里面的变量全是常量)的作用。说说反射的用途及实现Java反射机制主要提供了以下功能:在运行时构造一个类的对象;判断一个类所具有的成员变量和方法;调用一个对象的方法;生成动态代理。反射最大的应用就是框架Java反射的主要功能:确定一个对象的类取出类的modifiers,数据成员,方法,构造器,和超类.找出某个接口里定义的常量和方法说明.创建一个类实例,这个实例在运行时刻才有名字(运行时间才生成的对象).取得和设定对象数据成员的值,如果数据成员名是运行时刻确定的也能做到.在运行时刻调用动态对象的方法.创建数组,数组大小和类型在运行时刻才确定,也能更改数组成员的值.反射的应用很多,很多框架都有用到spring 的 ioc/di 也是反射….javaBean和jsp之间调用也是反射….struts的 FormBean 和页面之间…也是通过反射调用….JDBC 的 classForName()也是反射…..hibernate的 find(Class clazz) 也是反射….反射还有一个不得不说的问题,就是性能问题,大量使用反射系统性能大打折扣。怎么使用使你的系统达到最优就看你系统架构和综合使用问题啦,这里就不多说了。来源:http://uule.iteye.com/blog/1423512说说自定义注解的场景及实现(此题自由发挥,就看你对注解的理解了!==)登陆、权限拦截、日志处理,以及各种Java框架,如Spring,Hibernate,JUnit 提到注解就不能不说反射,Java自定义注解是通过运行时靠反射获取注解。实际开发中,例如我们要获取某个方法的调用日志,可以通过AOP(动态代理机制)给方法添加切面,通过反射来获取方法包含的注解,如果包含日志注解,就进行日志记录。HTTP 请求的 GET 与 POST 方式的区别GET方法会把名值对追加在请求的URL后面。因为URL对字符数目有限制,进而限制了用在客户端请求的参数值的数目。并且请求中的参数值是可见的,因此,敏感信息不能用这种方式传递。POST方法通过把请求参数值放在请求体中来克服GET方法的限制,因此,可以发送的参数的数目是没有限制的。最后,通过POST请求传递的敏感信息对外部客户端是不可见的。参考:https://www.cnblogs.com/wangli-66/p/5453507.htmlsession 与 cookie 区别cookie 是 Web 服务器发送给浏览器的一块信息。浏览器会在本地文件中给每一个 Web 服务器存储 cookie。以后浏览器在给特定的 Web 服务器发请求的时候,同时会发送所有为该服务器存储的 cookie。下面列出了 session 和 cookie 的区别:无论客户端浏览器做怎么样的设置,session都应该能正常工作。客户端可以选择禁用 cookie,但是, session 仍然是能够工作的,因为客户端无法禁用服务端的 session。JDBC 流程1、 加载JDBC驱动程序:在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),这通过java.lang.Class类的静态方法forName(String className)实现。例如:try{//加载MySql的驱动类Class.forName("com.mysql.jdbc.Driver") ;}catch(ClassNotFoundException e){System.out.println("找不到驱动程序类 ,加载驱动失败!");e.printStackTrace() ;}成功加载后,会将Driver类的实例注册到DriverManager类中。2、 提供JDBC连接的URL连接URL定义了连接数据库时的协议、子协议、数据源标识。书写形式:协议:子协议:数据源标识协议:在JDBC中总是以jdbc开始 子协议:是桥连接的驱动程序或是数据库管理系统名称。数据源标识:标记找到数据库来源的地址与连接端口。例如:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gbk;useUnicode=true;(MySql的连接URL)表示使用Unicode字符集。如果characterEncoding设置为 gb2312或GBK,本参数必须设置为true 。characterEncoding=gbk:字符编码方式。3、创建数据库的连接要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象, 该对象就代表一个数据库的连接。使用DriverManager的getConnectin(String url , String username , String password )方法传入指定的欲连接的数据库的路径、数据库的用户名和 密码来获得。例如: //连接MySql数据库,用户名和密码都是rootString url = "jdbc:mysql://localhost:3306/test" ;String username = "root" ;String password = "root" ;try{Connection con = DriverManager.getConnection(url , username , password ) ;}catch(SQLException se){System.out.println("数据库连接失败!");se.printStackTrace() ;}4、 创建一个Statement•要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3 种类型:1、执行静态SQL语句。通常通过Statement实例实现。2、执行动态SQL语句。通常通过PreparedStatement实例实现。3、执行数据库存储过程。通常通过CallableStatement实例实现。具体的实现方式:Statement stmt = con.createStatement() ; PreparedStatement pstmt = con.prepareStatement(sql) ; CallableStatement cstmt = con.prepareCall(“{CALL demoSp(? , ?)}”) ;5、执行SQL语句Statement接口提供了三种执行SQL语句的方法:executeQuery 、executeUpdate 和execute1、ResultSet executeQuery(String sqlString):执行查询数据库的SQL语句 ,返回一个结果集(ResultSet)对象。2、int executeUpdate(String sqlString):用于执行INSERT、UPDATE或 DELETE语句以及SQL DDL语句,如:CREATE TABLE和DROP TABLE等3、execute(sqlString):用于执行返回多个结果集、多个更新计数或二者组合的 语句。 具体
1、什么是线程池线程池的基本思想是一种对象池,在程序启动时就开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。2、使用线程池的好处减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。运用线程池能有效的控制线程最大并发数,可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。对线程进行一些简单的管理,比如:延时执行、定时循环执行的策略等,运用线程池都能进行很好的实现3、线程池的主要组件  一个线程池包括以下四个基本组成部分:线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;工作线程(WorkThread):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。4、ThreadPoolExecutor类讲到线程池,要重点介绍java.uitl.concurrent.ThreadPoolExecutor类,ThreadPoolExecutor线程池中最核心的一个类,ThreadPoolExecutor在JDK中线程池常用类UML类关系图如下: 我们可以通过ThreadPoolExecutor来创建一个线程池 new ThreadPoolExecutor(corePoolSize, maximumPoolSize,keepAliveTime,milliseconds,runnableTaskQueue, threadFactory,handler);1. 创建一个线程池需要输入几个参数corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads方法,线程池会提前创建并启动所有基本线程。maximumPoolSize(线程池最大大小):线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是如果使用了无界的任务队列这个参数就没什么效果。runnableTaskQueue(任务队列):用于保存等待执行的任务的阻塞队列。ThreadFactory:用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字,Debug和定位问题时非常又帮助。RejectedExecutionHandler(拒绝策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。以下是JDK1.5提供的四种策略。n AbortPolicy:直接抛出异常。keepAliveTime(线程活动保持时间):线程池的工作线程空闲后,保持存活的时间。所以如果任务很多,并且每个任务执行的时间比较短,可以调大这个时间,提高线程的利用率。TimeUnit(线程活动保持时间的单位):可选的单位有天(DAYS),小时(HOURS),分钟(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。2. 向线程池提交任务我们可以通过execute()或submit()两个方法向线程池提交任务,不过它们有所不同execute()方法没有返回值,所以无法判断任务知否被线程池执行成功threadsPool.execute(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stub}});submit()方法返回一个future,那么我们可以通过这个future来判断任务是否执行成功,通过future的get方法来获取返回值try {Object s = future.get();} catch (InterruptedException e) {// 处理中断异常} catch (ExecutionException e) {// 处理无法执行任务异常} finally {// 关闭线程池executor.shutdown();}3. 线程池的关闭我们可以通过shutdown()或shutdownNow()方法来关闭线程池,不过它们也有所不同shutdown的原理是只是将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。shutdownNow的原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止。shutdownNow会首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表。4. ThreadPoolExecutor执行的策略  线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务线程数量达到了corePools,则将任务移入队列等待队列已满,新建线程(非核心线程)执行任务队列已满,总线程数又达到了maximumPoolSize,就会由(RejectedExecutionHandler)抛出异常新建线程 -> 达到核心数 -> 加入队列 -> 新建线程(非核心) -> 达到最大数 -> 触发拒绝策略5. 四种拒绝策略AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满,线程池默认策略DiscardPolicy:不执行新任务,也不抛出异常,基本上为静默模式。DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行CallerRunPolicy:拒绝新任务进入,如果该线程池还没有被关闭,那么这个新的任务在执行线程中被调用)5、Java通过Executors提供四种线程池CachedThreadPool():可缓存线程池。线程数无限制有空闲线程则复用空闲线程,若无空闲线程则新建线程 一定程序减少频繁创建/销毁线程,减少系统开销FixedThreadPool():定长线程池。可控制线程最大并发数(同时执行的线程数)超出的线程会在队列中等待ScheduledThreadPool():定时线程池。支持定时及周期性任务执行。SingleThreadExecutor():单线程化的线程池。有且仅有一个工作线程执行任务所有任务按照指定顺序执行,即遵循队列的入队出队规则1. newCachedThreadPoolnewCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程 public class ThreadPoolExecutorTest1 {public static void main(String[] args) {ExecutorService cachedThreadPool = Executors.newCachedThreadPool();for (int i = 0; i < 1000; i++) {final int index = i;try {Thread.sleep(index * 1000);} catch (Exception e) {e.printStackTrace();}cachedThreadPool.execute(new Runnable() {public void run() {System.out.println(Thread.currentThread().getName()+":"+index);}});}}} 2. newFixedThreadPoolnewFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待,指定线程池中的线程数量和最大线程数量一样,也就线程数量固定不变示例代码如下public class ThreadPoolExecutorTest {public static void main(String[] args) {ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);// 每隔两秒打印3个数for (int i = 0; i < 10; i++) {final int index = i;fixedThreadPool.execute(new Runnable() {public void run() {try {System.out.println(Thread.currentThread().getName()+":"+index);//三个线程并发Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}});}}} 3. newscheduledThreadPoolnewscheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下.表示延迟1秒后每3秒执行一次public class ThreadPoolExecutorTest3 {public static void main(String[] args) {ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);scheduledThreadPool.scheduleAtFixedRate(new Runnable() {public void run() {System.out.println(Thread.currentThread().getName() + ": delay 1 seconds, and excute every 3 seconds");}}, 1, 3, TimeUnit.SECONDS);// 表示延迟1秒后每3秒执行一次}}  4. newSingleThreadExecutornewSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行public class ThreadPoolExecutorTest4 {public static void main(String[] args) {ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();for (int i = 0; i < 10; i++) {final int index = i;singleThreadExecutor.execute(new Runnable() {public void run() {try {System.out.println(Thread.currentThread().getName() + ":" + index);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});}}}结果依次输出,相当于顺序执行各个任务。使用JDK自带的监控工具来监控我们创建的线程数量,运行一个不终止的线程
本文作者在一年之内参加过多场面试,应聘岗位均为 Java 开发方向。在不断的面试中,分类总结了 Java 开发岗位面试中的一些知识点。主要包括以下几个部分:Java 基础知识点Java 常见集合高并发编程(JUC 包)JVM 内存管理Java 8 知识点网络协议相关数据库相关MVC 框架相关大数据相关Linux 命令相关面试,是大家从学校走向社会的第一步。互联网公司的校园招聘,从形式上说,面试一般分为 2-3 轮技术面试 +1 轮 HR 面试。但是一些公司确实是没有 HR 面试的,直接就是三轮技术面。技术面试中,面试官一般会先就你所应聘的岗位进行相关知识的考察,也叫基础知识和业务逻辑面试。只要你回答的不是特别差,面试官通常会说:“咱们写个代码吧”,这个时候就开始了算法面试。也就是说,一轮技术面试 = 基础知识和业务逻辑面试 + 算法面试。在本篇文章中,我们主要从技术面试聊起。技术面试包括:业务逻辑和基础知识面试。首先是业务逻辑面试 ,也就是讲项目。面试官会对你简历上写的若干个项目其中之一拿出来和你聊聊。在期间,会针对你所做的东西进行深度挖掘。包括:为什么要这么做?优缺点分析,假如重新让你做一次,你打算怎么做? 等等。这个环节主要考察我们对自己做过的项目(实习项目或者校内项目)是否有一个清晰的认识。关于业务逻辑面试的准备,建议在平时多多思考总结,对项目的数据来源、整体运行框架都应该熟悉掌握。比如说你在某公司实习过程中,就可以进行总结,而不必等到快离职的时候慌慌张张的去总结该项目。接下来是基础知识面试。Java 开发属于后台开发方向,有人说后台开发很坑,因为需要学习的东西太多了。没错,这个岗位就是需要学习好多东西。包括:本语言(Java/C++/PHP)基础、数据库、网络协议、Linux 系统、计算机原理甚至前端相关知识都可以考察你,而且,并不超纲 。有时候,你报的是后台开发岗,并且熟悉的是 Java 语言,但是面试官却是 C++ 开发方向的,就是这么无奈~好了,闲话少说,让我们开始分类讲解常见面试知识点。(一) Java 基础知识点1)面向对象的特性有哪些?答:封装、继承和多态。2)Java 中覆盖和重载是什么意思?解析:覆盖和重载是比较重要的基础知识点,并且容易混淆,所以面试中常见。答:覆盖(Override)是指子类对父类方法的一种重写,只能比父类抛出更少的异常,访问权限不能比父类的小。被覆盖的方法不能是 private 的,否则只是在子类中重新定义了一个方法;重载(Overload)表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同。面试官: 那么构成重载的条件有哪些?答:参数类型不同、参数个数不同、参数顺序不同。面试官: 函数的返回值不同可以构成重载吗?为什么?答:不可以,因为 Java 中调用函数并不需要强制赋值。举例如下:如下两个方法:12void f(){}int f(){ return 1;}只要编译器可以根据语境明确判断出语义,比如在 int x = f();中,那么的确可以据此区分重载方法。不过, 有时你并不关心方法的返回值,你想要的是方法调用的其他效果 (这常被称为 “为了副作用而调用”),这时你可能会调用方法而忽略其返回值,所以如果像下面的调用:1fun();此时 Java 如何才能判断调用的是哪一个 f() 呢?别人如何理解这种代码呢?所以,根据方法返回值来区分重载方法是行不通的。3)抽象类和接口的区别有哪些?答:抽象类中可以没有抽象方法;接口中的方法必须是抽象方法;抽象类中可以有普通的成员变量;接口中的变量必须是 static final 类型的,必须被初始化 , 接口中只有常量,没有变量。抽象类只能单继承,接口可以继承多个父接口;Java8 中接口中会有 default 方法,即方法可以被实现。面试官:抽象类和接口如何选择?答:如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。如果知道某个类应该是基类,那么第一个选择的应该是让它成为一个接口,只有在必须要有方法定义和成员变量的时候,才应该选择抽象类。因为抽象类中允许存在一个或多个被具体实现的方法,只要方法没有被全部实现该类就仍是抽象类。4)Java 和 C++ 的区别:解析:虽然我们不太懂 C++,但是就是会这么问,尤其是三面(总监级别)面试中。答:都是面向对象的语言,都支持封装、继承和多态;指针:Java 不提供指针来直接访问内存,程序更加安全;继承: Java 的类是单继承的,C++ 支持多重继承; Java 通过一个类实现多个接口来实现 C++ 中的多重继承; Java 中类不可以多继承,但是!!!接口可以多继承;内存: Java 有自动内存管理机制,不需要程序员手动释放无用内存。5)Java 中的值传递和引用传递解析:这类题目,面试官会手写一个例子,让你说出函数执行结果,详细举例请查阅我的博客:Java 值传递和引用传递基础分析。答:值传递是指对象被值传递,意味着传递了对象的一个副本,即使副本被改变,也不会影响源对象。引用传递是指对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象的改变会反映到所有的对象上。6)JDK 中常用的包有哪些?答:java.lang、java.util、http://java.io、http://java.net、java.sql。7)JDK,JRE 和 JVM 的联系和区别:答:JDK 是 java 开发工具包,是 java 开发环境的核心组件,并提供编译、调试和运行一个 java 程序所需要的所有工具,可执行文件和二进制文件,是一个平台特定的软件。JRE 是 java 运行时环境,是 JVM 的实施实现,提供了运行 java 程序的平台。JRE 包含了 JVM,但是不包含 java 编译器 / 调试器之类的开发工具。JVM 是 java 虚拟机,当我们运行一个程序时,JVM 负责将字节码转换为特定机器代码,JVM 提供了内存管理 / 垃圾回收和安全机制等。这种独立于硬件和操作系统,正是 java 程序可以一次编写多处执行的原因。区别:JDK 用于开发,JRE 用于运行 java 程序;JDK 和 JRE 中都包含 JVM;JVM 是 java 编程语言的核心并且具有平台独立性。Others:限于篇幅,面试中 Java 基础知识点还有:反射、泛型、注解等。小结:本节主要阐述了 Java 基础知识点,这些问题主要是一面面试官在考察,难度不大,适当复习下,应该没什么问题。(二)Java 中常见集合集合这方面的考察相当多,这部分是面试中必考的知识点。1)说说常见的集合有哪些吧?答:Map 接口和 Collection 接口是所有集合框架的父接口:Collection 接口的子接口包括:Set 接口和 List 接口;Map 接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap 以及 Properties 等;Set 接口的实现类主要有:HashSet、TreeSet、LinkedHashSet 等;List 接口的实现类主要有:ArrayList、LinkedList、Stack 以及 Vector 等。(2)HashMap 和 Hashtable 的区别有哪些?(必问)答:HashMap 没有考虑同步,是线程不安全的;Hashtable 使用了 synchronized 关键字,是线程安全的;前者允许 null 作为 Key;后者不允许 null 作为 Key。3)HashMap 的底层实现你知道吗?答:在 Java8 之前,其底层实现是数组 + 链表实现,Java8 使用了数组 + 链表 + 红黑树实现。此时你可以简单的在纸上画图分析:4)ConcurrentHashMap 和 Hashtable 的区别? (必问)答:ConcurrentHashMap 结合了 HashMap 和 HashTable 二者的优势。HashMap 没有考虑同步,hashtable 考虑了同步的问题。但是 hashtable 在每次同步执行时都要锁住整个结构。 ConcurrentHashMap 锁的方式是稍微细粒度的。 ConcurrentHashMap 将 hash 表分为 16 个桶(默认值),诸如 get,put,remove 等常用操作只锁当前需要用到的桶。面试官:ConcurrentHashMap 的具体实现知道吗?答:该类包含两个静态内部类 HashEntry 和 Segment;前者用来封装映射表的键值对,后者用来充当锁的角色;Segment 是一种可重入的锁 ReentrantLock,每个 Segment 守护一个 HashEntry 数组里得元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 锁。5)HashMap 的长度为什么是 2 的幂次方?答:通过将 Key 的 hash 值与 length-1 进行 & 运算,实现了当前 Key 的定位,2 的幂次方可以减少冲突(碰撞)的次数,提高 HashMap 查询效率;如果 length 为 2 的次幂 则 length-1 转化为二进制必定是 11111……的形式,在于 h 的二进制与操作效率会非常的快,而且空间不浪费;如果 length 不是 2 的次幂,比如 length 为 15,则 length-1 为 14,对应的二进制为 1110,在于 h 与操作,最后一位都为 0,而 0001,0011,0101,1001,1011,0111,1101 这几个位置永远都不能存放元素了,空间浪费相当大。更糟的是这种情况中,数组可以使用的位置比数组长度小了很多,这意味着进一步增加了碰撞的几率,减慢了查询的效率!这样就会造成空间的浪费。6)List 和 Set 的区别是啥?答:List 元素是有序的,可以重复;Set 元素是无序的,不可以重复。7)List、Set 和 Map 的初始容量和加载因子答:1. ListArrayList 的初始容量是 10;加载因子为 0.5; 扩容增量:原容量的 0.5 倍 +1;一次扩容后长度为 16。Vector 初始容量为 10,加载因子是 1。扩容增量:原容量的 1 倍,如 Vector 的容量为 10,一次扩容后是容量为 20。2. SetHashSet,初始容量为 16,加载因子为 0.75; 扩容增量:原容量的 1 倍; 如 HashSet 的容量为 16,一次扩容后容量为 323. MapHashMap,初始容量 16,加载因子为 0.75; 扩容增量:原容量的 1 倍; 如 HashMap 的容量为 16,一次扩容后容量为 328)Comparable 接口和 Comparator 接口有什么区别?答:前者简单,但是如果需要重新定义比较类型时,需要修改源代码。后者不需要修改源代码,自定义一个比较器,实现自定义的比较方法。具体解析参考我的博客:Java 集合框架—Set9)Java 集合的快速失败机制 “fail-fast”答:它是 java 集合的一种错误检测机制,当多个线程对集合进行结构上的改变的操作时,有可能会产生 fail-fast 机制。例如 :假设存在两个线程(线程 1、线程 2),线程 1 通过 Iterator 在遍历集合 A 中的元素,在某个时候线程 2 修改了集合 A 的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生 fail-fast 机制。原因: 迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变 modCount 的值。每当迭代器使用 hashNext()/next() 遍历下一个元素之前,都会检测 modCount 变量是否为 expectedmodCount 值,是的话就返回遍历;否则抛出异常,终止遍历。解决办法:在遍历过程中,所有涉及到改变 modCount 值得地方全部加上 synchronized;使用 CopyOnWriteArrayList
Arraylist 与 LinkedList 异同1. 是否保证线程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;2. 底层数据结构: Arraylist 底层使用的是Object数组;LinkedList 底层使用的是双向循环链表数据结构;3. 插入和删除是否受元素位置的影响: ① ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e)方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element))时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。 ② LinkedList 采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近似 O(n)。4. 是否支持快速随机访问: LinkedList 不支持高效的随机元素访问,而ArrayList 实现了RandmoAccess 接口,所以有随机访问功能。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。5. 内存空间占用: ArrayList的空 间浪费主要体现在在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。补充:数据结构基础之双向链表双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表,如下图所示,同时下图也是LinkedList 底层使用的是双向循环链表数据结构。   ArrayList 与 Vector 区别Vector类的所有方法都是同步的。可以由两个线程安全地访问一个Vector对象、但是一个线程访问Vector的话代码要在同步操作上耗费大量的时间。Arraylist不是同步的,所以在不需要保证线程安全时时建议使用Arraylist。HashMap的底层实现JDK1.8之前JDK1.8 之前 HashMap 由 数组+链表 组成的(“链表散列” 即数组和链表的结合体),数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的(HashMap 采用 “拉链法也就是链地址法” 解决冲突),如果定位到的数组位置不含链表(当前 entry 的 next 指向 null ),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度依然为 O(1),因为最新的 Entry 会插入链表头部,急需要简单改变引用链即可,而对于查找操作来讲,此时就需要遍历链表,然后通过 key 对象的 equals 方法逐一比对查找.所谓 “拉链法” 就是将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。   JDK1.8之后相比于之前的版本, JDK1.8之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。   TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。推荐阅读:《Java 8系列之重新认识HashMap》 :zhuanlan.zhihu.com/p/21673805HashMap 和 Hashtable 的区别线程是否安全: HashMap 是非线程安全的,HashTable 是线程安全的;HashTable 内部的方法基本都经过 synchronized 修饰。(如果你要保证线程安全的话就使用 ConcurrentHashMap 吧!);效率: 因为线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它;对Null key 和Null value的支持: HashMap 中,null 可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为 null。。但是在 HashTable 中 put 进的键值只要有一个 null,直接抛出 NullPointerException。初始容量大小和每次扩充容量大小的不同 : ①创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。②创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为2的幂次方大小。也就是说 HashMap 总是使用2的幂作为哈希表的大小,后面会介绍到为什么是2的幂次方。底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。HashMap 的长度为什么是2的幂次方为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀,每个链表/红黑树长度大致相同。这个实现就是把数据存到哪个链表/红黑树中的算法。这个算法应该如何设计呢?我们首先可能会想到采用%取余的操作来实现。但是,重点来了:“取余(%)操作中如果除数是2的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是2的 n 次方;)。” 并且 采用二进制位操作 &,相对于%能够提高运算效率,这就解释了 HashMap 的长度为什么是2的幂次方。HashSet 和 HashMap 区别   ConcurrentHashMap 和 Hashtable 的区别ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同。底层数据结构: JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的;实现线程安全的方式(重要): ① 在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。(默认分配16个Segment,比Hashtable效率提高16倍。) 到了 JDK1.8 的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;② Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put 添加元素,另一个线程不能使用 put 添加元素,也不能使用 get,竞争会越来越激烈效率越低。两者的对比图:图片来源:www.cnblogs.com/chengxiao/p…HashTable:  JDK1.7的ConcurrentHashMap: JDK1.8的ConcurrentHashMap(TreeBin: 红黑二叉树节点 Node: 链表节点):ConcurrentHashMap线程安全的具体实现方式/底层具体实现JDK1.7(上面有示意图)首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。ConcurrentHashMap 是由 Segment 数组结构和 HahEntry 数组结构组成。Segment 实现了 ReentrantLock,所以 Segment 是一种可重入锁,扮演锁的角色。HashEntry 用于存储键值对数据。 static class Segment<K,V> extends ReentrantLock implements Serializable { }一个 ConcurrentHashMap 里包含一个 Segment 数组。Segment 的结构和HashMap类似,是一种数组和链表结构,一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个HashEntry数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment的锁。JDK1.8 (上面有示意图)ConcurrentHashMap取消了Segment分段锁,采用CAS和synchronized来保证并发安全。数据结构跟HashMap1.8的结构类似,数组+链表/红黑二叉树。synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,效率又提升N倍。集合框架底层数据结构总结Collection1. ListArraylist: Object数组Vector: Object数组LinkedList: 双向循环链表2. SetHashSet(无序,唯一): 基于 HashMap 实现的,底层采用 HashMap 来保存元素LinkedHashSet: LinkedHashSet 继承与 HashSet,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 Hashmap 实现一样,不过还是有一点点区别的。TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树。)MapHashMap: JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突).JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间LinkedHashMap: LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。详细可以查看:《LinkedHashMap 源码详细分析(JDK1.8)》HashTable: 数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的TreeMap: 红黑树(自平衡的排序二叉树)推荐阅读:jdk1.8中ConcurrentHashMap的实现原理HashMap? ConcurrentHashMap? 相信看完这篇没人能难住你!HASHMAP、HASHTABLE、CONCURRENTHASHMAP的原理与区别ConcurrentHashMap实现原理及源码分析java-并发-ConcurrentHashMap高并发机制-jdk1.8
整理了下阿里近几年的java面试题目,大家参考下吧,希望对大家有帮助,可以帮大家查漏补缺。答对以下这些面试题,可以淘汰掉 80 % 的求职竞争者。1.hashcode相等两个类一定相等吗?equals呢?相反呢?2.介绍一下集合框架?3.hashmap hastable 底层实现什么区别?hashtable和concurrenthashtable呢?4.hashmap和treemap什么区别?低层数据结构是什么?5.线程池用过吗都有什么参数?底层如何实现的?6.sychnized和Lock什么区别?sychnize 什么情况情况是对象锁? 什么时候是全局锁为什么?7.ThreadLocal 是什么底层如何实现?写一个例子呗?8.volitile的工作原理?9.cas知道吗如何实现的?10.请用至少四种写法写一个单例模式?11.请介绍一下JVM内存模型??用过什么垃圾回收器都说说呗12.线上发送频繁full gc如何处理? CPU 使用率过高怎么办?13.如何定位问题?如何解决说一下解决思路和处理方法14.知道字节码吗?字节码都有哪些?Integer x =5,int y =5,比较x =y 都经过哪些步骤?15.讲讲类加载机制呗都有哪些类加载器,这些类加载器都加载哪些文件?16.手写一下类加载Demo17.知道osgi吗? 他是如何实现的???18.请问你做过哪些JVM优化?使用什么方法达到什么效果???19.classforName("java.lang.String")和String classgetClassLoader() LoadClass("java.lang.String") 什么区别啊?20.探查Tomcat的运行机制即框架?21.分析Tomcat线程模型?22.Tomcat系统参数认识和调优?23.MySQL底层B+Tree机制?24.SQL执行计划详解?25.索引优化详解?26.SQL语句如如如何优化?27.spring都有哪些机制啊AOP底层如何实现的啊IOC呢??28.cgLib知道吗?他和jdk动态代理什么区别?手写一个jdk动态代理呗?29.使用mysq1索引都有哪些原则? ?索引什么数据结构? 3+tree 和B tree 什么区别?30.MySQL有哪些存储引擎啊?都有啥区别? 要详细!31.设计高并发系统数据库层面该怎么设计??数据库锁有哪些类型?如何实现呀?32.数据库事务有哪些?33.如何设计可以动态扩容缩容的分库分表方案?34.用过哪些分库分表中间件,有啥优点和缺点?讲一下你了解的分库分表中间件的底层实现原理?35.我现在有一个未分库分表的系统,以后系统需分库分表,如何设计,让未分库分表的系统动态切换到分库分表的系统上?TCC? 那若出现网络原因,网络连不通怎么办啊?36.分布式事务知道吗? 你们怎么解决的?37.为什么要分库分表啊?38.RPC通信原理,分布式通信原理39.分布式寻址方式都有哪些算法知道一致性hash吗?手写一下java实现代码??你若userId取摸分片,那我要查一段连续时间里的数据怎么办???40.如何解决分库分表主键问题有什么实现方案??41.redis和memcheched 什么区别为什么单线程的redis比多线程的memched效率要高啊?42.redis有什么数据类型都在哪些场景下使用啊?43.reids的主从复制是怎么实现的redis的集群模式是如何实现的呢redis的key是如何寻址的啊?44.使用redis如何设计分布式锁?使用zk可以吗?如何实现啊这两种哪个效率更高啊??45.知道redis的持久化吗都有什么缺点优点啊? ?具体底层实现呢?46.redis过期策略都有哪些LRU 写一下java版本的代码吧??47.说一下dubbo的实现过程注册中心挂了可以继续通信吗??48.dubbo支持哪些序列化协议?hessian 说一下hessian的数据结构PB知道吗为啥PB效率是最高的啊??49.知道netty吗'netty可以干嘛呀NIO,BIO,AIO 都是什么啊有什么区别啊?50.dubbo复制均衡策略和高可用策略都有哪些啊动态代理策略呢?51.为什么要进行系统拆分啊拆分不用dubbo可以吗'dubbo和thrift什么区别啊?52.为什么使用消息队列啊消息队列有什么优点和缺点啊?53.如何保证消息队列的高可用啊如何保证消息不被重复消费啊54.kafka ,activemq,rabbitmq ,rocketmq都有什么优点,缺点啊???55.如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路56.说一下TCP 'IP四层?57.的工作流程?? ?http1.0 http1.1http2.0 具体哪些区别啊?58.TCP三次握手,四层分手的工作流程画一下流程图为什么不是四次五次或者二次啊?59.画一下https的工作流程?具体如何实现啊?如何防止被抓包啊??60.源码中所用到的经典设计思想及常用设计模式61.系统架构如何选择合适日志技术(log4j、log4j2、slf4j、jcl…….)62.springAOP的原理,springAOP和Aspectj的关系,springAOP的源码问题63.dubbo框架的底层通信原理64.RPC通信原理,分布式通信原理65.如何利用springCloud来架构微服务项目66.如何正确使用docker技术67.springMVC的底层原理、如何从源码来分析其原理68.mybaits的底层实现原理,如何从源码来分析mybaits69.mysql的索引原理,索引是怎么实现的70.索引的底层算法、如何正确使用、优化索引71.springboot如何快速构建系统72.zk原理知道吗zk都可以干什么Paxos算法知道吗?说一下原理和实现?73.如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路74.分布式事务知道吗? 你们怎么解决的?75.请问你做过哪些JVM优化?使用什么方法达到什么效果?
下列面试题都是在网上收集的,本人抱着学习的态度找了下参考答案,有不足的地方还请指正。1、面向对象的特征有哪些方面?抽象:将同类对象的共同特征提取出来构造类。继承:基于基类创建新类。封装:将数据隐藏起来,对数据的访问只能通过特定接口。多态性:不同子类型对象对相同消息作出不同响应。2、访问修饰符public,private,protected,以及不写(默认)时的区别?protected 当前类,同包,异包子类。3、String 是最基本的数据类型吗?答:不是。Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(reference type),Java 5以后引入的枚举类型也算是一种比较特殊的引用类型。4、float f=3.4;是否正确?答:不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;5、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?答:对于short s1 = 1; s1 = s1 + 1;由于1是int类型,因此s1+1运算结果也是int 型,需要强制转换类型才能赋值给short型。而short s1 = 1; s1 += 1;可以正确编译,因为s1+= 1;相当于s1 = (short)(s1 + 1);其中有隐含的强制类型转换。6、Java有没有goto?答:goto 是Java中的保留字,在目前版本的Java中没有使用。(根据James Gosling(Java之父)编写的《The Java Programming Language》一书的附录中给出了一个Java关键字列表,其中有goto和const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉C语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字)7、int和Integer有什么区别?答:Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。Java 为每个原始类型提供了包装类型:原始类型: boolean,char,byte,short,int,long,float,double包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double1 class AutoUnboxingTest {23 public static void main(String[] args) {4 Integer a = new Integer(3);5 Integer b = 3; // 将3自动装箱成Integer类型6 int c = 3;7 System.out.println(a == b); // false 两个引用没有引用同一对象8 System.out.println(a == c); // true a自动拆箱成int类型再和c比较9 }10 }最近还遇到一个面试题,也是和自动装箱和拆箱有点关系的,代码如下所示:1 public class Test03 {23 public static void main(String[] args) {4 Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;56 System.out.println(f1 == f2);7 System.out.println(f3 == f4);8 }9 }如果不明就里很容易认为两个输出要么都是true要么都是false。首先需要注意的是f1、f2、f3、f4四个变量都是Integer对象引用,所以下面的==运算比较的不是值而是引用。装箱的本质是什么呢?当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,如果看看valueOf的源代码就知道发生了什么。1 public static Integer valueOf(int i) {2 if (i >= IntegerCache.low && i <= IntegerCache.high)3 return IntegerCache.cache[i + (-IntegerCache.low)];4 return new Integer(i);5 }IntegerCache是Integer的内部类,其代码如下所示:1 /**2 * Cache to support the object identity semantics of autoboxing for values between3 * -128 and 127 (inclusive) as required by JLS.4 *5 * The cache is initialized on first usage. The size of the cache6 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.7 * During VM initialization, java.lang.Integer.IntegerCache.high property8 * may be set and saved in the private system properties in the9 * sun.misc.VM class.10 */1112 private static class IntegerCache {13 static final int low = -128;14 static final int high;15 static final Integer cache[];1617 static {18 // high value may be configured by property19 int h = 127;20 String integerCacheHighPropValue =21 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");22 if (integerCacheHighPropValue != null) {23 try {24 int i = parseInt(integerCacheHighPropValue);25 i = Math.max(i, 127);26 // Maximum array size is Integer.MAX_VALUE27 h = Math.min(i, Integer.MAX_VALUE - (-low) -1);28 } catch( NumberFormatException nfe) {29 // If the property cannot be parsed into an int, ignore it.30 }31 }32 high = h;3334 cache = new Integer[(high - low) + 1];35 int j = low;36 for(int k = 0; k < cache.length; k++)37 cache[k] = new Integer(j++);3839 // range [-128, 127] must be interned (JLS7 5.1.7)40 assert IntegerCache.high >= 127;41 }4243 private IntegerCache() {}44 }简单的说,如果整型字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,所以上面的面试题中f1==f2的结果是true,而f3==f4的结果是false。提醒:越是貌似简单的面试题其中的玄机就越多,需要面试者有相当深厚的功力。8、&和&&的区别?答:&运算符有两种用法:(1)按位与;(2)逻辑与。&&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true整个表达式的值才是true。&&之所以称为短路运算是因为,如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用&&而不是&,例如在验证用户登录时判定用户名不是null而且不是空字符串,应当写为:username != null &&!username.equals(""),二者的顺序不能交换,更不能用&运算符,因为第一个条件如果不成立,根本不能进行字符串的equals比较,否则会产生NullPointerException异常。注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。补充:如果你熟悉JavaScript,那你可能更能感受到短路运算的强大,想成为JavaScript的高手就先从玩转短路运算开始吧。9、解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。答:通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间;而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为Eden、Survivor(又可分为From Survivor和To Survivor)、Tenured;方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的100、"hello"和常量都是放在常量池中,常量池是方法区的一部分,。栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过JVM的启动参数来进行调整,栈空间用光了会引发Stack
上一篇:近5年常考Java面试题及答案整理(一)31、String s = new String("xyz");创建了几个字符串对象?答:两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。32、接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?答:接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。举一个多继承的例子,我们定义一个动物(类)既是狗(父类1)也是猫(父类2),两个父类都有“叫”这个方法。那么当我们调用“叫”这个方法时,它就不知道是狗叫还是猫叫了,这就是多重继承的冲突。而接口没有具体的方法实现,所以多继承接口也不会出现这种冲突。33、一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?答:可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。34、Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?答:可以继承其他类或实现其他接口,在Swing编程和Android开发中常用此方式来实现事件监听和回调。35、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。36、Java 中的final关键字有哪些用法?答:(1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。37、指出下面程序的运行结果。1 class A {23 static {4 System.out.print("1");5 }67 public A() {8 System.out.print("2");9 }10 }1112 class B extends A{1314 static {15 System.out.print("a");16 }1718 public B() {19 System.out.print("b");20 }21 }2223 public class Hello {2425 public static void main(String[] args) {26 A ab = new B();27 ab = new B();28 }2930 }答:执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。提示:如果不能给出此题的正确答案,说明之前第21题Java类加载机制还没有完全理解,赶紧再看看吧。38、数据类型之间的转换:如何将字符串转换为基本数据类型?如何将基本数据类型转换为字符串?答:调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;一种方法是将基本数据类型与空字符串("")连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf()方法返回相应字符串39、如何实现字符串的反转及替换?答:方法很多,可以自己写实现也可以使用String或StringBuffer/StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:1 public static String reverse(String originStr) {2 if(originStr == null || originStr.length() <= 1)3 return originStr;4 return reverse(originStr.substring(1)) + originStr.charAt(0);5 }40、怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?答:代码如下所示:1 String s1 = "你好";2 String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");41、日期和时间:如何取得年月日、小时分钟秒?如何取得从1970年1月1日0时0分0秒到现在的毫秒数?如何取得某月的最后一天?如何格式化日期?答:问题1:创建java.util.Calendar 实例,调用其get()方法传入不同的参数即可获得参数所对应的值。Java 8中可以使用java.time.LocalDateTimel来获取,代码如下所示。1 public class DateTimeTest {2 public static void main(String[] args) {3 Calendar cal = Calendar.getInstance();4 System.out.println(cal.get(Calendar.YEAR));5 System.out.println(cal.get(Calendar.MONTH)); // 0 - 116 System.out.println(cal.get(Calendar.DATE));7 System.out.println(cal.get(Calendar.HOUR_OF_DAY));8 System.out.println(cal.get(Calendar.MINUTE));9 System.out.println(cal.get(Calendar.SECOND));1011 // Java 812 LocalDateTime dt = LocalDateTime.now();13 System.out.println(dt.getYear());14 System.out.println(dt.getMonthValue()); // 1 - 1215 System.out.println(dt.getDayOfMonth());16 System.out.println(dt.getHour());17 System.out.println(dt.getMinute());18 System.out.println(dt.getSecond());19 }20 }问题2:以下方法均可获得该毫秒数。1 Calendar.getInstance().getTimeInMillis();2 System.currentTimeMillis();3 Clock.systemDefaultZone().millis(); // Java 8问题3:代码如下所示。1 Calendar time = Calendar.getInstance();2 time.getActualMaximum(Calendar.DAY_OF_MONTH);问题4:利用java.text.DataFormat 的子类(如SimpleDateFormat类)中的format(Date)方法可将日期格式化。Java 8中可以用java.time.format.DateTimeFormatter来格式化时间日期,代码如下所示。1 import java.text.SimpleDateFormat;2 import java.time.LocalDate;3 import java.time.format.DateTimeFormatter;4 import java.util.Date;56 class DateFormatTest {78 public static void main(String[] args) {9 SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy/MM/dd");10 Date date1 = new Date();11 System.out.println(oldFormatter.format(date1));1213 // Java 814 DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");15 LocalDate date2 = LocalDate.now();16 System.out.println(date2.format(newFormatter));17 }18 }补充:Java的时间日期API一直以来都是被诟病的东西,为了解决这一问题,Java 8中引入了新的时间日期API,其中包括LocalDate、LocalTime、LocalDateTime、Clock、Instant等类,这些的类的设计都使用了不变模式,因此是线程安全的设计。42、打印昨天的当前时刻。1 import java.util.Calendar;23 class YesterdayCurrent {4 public static void main(String[] args){5 Calendar cal = Calendar.getInstance();6 cal.add(Calendar.DATE, -1);7 System.out.println(cal.getTime());8 }9 }在Java 8中,可以用下面的代码实现相同的功能。1 import java.time.LocalDateTime;23 class YesterdayCurrent {45 public static void main(String[] args) {6 LocalDateTime today = LocalDateTime.now();7 LocalDateTime yesterday = today.minusDays(1);89 System.out.println(yesterday);10 }11 }43、比较一下Java和JavaSciprt。答:JavaScript 与Java是两个公司开发的不同的两个产品。Java 是原Sun Microsystems公司推出的面向对象的程序设计语言,特别适合于互联网应用程序开发;而JavaScript是Netscape公司的产品,为了扩展Netscape浏览器的功能而开发的一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言。JavaScript的前身是LiveScript;而Java的前身是Oak语言。下面对两种语言间的异同作如下比较:基于对象和面向对象:Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言,因而它本身提供了非常丰富的内部对象供设计人员使用。解释和编译:Java的源代码在执行之前,必须经过编译。JavaScript是一种解释性编程语言,其源代码不需经过编译,由
 上一篇:近5年常考Java面试题及答案整理(二)68、Java中如何实现序列化,有什么意义?答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。要实现序列化,需要让一个类实现Serializable接口,该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过writeObject(Object)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。序列化除了能够实现对象的持久化之外,还能够用于对象的深度克隆(可以参考第29题)。69、Java中有几种类型的流?答:字节流和字符流。字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。在 java.io 包中还有许多其他的流,主要是为了提高性能和使用方便。关于Java的I/O需要注意的有两点:一是两种对称性(输入和输出的对称性,字节和字符的对称性);二是两种设计模式(适配器模式和装潢模式)。另外Java中的流不同于C#的是它只有一个维度一个方向。面试题 - 编程实现文件拷贝。(这个题目在笔试的时候经常出现,下面的代码给出了两种实现方案)1 import java.io.FileInputStream;2 import java.io.FileOutputStream;3 import java.io.IOException;4 import java.io.InputStream;5 import java.io.OutputStream;6 import java.nio.ByteBuffer;7 import java.nio.channels.FileChannel;89 public final class MyUtil {1011 private MyUtil() {12 throw new AssertionError();13 }1415 public static void fileCopy(String source, String target) throws IOException {16 try (InputStream in = new FileInputStream(source)) {17 try (OutputStream out = new FileOutputStream(target)) {18 byte[] buffer = new byte[4096];19 int bytesToRead;20 while((bytesToRead = in.read(buffer)) != -1) {21 out.write(buffer, 0, bytesToRead);22 }23 }24 }25 }2627 public static void fileCopyNIO(String source, String target) throws IOException {28 try (FileInputStream in = new FileInputStream(source)) {29 try (FileOutputStream out = new FileOutputStream(target)) {30 FileChannel inChannel = in.getChannel();31 FileChannel outChannel = out.getChannel();32 ByteBuffer buffer = ByteBuffer.allocate(4096);33 while(inChannel.read(buffer) != -1) {34 buffer.flip();35 outChannel.write(buffer);36 buffer.clear();37 }38 }39 }40 }41 }注意:上面用到Java 7的TWR,使用TWR后可以不用在finally中释放外部资源 ,从而让代码更加优雅。70、写一个方法,输入一个文件名和一个字符串,统计这个字符串在这个文件中出现的次数。答:代码如下:1 import java.io.BufferedReader;2 import java.io.FileReader;34 public final class MyUtil {56 // 工具类中的方法都是静态方式访问的因此将构造器私有不允许创建对象(绝对好习惯)7 private MyUtil() {8 throw new AssertionError();9 }1011 /**12 * 统计给定文件中给定字符串的出现次数13 *14 * @param filename 文件名15 * @param word 字符串16 * @return 字符串在文件中出现的次数17 */18 public static int countWordInFile(String filename, String word) {19 int counter = 0;20 try (FileReader fr = new FileReader(filename)) {21 try (BufferedReader br = new BufferedReader(fr)) {22 String line = null;23 while ((line = br.readLine()) != null) {24 int index = -1;25 while (line.length() >= word.length() && (index = line.indexOf(word)) >= 0) {26 counter++;27 line = line.substring(index + word.length());28 }29 }30 }31 } catch (Exception ex) {32 ex.printStackTrace();33 }34 return counter;35 }3637 }71、如何用Java代码列出一个目录下所有的文件?答:如果只要求列出当前文件夹下的文件,代码如下所示:1 import java.io.File;23 class Test12 {45 public static void main(String[] args) {6 File f = new File("/Users/nnngu/Downloads");7 for(File temp : f.listFiles()) {8 if(temp.isFile()) {9 System.out.println(temp.getName());10 }11 }12 }13 }如果需要对文件夹继续展开,代码如下所示:1 import java.io.File;23 class Test12 {45 public static void main(String[] args) {6 showDirectory(new File("/Users/nnngu/Downloads"));7 }89 public static void showDirectory(File f) {10 _walkDirectory(f, 0);11 }1213 private static void _walkDirectory(File f, int level) {14 if(f.isDirectory()) {15 for(File temp : f.listFiles()) {16 _walkDirectory(temp, level + 1);17 }18 }19 else {20 for(int i = 0; i < level - 1; i++) {21 System.out.print("t");22 }23 System.out.println(f.getName());24 }25 }26 }在Java 7中可以使用NIO.2的API来做同样的事情,代码如下所示:1 class ShowFileTest {23 public static void main(String[] args) throws IOException {4 Path initPath = Paths.get("/Users/nnngu/Downloads");5 Files.walkFileTree(initPath, new SimpleFileVisitor<Path>() {67 @Override8 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)9 throws IOException {10 System.out.println(file.getFileName().toString());11 return FileVisitResult.CONTINUE;12 }1314 });15 }16 }72、用Java的套接字编程实现一个多线程的回显(echo)服务器。答:1 import java.io.BufferedReader;2 import java.io.IOException;3 import java.io.InputStreamReader;4 import java.io.PrintWriter
Java基础知识篇面向对象和面向过程的区别面向过程:优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。缺点:没有面向对象易维护、易复用、易扩展面向对象:优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护缺点:性能比面向过程低Java语言有哪些特点?1,简单易学;2,面向对象(封装,继承,多态);3,平台无关性(Java虚拟机实现平台无关性);4,可靠性;5,安全性;6,支持多线程(C++语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而Java语言却提供了多线程支持);7,支持网络编程并且很方便(Java语言诞生本身就是为简化网络编程设计的,因此Java语言不仅支持网络编程而且很方便);8,编译与解释并存;什么是字节码?采用字节码的最大好处是什么?什么Java是虚拟机?先看下java中的编译器和解释器:Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(即扩展名为.class的文件),它不面向任何特定的处理器,只面向虚拟机。每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行,这就是上面提到的Java的特点的编译与解释并存的解释。Java源代码---->编译器---->jvm可执行的Java字节码(即虚拟指令)---->jvm---->jvm中解释器----->机器可执行的二进制机器码---->程序运行。 采用字节码的好处:Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。什么是Java虚拟机任何一种可以运行Java字节码的软件均可看成是Java的虚拟机(JVM)什么是Java程序的主类?应用程序和小程序的主类有何不同?一个程序中可以有多个类,但只能有一个类是主类。在Java应用程序中,这个主类是指包含main()方法的类。而在Java小程序中,这个主类是一个继承自系统类JApplet或Applet的子类。应用程序的主类不一定要求是public类,但小程序的主类要求必须是public类。主类是Java程序执行的入口点。什么是JDK?什么是JRE?JDK: 顾名思义它是给开发者提供的开发工具箱,是给程序开发者用的。它除了包括完整的JRE(Java Runtime Environment),Java运行环境,还包含了其他供开发者使用的工具包。JRE:普通用户而只需要安装JRE(Java Runtime Environment)来 来运行Java程序。而程序开发者必须安装JDK来编译、调试程序。环境变量Path和ClassPath的作用是什么?如何设置这两个环境变量?Java环境变量PATH和CLASSPATH - 简书 http://www.jianshu.com/p/d63b099cf283Java应用程序与小程序之间有那些差别?简单说应用程序是从主线程启动(也就是main()方法)。applet小程序没有main方法,主要是嵌在浏览器页面上运行(调用init()线程或者run()来启动),嵌入浏览器这点跟flash的小游戏类似。字符型常量和字符串常量的区别1) 形式上:字符常量是单引号引起的一个字符字符串常量是双引号引起的若干个字符2) 含义上:字符常量相当于一个整形值(ASCII值),可以参加表达式运算字符串常量代表一个地址值(该字符串在内存中存放位置)3) 占内存大小字符常量只占一个字节字符串常量占若干个字节(至少一个字符结束标志)Java语言采用何种编码方案?有何特点?Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。构造器Constructor是否可被override在讲继承的时候我们就知道父类的私有属性和构造方法并不能被继承,所以Constructor也就不能被override,但是可以overload,所以你可以看到一个类中有多个构造函数的情况。重载和重写的区别重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类;如果父类方法访问修饰符为private则子类中就不是重写。java 面向对象编程三大特性------封装、继承、多态https://blog.csdn.net/jianyuerensheng/article/details/51602015String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的?可变性String类中使用字符数组保存字符串,privatefinalcharvalue[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[]value,这两种对象都是可变的。线程安全性String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。性能每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。对于三者使用的总结:如果要操作少量的数据用 = String单线程操作字符串缓冲区 下操作大量数据 = StringBuilder多线程操作字符串缓冲区 下操作大量数据 = StringBuffer自动装箱与拆箱装箱:将基本类型用它们对应的引用类型包装起来;拆箱:将包装类型转换为基本数据类型;Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。类、方法、成员变量和局部变量的可用修饰符 -http://blog.csdn.net/yttcjj/article/details/6939239在一个静态方法内调用一个非静态成员为什么是非法的?由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。在Java中定义一个不做事且没有参数的构造方法的作用Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。import java和javax有什么区别http://www.cnblogs.com/EasonJim/p/6993139.html接口和抽象类的区别是什么?1.接口的方法默认是public,所有方法在接口中不能有实现,抽象类可以有非抽象的方法2.接口中的实例变量默认是final类型的,而抽象类中则不一定3.一个类可以实现多个接口,但最多只能实现一个抽象类4.一个类实现接口的话要实现接口的所有方法,而抽象类不一定5.接口不能用new实例化,但可以声明,但是必须引用一个实现该接口的对象从设计层面来说,抽象是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。成员变量与局部变量的区别有那些?从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被public,private,static等修饰符所修饰,而局部变量不能被访问控制修饰符及static所修饰;成员变量和局部变量都能被final所修饰;从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被final修饰但没有被static修饰的成员变量必须显示地赋值);而局部变量则不会自动赋值。创建一个对象用什么运算符?对象实体与对象引用有何不同?new运算符,new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)什么是方法的返回值?返回值在类的方法里的作用是什么?方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收出结果,使得它可以用于其他的操作!一个类的构造方法的作用是什么?若一个类没有声明构造方法,改程序能正确执行吗?为什么?主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。构造方法有哪些特性?1,名字与类名相同;2,没有返回值,但不能用void声明构造函数;3,生成类的对象时自动执行,无需调用。静态方法和实例方法有何不同?静态方法和实例方法的区别主要体现在两个方面:在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制对象的相等与指向他们的引用相等,两者有什么不同?对象的相等 比的是内存中存放的内容是否相等而 引用相等 比较的是他们指向的内存地址是否相等。在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?帮助子类做初始化工作。什么是多态机制?Java语言是如何实现多态的?http://blog.csdn.net/bornlili/article/details/55213563equals 和 == 的区别?通俗点讲:==是看看左右是不是一个东西。equals是看看左右是不是长得一样。如何记住嘛。如果单纯是想记住,==:等于。equals:相同。两个长得一样的人,只能说长的相同(equals),但是不等于他们俩是一个人。你只要记住equals,==就不用记了。术语来讲的区别:1.==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是
适宜阅读人群需要面试的初/中/高级 java 程序员想要查漏补缺的人想要不断完善和扩充自己 java 技术栈的人java 面试官具体面试题下面一起来看 208 道面试题,具体的内容。一、Java 基础1.JDK 和 JRE 有什么区别?2.== 和 equals 的区别是什么?3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?4.final 在 java 中有什么作用?5.java 中的 Math.round(-1.5) 等于多少?6.String 属于基础的数据类型吗?7.java 中操作字符串都有哪些类?它们之间有什么区别?8.String str="i"与 String str=new String("i")一样吗?9.如何将字符串反转?10.String 类的常用方法都有那些?11.抽象类必须要有抽象方法吗?12.普通类和抽象类有哪些区别?13.抽象类能使用 final 修饰吗?14.接口和抽象类有什么区别?15.java 中 IO 流分为几种?16.BIO、NIO、AIO 有什么区别?17.Files的常用方法都有哪些?二、容器18.java 容器都有哪些?19.Collection 和 Collections 有什么区别?20.List、Set、Map 之间的区别是什么?21.HashMap 和 Hashtable 有什么区别?22.如何决定使用 HashMap 还是 TreeMap?23.说一下 HashMap 的实现原理?24.说一下 HashSet 的实现原理?25.ArrayList 和 LinkedList 的区别是什么?26.如何实现数组和 List 之间的转换?27.ArrayList 和 Vector 的区别是什么?28.Array 和 ArrayList 有何区别?29.在 Queue 中 poll()和 remove()有什么区别?30.哪些集合类是线程安全的?31.迭代器 Iterator 是什么?32.Iterator 怎么使用?有什么特点?33.Iterator 和 ListIterator 有什么区别?34.怎么确保一个集合不能被修改?三、多线程35.并行和并发有什么区别?36.线程和进程的区别?37.守护线程是什么?38.创建线程有哪几种方式?39.说一下 runnable 和 callable 有什么区别?40.线程有哪些状态?41.sleep() 和 wait() 有什么区别?42.notify()和 notifyAll()有什么区别?43.线程的 run()和 start()有什么区别?44.创建线程池有哪几种方式?45.线程池都有哪些状态?46.线程池中 submit()和 execute()方法有什么区别?47.在 java 程序中怎么保证多线程的运行安全?48.多线程锁的升级原理是什么?49.什么是死锁?50.怎么防止死锁?51.ThreadLocal 是什么?有哪些使用场景?52.说一下 synchronized 底层实现原理?53.synchronized 和 volatile 的区别是什么?54.synchronized 和 Lock 有什么区别?55.synchronized 和 ReentrantLock 区别是什么?56.说一下 atomic 的原理?四、反射57.什么是反射?58.什么是 java 序列化?什么情况下需要序列化?59.动态代理是什么?有哪些应用?60.怎么实现动态代理?五、对象拷贝61.为什么要使用克隆?62.如何实现对象克隆?63.深拷贝和浅拷贝区别是什么?六、Java Web64.jsp 和 servlet 有什么区别?65.jsp 有哪些内置对象?作用分别是什么?66.说一下 jsp 的 4 种作用域?67.session 和 cookie 有什么区别?68.说一下 session 的工作原理?69.如果客户端禁止 cookie 能实现 session 还能用吗?70.spring mvc 和 struts 的区别是什么?71.如何避免 sql 注入?72.什么是 XSS 攻击,如何避免?73.什么是 CSRF 攻击,如何避免?七、异常74.throw 和 throws 的区别?75.final、finally、finalize 有什么区别?76.try-catch-finally 中哪个部分可以省略?77.try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?78.常见的异常类有哪些?八、网络79.http 响应码 301 和 302 代表的是什么?有什么区别?80.forward 和 redirect 的区别?81.简述 tcp 和 udp的区别?82.tcp 为什么要三次握手,两次不行吗?为什么?83.说一下 tcp 粘包是怎么产生的?84.OSI 的七层模型都有哪些?85.get 和 post 请求有哪些区别?86.如何实现跨域?87.说一下 JSONP 实现原理?九、设计模式88.说一下你熟悉的设计模式?89.简单工厂和抽象工厂有什么区别?十、Spring/Spring MVC90.为什么要使用 spring?91.解释一下什么是 aop?92.解释一下什么是 ioc?93.spring 有哪些主要模块?94.spring 常用的注入方式有哪些?95.spring 中的 bean 是线程安全的吗?96.spring 支持几种 bean 的作用域?97.spring 自动装配 bean 有哪些方式?98.spring 事务实现方式有哪些?99.说一下 spring 的事务隔离?100.说一下 spring mvc 运行流程?101.spring mvc 有哪些组件?102.@RequestMapping 的作用是什么?103.@Autowired 的作用是什么?十一、Spring Boot/Spring Cloud104.什么是 spring boot?105.为什么要用 spring boot?106.spring boot 核心配置文件是什么?107.spring boot 配置文件有哪几种类型?它们有什么区别?108.spring boot 有哪些方式可以实现热部署?109.jpa 和 hibernate 有什么区别?110.什么是 spring cloud?111.spring cloud 断路器的作用是什么?112.spring cloud 的核心组件有哪些?十二、Hibernate113.为什么要使用 hibernate?114.什么是 ORM 框架?115.hibernate 中如何在控制台查看打印的 sql 语句?116.hibernate 有几种查询方式?117.hibernate 实体类可以被定义为 final 吗?118.在 hibernate 中使用 Integer 和 int 做映射有什么区别?119.hibernate 是如何工作的?120.get()和 load()的区别?121.说一下 hibernate 的缓存机制?122.hibernate 对象有哪些状态?123.在 hibernate 中 getCurrentSession 和 openSession 的区别是什么?124.hibernate 实体类必须要有无参构造函数吗?为什么?十三、Mybatis125.mybatis 中 #{}和 ${}的区别是什么?126.mybatis 有几种分页方式?127.RowBounds 是一次性查询全部结果吗?为什么?128.mybatis 逻辑分页和物理分页的区别是什么?129.mybatis 是否支持延迟加载?延迟加载的原理是什么?130.说一下 mybatis 的一级缓存和二级缓存?131.mybatis 和 hibernate 的区别有哪些?132.mybatis 有哪些执行器(Executor)?133.mybatis 分页插件的实现原理是什么?134.mybatis 如何编写一个自定义插件?十四、RabbitMQ135.rabbitmq 的使用场景有哪些?136.rabbitmq 有哪些重要的角色?137.rabbitmq 有哪些重要的组件?138.rabbitmq 中 vhost 的作用是什么?139.rabbitmq 的消息是怎么发送的?140.rabbitmq 怎么保证消息的稳定性?141.rabbitmq 怎么避免消息丢失?142.要保证消息持久化成功的条件有哪些?143.rabbitmq 持久化有什么缺点?144.rabbitmq 有几种广播类型?145.rabbitmq 怎么实现延迟消息队列?146.rabbitmq 集群有什么用?147.rabbitmq 节点的类型有哪些?148.rabbitmq 集群搭建需要注意哪些问题?149.rabbitmq 每个节点是其他节点的完整拷贝吗?为什么?150.rabbitmq 集群中唯一一个磁盘节点崩溃了会发生什么情况?151.rabbitmq 对集群节点停止顺序有要求吗?十五、Kafka152.kafka 可以脱离 zookeeper 单独使用吗?为什么?153.kafka 有几种数据保留的策略?154.kafka 同时设置了 7 天和 10G 清除数据,到第五天的时候消息达到了 10G,这个时候 kafka 将如何处理?155.什么情况会导致 kafka 运行变慢?156.使用 kafka 集群需要注意什么?十六、Zookeeper157.zookeeper 是什么?158.zookeeper 都有哪些功能?159.zookeeper 有几种部署模式?160.zookeeper 怎么保证主从节点的状态同步?161.集群中为什么要有主节点?162.集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可以使用吗?163.说一下 zookeeper 的通知机制?十七、MySql164.数据库的三范式是什么?165.一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?166.如何获取当前数据库版本?167.说一下 ACID 是什么?168.char 和 varchar 的区别是什么?169.float 和 double 的区别是什么?170.mysql 的内连接、左连接、右连接有什么区别?171.mysql 索引是怎么实现的?172.怎么验证 mysql 的索引是否满足需求?173.说一下数据库的事务隔离?174.说一下 mysql 常用的引擎?175.说一下 mysql 的行锁和表锁?176.说一下乐观锁和悲观锁?177.mysql 问题排查都有哪些手段?178.如何做 mysql 的性能优化?十八、Redis179.redis 是什么?都有哪些使用场景?180.redis 有哪些功能?181.redis 和 memecache 有什么区别?182.redis 为什么是单线程的?183.什么是缓存穿透?怎么解决?184.redis 支持的数据类型有哪些?185.redis 支持的 java 客户端都有哪些?186.jedis 和 redisson 有哪些区别?187.怎么保证缓存和数据库数据的一致性?188.redis 持久化有几种方式?189.redis 怎么实现分布式锁?190.redis 分布式锁有什么缺陷?191.redis 如何做内存优化?192.redis 淘汰策略有哪些?193.redis 常见的性能问题有哪些?该如何解决?十九、JVM194.说一下 jvm 的主要组成部分?及其作用?195.说一下 jvm 运行时数据区?196.说一下堆栈的区别?197.队列和栈是什么?有什么区别?198.什么是双亲委派模型?199.说一下类加载的执行过程?200.怎么判断对象是否可以被回收?201.java 中都有哪些引用类型?202.说一下 jvm 有哪些垃圾回收算法?203.说一下 jvm 有哪些垃圾回收器?204.详细介绍一下 CMS 垃圾回收器?205.新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?206.简述分代垃圾回收器是怎么工作
最近在备战面试的过程中,整理一下面试题。大多数题目都是自己手敲的,网上也有很多这样的总结。自己感觉总是很乱,所以花了很久把自己觉得重要的东西总结了一下。面向对象和面向过程的区别面向过程:   优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。缺点:没有面向对象易维护、易复用、易扩展面向对象:   优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护缺点:性能比面向过程低Java语言有哪些特点?1. 简单易学;2. 面向对象(封装,继承,多态);3. 平台无关性(Java虚拟机实现平台无关性);4. 可靠性;5. 安全性;6. 支持多线程(C++语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而Java语言却提供了多线程支持);7. 支持网络编程并且很方便(Java语言诞生本身就是为简化网络编程设计的,因此Java语言不仅支持网络编程而且很方便);8. 编译与解释并存;什么是字节码?采用字节码的最大好处是什么?什么Java是虚拟机?先看下java中的编译器和解释器:   Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(即扩展名为.class的文件),它不面向任何特定的处理器,只面向虚拟机。每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行,这就是上面提到的Java的特点的编译与解释并存的解释。 Java源代码---->编译器---->jvm可执行的Java字节码(即虚拟指令)---->jvm---->jvm中解释器----->机器可执行的二进制机器码---->程序运行。采用字节码的好处:   Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。什么是Java虚拟机:任何一种可以运行Java字节码的软件均可看成是Java的虚拟机(JVM)什么是Java程序的主类?应用程序和小程序的主类有何不同?一个程序中可以有多个类,但只能有一个类是主类。在Java应用程序中,这个主类是指包含main()方法的类。而在Java小程序中,这个主类是一个继承自系统类JApplet或Applet的子类。应用程序的主类不一定要求是public类,但小程序的主类要求必须是public类。主类是Java程序执行的入口点。什么是JDK?什么是JRE?JDK: 顾名思义它是给开发者提供的开发工具箱,是给程序开发者用的。它除了包括完整的JRE(Java Runtime Environment),Java运行环境,还包含了其他供开发者使用的工具包。 JRE:普通用户而只需要安装JRE(Java Runtime Environment)来 来运行Java程序。而程序开发者必须安装JDK来编译、调试程序。环境变量Path和ClassPath的作用是什么?如何设置这两个环境变量?Java环境变量PATH和CLASSPATH - 简书 http://www.jianshu.com/p/d63b099cf283Java应用程序与小程序之间有那些差别?简单说应用程序是从主线程启动(也就是main()方法)。applet小程序没有main方法,主要是嵌在浏览器页面上运行(调用init()线程或者run()来启动),嵌入浏览器这点跟flash的小游戏类似。字符型常量和字符串常量的区别形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符含义上: 字符常量相当于一个整形值(ASCII值),可以参加表达式运算 字符串常量代表一个地址值(该字符串在内存中存放位置)占内存大小 字符常量只占一个字节 字符串常量占若干个字节(至少一个字符结束标志)Java语言采用何种编码方案?有何特点?Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。构造器Constructor是否可被override在讲继承的时候我们就知道父类的私有属性和构造方法并不能被继承,所以Constructor也就不能被override,但是可以overload,所以你可以看到一个类中有多个构造函数的情况。重载和重写的区别重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。   重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类;如果父类方法访问修饰符为private则子类中就不是重写。java 面向对象编程三大特性------封装、继承、多态blog.csdn.net/jianyuerens…java中equals方法的用法以及==的用法www.cnblogs.com/bluestorm/a…String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的?可变性  String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[]value,这两种对象都是可变的。   线程安全性String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。   性能每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。 对于三者使用的总结: 如果要操作少量的数据用 = String 单线程操作字符串缓冲区 下操作大量数据 = StringBuilder 多线程操作字符串缓冲区 下操作大量数据 = StringBuffer自动装箱与拆箱装箱:将基本类型用它们对应的引用类型包装起来;拆箱:将包装类型转换为基本数据类型;   Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。类、方法、成员变量和局部变量的可用修饰符 -blog.csdn.net/yttcjj/arti…在一个静态方法内调用一个非静态成员为什么是非法的?由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。在Java中定义一个不做事且没有参数的构造方法的作用Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。import java和javax有什么区别www.cnblogs.com/EasonJim/p/…接口和抽象类的区别是什么?1.接口的方法默认是public,所有方法在接口中不能有实现,抽象类可以有非抽象的方法 2.接口中的实例变量默认是final类型的,而抽象类中则不一定 3.一个类可以实现多个接口,但最多只能实现一个抽象类 4.一个类实现接口的话要实现接口的所有方法,而抽象类不一定 5.接口不能用new实例化,但可以声明,但是必须引用一个实现该接口的对象 从设计层面来说,抽象是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。成员变量与局部变量的区别有那些?从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被public,private,static等修饰符所修饰,而局部变量不能被访问控制修饰符及static所修饰;成员变量和局部变量都能被final所修饰;从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被final修饰但没有被static修饰的成员变量必须显示地赋值);而局部变量则不会自动赋值。创建一个对象用什么运算符?对象实体与对象引用有何不同?new运算符,new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)什么是方法的返回值?返回值在类的方法里的作用是什么?方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收出结果,使得它可以用于其他的操作!一个类的构造方法的作用是什么?若一个类没有声明构造方法,改程序能正确执行吗?为什么?主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。构造方法有哪些特性?1. 名字与类名相同;2. 没有返回值,但不能用void声明构造函数;3. 生成类的对象时自动执行,无需调用。静态方法和实例方法有何不同?静态方法和实例方法的区别主要体现在两个方面:在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制对象的相等与指向他们的引用相等,两者有什么不同?对象的相等 比的是内存中存放的内容是否相等而 引用相等 比较的是他们指向的内存地址是否相等。在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?帮助子类做初始化工作。什么是多态机制?Java语言是如何实现多态的?blog.csdn.net/bornlili/ar…equals 和 == 的区别?通俗点讲:==是看看左右是不是一个东西。equals是看看左右是不是长得一样。如何记住嘛。如果单纯是想记住,==:等于。equals:相同。两个长得一样的人,只能说长的相同(equals),但是不等于他们俩是一个人。你只要记住equals,==就不用记了。术语来讲的
一、Java基础部分1. HashMap和Hashtable各有什么特点,它们有什么区别?(必背题,超级重要)HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。HashMap不能保证随着时间的推移Map中的元素次序是不变的。2. HashMap的工作原理?HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的链表中。键对象的equals()方法用来找到键值对。1和2参考博客链接这里还有许多相关问题的描述,都是比较重要的!建议将其背熟!3. ArrayList和LinkList各自的特点和区别?1、ArrayList和LinkedList可想从名字分析,它们一个是Array(动态数组)的数据结构,一个是Link(链表)的数据结构,此外,它们两个都是对List接口的实现。前者是数组队列,相当于动态数组;后者为双向链表结构,也可当作堆栈、队列、双端队列2、当随机访问List时(get和set操作),ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。3、当对数据进行增加和删除的操作时(add和remove操作),LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。4、从利用效率来看,ArrayList自由性较低,因为它需要手动的设置固定大小的容量,但是它的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;而LinkedList自由性较高,能够动态的随数据量的变化而变化,但是它不便于使用。5、ArrayList主要控件开销在于需要在lList列表预留一定空间;而LinkList主要控件开销在于需要存储结点信息以及结点指针信息。4. RESTFul风格接口的特点?此题是现在做应用开发常问的题目,RestFul风格在现在的应用开发还是比较常用的,所以还是比较重要,建议进行了解:以下是作者自认为不错的一篇关于RestFul架构风格的博客,推荐!博客·链接5. 面向对象的七种设计原则面向对象七大设计原则:1、 开闭原则(OCP:Open Closed Principle)核心:对扩展开放,对修改关闭。即在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。根据开闭原则,在设计一个软件系统模块(类,方法)的时候,应该可以在不修改原有的模块(修改关闭)的基础上,能扩展其功能(扩展开放)。2、 里氏替换原则(LSP:Liskov Substitution Principle)核心:在任何父类出现的地方都可以用他的子类来替代(子类应当可以替换父类并出现在父类能够出现的任何地方)1.子类必须完全实现父类的方法。在类中调用其他类是务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则。2.子类可以有自己的个性。子类当然可以有自己的行为和外观了,也就是方法和属性3.覆盖或实现父类的方法时输入参数可以被放大。即子类可以重载父类的方法,但输入参数应比父类方法中的大,这样在子类代替父类的时候,调用的仍然是父类的方法。即以子类中方法的前置条件必须与超类中被覆盖的方法的前置条件相同或者更宽松。4.覆盖或实现父类的方法时输出结果可以被缩小。3、 单一职责原则(SRP:Single responsibility principle)核心:解耦和增强内聚性(高内聚,低耦合)类被修改的几率很大,因此应该专注于单一的功能。如果你把多个功能放在同一个类中,功能之间就形成了关联,改变其中一个功能,有可能中止另一个功能,这时就需要新一轮的测试来避免可能出现的问题。4、 接口隔离原则(ISP:Interface Segregation Principle)核心思想:不应该强迫客户程序依赖他们不需要使用的方法。接口分离原则的意思就是:一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该把所有的操作都封装到一个接口当中.分离接口的两种实现方法:1.使用委托分离接口。(Separation through Delegation)2.使用多重继承分离接口。(Separation through Multiple Inheritance)5、 依赖倒置原则(DIP:Dependence Inversion Principle)核心:要依赖于抽象,不要依赖于具体的实现1.高层模块不应该依赖低层模块,两者都应该依赖其抽象(抽象类或接口)2.抽象不应该依赖细节(具体实现)3.细节(具体实现)应该依赖抽象。三种实现方式:1.通过构造函数传递依赖对象2.通过setter方法传递依赖对象3.接口声明实现依赖对象6、 迪米特原则(最少知识原则)(LOD:Law of Demeter)核心思想:一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。(类间解耦,低耦合)意思就是降低各个对象之间的耦合,提高系统的可维护性;在模块之间只通过接口来通信,而不理会模块的内部工作原理,可以使各个模块的耦合成都降到最低,促进软件的复用注:1.在类的划分上,应该创建有弱耦合的类;2.在类的结构设计上,每一个类都应当尽量降低成员的访问权限;3.在类的设计上,只要有可能,一个类应当设计成不变;4.在对其他类的引用上,一个对象对其它对象的引用应当降到最低;5.尽量降低类的访问权限;6.谨慎使用序列化功能;7.不要暴露类成员,而应该提供相应的访问器(属性)7、 组合/聚合复用原则(CRP:Composite Reuse Principle)核心思想:尽量使用对象组合,而不是继承来达到复用的目的。该原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分:新的对象通过向这些对象的委派达到复用已有功能的目的。复用的种类:1.继承2.合成聚合注:在复用时应优先考虑使用合成聚合而不是继承6. 谈谈堆和栈的区别!a.堆栈空间分配栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表b.堆栈缓存方式栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。c.堆栈数据结构区别堆(数据结构):堆可以被看成是一棵树,如:堆排序。栈(数据结构):一种先进后出的数据结构。7. 谈谈你所了解的设计模式,并简单描述其特点和用法,或简单写一个某某设计模式!1. 单例设计模式2. 工厂设计模式3. 代理模式4. 观察者设计模式5. 适配器模式6. 策略模式7. 门面模式8. 桥接模式来一个参考链接几种常用的设计模式参考博客链接注:设计模式有很多,这里列举几种常用的!读者需要自行将这几种设计模式理解清楚!前五种是常用也是常考的!8. 熟悉HTTP基本的状态码!一些常见的状态码为:200 - 服务器成功返回网页404 - 请求的网页不存在503 - 服务不可用具体详细的可以参考博客 HTTP状态码详细博客链接9. List、Set和Map的特点和区别(重点)List:1.可以允许重复的对象。2.可以插入多个null元素。3.是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。4.常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。Set:1.不允许重复对象2.无序容器,你无法保证每个元素的存储顺序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序。3.只允许一个 null 元素4.Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序容器。Map:1.不是collection的子接口或者实现类。Map是一个接口。2.Map 的 每个 Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。3.TreeMap 也通过 Comparator 或者 Comparable 维护了一个排序顺序。4.Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。5.Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)10.监听器、过滤器、拦截器、servlet的区别eb.xml 的加载顺序是:context- param -> listener -> filter -> servlet监听器(listener):在request、session、application三个对象创建消亡或者往其中增/删/改属性时自动执行指定代码的功能组件。生命周期:随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。作用:做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。过滤器(filter):拦截请求,filter能够在一个请求到达控制层之前预处理用户请求,也可以在离开控制层时处理http 响应,进行一些设置以及逻辑判断,然后再传入servlet或者struts的 action进行业务逻辑,基于函数回调。生命周期:它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当
1、什么是Mybatis?(1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。(2)MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。(3)通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。2、Mybaits的优点:(1)基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。(2)与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;(3)很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。(4)能够与Spring很好的集成;(5)提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。3、MyBatis框架的缺点:(1)SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。(2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。4、MyBatis框架适用场合:(1)MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。(2)对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。5、MyBatis与Hibernate有哪些不同?(1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。(2)Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。 (3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用hibernate开发可以节省很多代码,提高效率。 6、#{}和${}的区别是什么?#{}是预编译处理,${}是字符串替换。Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;Mybatis在处理${}时,就是把${}替换成变量的值。使用#{}可以有效的防止SQL注入,提高系统安全性。7、当实体类中的属性名和表中的字段名不一样 ,怎么办 ?第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。1     <select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”>2 select order_id id, order_no orderno ,order_price price form orders where order_id=#{id};3 </select>第2种: 通过<resultMap>来映射字段名和实体类属性名的一一对应的关系。1 <select id="getOrder" parameterType="int" resultMap="orderresultmap">2 select * from orders where order_id=#{id}3 </select>45 <resultMap type=”me.gacl.domain.order” id=”orderresultmap”>6 <!–用id属性来映射主键字段–>7 <id property=”id” column=”order_id”>89 <!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–>10 <result property = “orderno” column =”order_no”/>11 <result property=”price” column=”order_price” />12 </reslutMap>8、 模糊查询like语句该怎么写?第1种:在Java代码中添加sql通配符。1 string wildcardname = “%smi%”;2 list<name> names = mapper.selectlike(wildcardname);34 <select id=”selectlike”>5 select * from foo where bar like #{value}6 </select>第2种:在sql语句中拼接通配符,会引起sql注入1 string wildcardname = “smi”;2 list<name> names = mapper.selectlike(wildcardname);34 <select id=”selectlike”>5      select * from foo where bar like "%"#{value}"%"6 </select>9、通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?Dao接口即Mapper接口。接口的全限名,就是映射文件中的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MapperStatement。在Mybatis中,每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MapperStatement对象。举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面 id 为 findStudentById 的 MapperStatement。Mapper接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻找策略。Mapper 接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,转而执行MapperStatement所代表的sql,然后将sql执行结果返回。10、Mybatis是如何进行分页的?分页插件的原理是什么?Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。11、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?第一种是使用<resultMap>标签,逐一定义数据库列名和对象属性名之间的映射关系。第二种是使用sql列的别名功能,将列的别名书写为对象属性名。有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。12、如何执行批量插入?首先,创建一个简单的insert语句:1 <insert id=”insertname”>2     insert into names (name) values (#{value})3 </insert> 然后在java代码中像下面这样执行批处理插入:1 list<string> names = new arraylist();2 names.add(“fred”);3 names.add(“barney”);4 names.add(“betty”);5 names.add(“wilma”);67 // 注意这里 executortype.batch8 sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch);9 try {10 namemapper mapper = sqlsession.getmapper(namemapper.class);11 for (string name : names) {12 mapper.insertname(name);13 }14 sqlsession.commit();15 }catch(Exception e){16 e.printStackTrace();17 sqlSession.rollback();18 throw e;19     }20     finally {21     sqlsession.close();22 }13、如何获取自动生成的(主)键值?insert 方法总是返回一个int值 ,这个值代表的是插入的行数。如果采用自增长策略,自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中。示例:1 <insert id=”insertname” usegeneratedkeys=”true” keyproperty=”id”>2 insert into names (name) values (#{name})3 </insert> 1     name name = new name();2 name.setname(“fred”);34 int rows = mapper.insertname(name);5 // 完成后,id已经被设置到对象中6 system.out.println(“rows inserted = ” + rows);7 system.out.println(“generated key value = ” + name.getid());14、在mapper中如何传递多个参数?1 (1)第一种:2 //DAO层的函数3 Public UserselectUser(String name,String area);4 //对应的xml,#{0}代表
1、#{}和${}的区别是什么?#{}和${}的区别是什么?在Mybatis中,有两种占位符#{}解析传递进来的参数数据${}对传递进来的参数原样拼接在SQL中#{}是预编译处理,${}是字符串替换。使用#{}可以有效的防止SQL注入,提高系统安全性。2、当实体类中的属性名和表中的字段名不一样 ,怎么办 ?当实体类中的属性名和表中的字段名不一样 ,怎么办 ?第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致1 <select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”>2 select order_id id, order_no orderno ,order_price price form orders where order_id=#{id};3 </select>第2种: 通过来映射字段名和实体类属性名的一一对应的关系1 <select id="getOrder" parameterType="int" resultMap="orderresultmap">2 select * from orders where order_id=#{id}3 </select>4 <resultMap type=”me.gacl.domain.order” id=”orderresultmap”>5 <!–用id属性来映射主键字段–>6 <id property=”id” column=”order_id”>7 <!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–>8 <result property = “orderno” column =”order_no”/>9 <result property=”price” column=”order_price” />10 </reslutMap>我认为第二种方式会好一点。3、如何获取自动生成的(主)键值?如何获取自动生成的(主)键值?如果我们一般插入数据的话,如果我们想要知道刚刚插入的数据的主键是多少,我们可以通过以下的方式来获取需求:user对象插入到数据库后,新记录的主键要通过user对象返回,通过user获取主键值。解决思路:通过LAST_INSERT_ID()获取刚插入记录的自增主键值,在insert语句执行后,执行select LAST_INSERT_ID()就可以获取自增主键。mysql:1 <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">2 <selectKey keyProperty="id" order="AFTER" resultType="int">3 select LAST_INSERT_ID()4 </selectKey>5 INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})6 </insert>oracle:实现思路:先查询序列得到主键,将主键设置到user对象中,将user对象插入数据库。1 <!-- oracle2 在执行insert之前执行select 序列.nextval() from dual取出序列最大值,将值设置到user对象 的id属性3 -->4 <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">5 <selectKey keyProperty="id" order="BEFORE" resultType="int">6 select 序列.nextval() from dual7 </selectKey>89 INSERT INTO USER(id,username,birthday,sex,address) VALUES( 序列.nextval(),#{username},#{birthday},#{sex},#{address})10 </insert>4、在mapper中如何传递多个参数?在mapper中如何传递多个参数?第一种:使用占位符的思想在映射文件中使用#{0},#{1}代表传递进来的第几个参数**使用@param注解:来命名参数 **#{0},#{1}方式1 //对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。23 <select id="selectUser"resultMap="BaseResultMap">4 select * fromuser_user_t whereuser_name = #{0} anduser_area=#{1}5 </select>@param注解方式1 public interface usermapper {2 user selectuser(@param(“username”) string username,3 @param(“hashedpassword”) string hashedpassword);4 } 1 <select id=”selectuser” resulttype=”user”>2 select id, username, hashedpassword3 from some_table4 where username = #{username}5 and hashedpassword = #{hashedpassword}6 </select> 第二种:使用Map集合作为参数来装载1 try{2 //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL345 /**6 * 由于我们的参数超过了两个,而方法中只有一个Object参数收集7 * 因此我们使用Map集合来装载我们的参数8 */9 Map<String, Object> map = new HashMap();10 map.put("start", start);11 map.put("end", end);12 return sqlSession.selectList("StudentID.pagination", map);13 }catch(Exception e){14 e.printStackTrace();15 sqlSession.rollback();16 throw e;17 }finally{18 MybatisUtil.closeSqlSession();19 } 1 <!--分页查询-->2 <select id="pagination" parameterType="map" resultMap="studentMap">34 /*根据key自动找到对应Map集合的value*/5 select * from students limit #{start},#{end};67 </select>5、Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。Mybatis提供了9种动态sql标签:trim|where|set|foreach|if|choose|when|otherwise|bind。其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。6、Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?如果配置了namespace那么当然是可以重复的,因为我们的Statement实际上就是namespace+id如果没有配置namespace的话,那么相同的id就会导致覆盖了。7、为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。8、通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement举例:1 com.mybatis3.mappers.StudentDao.findStudentById,23 可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象。Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,
二叉树和二叉查找树之间的区别 凡是每个节点都最多有两个叉的树,都叫二叉树。 查找树和排序树是一个东西。特点是中序遍历一遍的结果是单调的。这种树建出来可以用来做二分搜索。 平衡树一般是排序树的一种,并且
&& 和& 的区别 按位与:a&b是把a和b都转换成二进制数然后再进行与的运算;逻辑与:a&&b就是当且仅当两个操作数均为 true时,其结果才为 tr
微信公众号搜索 “ 程序精选 ” ,选择关注!
微信公众号搜 "程序精选"关注