-----------------------------面试补充---------------------------------------
Java内存结构:堆,栈,方法区
Java后台开发面试知识汇总:https://uploadfiles.nowcoder.com/images/20180914/826546_1536916757441_FF474C03D9D513A3519773CB35561940
全局变量:堆
静态变量:方法区
临时变量:栈
堆大小由1/3新生代和2/3老生代构成,新生代又细分成一块eden和2块survivor区域
垃圾回收算法共4钟:MS(标记清除),CP(复制),MC(标记整理)GC(分代收集)【最常见】
垃圾收集器:Serial,parnew(Serial多线程版本),Parallel,G1
参考链接: https://blog.csdn.net/yrwan95/article/details/82829186
--------------------------------------------------------------------------------
一:对Java平台理解,“Java是解释执行”,这句话正确吗?:
Java平台特点: 1.跨平台,即书写一次,到处运行 2.垃圾回收,即通过GC回收分配内存,程序员不用担心内存分配问题 Java包括: JRE运行环境(包括JVM和Java类库,JVM提供JIT编译器,JIT就是编译执行) JDK(JRE超集,包含了更多东西,比如编译器,诊断工具等)
二:请对比Exception和Error,另外,运行时异常与一般异常有什么区别?NoClassDefFoundError和ClassNotFoundException有什么区别?
Exception和Error都继承Throwable类
Exception即可预料的错误,要被try,catch捕获
Error即不太可能出现的错误(OutMemoryError),不用try,catch捕获
Exception分为检查异常(需显示捕获)与不检查异常(运行异常,捕获与否看实际情况)
ClassNotFoundException:检查异常,找不到class报错(比如连接jdbc时候驱动放错位置)
NoClassDefFoundError:编译成功后找不到class报错(比如没有new 某个实例)
三:谈谈final、fnally、 fnalize有什么不同?
final:表示修饰的类不可继承,方法不可重写,变量不可修改 finally:try,catch,finally后面代码一定会执行 finalize:垃圾回收用到
//finally不会被执行的特例 try { System.exit(1); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { System.out.println("Test fianlly"); }
四:强引用、软引用、弱引用、幻象引用有什么区别?具体使用场景是什么?
强引用:普通new对象(str在栈,String对象实例在堆),不会被jvm回收
软应用(与引用队列一起使用):jvm认为内存不足会回收(类似缓存)
弱引用(与引用队列一起使用):GC发现即回收
幻象引用(虚引用,与引用队列一起使用):不能访问对象.
五:Java的字符串,String、StringBufer、StringBuilder有什么区别?
String:字符串常量
StringBuffer:字符串变量(线程安全)
StringBuilder:字符串变量(非线程安全)
(String改变内容就要新生成一个String对象,消耗内存,而Stringffer是用来字符串拼接用的,更换值不用新生成对象,StringBuilder是Java1.5新增,与StringBuffer没有本质区别,但是取消了线程安全,减少了开支,所以优先级是如下这样)
StringBuilder>StringBuffer>String
1 package Test; 2 3 import java.util.Scanner; 4 5 /** 6 * @author Empirefree 胡宇乔: 7 * @version 创建时间:2020年3月20日 上午9:30:15 8 */ 9 public class Main { 10 public static void main(String[] args) { 11 StringBuilder stringBuilder = new StringBuilder("牛逼哄哄"); 12 stringBuilder.append("陈牛逼哄哄"); 13 stringBuilder.append("余牛逼哄哄"); 14 stringBuilder.insert(0, "黄牛逼哄哄"); 15 16 stringBuilder.delete(0, 1); 17 stringBuilder.replace(0, 1, " Q"); 18 String str = stringBuilder.toString(); 19 System.out.println(stringBuilder); 20 System.out.println(str); 21 22 } 23 }
六:谈谈Java反射机制,动态代理是基于什么原理?
反射机制:正射:new对象,反射广泛应用于框架,Java基础功能,赋予程序运行时自省能力,可以利用反射直接操作类和对象
动态代理:方便运行时的动态构建代理,即原理就是反射机制,例子有AOP编程,
七:int和Integer有什么区别?谈谈Integer的值缓存范围。
int:原始数据类型 Integer:是int的包装类,可以在字符串,int转换等,自动装箱,自动拆箱
八:对比Vector、ArrayList、LinkedList有何区别?
vector:线程安全的动态数组
ArrayList:非线程安全的动态数组
LinkedList:非线程安全双向链表
九:对比Hashtable、HashMap、TreeMap有什么不同?
Hashtable:哈希表 HashMap:更广泛的哈希表,但是非同步,get,put时间复杂度是O(1) TreeMap:底层是红黑树,get,put时间复杂度是O(log(n))
十:如何保证容器是线程安全的?ConcurrentHashMap如何实现高效地线程安全?
利用同步容器实现(如Hashtable【只是给put,get加上synchronized,不能并发】)还有同步包装器(如Collection.synchronized) 后来采用并发容器(ConcurrentHashMap基于分离锁的并发实现),线程安全队列等
十一:Java提供了哪些IO方式? NIO如何实现多路复用?
早期传统的java.io包,提供了一些IO功能
后来引入NIO,NIO2,BIO方式,NIO是同步非阻塞IO,即Channel准备好后/处理完后(同步),线程才会进行处理(不会傻傻等待,即非阻塞)
多路复用由Channel,Selector,Buffer构成,主要过程是每个SelectChannel向Select注册,然后Select进行选择,避免大量客户连接时,频繁切换线程
1 package testio; 2 /** 3 * @author Empirefree 胡宇乔: 4 * @version 创建时间:2020年3月29日 下午7:46:01 5 */ 6 7 import java.io.BufferedReader; 8 import java.io.IOException; 9 import java.io.InputStreamReader; 10 import java.io.PrintWriter; 11 import java.net.InetAddress; 12 import java.net.ServerSocket; 13 import java.net.Socket; 14 import java.util.concurrent.ExecutorService; 15 import java.util.concurrent.Executors; 16 17 public class DemoServer extends Thread { 18 19 private ServerSocket serverSocket; 20 public int getPort() { 21 return serverSocket.getLocalPort(); 22 } 23 public void run() { 24 try { 25 serverSocket = new ServerSocket(0); 26 ExecutorService executor = Executors.newFixedThreadPool(8); //新建立线程池 27 while (true) { 28 Socket socket = serverSocket.accept(); 29 RequesHandler requesHandler = new RequesHandler(socket); 30 // requesHandler.start(); 31 executor.execute(requesHandler); //存储client线程 32 } 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } finally { 36 if (serverSocket != null) { 37 try { 38 serverSocket.close(); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 }; 42 } 43 } 44 } 45 public static void main(String[] args) throws IOException { 46 DemoServer server = new DemoServer(); 47 server.start(); 48 try (Socket client = new Socket(InetAddress.getLocalHost(), server.getPort())) { 49 BufferedReader buferedReader = new BufferedReader(new InputStreamReader(client.getInputStream())); 50 buferedReader.lines().forEach(s -> System.out.println(s)); 51 } 52 } 53 54 class RequesHandler extends Thread{ 55 private Socket socket; 56 public RequesHandler(Socket socket) { 57 // TODO Auto-generated constructor stub 58 this.socket = socket; 59 } 60 61 @Override 62 public void run() { 63 // TODO Auto-generated method stub 64 try (PrintWriter out = new PrintWriter(socket.getOutputStream());){ 65 out.println("Hello, NIO"); 66 out.flush(); 67 } catch (Exception e) { 68 // TODO: handle exception 69 e.printStackTrace(); 70 } 71 } 72 } 73 74 }
1 package testio; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 /** 7 * @author Empirefree 胡宇乔: 8 * @version 创建时间:2020年3月29日 下午7:57:21 9 */ 10 class Empirefree extends Thread{ 11 @Override 12 public void run() { 13 // TODO Auto-generated method stub 14 System.out.println(Thread.currentThread().getName() + "正在执行中...."); 15 } 16 } 17 18 public class Demothreadpool { 19 20 //测试下threadpool 21 public static void main(String[] args) { 22 ExecutorService pool = Executors.newFixedThreadPool(2); //固定,Cache是可变线程池 23 Thread t1 = new Empirefree(); 24 Thread t2 = new Empirefree(); 25 Thread t3 = new Empirefree(); 26 Thread t4 = new Empirefree(); 27 Thread t5 = new Empirefree(); 28 pool.execute(t1); 29 pool.execute(t2); 30 pool.execute(t3); 31 pool.execute(t4); 32 pool.execute(t5); 33 //关闭线程池 34 pool.shutdown(); 35 36 37 System.out.println("----------------------"); 38 Father father = new Son(); 39 father.name(); //先调用父类构造,再调用子类构造,只能使用父类继承过来的函数,继承的函数是子类的.... 40 System.out.println("----------------------"); 41 Son son = new Son(); 42 son.name(); 43 son.test(); 44 } 45 } 46 47 class Father{ 48 public Father() { 49 // TODO Auto-generated constructor stub 50 System.out.println("父类....."); 51 } 52 public void name() { 53 System.out.println("陈牛逼哄哄...."); 54 } 55 } 56 class Son extends Father{ 57 public Son() { 58 // TODO Auto-generated constructor stub 59 System.out.println("子类 ...."); 60 } 61 public void name() { 62 System.out.println("余牛逼哄哄...."); 63 } 64 public void test() { 65 System.out.println("你能调用这个方法吗?...."); 66 } 67 }
十二:Java有几种文件拷贝方式?哪一种最高效
常见的java.io中FIleInputStream读取,
然后还有java.nio中的transferTo或transferFrom(速度快,更加利用了现代操作系统的底层机制,避免了不必要copy和上下万切换)
package runoob; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; /** * @author Empirefree 胡宇乔: * @version 创建时间:2020年3月30日 下午9:16:08 */ public class StreamFileIo { public static void main(String[] args) throws IOException{ File source = new File("./test.txt"); File dest = new File("./newtest.txt"); try(FileChannel sourceChannel = new FileInputStream(source).getChannel(); FileChannel targetChannel = new FileOutputStream(dest).getChannel(); ){ for(long count = sourceChannel.size(); count > 0;){ long transferred = sourceChannel.transferTo(sourceChannel.position(), count, targetChannel); sourceChannel.position(sourceChannel.position() + transferred); count -= transferred; } } } }
十三:接口和抽象类有什么区别?
接口:不能实例化,是抽象方法的集合,不能有非常量成员,要么是抽象方法,要么是静态方法
(抽象方法,父类不知道实现某个功能,定义给抽象方法,给不同子类去定义)
抽象类:不能实例化,也是为了代码重用,共用方法或者成员变量就合成抽象类
十四:谈谈你知道的设计模式?请手动实现单例模式,Spring等框架中使用了哪些模式?
创建型模式:工厂模式,单例模式等 结构性型模式:桥接模式,适配器模式 行为型模式:策略模式,访问者模式 单例模式 public class Singleton{ private static Singleton instace; private Singleton(){} private static Singleton getInstace(){ if(instace == null) instace = new singleton(); return instace; } } Spring中的模式 BeanFactor和ApplicationContext应用了工厂模式 AOP:代理模式,适配器模式等 Bean创建:提供的单例和原型等模式。
十五: synchronized和ReentrantLock有什么区别?有人说synchronized最慢,这话靠谱吗?
synchronized:java内建的同步机制,保证了线程的互斥访问
ReentrantLock:再入锁,需要unlock()方法释放,不然就会一直占有该锁,然后可以定义条件,控制公平性
不靠谱,synchronized早期在不同场景下性能不一样,但是后来不断改进后性能优化了
十六:synchronized底层如何实现?什么是锁的升级、降级?
synchroinzed:由一对monitorenter/monitorexit指令实现 升级、降级:就是jvm优化synchronized运行的机制当jvm检查到不同的竞争状况时,就会自动切换到适合的锁。 没有竞争->默认是偏斜锁 有另外线程试图锁定某个偏斜过的对象->轻量级锁(轻量级锁依赖CAS获得锁失败->重量级锁)
十七:一个线程两次调用start()方法会出现什么情况?谈谈线程的生命周期和状态转移。
抛出出IllegalThreadStateException运行时异常 列出6种(线程是系统调度的最小单位) new(新建), runnable(就绪),blocked(阻塞),waiting(等待),timed_wait(计时等待),terminated(计时等待)
十八:什么情况下Java程序会产生死锁?如何定位、修复?
死锁:一种特定的程序状态,两个或多个线程之前,互相持有对方资源而不肯释放而造成永久阻塞状态
jstack(查看线程),jmap(查看内存),jstat(性能分析)