2019年的最新的最全的ava常见的面试题

 

1.抽象类和接口的区别三张思维导图教您更高效学习SSM框架

  1. 抽象类可以有构造方法,接口中不能有构造方法。
  2. 抽象类中可以有普通成员变量,接口中没有普通成员变量。
  3. 抽象类中可以包含非抽象普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的方法(1.8之前)。d. 抽象类中的抽象方法的访问权限可以是 public、protected 和(默认类型,虽然 eclipse 不报错,但也不能用,默认类型子类不能继承),接口中的抽象方法只能是 public 类型的,并且默认即为 public abstract 类型。e. 抽象类中可以包含静态方法,在 JDK1.8 之前接口中不能不包含静态方法,JDK1.8 以后可以包含。f. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问权限可以是任意的,但接口中定义的变量只能是 public static final 类型的,并且默认即为 public static final 类型。g. 一个类可以实现多个接口,用逗号隔开,但只能继承一个抽象类,接口不可以实现接口,但可以继承接口,并且可以继承多个接口,用逗号隔开。

 

2.重载和重写的区别

答:1.方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

2.重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。

 

3.stringBuffer和stringBuilder的区别

1StringBuffer StringBuilder 中的方法和功能完全是等价的,

2、只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。 

3、在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全,而StringBuffer则每次都需要判断锁,效率相对更低

 

4.  集合的体系架构(单列集合和双列集合)

由于需求不同,Java就提供了不同的集合类。这多个集合类的数据结构不同,但是它们都是要提供存储和遍历功能的,我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构图。

 

        Collection                                                Map

            |--List                                                      |--HashMap

                |--ArrayList                                        |--LinkedHashMap

                |--Vector                                    |--HashTable

                |--LinkedList                               |--Properties

            |--Set

                |--HashSet

                |--TreeSet

Collection:是集合的顶层接口,它的子体系有重复的,有唯一的(HashSet),有有序的(List),有无序的(Set)。

区别:Map集合存储元素是成对出现的,Map集合的键是唯一的,值是可重复的。可以把这个理解为:夫妻对,属于双列集合

Collection集合存储元素是单独出现的,Collection的儿子Set是唯一的,List是可重复的。可以把这个理解为:光棍(11.11) 属于单列集合

 

5.   ArrayListLinkedList的区别

1.ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。

2.对于随机访问的get和set方法,ArrayList要优于LinkedList,因为LinkedList要移动指针。

3.对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。

 

6.  hashMapHashTable的区别

Hashtable是基于陈旧的Dictionary类,HashMap是Java 1.2引进的Map接口的一个实现

Hashtable:线程安全,效率低。不允许null键和null值,HashMap:线程不安全,效率高。允许null键和null值

7. java的GC机制的理解

GC :Garbage Collections 字面意思是垃圾回收器,释放垃圾占用的空间。让创建的对象不需要像c、c++那样delete、free掉 。对于c、c++的开发人员来说内存是开发人员分配的,也就是说还要对内存进行维护和释放。对于Java程序员来说,一个对象的内存分配是在虚拟机的自动内存分配机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,而且不容易出现内存泄露和内存溢出问题,但是,如果出现了内存泄露和内存溢出问题,而开发者又不了解虚拟机是怎么分配内存的话,那么定位错误和排除错误将是一件很困难的事情。

 

8. 说下finalfinallyfinalize有什么区别

final:最终的意思,可以修饰类,方法和变量。

       它修饰的类,不能被继承

       它修饰的方法,不能被重写

       它修饰的变量,不能被改变

finally:是异常处理的一部分,用于释放资源的。它控制的代码永远会执行。

特殊情况:在执行到finally之前,JVM退出了。

finalize:是Object类的一个方法,用于垃圾回收。

 

9. ErrorException的区别,try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行,在return前还是后?

Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。

Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。

编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)

运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)

finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

什么时候的代码必须最终执行?

当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开的资源。

当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。如果try中有return语句,finally会在return之前执行。

 

10. 说说同步和异步的区别,多线程的几种实现方式,和run方法可以启动线程吗

1.如果系统中存在临界资源(资源数量少于竞争资源的线程数量的资源),例如正在写的数据以后可能被另外一个线程读到,或者正在读的数据可能已经被另外一个线程写过了,那么这些数据就必须进行同步存取(数据库中的排它锁就是最好的例子)

2.当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途经往往更有效率,事实上,所谓的同步就是指阻塞式操作,而异步就是非阻塞式操作

多线程的四种实现方式:

第一种方式:继承Thread类

万物皆对象,那么线程也是对象,对象就应该能够抽取其公共特性封装成为类,使用类可以实例化多个对象,那么实现线程的第一种方式就是继承Thread类。继承Thread类是最简单的一种实现线程的方式,通过JDK提供的Thread类,重写Thread类的run方法即可,那么当线程启动的时候,就会执行run方法体的内容。

第二种方式:实现Runnable接口

实现Runnable接口也是一种常见的创建线程的方式,使用接口的方式可以让我们的程序降低耦合度。Runnable接口中仅仅定义了一个方法,就是run。我们来看一下Runnable接口的代码。

其实Runnable就是一个线程任务,线程任务和线程的控制分离,这也就是上面所说的解耦。我们要实现一个线程,可以借助Thread类,Thread类要执行的任务就可以由实现了Runnable接口的类来处理。 这就是Runnable的精髓之所在!

第三种方式:使用内部类的方式

这并不是一种新的实现线程的方式,只是另外的一种写法。比如有些情况我们的线程就想执行一次,以后就用不到了。那么像上面两种方式(继承Thread类和实现Runnable接口)都还要再定义一个类,显得比较麻烦,我们就可以通过匿名内部类的方式来实现。使用内部类实现依然有两种,分别是继承Thread类和实现Runnable接口。

第四种方式:基于线程池的方式

我们知道,线程和数据库连接这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是使用线程池。当然了,线程池也不需要我们来实现,jdk的官方也给我们提供了API。

在启动线程的时候,并不是调用线程类的run方法,而是调用了线程类的start方法。那么我们能不能调用run方法呢?答案是肯定的,因为run方法是一个public声明的方法,因此我们是可以调用的,但是如果我们调用了run方法,那么这个方法将会作为一个普通的方法被调用,并不会开启线程。这里实际上是采用了设计模式中的模板方法模式,Thread类作为模板,而run方法是在变化的,因此放到子类来实现。

 

11.说说你对线程的几种状态的了解

1.新建状态(new):新创建一个线程对象的初始状态;也就是通过new关键字创建一个线程对象,但并没有调用start方法时候的状态;

2.就绪状态(Runnable):线程有资格运行,但调度程序还没有把它选为运行线程时的状态,此时,线程具备运行的条件,一旦被选中,马上就可以执行。线程创建后,调用了start方法,线程不处于运行状态;该状态下,等待操作系统的调度,获取cpu使用权之后就可以执行线程代码;

3.运行状态:从就绪状态池中被选择为当前执行的线程的状态;

4.阻塞状态(Blocked):线程在执行的过程中,遇到被synchronized关键字保护的代码,等待获得被保护对象的锁,此时线程会停止执行;这个地方要注意,只有synchronized锁才会让线程进入到Blocked状态,等待利用cas实现的锁(ReentrantLock),线程仍然处于Runnable状态。

5.等待状态(WATTING):线程处于等待状态只有一种情况,就是调用wait方法,如下所示

public static void timedWaiting() {

        final Object lock = new Object();

        synchronized (lock) {

            try {

                lock.wait();

            } catch (InterruptedException e) {

            }

        }

    }

6.死亡状态(Dead):线程执行完了或者异常退出run方法,线程结束生命周期;

 

12. 说说你对多线程锁机制的理解

在开发Java多线程应用程序中,各个线程之间由于要共享资源,必须用到锁机制。Java提供了多种多线程锁机制的实现方式,常见的有synchronized、ReentrantLock、Semaphore、AtomicInteger等。每种机制都有优缺点与各自的适用场景,必须熟练掌握他们的特点才能在Java多线程应用开发时得心应手。

几乎每一个Java开发人员都认识synchronized,使用它来实现多线程的同步操作是非常简单的,只要在需要同步的对方的方法、类或代码块中加入该关键字,它能够保证在同一个时刻最多只有一个线程执行同一个对象的同步代码,可保证修饰的代码在执行过程中不会被其他线程干扰。使用synchronized修饰的代码具有原子性和可见性,在需要进程同步的程序中使用的频率非常高,可以满足一般的进程同步要求(详见《Java多线程基础》)。

  synchronized实现的机理依赖于软件层面上的JVM,因此其性能会随着Java版本的不断升级而提高。事实上,在Java1.5中,synchronized是一个重量级操作,需要调用操作系统相关接口,性能是低效的,有可能给线程加锁消耗的时间比有用操作消耗的时间更多。到了Java1.6,synchronized进行了很多的优化,有适应自旋、锁消除、锁粗化、轻量级锁及偏向锁等,效率有了本质上的提高。在之后推出的Java1.7与1.8中,均对该关键字的实现机理做了优化。

  需要说明的是,当线程通过synchronized等待锁时是不能被Thread.interrupt()中断的,因此程序设计时必须检查确保合理,否则可能会造成线程死锁的尴尬境地。

最后,尽管Java实现的锁机制有很多种,并且有些锁机制性能也比synchronized高,但还是强烈推荐在多线程应用程序中使用该关键字,因为实现方便,后续工作由JVM来完成,可靠性高。只有在确定锁机制是当前多线程程序的性能瓶颈时,才考虑使用其他机制,如ReentrantLock等。

 

Java中锁的机制

synchronized–Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

1.当两个并发线程访问同一个对象Object中的这个synchronized同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块后才能执行该代码块。

2.然而,当一个线程访问Object的一个synchronized同步代码块时,另一个线程仍然可以访问该Object中的非synchronized同步代码块。

3.尤其关键的是,当一个线程访问Object的一个同步代码块时,其他线程对Object中所有其他同步代码块的访问将被阻塞。也就是说,当一个线程访问Object的一个同步代码块时,他就获得了这个Object的对象锁。结果,其他线程对该Object对象所有同步代码部分的访问都被暂时阻塞。

注:只能放在方法声明上(限定修饰符public、private之后,返回值void、Object之前)和方法内部使用。

 

13. 反射获取class对象的方式有哪些,反射创建对象的方式有哪些。

反射中,欲获取一个类或者调用某个类的方法,首先要获取到该类的 Class 对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值