1. Java虚拟机中内存分为哪些区域?每个区域的作用?哪些区域是线程共享的?
2. 请解释抽象类与接口的区别
JDK1.8之前抽象类与接口的差别很大,JDK1.8之后接口越来越像抽象类了。
|
抽象类 |
接口 |
|
单继承限制 |
有 |
一个类可以实现多个接口, 而且接口也可以继承多个接口 |
|
成员 |
属性 |
可以有 |
只能有公共的静态的常量属性 |
|
构造器 |
有 |
无 |
|
代码块 |
可以有 |
无 |
|
抽象方法 |
可以有 |
只能是公共的抽象方法 |
|
静态方法 |
可以有 |
JDK1.8之后可以有公共的静态方法 |
|
方法的默认实现 |
可以有 |
JDK1.8之后可以有公共的默认方法 |
相同点 |
都不能直接实例化,都是上层的抽象层 |
3. Object类中equals方法的实现是什么?重写一个equals方法有什么注意事项?
Object类中的equals方法,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。 |
在重写equals方法时,要注意满足离散数学上的特性 (1)自反性:对任意引用值x,x.equals(x)的返回值一定为true. (2)对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true; (3)传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true (4)一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变 (5)非空性:任何非空的引用值x,x.equals(null)的返回值一定为false
注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明: (1)相等对象必须具有相等的哈希码, (2)两个对象的哈希码不相等,那么equals一定不相等。 两个对象的哈希码相等,那么equals结果可能相等也可能不相等 |
4. 比特(Bit),字节(Byte),字符(char/word),各有什么区别,通常说存储容量为KB,MB,GB,TB又是什么意思?通常说传输速率有bps和Bps有什么区别?
Bit最小的二进制单位 ,是计算机的操作部分,取值0或者1。 Byte是是计算机信息技术用于计量存储容量的一种计量单位,由8位bit组成,取值(-128-127)。 char/word是用户的可读写的最小单位,在Java里面一个char类型的变量占2个字节,取值(0-65535),但实际一个char存储到文件中占几个字节要看字符编码方式。 |
1KB = 1024Byte,1MB = 1024KB,1GB = 1024MB,1TB = 1024GB。 |
bps是 bits per second 的简称,一般用于表示网络或USB等接口的数据传输速率。Bps即是Byte per second 的简称,电脑一般都以Bps 显示速度,如1Mbps 大约等同 128 KBps。 |
5. 运行时异常与编译时异常有何异同?请列举一些运行时异常和编译时异常的类型。
运行时异常是非受检异常,是RuntimeException的子类,即编译器无法检测,因此也不会强制要求程序员处理。 编译时异常是受检异常,编译器检测到代码抛出编译时异常时,会要求程序员必须对该异常做处理(throws或try...catch)否则,编译不通过。 |
运行时异常: 数组下标越界异常:ArrayIndexOutOfBoundsException 类型转换异常:ClassCastException 算术异常:ArithmeticException 空指针异常:NullPointerException 编译时异常: IO操作异常:IOException 文件找不到异常:FileNotFoundException 已到达文件流末尾异常:EOFException 类找不到异常:ClassNotFoundException 没有对应的方法异常:NoSuchMethodException |
6. HashMap的底层实现及扩容机制?
简单回答:
HashMap在JDK1.8之前:底层实现是数组+链表,扩容机制是当table中元素的个数已经达到阈值(table.length*0.75)时并且新添加[index]桶已经是非空,那么table.length需要扩容为2倍。
HashMap在JDK1.8之后:底层实现是数组+链表/红黑树,扩容机制(1)是当table中元素的个数已经达到阈值(table.length*0.75)时并且新添加[index]桶已经是非空,那么table需要扩容为2倍。(2)当添加到[index]下时,发现[index]下的链表结点个数已经达到8个,而table的长度未达到64,此时table.length也会扩容为2倍
7. HashMap的相关常量
DEFAULT_LOAD_FACTOR:默认加载因子,值为0.75
TREEIFY_THRESHOLD:链表树化阈值,值为8
MIN_TREEIFY_CAPACITY:最小树化容量,值为64
UNTREEIFY_THRESHOLD:反树化阈值,值为6
8. 如何实现序列化,有什么意义
9. synchronized关键字的用法?
synchronized关键字是解决线程安全问题的方式之一。共有两种用法:
1、同步代码块
语法格式:
synchronized(锁对象){
需要加锁的代码
}
注意锁:
(1)任意类型的对象都可以当做锁
(2)多个线程之间共用一把锁,即多个线程之间共用同一个锁对象
(3)同步代码块的范围:不能太大,太小
2、同步方法
语法结构:
synchronized 【修饰符】 返回值类型 方法名(【形参列表】)【抛出异常列表】
同步方法的锁对象:
静态方法:当前类的Class对象,即当前类名.class
非静态方法:当前对象this(需要谨慎,确保是同一个this)
10. 请列出你所知道的设计模式?
Java 中一般认为有 23 种设计模式,我们不需要所有的都会,但是其中常用的几种设计模式应该去掌握。总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
11. Object中有哪些方法
(1)protected Object clone()--->创建并返回此对象的一个副本。
(2)boolean equals(Object obj)--->指示某个其他对象是否与此对象“相等”。
(3)protected void finalize()--->当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
(4)Class<? extendsObject> getClass()--->返回一个对象的运行时类型。
(5)int hashCode()--->返回该对象的哈希码值。
(6)void notify()--->唤醒在此对象监视器上等待的单个线程。
(7)void notifyAll()--->唤醒在此对象监视器上等待的所有线程。
(8)String toString()--->返回该对象的字符串表示。
(9)void wait()--->导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
void wait(long timeout)--->导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll()方法,或者超过指定的时间量。
void wait(long timeout, int nanos)--->导致当前的线程等待,直到其他线程调用此对象的 notify()
12. 请描述一下JVM加载class的过程和原理?
系统可能在第一次使用某个类时加载该类,但也可能采用预先加载机制来预加载某个类,不管怎样,类的加载必须由类加载器完成,系统会通过加载、连接、初始化三个步骤来对该类进行初始化。不管类的字节码内容从哪里加载,加载的结果都一样,这些字节码内容加载到内存后,都会将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(即引用地址),所有需要访问和使用类数据只能通过这个Class对象。
13. 请阐述类加载器的类型
Java的类加载器有如下四种:
1.引导类加载器(Bootstrap Classloader):又称为根类加载器
它负责加载Java的核心库JAVA_HOME/jre/lib/rt.jar等,是用原生代码(C/C++)来实现的,并不继承自java.lang.ClassLoder,所以通过Java代码获取引导类加载器对象将会得到null。
2.扩展类加载器(Extension ClassLoader)
它由sun.misc.Launcher$ExtClassLoader实现,是java.lang.ClassLoader的子类,负责加载Java的扩展库JAVA_HOME/jre/ext/*.jar等。
3.应用程序类加载器(Application Classloader)
它由sun.misc.Launcher$AppClassLoader实现,是java.lang.ClassLoader的子类,负责加载Java应用程序类路径下的内容。
4.自定义类加载器
开发人员可以通过继承java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求,例如对字节码进行加密来避免class文件被反编译,或者加载特殊目录下的字节码数据。