1. Java面向对象:对象的概念及面向对象的三个基本特征
-
封装
:隐藏内部实现细节,对外提供可访问的方法 -
继承
:子类自动继承父类中所有的非私有属性和方法Java 语言是单继承的,即只能有一个父类,但 Java 可以实现多个接口(接口类似于类,但接口的成员没有执行体。可以防止多继承所引起的冲突问题。 -
多态
:同一事物,多种不同的表示形态,例如:重载、重写 -
抽象
:可以不用管具体的实现,定义统一的抽象规则
2. HashMap的特性
-
HashMap
存储键值对实现快速存取,允许为null
。key
值不可重复,若key
值重复则覆盖。 - 非同步,线程不安全。
- 底层是
hash
表,不保证有序 - JDK7 采用的是
数组+链表
- JDK8 采用的
数组+链表+红黑树
-
链表
主要是为了解决数组中的key发生hash冲突时,将发生碰撞的key存到链表中 -
红黑树
主要是为了解决链表过长,的查询速度太慢问题
3. 单例模式
属于对象创建模式,它可以确保系统中一个类只产生一个实例。这样的行为能带来两大好处:
对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销。由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间。
- 单例饿汉式和懒汉式区别
饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。
懒汉式懒汉式是延时加载,他是在需要的时候才创建对象,而饿汉式在虚拟机启动的时候就会创建。
两者建立单例对象的时间不同。 “懒汉式”是在你真正用到的时候才去建这个单例对象, “饿汉式”是在不管用不用得上,一开始就建立这个单例对象。
- 单例饿汉式和懒汉式区别
- java单例模式之
双重校验锁
- java单例模式之
public class Singleton03 {
private volatile static Singleton03 instance;
/**
* 私有构造方法
*/
private Singleton03(){}
public static Singleton03 getInstance() {
if(instance == null) {
synchronized (Singleton03.class) {
if (instance == null) {
instance = new Singleton03();
}
}
}
return instance;
}
}
- 第一次校验, if(singleton == null) 意义是由于单利模式只需创建一个实列,所以当第一次创建实列成功之后,再次调用Singleton.getInstance() 就没必要进入同步锁代码块,直接返回之前创建的实列即可。
- 第二次校验是为了防止二次创建实列,我们假设一种状况,当singleton还未被创建的时候,线程r1 调用了getInstance 方法,由于此时的singleton 为空,则可以进入第一层判断,线程r1正准备继续执行,此时,线程r2抢占cpu资源,此时r2也调用了getInstance 方法,同理线程r1并没有实例化singleton,线程r2也可以进去判断,然后继续往下执行,进入到同步代码块,进入第二层判断,完成了singleton 的创建,并分配空间,r2线程运行周期结束。执行任务又回到了r1,如果没有第二层判断,线程r1 也会创建一个实列(r2线程已经创建一个实列,第二层判断为false),这样就完全避免掉多线程环境下会创建多个实列的的问题
- private static volatile Singleton singleton = null;这是必要的 因为volatile关键字可以防止jvm指令重排优化,就是 singleton = new Singleton() 可以理解为三个阶段:1 为singleton 分配空间 2 初始化singleton 3 将创建的singleton实列指向分配的内存空间。
因为JVM具有指令重排的特性,执行顺序有可能变成 1-3-2。 指令重排在单线程下不会出现问题,但是在多线程下会导致一个线程获得一个未初始化的实例。例如:线程r1执行了1和3,此时r2调用 getInstance() 后发现 singleton 不为空,因此返回 singleton, 但是此时的 singleton 还没有被初始化。
- private static volatile Singleton singleton = null;这是必要的 因为volatile关键字可以防止jvm指令重排优化,就是 singleton = new Singleton() 可以理解为三个阶段:1 为singleton 分配空间 2 初始化singleton 3 将创建的singleton实列指向分配的内存空间。
- 使用
volatile
会禁止JVM指令重排,从而保证在多线程下也能正常执行
- 使用
4. 反射机制
- 优点:运行期类型判断,动态加载,提高代码的灵活性。
- 缺点:性能瓶颈:反射相当于一系列的解释操作,通知JVM要做的事情,性能比直接的Java代码要慢很多。安全问题:让我们可以动态操作改变类的属性同时也增加了类的安全隐患。
- 反射的应用场景:
例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式,也采用了反射机制;还有Spring等框架,也是利用反射机制实现的(反射是框架设计的灵魂)。
5. 泛型的实现
- 泛型是通过
类型擦除
来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。也就是说,泛型只在编译期有效
6. 注解
-
Annotation
是Java 5
开始引入的新特性.Java 注解
是附加在代码中的一些元信息,用于一些工具的编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在java.lang.annotation
包中。
7. 垃圾回收算法
- 标记清除算法:
1.1 标记: 从根集合进行扫描,对存活的对象进行标记。
1.2 清除: 对堆内存从头到尾进行线性遍历,回收不
1.3 标记-清除算法的缺点是会造成很多内存碎片
- 标记清除算法:
- 复制算法: 将内存按容量按一定的比例分为对象面和空闲面。对象在对象面上创建。存活的对象被从对象面复制到空闲面。 年轻代很多垃圾收集器,都用这个算法回收
2.1 优点:
解决了内存碎片化的问题。顺序分配内存,简单高效。适用于对象存活率低的场景。
2.2 缺点:
对于对象存活率高的场景不适合。
标记整理算法。分代收集算法
- 复制算法: 将内存按容量按一定的比例分为对象面和空闲面。对象在对象面上创建。存活的对象被从对象面复制到空闲面。 年轻代很多垃圾收集器,都用这个算法回收
-
- 标记-整理算法?
-
标记
: 从根集合进行扫描,对存活的对象进行标记。
-
-
清除
: 移动所有存活的对象, 且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收
-
- 避免了内存的不连续性。不用设置两块内存互换。
适用于存活率高的场景。
- 避免了内存的不连续性。不用设置两块内存互换。
- 分代收集算法:
4.1 垃圾回收算法的组合拳。
4.2 按照对象生命周期的不同划分区域以 采用不同的垃圾回收算法。
4.3 目的: 提高JVM的 回收效率。
- 分代收集算法:
8. java有几种解决线程安全方法
- 同步代码块
synchronized(同步监视器=对象){
//需要被同步的代码
}
- 同步方法
2.1 同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。
2.2 非静态的同步方法,同步监视器是:this.静态的同步方法,同步监视器是:当前类本身
- 同步方法
- Lock锁 — JDK5.0新增
网友评论