61.什么是并发修改异常?java
什么是并发修改异常: 当咱们在遍历实现了collection接口 与iterator接口的集合时(List、Set、Map), 咱们能够经过遍历索引 也能够经过迭代器进行遍历。 在咱们使用迭代器进行遍历集合的时候, 会获取到当前集合的迭代对象。 在里面有封装了迭代器的remove方法 与集合自带的remove方法, 若是咱们调用迭代器对象的remove方法 是没问题的, 可是当咱们调用集合自带的remove方法时, 就会产生ConcurrentModificationException 并发修改异常。 也就是说, 当咱们经过迭代器进行遍历集合的时候, 是不容许集合自己在结构上发生变化的。
62.什么是CopyOnWriteArrayList,它与ArrayList有何不一样?程序员
CopyOnWriteArrayList: CopyOnWriteArrayList这是一个 ArrayList的线程安全的变体, 其原理大概能够通俗的理解为: 初始化的时候只有一个容器, 很常一段时间, 这个容器数据、 数量等没有发生变化的时候, 你们(多个线程),都是读取 假设这段时间里只发生读取的操做 同一个容器中的数据, 因此这样你们读到的数据都是 惟1、一致、安全的, 可是后来有人往里面增长了一个数据, 这个时候CopyOnWriteArrayList 底层实现 添加的原理是先copy出一个容器 能够简称副本, 再往新的容器里添加这个新的数据, 最后把新的容器的引用地址 赋值给了以前那个旧的的容器地址, 可是在添加这个数据的期间, 其余线程若是要去读取数据, 仍然是读取到旧的容器里的数据。 Vector ArrayList CopyOnWriteArrayList 这三个集合类都继承List接口 一、ArrayList是线程不安全的; 二、Vector是比较古老的线程安全的, 但性能不行; 三、CopyOnWriteArrayList在兼顾了 线程安全的同时, 又提升了并发性, 性能比Vector有很多提升
63.迭代器和枚举之间的区别?面试
在Java集合中, 咱们一般都经过 “Iterator(迭代器)” 或 “Enumeration(枚举类)” 去遍历集合。 Enumeration是一个接口,它的源码以下: package java.util; public interface Enumeration<E> { boolean hasMoreElements() E nextElement(); } Iterator也是一个接口,它的源码以下: package java.util; public interface Iterator<E> { boolean hasNext(); E next(); void remove(); } 区别: 1 函数接口不一样 Enumeration只有2个函数接口。 经过Enumeration, 咱们只能读取集合的数据, 而不能对数据进行修改。 Iterator只有3个函数接口。 Iterator除了能读取集合的数据以外, 也能数据进行删除操做。 2.Iterator支持fail-fast机制,而Enumeration不支持。 Enumeration 是JDK 1.0添加的接口。 使用到它的函数包括Vector、Hashtable等类, 这些类都是JDK 1.0中加入的, Enumeration存在的目的 就是为它们提供遍历接口。 Enumeration自己并无支持同步, 而在Vector、Hashtable实现Enumeration时, 添加了同步。 而Iterator 是JDK 1.2才添加的接口, 它也是为了HashMap、ArrayList等集合 提供遍历接口。 Iterator是支持fail-fast机制的: 当多个线程对同一个集合的内容进行操做时, 就可能会产生fail-fast事件。 Java API规范建议, 对于较新的程序, Iterator应优先于Enumeration, 由于“ Iterator在Java集合框架中 代替Enumeration。” 64.Hashmap如何同步? 一、使用 synchronized 关键字, 这也是最原始的方法。 synchronized(anObject) { value = map.get(key); } 二、使用 JDK1.5 提供的锁 Java.util.concurrent.locks.Lock lock.lock(); value = map.get(key); lock.unlock(); 3.可使用 JDK1.5 提供的读写锁 java.util.concurrent.locks.ReadWriteLock rwlock.readLock().lock(); value = map.get(key); rwlock.readLock().unlock(); 4.使用 JDK1.5 提供的 java.util.concurrent.ConcurrentHashMap 类 该类将 Map 的存储空间分为若干块, 每块拥有本身的锁, 大大减小了多个线程 争夺同一个锁的状况 value = map.get(key); 一、不一样步确实最快,与预期一致。 二、四种同步方式中, ConcurrentHashMap 是最快的, 接近不一样步的状况。 三、synchronized 关键字很是慢 四、使用读写锁的读锁,比普通所稍慢。 一、若是 ConcurrentHashMap 够用, 则使用 ConcurrentHashMap。 二、若是需本身实现同步, 则使用 JDK1.5 提供的锁机制, 避免使用 synchronized 关键字。
65.IdentityHashMap和HashMap的区别?编程
前者比较key时是 “引用相等” 然后者是 “对象相等”, 即对于 k1和k2,当k1==k2时, IdentityHashMap认为两个key相等, 而HashMap只有在k1.equals(k2) == true 时 才会认为两个key相等。 2.IdentityHashMap 容许使用null做为key和value. 不保证任何Key-value对的之间的顺序, 更不能保证他们的顺序 随时间的推移不会发生变化。 3.IdentityHashMap有其特殊用途, 好比序列化或者深度复制。或 者记录对象代理。 举个例子, jvm中的全部对象都是独一无二的, 哪怕两个对象是同一个class的对象 并且两个对象的数据彻底相同, 对于jvm来讲, 他们也是彻底不一样的, 若是要用一个map来记录这样jvm中的对象, 你就须要用IdentityHashMap, 而不能使用其余Map实现
66.如何获取某个日期是当月的最后一天?后端
import java.util.Calendar; public class Test { public static void main(String[] args) { System.out.println(daysCount(2010, 2)); } public static int daysCount(int year, int month) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR, year); cal.set(Calendar.MONTH, month); cal.set(Calendar.DATE, 0); return cal.get(Calendar.DATE); } }
67.java中会存在内存泄漏吗,请简单描述缓存
所谓内存泄露就是指 一个再也不被程序使用的对象或变量 一直被占据在内存中。 Java中有垃圾回收机制, 它能够保证一对象再也不被引用的时候, 即对象编程了孤儿的时候, 对象将自动被垃圾回收器 从内存中清除掉。 因为Java 使用有向图的方式 进行垃圾回收管理, 能够消除引用循环的问题, 例若有两个对象,相互引用, 只要它们和根进程不可达的, 那么GC也是能够回收它们的。 java中的内存泄露的状况: 长生命周期的对象持有 短生命周期对象的引用 就极可能发生内存泄露, 尽管短生命周期对象已经再也不须要, 可是由于长生命周期对象 持有它的引用而致使不能被回收, 这就是java中内存泄露的发生场景, 通俗地说, 就是程序员可能建立了一个对象, 之后一直再也不使用这个对象, 这个对象却一直被引用, 即这个对象无用 可是却没法被垃圾回收器回收的, 这就是java中可能出现 内存泄露的状况, 例如,缓存系统, 咱们加载了一个对象放在缓存中(例如放在一个全局map对象中), 而后一直再也不使用它, 这个对象一直被缓存引用, 但却再也不被使用。 检查java中的内存泄露, 必定要让程序将各类分支状况 都完整执行到程序结束, 而后看某个对象是否被使用过, 若是没有, 则才能断定这个对象属于内存泄露。 若是一个外部类的实例对象的方法 返回了一个内部类的实例对象, 这个内部类对象被长期引用了, 即便那个外部类实例对象再也不被使用, 但因为内部类持久外部类的实例对象, 这个外部类对象将不会被垃圾回收, 这也会形成内存泄露。 内存泄露的另一种状况: 当一个对象被存储进HashSet集合中之后, 就不能修改这个对象中的 那些参与计算哈希值的字段了, 不然,对象修改后的哈希值 与最初存储进HashSet集合中时的哈希值 就不一样了, 在这种状况下, 即便在contains方法使用该对象的 当前引用做为的参数去HashSet集合中 检索对象, 也将返回找不到对象的结果, 这也会致使没法从HashSet集合中 单独删除当前对象, 形成内存泄露 68.java中实现多态的机制是什么? 靠的是父类或接口的 引用指向子类或实现类的对象, 调用的方法是内存中 正在运行的那个对象的方法。 Java实现多态有三个必要条件: 继承、 重写、 向上转型。 继承: 在多态中必须存在 有继承关系的子类和父类。 重写: 子类对父类中某些方法进行从新定义, 在调用这些方法时 就会调用子类的方法。 向上转型: 在多态中须要将子类的引用 赋给父类对象, 只有这样该引用才可以具有 技能调用父类的方法和子类的方法。 只有知足了上述三个条件, 咱们才可以在同一个继承结构中 使用统一的逻辑实现代码处理不一样的对象, 从而达到执行不一样的行为。 多态机制遵循的原则归纳为 当超类对象引用变量引用子类对象时, 被引用对象的类型 而不是引用变量的类型 决定了调用谁的成员方法, 可是这个被调用的方法 必须是在超类中定义过的, 也就是说被子类覆盖的方法, 可是它仍然要根据继承链中 方法调用的优先级来确认方法, 该优先级为: this.method(O)、 super.method(O)、 this.method((super)O)、 super.method((super)O)。
68.java中实现多态的机制是什么?安全
靠的是父类或接口的 引用指向子类或实现类的对象, 调用的方法是内存中 正在运行的那个对象的方法。 Java实现多态有三个必要条件: 继承、 重写、 向上转型。 继承: 在多态中必须存在 有继承关系的子类和父类。 重写: 子类对父类中某些方法进行从新定义, 在调用这些方法时 就会调用子类的方法。 向上转型: 在多态中须要将子类的引用 赋给父类对象, 只有这样该引用才可以具有 技能调用父类的方法和子类的方法。 只有知足了上述三个条件, 咱们才可以在同一个继承结构中 使用统一的逻辑实现代码处理不一样的对象, 从而达到执行不一样的行为。 多态机制遵循的原则归纳为 当超类对象引用变量引用子类对象时, 被引用对象的类型 而不是引用变量的类型 决定了调用谁的成员方法, 可是这个被调用的方法 必须是在超类中定义过的, 也就是说被子类覆盖的方法, 可是它仍然要根据继承链中 方法调用的优先级来确认方法, 该优先级为: this.method(O)、 super.method(O)、 this.method((super)O)、 super.method((super)O)。
69.局部变量和成员变量的区别?性能优化
成员变量与局部变量的区别 一、在类中的位置不一样 成员变量: 在类中方法外面 局部变量: 在方法或者代码块中, 或者方法的声明上 二、在内存中的位置不一样, 成员变量:在堆中(方法区中的静态区) 局部变量:在栈中 三、生命周期不一样 成员变量: 随着对象的建立而存在, 随着对象的消失而消失 局部变量: 随着方法的调用或者代码块的执行 而存在, 随着方法的调用完毕或者 代码块的执行完毕而消失 四、初始值 成员变量: 有默认初始值 局部变量: 没有默认初始值, 使用以前须要赋值, 不然编译器会报错
70.什么是匿名类,有什么好处?架构
简单地说: 匿名内部类就是没有名字的内部类。 什么状况下须要使用匿名内部类? 若是知足下面的一些条件, 使用匿名内部类是比较合适的: 只用到类的一个实例。 类在定义后立刻用到。 类很是小(SUN推荐是在4行代码如下) 给类命名并不会致使你的代码更容易被理解。 在使用匿名内部类时,要记住如下几个原则: 匿名内部类不能有构造方法。 匿名内部类不能定义任何静态成员、方法和类。 匿名内部类不能是 public,protected,private,static。 只能建立匿名内部类的一个实例。 一个匿名内部类必定是在new的后面, 用其隐含实现一个接口或实现一个类。 因匿名内部类为局部内部类, 因此局部内部类的全部限制都对其生效。
这里推荐一下个人Java后端高级技术群:479499375 ,群里有(Java高架构、分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、等学习资源)进群免费送给每一位Java小伙伴,无论你是转行,仍是工做中想提高本身能力均可以!并发