LZ名約山炮

博客园 首页 新随笔 联系 订阅 管理

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文件被反编译,或者加载特殊目录下的字节码数据。

posted on 2021-03-25 22:03  LZ名約山炮  阅读(131)  评论(0编辑  收藏  举报