Java知识点汇总(面试用)

1. java中的基本数据类型有哪些? 

答:byte, short, int, long, float, double, char,  boolean. 剩下的都是引用类型(reference type)

2. String类可以被继承吗?

答:不可以. 因为String类是final类.

3. String和StringBuilder,StringBuffer的区别?

答:String是只读字符串,String引用的字符串内容是不能被改变的.而StringBuffer和StringBuilder是可变字符串.StringBuilder和StringBuffer的用法相同, 区别是StringBuffer被synchronized修饰,是线程安全的,但效率比StringBuilder低。

4.构造器是否可以被重写?

答: 构造器不能被继承,因此不能被重写,但是可以被重载.

5.抽象类和接口的相同点和不同点.

答: 1)抽象类和接口都不能实例化对象,但是可以定义抽象类和接口类型的引用. 

    2)继承抽象类和实现接口都要对其中的抽象方法全部实现

    3)接口比抽象类更加抽象,抽象类中可以定义构造器,可以有抽象方法和具体方法.

    4)接口中方法全部都是抽象方法.

    5)抽象类中的成员可以是private,protected,public,接口全部都是public

    6)抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量.

    7)有抽象方法的类必须声明为抽象类,而抽象类未必要有抽象方法.

6. java中会存在内存泄露吗?

答:理论上java不会存在内存泄露的问题,应为有垃圾回收机制(GC).然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此会导致内存泄露. 例如hibernated的Session中的对象属于持久态,垃圾回收器不会回收这些对象,这些对象中有可能存在无用的垃圾对象.如果关闭不及时,一级缓存就可能导致内存泄露.

7.final,finally, finalize有什么区别?

答:

  • final用于声明属性、方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
  • finally是异常处理语句结构的一部分,表示总是执行
  • finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。

8. List,Map,Set 三个接口存取元素时,各自有什么特点?

答:

  • List以特定的索引来存取元素,可以有重复元素
  • Set不能存放重复元素.
  • Map保存键值对的映射,映射关系可以是一对一或多对一.
  • Set和Map容器都有基于哈希存储和排序树的两种实现版本,基于哈希存储理论存取时间复杂度是O(1).

9. 线程的sleep()方法和yield()方法有什么区别?

答:

  • sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;
  • yield()方法只会给相同优先级或更高优先级的线程以运行的机会; 
  • 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态; 
  • sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
  • sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。

10. 转发(forward)和重定向(redirect)的区别?

答:forward是容器中控制权的转向,是服务器请求资源,服务器直接访问目标地址的URL,把那个URL 的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址redirect就是服务器端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,因此从浏览器的地址栏中可以看到跳转后的链接地址,很明显redirect无法访问到服务器保护起来资源,但是可以从一个网站redirect到其他网站。

11.Cookie和Session的区别:

1)cookie数据存放在客户的浏览器上,session数据放在服务器上。

2)cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。

3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。

4)单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

    所以个人建议:将登陆信息等重要信息存放为session;其他信息如果需要保留,可以放在cookie中。

12.位运算符可能会出现的笔试题目:

1)交换两个变量的值,不准出现第三方变量。例如:int a = 3;int b = 5;

               /*
		第一种方式: 定义第三方变量。
		int temp = a;  //3 
		a = b; //a = 5 
		b = temp; 
		
		方式2:相加法, 缺点: 两个int类型的数据相加,有可能会出现超出int的表示范围。
		a = a+b;  // a =8
		b = a-b; //b = 8 - 5 = 3
		a = a-b; // a = 8 - 3 = 5
		
		方式3: 可以使用异或。 缺点: 逻辑不清晰。
		*/
		a = a^b;  // a = 3^5
		b = a^b;  // b = (3^5)^5 = 3
		a = a^b; //  a = (5^3)^3 = 5 

      2)取出一个二进制数据的指定位数。要求读取该二进制数据的低4位。则用与的方式来做,即低4位用1去与,其他位用0去与运算。

 13.解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法。   

答:通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;而通过new关键字和构造器创建的对象放在堆空间;程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在静态区中。栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,理论上整个内存没有被其他进程使用的空间甚至硬盘上的虚拟内存都可以被当成堆空间来使用。

如:String str = new String("hello");语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而”hello”这个字面量放在静态区。

14.为什么使用数据索引能提高效率?

答:

1)数据索引的存储是有序的

2)在有序的情况下,通过索引查询一个数据是无需遍历索引记录的

3)极端情况下,数据索引的查询效率为二分法查询效率,趋近于 log2(N)

15.重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

答:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求。

16.抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

答:都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

17.请说出与线程同步以及线程调度相关的方法。

答:

  • wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
  • sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;
  • notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;
  • notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态。

提示:关于Java多线程和并发编程的问题,建议大家看我的另一篇文章《关于Java并发编程的总结和思考》

补充:Java 5通过Lock接口提供了显式的锁机制(explicit lock),增强了灵活性以及对线程的协调。Lock接口中定义了加锁(lock())和解锁(unlock())的方法,同时还提供了newCondition()方法来产生用于线程之间通信的Condition对象;此外,Java 5还提供了信号量机制(semaphore),信号量可以用来限制对某个共享资源进行访问的线程的数量。在对资源进行访问之前,线程必须得到信号量的许可(调用Semaphore对象的acquire()方法);在完成对资源的访问后,线程必须向信号量归还许可(调用Semaphore对象的release()方法)。

18. 编写多线程程序有几种实现方式?

答:Java 5以前实现多线程有两种实现方法:一种是继承Thread类;另一种是实现Runnable接口。两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用Runnable接口更为灵活。

补充:Java 5以后创建线程还有第三种方式:实现Callable接口,该接口中的call方法可以在线程执行结束时产生一个返回值,代码如下所示:

19. Java中如何实现序列化,有什么意义?

答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。
要实现序列化,需要让一个类实现Serializable接口,该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过writeObject(Object)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。序列化除了能够实现对象的持久化之外,还能够用于对象的深度克隆。

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

答:字节流和字符流。字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。在java.io 包中还有许多其他的流,主要是为了提高性能和使用方便。

关于Java的I/O需要注意的有两点:一是两种对称性(输入和输出的对称性,字节和字符的对称性);二是两种设计模式(适配器模式和装潢模式)。另外Java中的流不同于C#的是它只有一个维度一个方向。

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

答:

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

22. MyBatis中使用#和$书写占位符有什么区别?

答:#将传入的数据都当成一个字符串,会对传入的数据自动加上引号;$将传入的数据直接显示生成在SQL中。注意:使用$占位符可能会导致SQL注射攻击,能用#的地方就不要使用$,写order by子句的时候应该用$而不是#。

23.MyBatis中的动态SQL是什么意思?

答:对于一些复杂的查询,我们可能会指定多个查询条件,但是这些条件可能存在也可能不存在,例如在58同城上面找房子,我们可能会指定面积、楼层和所在位置来查找房源,也可能会指定面积、价格、户型和所在位置来查找房源,此时就需要根据用户指定的条件动态生成SQL语句。如果不使用持久层框架我们可能需要自己拼装SQL语句,还好MyBatis提供了动态SQL的功能来解决这个问题。MyBatis中用于实现动态SQL的元素主要有:

  • if
  • choose / when / otherwise
  • trim
  • where
  • set
  • foreach

24.什么是IoC和DI?DI是如何实现的?

答:IoC叫控制反转,是Inversion of Control的缩写,DI(Dependency Injection)叫依赖注入,是对IoC更简单的诠释。控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的”控制反转”就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。IoC体现了好莱坞原则 – “Don’t call me, we will call you”。依赖注入的基本原则是应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI是对IoC更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。

举个例子:一个类A需要用到接口B中的方法,那么就需要为类A和接口B建立关联或依赖关系,最原始的方法是在类A中创建一个接口B的实现类C的实例,但这种方法需要开发人员自行维护二者的依赖关系,也就是说当依赖关系发生变动的时候需要修改代码并重新构建整个系统。如果通过一个容器来管理这些对象以及对象的依赖关系,则只需要在类A中定义好用于关联接口B的方法(构造器或setter方法),将类A和接口B的实现类C放入容器中,通过对容器的配置来实现二者的关联。

依赖注入可以通过setter方法注入(设值注入)、构造器注入和接口注入三种方式来实现,Spring支持setter注入和构造器注入,通常使用构造器注入来注入必须的依赖关系,对于可选的依赖关系,则setter注入是更好的选择,setter注入需要类提供无参构造器或者无参的静态工厂方法来创建对象。

25.解释一下什么叫AOP(面向切面编程)?

答:AOP(Aspect-Oriented Programming)指一种程序设计范型,该范型以一种称为切面(aspect)的语言构造为基础,切面是一种新的模块化机制,用来描述分散在对象、类或方法中的横切关注点(crosscutting concern)。

”横切关注”是会影响到整个应用程序的关注功能,它跟正常的业务逻辑是正交的,没有必然的联系,但是几乎所有的业务逻辑都会涉及到这些关注功能。通常,事务、日志、安全性等关注就是应用中的横切关注功能。

26.Spring中自动装配的方式有哪些?

答:

  • no:不进行自动装配,手动设置Bean的依赖关系。
  • byName:根据Bean的名字进行自动装配。
  • byType:根据Bean的类型进行自动装配。
  • constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。
  • autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。

说明:自动装配没有自定义装配方式那么精确,而且不能自动装配简单属性(基本类型、字符串等),在使用时应注意。

27.Spring中的自动装配有哪些限制?

答:

  • 如果使用了构造器注入或者setter注入,那么将覆盖自动装配的依赖关系。
  • 基本数据类型的值、字符串字面量、类字面量无法使用自动装配来注入。
  • 优先考虑使用显式的装配来进行更精确的依赖注入而不是使用自动装配。

28. 线程和进程的区别?

答:线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。

29.B+树索引和哈希索引的区别?

答:

1)B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且同层级的节点间有指针相互链接,是有序的;

2)哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可,是无序的。

30.Runnable接口和Callable接口的区别?

答:Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。

31.volatile关键字的作用?

答:

1)使用volatile关键字修饰的变量,保证了其在多线程之间的可见性,即每次读取到volatile变量,一定是最新的数据。

2)对任意单个volatile关键字修饰的变量的读/写具有原子性,即不可被中断的一个或一系列操作。

32.sleep方法和wait方法有什么区别 ?

答:sleep方法和wait方法都可以用来放弃CPU一定的时间,不同点在于如果线程持有某个对象的监视器,sleep方法不会放弃这个对象的监视器,wait方法会放弃这个对象的监视器。

33.什么是乐观锁和悲观锁?

答:

1)乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁;

2)悲观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态,悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁。

34.垃圾回收的优点和原理,并考虑2种回收机制?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
答:

1)优点:可以有效的防止内存泄漏,有效的使用可以使用的内存;

2)原理:对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆中的所有对象。通过这种方式确定哪些对象是“可达的”,哪些对象是“不可达的”。当GC确定一些对象为“不可达”时,GC就有责任回收这些内存空间。

3)回收机制:分代复制垃圾回收、标记垃圾回收和增量垃圾回收。

4)垃圾回收器可以马上回收内存。

5)程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定执行。

35.请说出 ArrayList和Vector的区别?

答:主要从两方面来说:

1)同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程不安全的,不是同步的。

2)数据增长:当需要增长时,Vector默认增长为原来的一倍,而ArrayList却是原来的一半。

36.HashMap和Hashtable的区别?

答:

  • Hashtable是线程安全,而HashMap则非线程安全;
  • HashMap可以使用null作为key,而Hashtable则不允许null作为key;
  • HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类。

猜你喜欢

转载自blog.csdn.net/xudasong123/article/details/79772671