Java基础问题

1. static关键字有哪些作用?

static修饰变量、修饰方法。

static修饰静态块、静态内部类、静态导包。

2. volatile关键字的底层实现原理

变量被volatile关键字修饰,那么所有线程都是可见的。

  • 对于普通变量:普通变量的值在线程间传递均需要通过主内存来完成。
  • 对于volatile关键字修饰的变量:多线程下jvm会为每个线程分配一个独立的缓存来提高效率。

volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,保证了每次读写变量都从主内存中读,跳过CPU cache这一步。

指令重排序是JVM为了优化指令提高程序运行效率在不影响单线程程序执行结果的前提下,尽可能地提高并行度

指令重排序包括编译器重排序运行时重排序

volatile关键字提供内存屏障的方式来防止指令被重排,编译器在生成字节码文件时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。

3. ConcurrentHashMap的锁分段技术

HashMap与HashTable都是哈希表,但是hashmap线程不安全;hashtable线程安全,效率非常低。

ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用来存储键值对数据。(Segment数组+HashEntry数组)

4. ConcurrentHashMap的读是否要加锁,为什么

不需要,ConcurrentHashMap实现技术是保证HashEntry几乎是不可变的。

5. ConcurrentHashMap的迭代器是强一致性的迭代器还是弱一致性的迭代器

弱一致迭代器。

6. 知道常用设计模式的优缺点
  • 简单工厂模式(Static Factory Method

优点:

  1. 工厂类是整个模式的关键。包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象。
  2. 通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了,而不必管这些对象究竟如何创建及如何组织。

缺点:

  1. 由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中,它所能创建的类只能是事先考虑到的,如果需要添加新的类,就需要改变工厂类。
  2. 当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求。对系统的维护扩展非常不利。
  • 策略模式(Strategy

优点:

  1. 每个算法单独封装减少了算法和算法调用者的耦合。
  2. 合理使用继承有助于提取出算法中的公共部分。
  3. 简化了单元测试。

缺点:

  1. 策略模式只适用于客户端知道所有的算法或行为的情况。
  2. 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。
  • 装饰模式(Decorator

优点:

  1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
  2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点:

  1. 更加复杂
  • 代理模式(Proxy

优点:

  1. 权责清晰,真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
  2. 代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。
  3. 高扩展性

缺点:

  1. 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
  2. 增加了系统的复杂度。
  • 工厂方法模式(Factory Method

优点:

  1. 良好的封装性,代码结构清晰,减少模块间的耦合
  2. 工厂方法模式的扩展性非常优秀。
  3. 屏蔽产品类。
  4. 工厂方法模式就是典型的解耦框架。

缺点:

  1. 使用者必须知道相应工厂的存在。
  2. 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
  • 原型模式(Prototype

优点:

  1. 隐藏了对象创建的细节。
  2. 提高了性能。
  3. 不用重新初始化,动态获得对象运行的状态。

缺点:

  1. 适用性不是很广。
  2. 每一个类必须配备一个克隆方法
  3. 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象或者引用含有循环结构的时候。
  • 模板方法模式(Template Method

优点:

  1. 提高代码复用性
  2. 帮助子类摆脱重复的不变行为

缺点:

  1. 考虑不全面统一出现问题。

(更多模式待补充……..)

7. 构造器(constructor)是否可被重写(override)?

构造器不能被继承,因此不能被重写,但可以被重载。

8. 是否可以继承String类?

String类是final类,不可以被继承。

ps:继承String本身就是一个错误的行为,对String类型最好的重用方式是关联关系和依赖关系而不是继承关系。

9. 重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常。重载对返回类型没有特殊的要求。

10. get和post请求的区别?

①get请求用来从服务器上获得资源,而post是用来向服务器提交数据;

②get将表单中数据按照name=value的形式,添加到action所指向的URL后面,并且两者使用“?”连接,而各个变量之间使用“&”连接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action所指向URL;

③get传输的数据要受到URL长度限制(1024字节);而post可以传输大量的数据,上传文件通常要使用post方式;

④使用get时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏感数据应使用post;

⑤get使用MIME类型百分号编码文本的格式传递参数,保证被传送的参数由遵循规范的文本组成。

11. 实现会话跟踪的技术有哪些?
  • URL重写:在URL中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到URL结尾以标识一个会话。
  • 设置表单隐藏域:将和会话跟踪相关的字段添加到隐式表单域中,这些信息不会在浏览器中显示但是提交表单时会提交到服务器。这两种方式很难处理跨越多个页面的信息传递,因为如果每次都要修改URL或在页面中添加隐式表单域来存储用户会话相关信息,事情将变得非常麻烦。
  • cookie:cookie有两种,一种是基于窗口的,浏览器窗口关闭后,cookie就没有了;另一种是将信息存储在一个临时文件中,并设置存在的时间。当用户通过浏览器和服务器建立一次会话后,会话ID就会随响应信息返回存储在基于窗口的cookie中,那就意味着只要浏览器没有关闭,会话没有超时,下一次请求时这个会话ID又会提交给服务器让服务器识别身份。

ps: HTML5中可以用Web Storage技术通过JavaScript来保存数据,例如localStoragesessionStorage来保存用户会话的信息,也能够实现会话跟踪。

12. 什么是ORM?

对象关系映射是一种为了解决程序的面向对象模型与数据库的关系模型互不匹配问题的技术;简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中或者将关系数据库表中的行转换成Java对象,其本质上就是将数据从一种形式转换到另一种形式。

13. 持久层设计要考虑的问题有哪些?持久层框架有哪些?

持久层设计的目标包括:

  1. 数据存储逻辑的分离,提供抽象化的数据访问接口。
  2. 数据访问底层实现的分离,可以在不修改代码的情况下切换底层实现。
  3. 资源管理和调度的分离,在数据访问层实现统一的资源调度。
  4. 数据抽象,提供更面向对象的数据操作。

持久层框架有:

  • Hibernate
  • MyBatis
  • Spring Data
  • ActiveJDBC
  • Guzz
  • jOOQ