Offer

Java核心技术---学习笔记【更新中....】

-----------------------------面试补充---------------------------------------

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保证线程安全:

  • 原子性:互斥访问
  • 可见性:volatile线程对内存的修改能被其他线程看到
  • 有序性:一个线程观察其他线程指令的执行顺序

 

--------------------------------------------------------------------------------

 

一:对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:表示修饰的类不可继承,方法不可重写,变量不可修改
finallytry,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(性能分析)

 

posted @ 2020-05-28 22:33  Empirefree  阅读(247)  评论(0编辑  收藏  举报