最近想督促自己在做码农的同时增加自己的知识储备;所以开了一个专题,也算一个笔记;主要从各大牛人博客和一些资料中总结一些比价常见的面试题;
1.谈谈你对Java平台的理解;“Java是解释执行”,这句话对吗?
回答:
1.Java本身是一种面向对象的语言;有最显著的两个方面:1:一次编译,到处运行;2.有自己的回收机制(GC)。
我们日常接触到JRE,JDK也就是Java环境,包含了很多JVM和Java类库,以及一些模块。而JDK包含了JRE,同时也提供了很多工具,,比如编译器等等。Java能一次编译,到处运行的前提是JVM,因为Java提供了不同平台的JVM,所以能做到一次编译,到处运行。
2.Java不是解释执行的语言,应该说并不全是。一个Java程序写出来后,编译器首先会将Java代码转换成(通过Javac)字节码文件,然后JVM内嵌的解释器会将字节码文件转换成计算机看得懂的机器码,让我们的程序跑起来。但是在常见的JVM中,比如说Oracle JDK提供的JVM,JIT(Just-In-Time)编译器,能够将热点代码编译成机器码,这种属于编译执行,而不是解释执行。也就是说,JIT编译的这一段代码直接是转成了机器码,而不是先转成.class代码,再让JVM去解析成机器码。
知识拓展:
1.在我们回答这个问题的时候,可以加上Java语言面向对象的三大特性,和一些Lambda等语言特性。包含了一些基础的类库,比如IO,NIO,网络等等;
2.或者可以谈一下虚拟机;
关于JIT知识点链接
知识点链接:https://www.cnblogs.com/insistence/p/5901457.html
2.Exception和Error有什么区别;运行时异常和一般异常有什么区别
回答:Exception和Error都继承了Throwable类;
- Exception:Exception分为检查异常和不检查异常;可检查异常要在我们编写代码的时候显示地进行捕获和处理。这在我们写代码的时候,编译器会提醒我们;不检查异常则是在我们程序运行的时候会抛出的异常;比如我们常见的NullPointerException,ArrayIndexOutOfBoundsException;这类异常通常是我们的逻辑出错。
- Error:是指在正常情况下,不太可能出现的错误。比如常见OutOfMemoryError之类的
知识拓展:
NoClassDefFoundError和ClassNOtFoundException两种异常有什么区别?
回答:
1.从两个异常的命名我们可以看出来,这两个异常应该是发生在不同阶段,一个是Error,一个是Exception;那么NoClassDefFoundError应该是发生在JVM阶段,而ClassNOtFoundException应该是发生在编译阶段。
2.ClassNotFoundException发生的原因:
当我们使用Class.forName方法动态加载类的时候,我们是需要指定类的路径在哪的;如果编译器没找到这个类,就会出现ClassNotFoundException;这时候我们就要检查一下,自己的类名有没有写错;还有一种情况就是,A类已经将某个类加载到内存里面了,B类也要尝试动态地去加载这个类,这个时候也会出现ClassNotFoundException。这个时候我们就要去控制一下动态加载类的顺序
3.NoClassDefFoundError发生的原因:
当JVM尝试从我们已经编译好的.class文件解释成机器码的时候,或者ClassLoader实例尝试加载类的时候却发现找不到这个类了。就会导致NoClassDefFoundError这种错误的出现。
造成中问题的原因可能是打包过程中这个类丢失了
知识点链接:https://blog.csdn.net/wdw131409/article/details/78316919
3.final,finally,finalize;
这三个玩意压根就没什么联系,之所以会用来做经典的面试题,应该是因为他们长的有点像。
final:常用来修饰类,变量,方法;被修饰的类为final的话,将不可以继承,修饰变量的话则该变量不可以被修改,final方法则不可以被覆盖
finally:是保证重点代码一定会被执行的一种机制。可以使用finally块,来关闭数据库连接等等。
finalize:保证对象在被垃圾收集前完成特定资源的回收。
4.String,StringBuilder,StringBuffer有什么区别
String是Java语言中非常基础和重要的类,提供了构造和管理字符串的各种基本逻辑。我们实际开发中对字符串的操作也占了大多数。String是典型的Immutable(不可变)类,被声明final class,所有的属性也是final的。也由于它的不可变性,类似拼接字符串等一些动作,都会产生新的String对象。其运行机制是:创建一个字符串的时候,首先检查常量池中是否有相同的字符串,有的话则直接返回查到的对象的引用。如果没有则创建新的串,然后返回对象的引用,并将新的对象放入池中。而通过new方式的创建String对象,是不检查常量池的直接在堆里创建一个对象。
String a = "AB";//会放进常量池
String b = new String("AB");//放入非常量池
System.out.println(a == b);//false
注意:String提供了inter()方法。调用该方法时,如果常量池中包括了一个等于此String对象的字符串(由equals方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并且返回此池中对象的引用。
String c = a.iner();
System.out.println(a == c);//true
总结:
String的特性
- 不可变性;不可变的主要作用在于当一个对象需要被多线程共享,并且访问频繁时,可以省略同步和锁等待的时间,从而大幅度提高系统性能。不可变模式是一个可以提高多线程程序的性能,降低多线程程序复杂度的设计模式。因此,当我们考虑一个对象的线程安全性的时候,可以直接将这个类设计为final。
- 常量池。当2个String对象拥有相同的值时,他们只引用常量池中的同一个拷贝。
StringBuilder是为了解决String字符串拼接,从而产生很多新对象的问题而产生的一个类。我们可以用append方法,直接拼接字符串。
StringBuffer本质是一个线程安全的可修改字符序列,StringBuffer类中方法定义前面都会有synchronize关键字。为此,StringBuffer的性能要远低于StringBuilder。保证了线程安全。同时也会带来了一些开销。除非有线程安全的需要,不然还是推荐使用StringBuilder
知识拓展
应用场景:
1.在字符串内容不经常发生变化的业务场景优先使用String类。例如:常量声明、少量的字符串拼接操作等。如果有大量的字符串内容拼接,避免使用String与String之间的“+”操作,因为这样会产生大量无用的中间对象,耗费空间且执行效率低下(新建对象、回收对象花费大量时间)。
2.在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在多线程环境下,建议使用StringBuffer,例如XML解析、HTTP参数解析与封装。
3.在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在单线程环境下,建议使用StringBuilder,例如SQL语句拼装、JSON封装等。
参考:
公号:Java大后端
网友评论