Java基础

151 阅读7分钟

Java

1.  java语言有什么特性,继承有什么用处,多态有什么用处

答:java有八大特性:

  1. 面向对象语言,具备抽象、封装、继承、多态特性。
  2. 平台无关性,jvm屏蔽了操作系统差异,使得java语言通过字节码在不同操作系统的jvm上被差异化解释,实现java语言的平台无关性。
  3. 解释型语言,不同于C++、C语言,编译生成针对CPU的机器码,java语言编译生成字节码,会按句翻译执行。在jit即使编译技术加持下,可以将字节码转化成高效的本地机器码,提高执行效率。
  4. 多线程,java内置多线程支持,比C++语言更加方便,不需要调用操作系统多线程功能接口即可完成程序设计。
  5. 安全,java小程序运行在java环境中,不允许它访问计算机的其他部分。
  6. 动态编译,由于java类来自于开发者编写、类库引入,类是动态加载的,可以在分布式环境中动态地维护程序和类库,不用像C++,每次类库升级需要重新编译整个程序。   继承的作用:很方便地复用代码+不破坏现有代码的结构和功能。多态的用处:分离做什么和怎么做,进一步分离接口和实现。不仅可以改善代码组织结构和可读性,而且可扩展性也很强。

 

2.  反射是什么,在哪里用到,怎么利用反射创建一个对象

定义:在运行期间打开和检查java类,并提供获取方法、构造器和字段的接口的类库,在跨网络远程调用、基于RAD可视化编程中用到;

反射获取对象:根据class名称获取类字节码对象,通过newInstance()调用无参构造器;getConstructor获取有参构造器,并完成对象构造。

1. Class<?> cls = Class.forName("class.name"); 
   Object obj = cls.newInstance();

2. Class<?> cls = Class.forName("class.name"); 
   Construct<?> con = cls.getConstructor(String.class,String.class); 
   Object obj = con.newInstance(str1,str2);

 

3.  对象加载的过程,属性先加载还是方法先加载

1. 规律

  1. 静态属性和代码块,跨类高优先级;
  2. 非静态属性和代码块同类中优先级高于构造函数;
  3. 静态和非静态的属性和代码块的加载顺序,同对应的定义顺序。

2. 结果

  1. 父类静态属性 (可以是对象) 和静态代码块,看其在类中的先后顺序
  2. 子类静态属性和静态代码块 ,看其在类中的先后顺序
  3. 父类非静态属性和非静态代码块 ,看其在类中的先后顺序
  4. 父类构造方法
  5. 子类非静态属性和非静态代码块 ,看其在类中的先后顺序
  6. 子类构造方法  

4.  垃圾回收机制与jvm结构

类加载: java虚拟机是由启动类加载器加载的,负责执行java程序;java类加载器的结构:启动类加载器-->扩展类加载器-->应用程序类加载器-->用户自动定义加载器,满足双亲委派原则,保护java核心库类不被轻易篡改、避免类重复加载。

image.png java类实例相同的判断:1.相同的类路径 2.同一个类加载器(避免不同虚拟机加载同一个class文件的情况)

 

内存结构:

image.png 本地方法栈

1.     线程私有

2.     存储的是本地方法的栈帧


程序计数器

1.     线程私有

2.     当前线程所执行的字节码的指示器,

3.     Java方法:存储的字节码指令地址;native方法,计数器值为空。

4.     唯一没有oom异常的数据区,因为只需要存储下一条指令地址,不会存在空间扩张。


方法区

1.     线程共享

2.     存储加载的类信息、常量池、静态变量

 

线程栈

1.  线程私有

2.  保存方法执行的栈帧

3.  栈帧存储了方法的局部变量表、操作数栈、动态链接和方法返回地址

image.png

1. 线程共享

2. 存储对象实例

3. 物理空间可以不连续

4. 堆中的代划分

image.png

可达性分析:由GC root(线程栈中的对象、方法区的静态对象和常量对象、本地方法区对象)开始,寻找所持有的引用节点,不可达的对象需要回收。

拷贝复制:新生代的minor GC采用本方式,对象中存活率低,只需要进行少量对象复制即可完成垃圾回收;缺点是需要牺牲一部分存储开销。优点是:效率高,且没有空间间隙产生。

标记删除/整理:老年代FullGC采用此方法,持续存活的对象,采用复制方式成本很高。

Eden满了,会进入survivor区进行迭代(复制算法),达到迭代的阈值没销毁的对象,会进入老年区,老年区无法放入,进行FullGC(标记—整理算法)。永久代放置静态变量和常量、类信息等。

数据结构

hashMap

1. 结构

数组+链表组成,数组中存储Node节点,ArrayList,Node节点中存储hash、key、Value、Node成员。 image.png

2. 扩容规则

  • Capacity:HashMap长度。
  • LoadFactor:负载因子,默认0.75f,控制数据密度或作为扩容阈值。 当数据总量达到负载因子密度时,则需要进行扩容。

3. 链表插入方式:尾插法,保证转换为红黑树时,不会出现循环指针;hash规则,(length-1)& key;

4. 红黑树:引入原因,hash冲突过多时,链表查询效率过低;不用二叉树,不需要过多的平衡,红黑树最多三次自旋调节。

5. 链表和红黑树转换:- TREEIFY_THRESHOLD8 桶中数据数量 MIN_TREEIFY_CAPACITY64元素总量,都超过阈值时,进行数据结构升级;同时,当节点个数小于UNTREEIFY_THRESHOLD6,降级为链表

TreeMap

1.结构

private transient Entry<K,V> root,实际是红黑树。

2. 和hashMap比较区别

  1. 数据存储是有序的
  2. 不允许有null值的key
  3. 因为hashMap底层是Array,添加、查找、删除方法上效率更高,treeMap更慢
  4. 不需要额外的数组开销,空间上更省
  5. hashMap存在hash冲突,但是java 8后支持treeNode转换效率有很大提升。
  6. treeMap添加节点和删除节点会有自旋调整,对性能有一定影响。

3. 和hashMap的共同点

  1. 都不允许key重复
  2. 两者都是线程不安全的

多线程

1. 多线程安全保障机制

  1. 使用线程安全的类
  2. 使用synchronized锁、Lock锁
  3. 多线程并发情况下,线程共享的变量改为方法局部级变量。

2. 线程池

线程池任务创建流程.jpg

拒绝策略

  • AbortPolicy(抛出异常,default)

  • DiscardPolicy(丢弃任务)

  • DiscardOldestPolicy(Queue队列出队一个,将当前这个任务继续提交给线程池)

  • CallerRunsPolicy(交给线程池调用所在的线程进行处理)

runnable执行异常处理

  1. try-catch捕获异常
  2. submit执行任务,从返回的Future对象,调用get方法捕获异常
  3. 重新poolexcutor.afterExcue方法,处理传递的异常引用
  4. 线程工厂中,对线程设置

1. newCachedThreadPool (并发执行大量短期的小任务)

可缓存线程池:不固定线程数量,且支持最大为Integer.MAX_VALUE的线程数量。

ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                60L, TimeUnit.SECONDS,
                                new SynchronousQueue<Runnable>())
  1. 线程数无限制。
  2. 有空闲线程则复用空闲线程,若无空闲线程则新建线程。
  3. 一定程度减少频繁创建/销毁线程,减少系统开销。

2. newFixedThreadPool (CPU密集型的耗时任务)

定长线程池:一个固定线程数量的线程池。

ThreadPoolExecutor(nThreads, nThreads,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>(),
                                threadFactory);
  1. 可控制线程最大并发数(同时执行的线程数),核心线程数和最大线程数相等。
  2. 配置无界阻塞队列,超出的线程会在队列中等待。

3. newSingleThreadExecutor (串行执行任务)

单线程的线程池:一个固定线程数量的线程池。

new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()))
  1. 有且仅有一个工作线程执行任务。
  2. 所有任务按照指定顺序执行,即FIFO规则。
  3. FinalizableDelegatedExecutorService类实现了finalize方法,在JVM垃圾回收的时候会关闭线程池。

4. newScheduledThreadPool (周期性执行任务且限制线程数量)

定时任务的线程池:定时周期性执行任务。

ScheduledThreadPoolExecutor(corePoolSize);