JavaSE基础面试题(四)

1. Java虚拟机中内存分为哪些区域?每个区域的作用?哪些区域是线程共享的?

2. 请解释抽象类与接口的区别

JDK1.8之前抽象类与接口的差别很大,JDK1.8之后接口越来越像抽象类了。

 

抽象类

接口

单继承限制

一个类可以实现多个接口,

而且接口也可以继承多个接口

成员

属性

可以有

只能有公共的静态的常量属性

 

构造器

 

代码块

可以有

 

抽象方法

可以有

只能是公共的抽象方法

 

静态方法

可以有

JDK1.8之后可以有公共的静态方法

 

方法的默认实现

可以有

JDK1.8之后可以有公共的默认方法

相同点

都不能直接实例化,都是上层的抽象层

3. Object类中equals方法的实现是什么?重写一个equals方法有什么注意事项?

Object类中的equals方法,对于任何非空引用值 x y,当且仅当 x y 引用同一个对象时,此方法才返回 truex == y 具有值 true)。

在重写equals方法时,要注意满足离散数学上的特性

1)自反性:对任意引用值xx.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)非空性:任何非空的引用值xx.equals(null)的返回值一定为false

 

注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明:

(1)相等对象必须具有相等的哈希码,

(2)两个对象的哈希码不相等,那么equals一定不相等。

两个对象的哈希码相等,那么equals结果可能相等也可能不相等

4. 比特(Bit),字节(Byte),字符(char/word),各有什么区别,通常说存储容量为KB,MB,GB,TB又是什么意思?通常说传输速率有bpsBps有什么区别?

Bit最小的二进制单位 ,是计算机的操作部分,取值0或者1

Byte是是计算机信息技术用于计量存储容量的一种计量单位,由8bit组成,取值(-128-127)。

char/word是用户的可读写的最小单位,在Java里面一个char类型的变量占2个字节,取值(0-65535),但实际一个char存储到文件中占几个字节要看字符编码方式。

1KB = 1024Byte1MB = 1024KB1GB = 1024MB1TB = 1024GB

bpsbits per second 的简称,一般用于表示网络或USB等接口的数据传输速率。Bps即是Byte per second 的简称,电脑一般都以Bps 显示速度,如1Mbps 大约等同 128 KBps。

5. 运行时异常与编译时异常有何异同?请列举一些运行时异常和编译时异常的类型。

运行时异常是非受检异常,是RuntimeException的子类,即编译器无法检测,因此也不会强制要求程序员处理。

编译时异常是受检异常,编译器检测到代码抛出编译时异常时,会要求程序员必须对该异常做处理(throwstry...catch)否则,编译不通过。

运行时异常:

数组下标越界异常:ArrayIndexOutOfBoundsException

类型转换异常:ClassCastException

算术异常:ArithmeticException

空指针异常:NullPointerException

编译时异常:

IO操作异常:IOException

文件找不到异常:FileNotFoundException

已到达文件流末尾异常:EOFException

类找不到异常:ClassNotFoundException

没有对应的方法异常:NoSuchMethodException

6. HashMap的底层实现及扩容机制?

简单回答:

HashMapJDK1.8之前:底层实现是数组+链表,扩容机制是当table中元素的个数已经达到阈值(table.length*0.75)时并且新添加[index]桶已经是非空,那么table.length需要扩容为2倍。

 

HashMapJDK1.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. 如何实现序列化,有什么意义

如何实现序列化

1)实现Serializable接口或Externalizable接口,并且视情况而定指定一个序列化版本IDserialVersionUID)值;而且要保留公共的无参构造。

2)如果某个对象的属性也是引用数据类型,那么该数据类型也要实现Serializable接口或Externalizable接口;

3)如果要序列化,则使用一个输出流来构造一个对象输出流ObjectOutputStream并通过writeObject(Object obj)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流ObjectInputStream,然后通过readObject方法从流中读取对象。

4)如果某些属性不参与序列化,如果是实现Serializable接口的,直接在属性前面加transient修饰,注意:static修饰的属性也不会被序列化,如果是实现Externalizable接口,那么只要在重写writeExternal()readExternal()方法时,不处理该属性即可。

意义

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,即把对象的内容转成二进制数据。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。

9. synchronized关键字的用法?

synchronized关键字是解决线程安全问题的方式之一。共有两种用法:

1、同步代码块

语法格式:

  synchronized(锁对象){

     需要加锁的代码

  }

注意锁:

1)任意类型的对象都可以当做锁

2)多个线程之间共用一把锁,即多个线程之间共用同一个锁对象

3)同步代码块的范围:不能太大,太小

2、同步方法

  语法结构:

    synchronized 【修饰符】  返回值类型  方法名(【形参列表】)【抛出异常列表】

同步方法的锁对象:

  静态方法:当前类的Class对象,即当前类名.class

  非静态方法:当前对象this(需要谨慎,确保是同一个this

10. 请列出你所知道的设计模式?

Java 中一般认为有 23 种设计模式,我们不需要所有的都会,但是其中常用的几种设计模式应该去掌握。总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

11. Object中有哪些方法

1protected Object clone()--->创建并返回此对象的一个副本。 
2boolean equals(Object obj)--->指示某个其他对象是否与此对象“相等”。 
3protected void finalize()--->当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。 
4Class<? extendsObject> getClass()--->返回一个对象的运行时类型。 
5int hashCode()--->返回该对象的哈希码值。 
6void notify()--->唤醒在此对象监视器上等待的单个线程。 
7void notifyAll()--->唤醒在此对象监视器上等待的所有线程。 
8String toString()--->返回该对象的字符串表示。 
9void 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文件被反编译,或者加载特殊目录下的字节码数据。

原文地址:https://www.cnblogs.com/LzMingYueShanPao/p/14579326.html