您的位置:首页 > 职场人生

Java常见面试题总结,大厂 HR 如何面试

2019-04-16 01:22 926 查看


写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。扫码加微信好友进【程序员面试学习交流群】,免费领取。也欢迎各位一起在群里探讨技术。

 

转载请注明出处https://www.cnblogs.com/lwy521/

 

1.面向对象

面向对象是基于现实事物,将事物抽象成对象,赋予对象属性和方法,让后让每一对象去执行自己的方法与属性,面向对象有三大基本特性:

封装:把对象的属性方法结合在一起,成为一个独立的代码块。并尽可能隐藏对象的内部实现环节

继承:从已有的类派生新的类。新类能得到已有的类的属性和方法,并可以扩展出新的属性和行为,继承的作用是为了提高代码的复用性,继承具有传递性,单一性

多态:是同一种行为,有多重不同的表现状态或形态的能力,分为行为的多态和对象的多态,表现形式有重写重载向上造型

2.重载重写的区别

1>重写:发生在父子类中,方法名相同,参数列表相同,方法体不同,遵循运行期绑定,看对象类型类调用方法

两同两小一大

两小:返回值,异常小于等于父类返回值,异常

一大:访问修饰符大于等于父类访问修饰符

2>重载:发生在一个类中,方法名相同,参数列表不同,方法体不用,遵循"编译期绑定",看引用/参数类型来绑定方法.

为什么不能根据返回类型来区分重载",快说出你的答案吧!

因为调用时不能指定类型信息,编译器不知道你要调用哪个函数。 例如:

float max(int a, int b);

int max(int a, int b);

当调用max(1, 2);时无法确定调用的是哪个,单从这一点上来说,仅返回值类型不同的重载是不应该允许的。

3.抽象类与接口的区别

1>接口是完全抽象的,不存在方法的实现

抽象类可以方法的实现

2>接口使用implement实现方法,子类必须实现方法

抽象类通过extends继承,如果子类不是抽象类,那么必须去实现抽象方法

3>接口没有构造器

抽象类有构造器,但不能被实例化

4>抽象方法可以有public、protected和default这些修饰符

接口只能被默认的public修饰

5>抽象方法可以有main方法并且我们可以运行它;

接口没有

6>抽象方法可以继承一个类和实现多个接口

接口只可以继承一个或多个其他接口

声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。

接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。

4.什么是匿名内部类

没有名字的类称为匿名内部类,想要创建一个父类接口的子类对象,且该对象只被创建一次,此时 该类不必命名,称为匿名内部类

1.只能用于继承一个类或者实现一个接口,并且只能创建一个该类的实例

2.匿名内部类中没有构造方法,访问控制修饰符.也不能有静态的变量,方法和类.

3.匿名内部类属于局部内部类,所以局部内部类的限制也对其有效,只能访问外部类的静态方法和静态变量

5.int 与integer的区别

1>int是基本数据对象,不能直接参与面向对象的开发,所以提供了包装类Integer

2>integer变量必须实例化后才能使用,int变量不需要.

3>Integer的默认值为null,int的默认值为0;

4>jdk1.5提供自动拆装箱,满足了基本数据变量与引用类型的赋值

6.正则表达式

正则表达式是用于字符串的匹配和替换,验证当前字符串是否满足各种需求.

7.String,StringBuilder和StringBuffer的区别。

1.String:字符串常量,是不可变对象,每次对String类型进行改变都等同于生成了一个新的String对象,速度慢. 适用于少量字符串操作的情况.

2.StringBuffer:其中很多方法有synchronized关键字,是线程安全的可变字符序列,速度较快.适用于多线程下在字符缓冲区进行大量操作的情况

2.StringBuilder,JDK1.5之后推出的与StringBuffer兼容的API,用作StringBuffer的一个简单替换,单个线程使用时,建议优先采用,速度最快.适用于多线程下载字符缓冲区进行大量操作的情况.

8.什么是socket?

套接字(socket)是一个网络中特定节点的网络标识符,套接字包含一个特定的地址和端口号,java中的网络通信是通过socket实现的,socket包含两大类: serversocket和socket两大类,ServerSocket用于服务器端,可以通过accept方法监听请求,监听请求后返回Socket,Socket用于完成具体数据传输,客户端也可以使用Socket发起请求并传输数据.

9.Html与xml的区别。

1.HTML:超文本标记语言,XML:可扩展标记语言

2.HTML语法不严格区分大小写,可以自动过滤空格,可以不适用引号等,XML却相反

3.HTML中有固定的标签,xml可以自定义和扩展标签

4.HTML是用来显示数据的,xml是用来描述,存放数据的.

10.Throw与throws的区别

1.Throws出现在方法函数头;而throw出现在函数体

2.throws表示出现异常的一种可能性,并不一定会发生这些异常;

throw则是抛出了异常,执行throw则一定抛出了某种异常对象.

3.它们都是消极处理异常的方式,只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理.

11.说一说你对异常处理机制的理解

如果程序不能正常的运行,那么可以就可以通过另一种路径退出方法,在这种情况下会抛出一个封装了错误信息的对象。这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其他代码也无法继续执行,异常处理机制会将代码执行交给异常处理器。

如果出现RuntimeException,那么一定是程序员的错误

遇到问题不进行具体处理,而是继续抛给调用者 抛出异常有三种形式,

1.是throw,一个throws,还有一种系统自动抛异常。

2.针对性处理方式:使用try-catch捕获异常

12. Final和finally以及finalize的区别

1.Final:修饰符关键字,用于声明属性,方法和类,分别表示:属性不可改变,方法不能被重写,类不能被继承.

2.Finally:是异常处理机制的一部分,finally确保只要程序执行到try块中,那么finally块中的代码必定执行.

3.Finalize:是Object类的一个方法,在垃圾收集器(gc)将对象从内存中清除出去之前,做必要的清理工作和其他资源的回收.

13.List,set,map的区别。

1.List是Collection的一个子接口,称为线性表,是可重复有序集,可以通过下标对元素操作,常用实现类有ArrayList:数组实现,查询性能好.和LinkedList:链表实现,便于增删元素.

2.set也是Collection的一个子接口,是不可重复且无序集,但其实现类能对集合中的对象按照特定的方式排序,比如TreeSet.常用实现类有HashSet和TreeSet.

3.Map接口,查找表,其中的每一个元素是一个键值对,键对象不可重复,值对象可重复.常用实现类有:HashMap:当今世界查询速度最快的数据结构.HashTable 和LinkedHashMap 等.

Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别:

Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。

equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。

14.HashMap与HashTable的区别。

1.HashMap是线程不安全的,HashMap是Map的一个子接口,是将键映射到值得到对象,不允许键值重复,允许空键和空值.

2.HashTable是线程安全的集合,不允许null值作为key或value,它是synchronized修饰的,多个线程访问时不需要自己为它的方法实现同步,而HashMap在被多个线程访问时需要自己为它的方法实现同步.

3.由于HashMap非线程安全,所以HashMap的效率要比HashTable的效率高一些.

15.线程与进程的区别

1、定义

进程:是执行中一段程序,即一旦程序被载入到内存中并准备执行,它就是一个进程。进程是操作系统资源分配的基本单位.

线程:单个进程中执行中每个任务就是一个线程。

线程:是进程中任务调度和执行的基本单位

2、一个线程只能属于一个进程,但是一个进程可以拥有多个线程。多线程处理就是允许一个进程中在同一时刻执行多个任务。

3、线程是一种轻量级的进程,与进程相比,线程给操作系统带来侧创建、维护、和管理的负担要轻,意味着线程的代价或开销比较小。

4.没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

16.线程的生命周期?线程有哪些状态

1、线程的生命周期:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5种状态。

17.说一说你对反射机制的看法?反射机制的优缺点?

1.反射机制:将在编译期实例化一个类,操作其属性和方法的操作转换为运行期决定.

2.适度使用可以提高代码的灵活度,过度使用会降低代码运行效率,增加资源开销.

3.步骤:

1.通过class类中的forName静态方法获取加载类对象

2.通过类对象实例化该类.newInstance方法

3.获取类中的方法,通过传入参数匹配对应的方法

getDeclaredMethods("方法名","数据类型.class")

4.传入实参,执行该方法

invoke(obj,"实参").

18.如何创建一个线程池?利用线程池有哪些好处。(数据库连接池)

1.线程池:管理线程机制,主要解决重用线程和控制线程数量.

2.可以有效处理多个线程的并发问题,避免大量的线程因为互相强占系统资源导致阻塞现象,有效降低频繁创建和销毁对性能带来的开销.

3.对线程数量的控制也应在硬件的承受范围之内.

4.创建:fixedThreadPool:正规线程池,指定了线程数,有核心线程,正规的并发线程,响应速度快,多用于服务器.

ExecutorService threadpool = Executors.newFixedThreadPool(3);

19.HTTP协议

HttP协议:超文本传输协议

1.该协议是应用层协议,该协议应用在浏览器与服务器之间

2.规定了浏览器与服务器之间数据传输的方式,以及数据内容定义等规则

3.HTTP协议要求必须建立在可靠的传输协议基础上,通常使用的是TCP协议.

4.HTTP协议定义了浏览器(浏览器)与服务器之间的交互规则:要求客户端发起请求,服务端接收请 求并处理,然后响应客户端.不允许服务端主动响应客户端.

5.HTTP协议要求使用的字符集为ISO8859-1,不支持中文字符,所以传输中文时需要特别处理.

19.静态变量和实例变量的区别

1.实例变量是属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量.

2.静态变量属于类,也称类变量,只要程序加载了类的字节码文件,无需创建任何实例对象,静态变量就会被分配空间(方法区),就可以被使用

3.总结:实例变量必须在创建对象后才可以通过这个对象来使用,而静态变量可以直接使用类名类引用.

2 20000 0.内存管理:

1.堆中存放: new出来的对象(包括实例变量)

实例变量生命周期:从对象被创建到被回收

2.栈中存放: 正在调用的方法中的局部变量(包括方法中的参数)

局部变量生命周期:调用方法时存在栈中,方法结束时与栈帧一次消失.

3.方法区: 存储.class字节码文件(包括方法,静态变量);

21.&和&&的区别:

&是位运算符。&&是布尔逻辑运算符。

22.Collection 和 Collections的区别:

Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。

Collection是个java.util下的接口,它是各种集合结构的父接口。

22.GC是什么? 为什么要有GC? (基础):

GC是垃圾收集器。Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:

System.gc()

Runtime.getRuntime().gc()。

23.String s = new String("xyz");创建了几个String Object:

两个对象,一个是“xyx”,一个是指向“xyx”的引用对象s。

第一个对象是字符串常量"xyz" 第二个对象是new String("xyz")的时候产生的,在堆中分配内存给这个对象,只不过这个对象的内容是指向字符串常量"xyz" 另外还有一个引用s,指向第二个对象。这是一个变量,在栈中分配内存。

24.sleep() 和 wait() 有什么区别:

sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)“醒来”的线程具有更高的优先级(b)正在运行的线程因为其它原因而阻塞。

wait()是线程交互时,如果线程对一个同步对象x 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。

25.数组有没有length()这个方法? String有没有length()这个方法:

数组没有length()这个方法,有length的属性。

String有有length()这个方法。

26.启动一个线程是用run()还是start():

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。

27.构造器Constructor是否可被override:

构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading。

28.try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后:

会执行,在return前执行。

在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,就会返回修改后的值。显然,在finally中返回或者修改返回值会对程序造成很大的困扰,C#中直接用编译错误的方式来阻止程序员干这种龌龊的事情,Java中也可以通过提升编译器的语法检查级别来产生警告或错误,Eclipse中可以在如图所示的地方进行设置,强烈建议将此项设置为编译错误。

29.ArrayList和Vector的区别,HashMap和Hashtable的区别:

答:就ArrayList与Vector主要从二方面来说.

一.同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的

二.数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半

就HashMap与HashTable主要从三方面来说。

一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现

二.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的

三.值:只有HashMap可以让你将空值作为一个表的条目的key或value。

30.说一说Servlet的生命周期:

答:servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。

31.JAVA SERVLET API中forward() 与redirect()的区别:

答:前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,前者更加高效,在前者可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用sendRedirect()方法。

32.Class.forName的作用?为什么要用:

答:调用该访问返回一个以字符串指定类名的类的对象。

33.Jdo是什么:

JDO是Java对象持久化的新的规范

34.xml有哪些解析技术?区别是什么:

答:有DOM,SAX,STAX等

DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问

SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问

STAX:Streaming API for XML (StAX)。

35.基本数据类型包括byte1、short2、int4、long8、char2、float4、double8、boolean1

36.序列化和反序列化的概念

把对象转换为字节序列的过程称为对象的序列化

把字节序列恢复为对象的过程称为对象的反序列化

37.heap和stack有什么区别:

栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。堆是栈的一个组成元素。

38.J2EE是技术还是平台还是框架:

J2EE本身是一个标准,一个为企业分布式应用的开发提供的标准平台。

J2EE也是一个框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技术。

编写 java文件的注意事项:

39.常用的设计模式?说明工厂模式:

Java中的23种设计模式:Factory(工厂模式),Builder(建造模式), Factory Method(工厂方法模式),Prototype(原始模型模式),Singleton(单例模式), Facade(门面模式),Adapter(适配器模式), Bridge(桥梁模式), Composite(合成模式),Decorator(装饰模式), Flyweight(享元模式), Proxy(代理模式),Command(命令模式), Interpreter(解释器模式), Visitor(访问者模式),Iterator(迭代子模式), Mediator(调停者模式), Memento(备忘录模式),Observer(观察者模式),State(状态模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibleity(责任链模式)。

工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,通常这一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

40.java中有几种方法可以实现一个线程?

有两种实现方法,分别是继承Thread类与实现Runnable接口

41.什么是java序列化,如何实现java序列化:

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

42.垃圾回收的优点和原理。并考虑2种回收机制

答:Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

43.是否可以继承String类

答:String类是final类故不可以继承

44.抽象类的特点:

1:抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。

2:抽象方法只定义方法声明,并不定义方法实现。

3:抽象类不可以被创建对象(实例化)。

4:只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。

5: 抽象类只能单继承。

45.js块元素,行元素

块元素

<address> 定义地址

<caption> 定义表格标题

<dd> 定义列表中定义条目

<div> 定义文档中的分区或节

<dl> 定义列表

<dt> 定义列表中的项目

<fieldset> 定义一个框架集

<form> 创建 HTML 表单

<h1> 定义最大的标题

<h2> 定义副标题

<h3> 定义标题

<h4> 定义标题

<h5> 定义标题

<h6> 定义最小的标题

<hr> 创建一条水平线

<legend> 元素为 fieldset 元素定义标题

<li> 标签定义列表项目

<noframes> 为那些不支持框架的浏览器显示文本,于 frameset 元素内部

<noscript> 定义在脚本未被执行时的替代内容

<ol> 定义有序列表

<ul> 定义无序列表

<p> 标签定义段落

<pre> 定义预格式化的文本

<table> 标签定义 HTML 表格

<tbody> 标签表格主体(正文)

<td> 表格中的标准单元格

<tfoot> 定义表格的页脚(脚注或表注)

<th> 定义表头单元格

<thead> 标签定义表格的表头

<tr> 定义表格中的行

<a>行元素 标签可定义锚

<abbr> 表示一个缩写形式

<acronym> 定义只取首字母缩写

<b> 字体加粗

<bdo> 可覆盖默认的文本方向

<big> 大号字体加粗

<br> 换行

<cite> 引用进行定义

<code> 定义计算机代码文本

<dfn> 定义一个定义项目

<em> 定义为强调的内容

<i> 斜体文本效果

<img> 向网页中嵌入一幅图像

<input> 输入框

<kbd> 定义键盘文本

<label> 标签为 input 元素定义标注(标记)

<q> 定义短的引用

<samp> 定义样本文本

<select> 创建单选或多选菜单

<small> 呈现小号字体效果

<span> 组合文档中的行内元素

<strong> 语气更强的强调的内容

<sub> 定义下标文本

<sup> 定义上标文本

<textarea> 多行的文本输入控件

<tt> 打字机或者等宽的文本效果

<var> 定义变量

46.修饰权限问题

47.描述一下JVM加载class文件的原理机制?

答:JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。 由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始化语句。 类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加载器的说明:

Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);

Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;

System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中加载类,是用户自定义加载器的默认父加载器。

48.静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?

答:Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化,其语法看起来挺诡异的,如下所示。

面试题 - 下面的代码哪些地方会产生编译错误?

class Outer {

class Inner {}

public static void foo() { new Inner(); }

public void bar() { new Inner(); }

public static void main(String[] args) {

new Inner();

}

}

注意:Java中非静态内部类对象的创建要依赖其外部类对象,上面的面试题中foo和main方法都是静态方法,静态方法中没有this,也就是说没有所谓的外部类对象,因此无法创建内部类对象,如果要在静态方法中创建内部类对象,可以这样做:

new Outer().new Inner();

49.数据类型之间的转换:

如何将字符串转换为基本数据类型?

如何将基本数据类型转换为字符串?

答:

调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;

一种方法是将基本数据类型与空字符串("")连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf()方法返回相应字符串

50.如何实现字符串的反转及替换?

答:方法很多,可以自己写实现也可以使用String或StringBuffer/StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:

public static String reverse(String originStr) {

if(originStr == null || originStr.length() <= 1)

return originStr;

return reverse(originStr.substring(1)) + originStr.charAt(0);

}

51.Error和Exception有什么区别?

答:Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;Exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。

52.列出一些你常见的运行时异常?

答:

ArithmeticException(算术异常)

ClassCastException (类转换异常)

IllegalArgumentException (非法参数异常)

IndexOutOfBoundsException (下标越界异常)

NullPointerException (空指针异常)

SecurityException (安全异常)

53、List、Set、Map是否继承自Collection接口?

答:List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。

54.List、Set、Map是否继承自Collection接口?

答:List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。

55.synchronized关键字的用法?

答:synchronized关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问,可以用synchronized(对象) { … }定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符。在第60题的例子中已经展示了synchronized关键字的用法。

56.Java中有几种类型的流?

答:字节流和字符流。字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。在 java.io 包中还有许多其他的流,主要是为了提高性能和使用方便。关于Java的I/O需要注意的有两点:一是两种对称性(输入和输出的对称性,字节和字符的对称性);二是两种设计模式(适配器模式和装潢模式)。另外Java中的流不同于C#的是它只有一个维度一个方向。

面试题 - 编程实现文件拷贝。(这个题目在笔试的时候经常出现,下面的代码给出了两种实现方案)

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

public final class MyUtil {

private MyUtil() {

throw new AssertionError();

}

public static void fileCopy(String source, String target) throws IOException {

try (InputStream in = new FileInputStream(source)) {

try (OutputStream out = new FileOutputStream(target)) {

byte[] buffer = new byte[4096];

int bytesToRead;

while((bytesToRead = in.read(buffer)) != -1) {

out.write(buffer, 0, bytesToRead);

}

}

}

}

public static void fileCopyNIO(String source, String target) throws IOException {

try (FileInputStream in = new FileInputStream(source)) {

try (FileOutputStream out = new FileOutputStream(target)) {

FileChannel inChannel = in.getChannel();

FileChannel outChannel = out.getChannel();

ByteBuffer buffer = ByteBuffer.allocate(4096);

while(inChannel.read(buffer) != -1) {

buffer.flip();

outChannel.write(buffer);

buffer.clear();

}

}

}

}

}

注意:上面用到Java 7的TWR,使用TWR后可以不用在finally中释放外部资源 ,从而让代码更加优雅。

57.你在项目中哪些地方用到了XML?

答:XML的主要作用有两个方面:数据交换和信息配置。在做数据交换时,XML将数据用标签组装成起来,然后压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再从XML文件中还原相关信息进行处理,XML曾经是异构系统间交换数据的事实标准,但此项功能几乎已经被JSON(JavaScript Object Notation)取而代之。当然,目前很多软件仍然使用XML来存储配置信息,我们在很多项目中通常也会将作为配置信息的硬代码写在XML文件中,Java的很多框架也是这么做的,而且这些框架都选择了dom4j作为处理XML的工具,因为Sun公司的官方API实在不怎么好用。

补充:现在有很多时髦的软件(如Sublime)已经开始将配置文件书写成JSON格式,我们已经强烈的感受到XML的另一项功能也将逐渐被业界抛弃。

58.获得一个类的类对象有哪些方式?

答:

方法1:类型.class,例如:String.class

方法2:对象.getClass(),例如:"hello".getClass()

方法3:Class.forName(),例如:Class.forName("java.lang.String")

59.如何通过反射创建对象?

答:

方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()

方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance("Hello");

60.用Java写一个单例类。

答:

饿汉式单例

public class Singleton {

private Singleton(){}

private static Singleton instance = new Singleton();

public static Singleton getInstance(){

return instance;

}

}

懒汉式单例

public class Singleton {

private static Singleton instance = null;

private Singleton() {}

public static synchronized Singleton getInstance(){

if (instance == null) instance = new Singleton();

return instance;

}

}

注意:实现一个单例有两点注意事项,①将构造器私有,不允许外界通过构造器创建对象;②通过公开的静态方法向外界返回类的唯一实例。这里有一个问题可以思考:Spring的IoC容器可以为普通的类创建单例,它是怎么做到的呢?

61.冒泡排序几乎是个程序员都写得出来,但是面试的时候如何写一个逼格高的冒泡排序却不是每个人都能做到,下面提供一个参考代码:

import java.util.Comparator;

/**

* 排序器接口(策略模式: 将算法封装到具有共同接口的独立的类中使得它们可以相互替换)

* @author nnngu

*

*/

public interface Sorter {

/**

* 排序

* @param list 待排序的数组

*/

public <T extends Comparable<T>> void sort(T[] list);

/**

* 排序

* @param list 待排序的数组

* @param comp 比较两个对象的比较器

*/

public <T> void sort(T[] list, Comparator<T> comp);

}

import java.util.Comparator;

/**

* 冒泡排序

*

* @author nnngu

*

*/

public class BubbleSorter implements Sorter {

@Override

public <T extends Comparable<T>> void sort(T[] list) {

boolean swapped = true;

for (int i = 1, len = list.length; i < len && swapped; ++i) {

swapped = false;

for (int j = 0; j < len - i; ++j) {

if (list[j].compareTo(list[j + 1]) > 0) {

T temp = list[j];

list[j] = list[j + 1];

list[j + 1] = temp;

swapped = true;

}

}

}

}

@Override

public <T> void sort(T[] list, Comparator<T> comp) {

boolean swapped = true;

for (int i = 1, len = list.length; i < len && swapped; ++i) {

swapped = false;

for (int j = 0; j < len - i; ++j) {

if (comp.compare(list[j], list[j + 1]) > 0) {

T temp = list[j];

list[j] = list[j + 1];

list[j + 1] = temp;

swapped = true;

}

}

}

}

 


转载:https://www.cnblogs.com/lwy521/p/9991535.html

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: