关键字
protected变量
-
protected
- 父类的protected成员包内可见并且对子类可见
- 父子类不在一个包,子类只能访问从父类继承的protected方法,不能访问父类实例的protected方法
-
public
- 修饰的类,接口,成员无论所处包定义在哪,都可被访问到
-
private
- 被修饰的类,成员只能被该类的对象访问,子类不能访问,同包不能访问,跨包不可
-
default
- 默认访问,只允许在同包内访问
介绍static
static方法是方便在没有创建对象的情况下来进行方法/变量的调用(只要类加载就可以使用)
- 修饰代码块,静态代码块,类加载时会按顺序执行每个静态代码块优化程序性能
- 修饰方法,静态方法,通过类名.方法名访问,静态方法不能访问类的非静态成员
- 修饰变量,静态变量,类加载时初始化,被所有对象共享
Final关键字
- 修饰类,该类不能被继承
- 修饰方法,锁定方法无法被修改(早期版本还可以将方法转为内嵌调用提高效率)
- 修饰变量,基本数据类型则数值不会改变;引用类型则初始化后不能指向另一个对象
抽象方法能否用static,native,synchronized修饰
- 抽象方法abstract不能为static,abstract方法要被实现则属于多个类,静态方法只能署遇一个类
- native方法表示该方法要用另一种依赖平台语言实现不存在被子类是实现问题,abstract方法不能被native修饰
- synchronized方法的锁对象为this,abstract方法无法确定this是什么,所以不能共存
集合
HashMap原理,如何实现线程安全
- HashMap在多线程下扩容过程rehash易造成元素形成循环链表而死循环所以线程不安全,多线程保证HashMap线程安全:
- 使用Hashtable
- 使用Java.util.concurrent.ConcurrentHashMap
- 使用Java.util.Collections.synchronizedMap()包装HashMap并在此map上操作
各种实现方式下为什么选用ConcurrentHashMap?
- 底层数组+链表实现,无论key还是value都不能为null;实现线程安全的方式是写数据时锁住整个HashTable,效率低
- ConcurrentHashMap分段的数组+链表实现,只锁住需要的某个segment,允许多个写操作不同segment
ConcurrentHashMap原理
- ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成
- 一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,对HashEntry修改时需要获得对应的Segment锁
- ConcurremtHashMap设计思路与HashMap一致,,除了锁机制
ConcurrentHashMap分段锁如何实现
- 将数据分段存储,每一个段配一把锁segment(一种ReentrantLock);一个段被访问允许其他段被访问
- 跨段操作需要按顺序锁住所有段,操作完后又按顺序释放所有段(有序锁可以避免死锁)
Map put和get原理(hashCode()/equals())
-
为什么重写equals必须重写hashCode()
不重写hashcode()可能会出现两个无关对象equals()相同,但是hashcode却不相同 -
为什么先调用hashCode()再调用equals()
先调用hashcode()提交校验,对于set这种无序集合(List有序所以可以重复)避免每一个集合元素对比调用equals提高效率
讲一下hashset
一致性哈希讲下
-
使用Hash算法进行缓存:将负载按照hash算法对服务器数量取余根据得到存入缓存服务器的编号,例如3台服务器,对负载键hash后对3取余会得到0,1,2分别存入缓存即可
- 缓存服务器数量变化时会引起缓存雪崩, 造成系统崩溃
- 缓存服务器数量变化时几乎所有缓存位置变化,检索时开销太大
-
一致性Hash是对2^32取模
- 将缓存服务器(hash(服务器B的IP地址) % 2^32)与被缓存对象(hash(检索key) % 2^32)都映射到hash环上以后,从被缓存对象的位置出发,沿顺时针方向遇到的第一个服务器,就是当前对象将要缓存于的服务器,由于被缓存对象与服务器hash后的值是固定的,所以,在服务器不变的情况下,环翠对象必定会被缓存到固定的服务器上
- 使用之前的hash算法,服务器数量发生改变时,所有服务器的所有缓存在同一时间失效了,而使用一致性哈希算法时,服务器的数量如果发生改变只有部分缓存会失效,前端的缓存仍然能分担整个系统的压力,而不至于所有压力都在同一时间集中到后端服务器上
list循环遍历有几种方法
- iterator
- foreach
- listiterator
集合比较
hashmap和hashtable的区别
IO/异常
error和exception
简单Java I/O
设计模式
装饰者模式,应用业务背景
- 动态地给对象添加功能
- Java I/O使用到了装饰者模式,对于输入流Inputstream为接口,DataInputStream 为子类,BufferedReader为装饰者,通过减少读写次数提高I/O速度
模板方法模式,应用业务背景
观察者模式,应用业务背景
- 定义对象间一对多的依赖关系,一个对象发生改变时(观察目标)将自动通知其他对象,其他对象(观察者)将相应做出反应,也叫发布-订阅模式
- 主题与观察者,观察者之间都是松耦合的关系
说说工厂模式实现
- 简单工厂模式:创建单一实体类实例对象
- 工厂方法模式:定义用于创建对象的接口,让子类决定要实例化的类,工厂方法模式将一个类的实例化延迟倒子类
- 抽象工厂模式:提供一个创建一系列相关或互相依赖对象(对象家族,之间相关或互相依赖)的接口,而无需指定它们具体的类
适配器模式的实现
- 作为接口之间的桥梁起到适配作用,分为类适配器和对象适配器
- SpringMVC中的DispatcherServlet就是适配器模式的典型应用
单例模式保证线程安全性的创建方式
- 单例模式各种情况和优缺点
代理模式
-
常说的代理,指的就是代理模式,代理类为委托类提供消息预处理,消息转发,事后消息处理等功能;Java代理分为三种角色
- 代理类
- 委托类
- 接口
-
静态代理
- 要求代理类(ProxySubject)和委托类(RealSubject)都实现同一个接口(Subject)
- 代理类在编译期已确定,效率更高但代码冗余大,修改接口则代理类委托类都要修改
-
动态代理
- Java中的动态代理依靠反射实现
- 委托类需要实现接口,代理类在JVM允许时动态生成
- 代理类需要实现invocationHandler接口或者实现其匿名内部类;Proxy创建动态代理
-
动态代理有哪些,JDK动态代理和CGlib动态代理分别怎么实现的。Spring默认用的哪个动态代理
其他
深拷贝和浅拷贝的定义
获得类的方式
编译型语言/解释型语言
-
编译型语言
针对特定的平台,使用专门的编译器将源代码一次性的编译成可被该平台硬件执行的机器码,并包装成该平台所能识别的可执行性程序格式 -
解释型语言
使用专门的解释器对源程序逐行解释成特定平台的机器码并立即执行,Java就是解释型语言(但是从反射的角度上来说Java算是办解释型语言)
数字转字符串方式
float类型的1与int类型的1用==判断返回true or false
Java八大基本类型
char/byte/short/int/double/float/long/boolean