李逍遥

2018 Java开发工程师面试题——Java基础

李逍遥 面试技巧 2018-01-23

我来自河南郑州,刚从XXX离职,我在北京已经两年了,一直从事java软件开发工作,今天来是希望能够获得贵公司的Java工程师岗位,不管今天的结果如何,也都感谢经理您能从百忙中抽出时间来面试我。

JAVA基础面试题

1.JAVA 中的几种基本数据类型是什么,各自占用多少字节。

 2018 Java开发工程师面试题——Java基础 面试技巧

类型位数字节数范围

 2018 Java开发工程师面试题——Java基础 面试技巧

==================================================

2.String 类能被继承吗,为什么。

一,在Java中,只要是被定义为final的类,也可以说是被final修饰的类,就是不能被继承的。

二,final是java中的一个关键字,可以用来修饰变量、方法和类。用关键词final修饰的域成为最终域。用关键词final修饰的变量一旦赋值,就不能改变,也称为修饰的标识为常量。如果一个类的域被关键字final所修饰,它的取值在程序的整个执行过程中将不会改变。

三,假如说整个类都是final,就表明自己不希望从这个类继承,或者不答应其他任何人采取这种操作。换言之,出于这样或那样的原因,我们的类肯定不需要进行任何改变;或者出于安全方面的理由,我们不希望进行子类化(子类处理)。

==================================================

3.String,Stringbuffer,StringBuilder 的区别。

1.String类型,是java内的对象,是不可改变的对象,当每次对String进行改变时,都需要生成一个新的String对象,然后将指针指向一个新的对象,如果在一个循环里,不断的改变一个对象,就要不断的生成新的对象,如果对象多了,java的垃圾自动回收机制会开始工作了,所以效率很低,建议在不断更改String对象的地方不要使用String类型。

2.StringBuffer是个可变的对象,就是每次操作都是对对象本身进行操作,而不用生成新的对象,这样效率就会有很大的提高,在大部分情况下StringBuffer的效率要比String类型更高。

3.StringBuilder与StringBuffer一样是个可变的字符序列,提供与StringBuffer兼容的API,但是不能保证同步,

在用在字符串缓冲区被当作线程的情况使用,在单机非多线程的情况下使用StringBuilder会有比较好的效率,因为StringBuilder没有处理同步(Synchronized)问题。StringBuffer则会处理同步问题,StringBuild会在多线程下被操作,要改用Stringbuffer,让对象自行管理同步问题。

==================================================

4.ArrayList 和 LinkedList 有什么区别。

1、ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。

2、相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。

3、LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素

==================================================

5.讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new 的时候,他们的执行顺序。

父类静态代变量、

父类静态代码块、

子类静态变量、

子类静态代码块、

父类非静态变量(父类实例成员变量)、

父类构造函数、

子类非静态变量(子类实例成员变量)、

子类构造函数。

==================================================

6.用过哪些Map 类,都有什么区别,HashMap 是线程安全的吗,并发下使用的 Map 是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。

hashMap是线程不安全的,HashMap是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,采用哈希表来存储的,

参照该链接:https://zhuanlan.zhihu.com/p/21673805

JAVA8 的 ConcurrentHashMap 为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计。

参照:https://yq.aliyun.com/articles/36781

有没有顺序的Map实现类,如果有,他们是怎么保证有序的。

TreeMap和LinkedHashMap是有序的(TreeMap默认升序,LinkedHashMap则记录了插入顺序)。

参照:http://uule.iteye.com/blog/1522291

==================================================

7.JAVA8 的 ConcurrentHashMap 为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计。

jdk8 放弃了分段锁而是用了Node锁,减低锁的粒度,提高性能,并使用CAS操作来确保Node的一些操作的原子性,取代了锁。

但是ConcurrentHashMap的一些操作使用了synchronized锁,而不是ReentrantLock,虽然说jdk8的synchronized的性能进行了优化,但是我觉得还是使用ReentrantLock锁能更多的提高性能

==================================================

8.有没有有顺序的Map 实现类,如果有,他们是怎么保证有序的。

顺序的Map 实现类:LinkedHashMap,TreeMap

LinkedHashMap 是基于元素进入集合的顺序或者被访问的先后顺序排序,TreeMap 则是基于元素的固有顺序 (由 Comparator 或者 Comparable 确定)。

==================================================

9.抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么。

1.抽象类可以有自己的实现方法,接口在jdk8以后也可以有自己的实现方法(default);

2.抽象类的抽象方法是由非抽象类的子类实现,接口的抽象方法有接口的实现类实现;

3.接口不能有私有的方法跟对象,抽象类可以有自己的私有的方法跟对象类不可以继承多个类,接口可以继承多个接口,类可以实现多个接;

==================================================

10.继承、实现、依赖、关联、聚合、组合的联系与区别。

分别介绍这几种关系:

继承

指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系;在Java中此类关系通过关键字extends明确标识,在设计时一般没有争议性;

 2018 Java开发工程师面试题——Java基础 面试技巧

实现

指的是一个class类实现interface接口(可以是多个)的功能;实现是类与接口之间最常见的关系;在Java中此类关系通过关键字implements明确标识,在设计时一般没有争议性;

 2018 Java开发工程师面试题——Java基础 面试技巧

依赖

可以简单的理解,就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、、临时性的、非常弱的,但是B类的变化会影响到A;比如某人要过河,需要借用一条船,此时人与船之间的关系就是依赖;表现在代码层面,为类B作为参数被类A在某个method方法中使用;

关联

他体现的是两个类、或者类与接口之间语义级别的一种强依赖关系,比如我和我的朋友;这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,一般是长期性的,而且双方的关系一般是平等的、关联可以是单向、双向的;表现在代码层面,为被关联类B以类属性的形式出现在关联类A中,也可能是关联类A引用了一个类型为被关联类B的全局变量;

聚合

聚合是关联关系的一种特例,他体现的是整体与部分、拥有的关系,即has-a的关系,此时整体与部分之间是可分离的,他们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享;比如计算机与CPU、公司与员工的关系等;表现在代码层面,和关联关系是一致的,只能从语义级别来区分;

组合

组合也是关联关系的一种特例,他体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合;他同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束;比如你和你的大脑;表现在代码层面,和关联关系是一致的,只能从语义级别来区分;

11.讲讲你理解的nio。他和 bio 的区别是啥,谈谈 reactor 模型。

BIO:同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

NIO:同步非阻塞式IO,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

reactor模型:反应器模式(事件驱动模式):当一个主体发生改变时,所有的属体都得到通知,类似于观察者模式。

==================================================

12.反射的原理,反射创建类实例的三种方式是什么。

反射的原理:如果知道一个类的名称/或者它的一个实例对象, 就能把这个类的所有方法和变量的信息(方法名,变量名,方法,修饰符,类型,方法参数等等所有信息)找出来。

反射创建类实例的三种方式:

1.Class.forName("com.A");

2.new A().getClass();

3.A.class;

==================================================

13.反射中,Class.forName 和 ClassLoader 区别。

class.forName()除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。

classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。

==================================================

14.描述动态代理的几种实现方式,分别说出相应的优缺点。

动态代理有两种实现方式,分别是:jdk动态代理和cglib动态代理

jdk动态代理的前提是目标类必须实现一个接口,代理对象跟目标类实现一个接口,从而避过虚拟机的校验。

cglib动态代理是继承并重写目标类,所以目标类和方法不能被声明成final。

==================================================

15.动态代理与cglib 实现的区别。

动态代理有两种实现方式,分别是:jdk动态代理和cglib动态代理

jdk动态代理的前提是目标类必须实现一个接口,代理对象跟目标类实现一个接口,从而避过虚拟机的校验。

cglib动态代理是继承并重写目标类,所以目标类和方法不能被声明成final。

==================================================

16.为什么CGlib 方式可以对接口实现代理。

cglib动态代理是继承并重写目标类,所以目标类和方法不能被声明成final。而接口是可以被继承的。

==================================================

17.final 的用途。

1.final修饰的对象不能被修改;

2.final修饰的类不能被继承;

3.final修饰的方法不能被重写;

==================================================

18.写出三种单例模式实现。

/**

*单例模式

*/

public classSingleton {

/**

* hungryType单例模式

*类在加载时就实例化,

*提供一个公共的方法获取实例化的类

*

*优点:线程安全

*

*缺点:类被加载时就实例化,

*有可能在整个代码周期都没有使用

*且不会被回收,会一直存在

*/

private static classhungryType {

private statichungryTypehungryType=newhungryType();

privatehungryType() {

}

statichungryType gethungryType() {

returnhungryType;

}

}

/**

* lazyType单例模式

*只有在真正使用的时候,才实例化

*

*优点:只有在真正使用的时候才实例化

*

*缺点:线程不安全

*/

private static classlazyType {

private staticlazyTypelazyType;

privatelazyType() {

}

static synchronizedlazyType getlazyType() {

if(null==lazyType) {

lazyType=newlazyType();

}

returnlazyType;

}

}

/**

* enumType单例模式

*跟hungryType一样

*/

private enumenumType {

enumType;

publicenumType getenumType() {

returnenumType;

}

}

public static voidmain(String[] args) {

Singleton.lazyType lazyType = Singleton.lazyType.getlazyType();

if(lazyType == Singleton.lazyType.getlazyType()) {

System.out.println("lazyType--单例生效");

}

Singleton.hungryType hungryType = Singleton.hungryType.gethungryType();

if(hungryType == Singleton.hungryType.gethungryType()) {

System.out.println("hungryType--单例生效");

}

if(enumType.enumType.getenumType() == enumType.enumType.getenumType()) {

System.out.println("enumType--单例生效");

}

}

}

==================================================

19.如何在父类中为子类自动完成所有的hashcode 和 equals 实现?这么做有何优劣。

父类的equals不一定满足子类的equals需求。比如所有的对象都继承Object,默认使用的是Object的equals方法,在比较两个对象的时候,是看他们是否指向同一个地址。

但是我们的需求是对象的某个属性相同,就相等了,而默认的equals方法满足不了当前的需求,所以我们要重写equals方法。

如果重写了equals 方法就必须重写hashcode方法,否则就会降低map等集合的索引速度。

==================================================

20.请结合OO 设计理念,谈谈访问修饰符 public、private、protected、default 在应用设计中的作用。

OO设计理念:封装、继承、多态

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。所以我们可以通过public、private、protected、default 来进行访问控制

 2018 Java开发工程师面试题——Java基础 面试技巧

==================================================

21.深拷贝和浅拷贝区别。

浅拷贝只拷贝指针,深拷贝就是拷贝他的值,重新生成的对像。

==================================================

22.数组和链表数据结构描述,各自的时间复杂度。

数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。

链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。

访问数组中第n 个数据的时间花费是 O(1) 但是要在数组中查找一个指定的数据则是 O(N) 。当向数组中插入或者删除数据的时候,最好的情况是在数组的末尾进行操作,时间复杂度是 O(1) ,但是最坏情况是插入或者删除第一个数据,时间复杂度是 O(N) 。在数组的任意位置插入或者删除数据的时候,后面的数据全部需要移动,移动的数据还是和数据个数有关所以总体的时间复杂度仍然是 O(N) 。

在链表中查找第 n 个数据以及查找指定的数据的时间复杂度是 O(N) ,但是插入和删除数据的时间复杂度是 O(1)

==================================================

23.error 和 exception 的区别,CheckedException,RuntimeException 的区别。

Error(错误)表示系统级的错误和程序不必处理的异常,是java运行环境中的内部错误或者硬件问题。比如:内存资源不足等。对于这种错误,程序基本无能为力,除了退出运行外别无选择,它是由Java虚拟机抛出的。

Exception(违例)表示需要捕捉或者需要程序进行处理的异常,它处理的是因为程序设计的瑕疵而引起的问题或者在外的输入等引起的一般性问题,是程序必须处理的。

Exception又分为运行时异常,受检查异常。

RuntimeException(运行时异常),表示无法让程序恢复的异常,导致的原因通常是因为执行了错误的操作,建议终止程序,因此,编译器不检查这些异常。

CheckedException(受检查异常),是表示程序可以处理的异常,也即表示程序可以修复(由程序自己接受异常并且做出处理), 所以称之为受检查异常。

==================================================

24.请列出5 个运行时异常。

NullPointerException

IndexOutOfBoundsException

ClassCastException

ArrayStoreException

BufferOverflowException

=================================================

25.在自己的代码中,如果创建一个java.lang.String 对象,这个对象是否可以被类加载器加载?为什么。

不可以,双亲委派模式会保证父类加载器先加载类,就是BootStrap(启动类)加载器加载jdk里面的java.lang.String类,而自定义的java.lang.String类永远不会被加载到

===================================================

26.说一说你对java.lang.Object 对象中 hashCode 和 equals 方法的理解。在什么场景下需要重新实现这两个方法。

父类的equals不一定满足子类的equals需求。比如所有的对象都继承Object,默认使用的是Object的equals方法,在比较两个对象的时候,是看他们是否指向同一个地址。

但是我们的需求是对象的某个属性相同,就相等了,而默认的equals方法满足不了当前的需求,所以我们要重写equals方法。

如果重写了equals 方法就必须重写hashcode方法,否则就会降低map等集合的索引速度。

===================================================

27.在jdk1.5 中,引入了泛型,泛型的存在是用来解决什么问题。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

===================================================

28.这样的a.hashcode() 有什么用,与 a.equals(b)有什么关系。

hashCode() 方法是相应对象整型的 hash 值。它常用于基于 hash 的集合类,如 Hashtable、HashMap、LinkedHashMap等等。它与 equals() 方法关系特别紧密。根据 Java 规范,两个使用 equal() 方法来判断相等的对象,必须具有相同的 hash code。

===================================================

29.有没有可能2 个不相等的对象有相同的 hashcode。

有可能,最简单的方法,百分百实现的方式就是重写hascode();

===========================================

30.Java 中的 HashSet 内部是如何工作的。

publicHashSet() {

map=newHashMap();

}

默认使用的是HaseMap;

===========================================

31.什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决。

序列化是一种用来处理对象流的机制,所谓对象流就是将对象的内容进行流化。

序列化是为了解决在对对象流进行读写操作时所引发的问题。

序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流;

===========================================

以上仅仅为Java基础部分。后续会发其他部分。

 2018 Java开发工程师面试题——Java基础 面试技巧
继续浏览有关 Java工程师Java面试题2018 的文章
发表评论