微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!
近5年常考Java面试题及答案整理一
下列面试题都是在网上收集的,本人抱着学习的态度找了下参考答案,有不足的地方还请指正。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面试题及答案整理二
上一篇:近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面试题及答案整理三
 上一篇:近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面试题考点全面总结
我通过两个月的复习拿到了阿里巴巴的 offer,有一些运气,也有一些心得,借着跳槽季来临特此分享出来。简单梳理一下我的复习思路,同时也希望和大家一起交流讨论,一起学习,如果不对之处欢迎指正一起学习。本文即是复习思路,亦可当做学习思路。我大致把 JAVA 的复习分为如下几个方向。JVM;排序算法和 Java 集合&工具类;多线程和并发包;存储相关:Redis 、Elastic Search、MySQL;框架:Spring,SpringMVC,Spring Boot分布式:Dubbo;设计模式;下面简单说一下如何复习上面的知识,首先明确,我不会讲解具体的知识点,而是一个思路,纵观互联网上面的帖子、文章误人子弟的多一些,所以就不误人子弟了,而是推荐分析出知识点然后以看书为主。毕竟书是多方校对权威出版的读物。JVMJVM 是每一个开发人员必备的技能,推荐看国内比较经典的 JVM 书籍,里面包含JVM的内存接口,类的加载机制等基础知识,是不是觉得这些在面试中似曾相识?所以对于 JVM 方面的知识的巩固与其在网上看一些零零碎碎的文章不如啃一下这本书。《深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第 2 版)》,当然了如果你的英文好强烈推荐看 Oracle 最新发布的 JAVA 虚拟机规范。在啃书的时候切记不能图快,你对知识的积累不是通过看书的数量来决定,而是看书的深度。所以在看每一章节的时候看到不懂的要配合网上的文章理解,并且需要看几篇文章理解,因为一篇文章很可能是错误的,我认为文章的可信度顺序自建域名>*.github.io>SF>简书=博客园>CSDN>转载排序算法和 Java 集合、工具类这一个分类是每一个人必须掌握的并熟练使用的,那么为什么我把他们放在一起呢?  因为工具和集合类都源于算法,在准备算法复习之前你要理解,为什么要必考算法。正式因为排序算法和我们编程息息相关。举两个“栗子”。你可以看一下Collections 中的mergeSort和sort 方法,你会发现 mergeSort 就是归并排序的实现,而 sort 方法结合了归并排序和插入排序,这样使得 sort 方法最差O(NlogN)最好可以达到O(N)的效果。那么只有你自己理解了排序方法的实现,才能更好的使用 JAVA 中的集合类啊?第二个“栗子”,大家都听闻过 TopN 问题吧,经常在面试中遇到请写一下 TopN 的实现,说到算法它就是一个大顶堆,说到 JAVA 它是一个 PriorityQueue 的实现,那么你理解了 TopN 问题,知道他的时间复杂度,优缺点了,那么是不是就可以熟练运用 JAVA 的工具类写更高效的程序了?之所以排序算法和 JAVA  集合&工具类 一样重要是因为它们和我们每天的编程息息相关。面试官总是问排序算法也不是在难为你,而是在考察你的编程功底。所以你需要对着排序算法和基本的算法配合 JAVA 的集合类、工具类仔细的研究一番,这样才能更深入的理解他们的关联关系。  多线程和并发包多线程和并发包,重要性就不累述了,直接说一下学习方法。你首先要理解多线程不仅仅是 Thread 和 Runnable 那么简单,整个并发包下面的工具都是在为多线程服务。对于多线程的学习切不可看几篇面试文章,或者几个关键字 CountDownLatch,Lock 巴拉巴拉就以为理解了多线程的精髓,我整理了一个大图你需要针对这个大图或者自己梳理一个大图,对里面的类各个击破,他们的使用场景,优缺点。当然你需要配合源码看,源码就是大图里面的每一个源码,和上面讲的 JVM 一样,不要着急马上看完,而是看懂每一个地方是为什么。看的差不多你就会发现,其实他和 JAVA 集合类、工具类密不可分。那么自然把它列为重要知识点的原因不言而喻。Redis、MySQL、ElasticSearch存储相关相关都是我们平时常用的工具,Redis,MySQL,ElasticSearch。它的知识点分为两方面,一方面是你平时使用过程中积累的经验,另一方面是你对其的深入理解。所以对这个地方的建议就是通过书籍来巩固技术知识, 《Redis设计与实现 (数据库技术丛书)》,《高性能 MySQL》,《ElasticSearch 权威指南》这三本书不一定是该领域最好的书籍,但是如果你吃透了,对于你对知识的理解和程序的设计必定有很大帮助。书里面的内容太多,还是举两个“栗子”。第一个“栗子”,使用 Redis 切不可只用他当做 key-value 缓存数据库。我了解到它的5种基本类型中一种类型叫做 sorted set。sorted set 里 items 内容大于 64 的时候同时使用了 hash 和 skiplist 两种设计实现。这也会为了排序和查找性能做的优化。添加和删除都需要修改 skiplist,所以复杂度为 O(log(n))。 但是如果仅仅是查找元素的话可以直接使用 hash,其复杂度为 O(1) ,其他的 range 操作复杂度一般为 O(log(n)),当然如果是小于 64 的时候,因为是采用了 ziplist 的设计,其时间复杂度为 O(n)。这样以后查询和更新阅读都变得简单,那是不是可以用其实现 TopN 的需求呢?这样类似的需求就不需要你查数据,再在内存里面计算和操作了。比如我们简单的周排行,月排行都可以考虑使用这个数据结构实现,当然并不一定这是最好的解决方案,而是提供了一种解题思路。 另一个“栗子”,PriorityQueue 是优先队列我们上文已经了解,那么 ElasticSearch 的 query 也是用的优先队列分别在每一个分片上面获取,然后再合并优先队列你了解吗?这个“栗子”告诉我们其实算法是想通的,你理解一个便可以举一反三触类旁通。框架一谈框架就想起来 Spring,一说 Spring 就想起来 IOC,AOP。因为大家都在用这个框架,所以对于框架也不需要看一些其他的,直接就深入了解一下 Spring 就可以了。通过上面的叙述你已经了解了我的思路,看什么都要看他的实现原理,所以直接推荐你一本书《Spring 技术内幕》然后对着自己现有的 Spring 项目 Debug,从请求的流转梳理知识点。Spring 出来这么久大家对基本的知识已经了然于胸,重要的是看其解决问题的思路和原理,栗子又来了。  比如需要实现在 Bean 刚刚初始化的时候做一些操作,是不是需要使用InitializingBean?那么具体怎么使用,它的原理是什么,Spring Bean 的生命周期是什么样子,通过具体的使用场景逐步展开说明。这样复习效果会更好一些,然后再逐步的思考每一个知识点里面涉及的更多的知识点,比如 AOP 里面的 Proxy 都是基于什么原理实现,有什么优缺点。分布式这是一个老生常谈的话题,也是这几年比较火的话题,说起分布式就一定和 Dubbo 有关系,但是不能仅仅就理解到 Dubbo。首先我们需要思考它解决的问题,为什么要引入 Dubbo 这个概念。随着业务的发展、用户量的增长,系统数量增多,调用依赖关系也变得复杂,为了确保系统高可用、高并发的要求,系统的架构也从单体时代慢慢迁移至服务SOA时代,应运而生的 Dubbo 出现了,它作为 RPC 的出现使得我们搭建微服务项目变得简单,但是我们不仅仅要思考 Dubbo带来的框架支撑。同时需要思考服务的幂等、分布式事务、服务之间的 Trace 定位、分布式日志、数据对账、重试机制等,与此同时考虑 MQ 对系统的解耦和压力的分担、数据库分布式部署和分库分表、限流、熔断等机制。所以最终总结是不仅仅要看 Dubbo 的使用、原理同时还要思考上下游和一些系统设计的问题,这块相对的知识点较多,可以针对上面抛出来的点各个击破。设计模式设计模式很多,但是常用的就几种,这个地方可以分两个地方准备。1. 学以致用,设计模式不是背出来的,而是用出来了。平时多注意思考当前项目的设计,是否可以套用设计模式,当然必须先理解每一个设计模式存在的意义。  2. 在现有框架中思考设计模式的体现,上面已经讲过框架怎么学习,用 Spring 距离,它里面用了超过9种设计模式,你都知道用到哪里了吗?如果不知道,试着把他们找出来,同时思考为什么这么设计,全部找到以后,基本的设计模式的用法和原理你也就都理解了。
最新最全的Java面试题整理内附答案
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是判断两个变量或实例所指向的内存空间的值是不是
208道最常见的Java面试题整理面试必备
适宜阅读人群需要面试的初/中/高级 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.简述分代垃圾回收器是怎么工作
最新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的小游戏类似。字符型常量和字符串常量的区别形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符含义上: 字符常量相当于一个整形值(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开发面试题整理2019春招
一、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应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当
Java开发面试题汇总整理
又是金三银四的时候,我希望这份面试题能够祝你一臂之力!自我和项目相关1、自我介绍2、你觉得自己的优点是?你觉得自己有啥缺点?3、你有哪些 offer?4、你为什么要离开上家公司?你上家公司在xxx,我们公司在xxx,离这么远为什么要选择我们这里?5、上家公司的同事和领导是怎么评价你的?6、介绍下你的上家公司是做哪块的吧7、在上家公司你做了哪些项目?8、你在项目中是什么角色?9、这个项目的数据量和并发量多大?10、这个项目用的什么技术?11、项目过程中有遇到什么很印象深刻的问题吗?12、是怎么解决的这些问题?13、项目有没有还可以继续优化的地方?14、该怎么优化?有什么思路没?15、叫你设计一个并发xxx,数据存储量xxx 量级的系统,你该如何设计?从你知道的点尽可能的多说出些?Java 基础1、Object 对象的方法有哪些?分别有什么作用?该什么场景用?2、Integer 的常量缓存池3、Java 特性?什么是多态?举个例子4、重载重写的区别?5、画下 HashMap 的结构图?HashMap 、 HashTable 和 ConcurrentHashMap 的区别?使用场景分别是?6、HashMap 中怎么解决冲突的?7、ConcurrentHashMap 和 HashTable 中线程安全的区别?为啥建议用 ConcurrentHashMap ?能把 ConcurrentHashMap 里面的实现详细的讲下吗?8、保证线程安全的还有其他的方式吗?9、讲下 Synchronized?10、讲下 ReentrantLock 可重入锁? 什么是可重入锁?为什么要设计可重入锁?11、Synchronized 和 ReentrantLock 有什么区别?这两个有没有深入了解源码?12、讲下 Volatile 吧?他是怎样做到同步的?13、Volatile 为什么不支持原子性?举个例子14、Atomic 怎么设计的?有用过里面的类吗?15、线程安全类和线程不安全的类,项目使用的时候你会怎么选择?怎么判断项目代码哪里会有线程不安全问题?16、Map、List、Set 分别说下你了解到它们有的线程安全类和线程不安全的类?17、TreeSet 清楚吗?能详细说下吗?18、ThreadLocal 了解吗?项目有用过吗?可以说说19、JUC 里面你还知道什么其他的类吗?比如 CountDownLatch、Condition20、从源码详细说下 Java 里面的线程池吧,使用线程池有什么要注意的地方?你们公司有规范吗?JVM1、JAVA 类加载器2、Java 内存结构(注:不是 Java 内存模型,别搞混)3、怎么判断对象是否可 GC?Java 对象有哪些引用类型?有什么区别?4、OOM 出现的有哪些场景?为什么会发生?5、Minor GC 和 Full GC 有什么区别?分析过 GC 日志吗?6、说下你知道的垃圾回收算法7、说下你知道的垃圾收集器8、CMS 和 G1 的区别知道吗?使用场景分别是?你项目中用的是哪个?9、你还知道哪些 JVM 调优参数?10、假如线上服务发生 OOM,有哪些措施可以找到问题?11、假如线上服务 CPU 很高该怎么做?有哪些措施可以找到问题?12、假如线上应用频繁发生 Full GC,有哪些措施可以找到问题?13、一般线上环境遇到 JVM 问题,你会使用哪些工具来分析?找到问题后又该如何去解决呢?Spring1、说下你对 Spring 生态的了解?2、说下你对 Spring AOP 和 IOC 的理解?看过实现原理吗?3、说下 Bean 在 Spring 中的生命周期?4、讲下你知道的 Spring 注解有哪些?该什么场景使用?5、Spring 事务知道吗?有了解过吗?6、说下你刚才说的 SpringBoot 吧,你觉得 SpringBoot 有什么优点?7、SpringBoot 自动化配置是怎么做的?有看过实现源码吗?8、Spring Boot 中最核心的注解 SpringBootApplication 有看过源码分析过吗?9、你的项目中 SpringBoot 用到了哪些和其他技术栈整合的?10、使用 Spring 或者 SpringBoot 有遇到过什么印象深刻的问题吗?当时是怎么解决的?数据库1、你的项目使用的是什么数据库?2、你对数据库了解多少?说下数据库的索引实现和非主键的二级索引3、说下 MySQL 的索引原理4、讲下 InnoDB 和 MyISAM 的区别?使用场景是?5、有和 ElasticSearch 的索引原理对比过吗?6、如何判断一个查询 sql 语句是否使用了索引?7、数据库事务特性和隔离级别8、项目数据库表是你设计的吗?一般要注意什么?如何考虑扩展性?9、项目 MySQL 的数据量和并发量有多大?量大后的影响有哪些,有考虑吗?SQL 调优有哪些技巧?10、说下你项目里面关于数据库印象最深的一个问题?当时是怎么解决的其他1、描述下网页一个 Http 请求到 www.54tianzhisheng.cn/,到后端的整个请求过程2、有比较过 Http 和 RPC 吗?如果叫你设计一个高性能的 Http 或者 RPC,你会从哪些方面考虑?3、项目中我看使用了 xxx (ElasticSearch、Hbase、Redis、Flink 等),有深入了解它们的原理和懂点调优技巧吗?4、项目中我看使用了 xxx (ElasticSearch、Hbase、Redis、Mysql 等),有深入了解它们数据同步是怎么做吗?5、项目中我看使用了 xxx (ElasticSearch、Hbase、Redis、Mysql 等),有深入了解它们常见的监控指标吗?6、如果叫你设计一个秒杀系统,你会从哪些方面考虑?7、如果叫你设计一个电商系统,你会从哪些方面考虑?8、如果叫你设计一个监控告警系统,你会从哪些方面考虑?总结本文的面试题以 HR & 技术官角度常问的面试题,技术方面从 Java 基础、JVM、Spring、数据库、拓展题等方面考察你,当然面试官可能还会问些其他的技术点,我一篇文章也难以概全。总的来说,还是得多准备充分,面试时灵活答辩,相信你最后能拿到满意的 offer!加油,骚年!
Mybatis面试题整理超详细
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}代表
Mybatis常考面试题汇总附答案
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对象,
史上最全Java面试题整理附参考答案
下列面试题都是在网上收集的,本人抱着学习的态度找了下参考答案,有不足的地方还请指正,更多精彩内容可以关注我的微信公众号:Java团长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,Doubleclass AutoUnboxingTest {public static void main(String[] args) {Integer a = new Integer(3);Integer b = 3; // 将3自动装箱成Integer类型int c = 3;System.out.println(a == b); // false 两个引用没有引用同一对象System.out.println(a == c); // true a自动拆箱成int类型再和c比较}}最近还遇到一个面试题,也是和自动装箱和拆箱有点关系的,代码如下所示:public class Test03 {public static void main(String[] args) {Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;System.out.println(f1 == f2);System.out.println(f3 == f4);}}如果不明就里很容易认为两个输出要么都是true要么都是false。首先需要注意的是f1、f2、f3、f4四个变量都是Integer对象引用,所以下面的==运算比较的不是值而是引用。装箱的本质是什么呢?当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,如果看看valueOf的源代码就知道发生了什么。public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}IntegerCache是Integer的内部类,其代码如下所示:/*** Cache to support the object identity semantics of autoboxing for values between* -128 and 127 (inclusive) as required by JLS.** The cache is initialized on first usage. The size of the cache* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.* During VM initialization, java.lang.Integer.IntegerCache.high property* may be set and saved in the private system properties in the* sun.misc.VM class.*/private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}}简单的说,如果整型字面量的值在-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的启动参数来进行调整,栈空间用光了会引发StackOverflowError,而堆和常量池空间不足则会引发OutOfMemoryError。String str = new String("hello");上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而"hello"这个字面量是放在方法区的。补充1:较新版本的Java(从Java 6的某个更新开始)中,由于JIT编译器的发展和"逃逸分析"技术的逐渐成熟,栈上分配、标量替换等优化技术使得对象一定分配在堆上这件事情已经变得不那么绝对了。补充2:运行时常量池相当于Class文件常量池具有动态性,Java语言并不要求常量一定只有编译期间才能产生,运行期间也可以将新的常量放入池中,String类的intern()方法就是这样的。看看下面代码的执行结果是什么并且比较一下Java 7以前和以后的运行结果是否一致。String s1 = new StringBuilder("go").append("od").toString();System.out.println(s1.intern() == s1);String s2 = new StringBuilder("ja").append("va").toString();System.out.println(s2.intern() == s2);10、Math.round(11.5) 等于多少?Math