面经 - Java 基础面试题4

简介: 面经 - Java 基础面试题4

161、Java中的泛型是什么?使用泛型的好处是什么?

解析:泛型是JavaSE1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。好处:

1、类型安全,提供编译期间的类型检测。

2、前后兼容。

3、泛化代码,代码可以更多的重复利用。

4、性能较高,用GJ(泛型JAVA)编写的代码可以为java编译器和虚拟机带来更多的类型信息,这些信息对java程序做进一步优化提供条件。


162、Java的泛型是如何工作的?什么是类型擦除?如何工作?

解析:

1、类型检查:在生成字节码之前提供类型检查

2、类型擦除:所有类型参数都用他们的限定类型替换,包括类、变量和方法(类型擦除)

3、如果类型擦除和多态性发生了冲突时,则在子类中生成桥方法解决

4、如果调用泛型方法的返回类型被擦除,则在调用该方法时插入强制类型转换


类型擦除:所有类型参数都用他们的限定类型替换:

比如:T -> Object ? extends BaseClass -> BaseClass

如何工作:泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如List在运行时仅用一个List来表示。

这样做的目的,是确保能和Java5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。

根据你对这个泛型问题的回答情况,你会得到一些后续提问,比如为什么泛型是由类型擦除来实现的或者给你展示一些会导致编译器出错的错误泛型代码。

详情:https://blog.csdn.net/Dream_Weave/article/details/116660646


163、你可以把List传递给一个接受List参数的方法吗?

解析:对任何一个不太熟悉泛型的人来说,这个Java泛型题目看起来令人疑惑,因为乍看起来String是一种Object,所以List应当可以用在需要List的地方,但是事实并非如此。真这样做的话会导致编译错误。如果你再深一步考虑,你会发现Java这样做是有意义的,因为List可以存储任何类型的对象包括String, Integer等等,而List却只能用来存储Strings。

List<Object>objectList;
List<String>stringList;
objectList=stringList;  // compilation error incompatible types


164、如何阻止Java中的类型未检查的警告?

解析:如果你把泛型和原始类型混合起来使用,例如下列代码,Java5的Javac编译器会产生类型未检查的警告,例如

List<String>rawList=newArrayList();

注意:Hello.java使用了未检查或称为不安全的操作;这种警告可以使用@SuppressWarnings(“unchecked”)注解来屏蔽。


165、Java中List和原始类型List之间的区别?

解析:原始类型和带参数类型之间的主要区别是,在编译时编译器不会对原始类型进行类型安全检查,却会对带参数的类型进行检查,通过使用Object作为类型,可以告知编译器该方法可以接受任何类型的对象,比如String或Integer。这道题的考察点在于对泛型中原始类型的正确理解。它们之间的第二点区别是,你可以把任何带参数的类型传递给原始类型List,但却不能把List传递给接受List的方法,因为会产生变异错误。


166、编写一段泛型程序来实现LRU缓存?

解析:Java - 快速手撕 LRU 算法


167、Array中可以用泛型吗?

解析:这可能是Java泛型面试题中最简单的一个了,当然前提是你要知道Array事实上并不支持泛型,这也是为什么Joshua Bloch在Effective Java一书中建议使用List来代替Array,因为List可以提供编译期的类型安全保证,而Array却不能。


168、如何编写一个泛型方法,让它能接受泛型参数并返回泛型类型?

解析:编写泛型方法并不困难,你需要用泛型类型来替代原始类型,比如使用T,E or K,V等被广泛认可的类型占位符。最简单的情况下,一个泛型方法可能会像这样:

publicVput(Kkey, Vvalue) {
returncache.put(key, value);
}


169、C++ 模板和 Java 泛型之间有何不同?

解析:Java泛型实现根植于“类型消除”这一概念。当源代码被转换为Java虚拟机字节码时,这种技术会消除参数化类型。有了Java泛型,我们可以做的事情也并没有真正改变多少;他只是让代码变得漂亮些。鉴于此,Java泛型有时也被称为“语法糖”。

这和C++模板截然不同。在C++中,模板本质上就是一套宏指令集,只是换了个名头,编译器会针对每种类型创建一份模板代码的副本。

由于架构设计上的差异,Java泛型和C++模板有很多不同点:

C++模板可以使用int等基本数据类型。Java则不行,必须转而使用Integer。

在Java中,可以将模板的参数类型限定为某种特定类型。

在C++中,类型参数可以实例化,但java不支持。

在Java中,类型参数不能用于静态方法(?)和变量,因为它们会被不同类型参数指定的实例共享。在C++,这些类时不同的,因此类型参数可以用于静态方法和静态变量。

在Java中,不管类型参数是什么,所有的实例变量都是同一类型。类型参数会在运行时被抹去。在C++中,类型参数不同,实例变量也不同。


170、AJAX有哪些优点和缺点?

解析:

  • 优点

1、最大的一点是页面无刷新,用户的体验非常好。

2、使用异步方式与服务器通信,具有更加迅速的响应能力。

3、可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。

4、基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。


  • 缺点

1、ajax不支持浏览器back按钮。

2、安全问题AJAX暴露了与服务器交互的细节。

3、对搜索引擎的支持比较弱。

4、破坏了程序的异常机制。

5、不容易调试。


171、AJAX应用和传统Web应用有什么不同?

解析:在传统的Javascript编程中,如果想得到服务器端数据库或文件上的信息,或者发送客户端信息到服务器,需要建立一个HTML form然后GET或者POST数据到服务器端。用户需要点击”Submit”按钮来发送或者接受数据信息,然后等待服务器响应请求,页面重新加载。

因为服务器每次都会返回一个新的页面,所以传统的web应用有可能很慢而且用户交互不友好。

使用AJAX技术,就可以使Javascript通过XMLHttpRequest对象直接与服务器进行交互。

通过HTTP Request,一个web页面可以发送一个请求到web服务器并且接受web服务器返回的信息(不用重新加载页面),展示给用户的还是同一个页面,用户感觉页面刷新,也看不到到Javascript后台进行的发送请求和接受响应,体验非常好。


172、Ajax的实现流程是怎样的?

解析:

(1) 创建XMLHttpRequest对象,也就是创建一个异步调用对象

(2) 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息

(3) 设置响应HTTP请求状态变化的函数

(4) 发送HTTP请求

(5) 获取异步调用返回的数据

(6) 使用JavaScript和DOM实现局部刷新


具体一点:

1、创建XNLHttpRequest对象(不考虑ie)XMLHttpRequest request = new XMLHttprequest();

2、创建新的Http请求XMLHttprequest.open(method, url, flag, name, password);

3、设置响应Http请求变化的函数XMLHttprequest.onreadystatechange=getData;

functiongetData() {
if(XMLHttprequest.readyState==4){
// 获取数据    }
}

4、发送http请求:XMLHttprequest.send(data);

5、获取异步调用返回的对象

function(data) {
// 异步提交后,交互成功,返回的data便是异步调用返回的对象,该对象是一个string类型的}

6、使用js、DOM实现局部刷新:myDiv.innerHTML=''这是刷新后的数据''


173、简单说一下数据库的三范式?

解析:

  • 第一范式:数据库表的每一个字段都是不可分割的
  • 第二范式:数据库表中的非主属性只依赖于主键
  • 第三范式:不存在非主属性对关键字的传递函数依赖关系


174、Java集合框架是什么?说出一些集合框架的优点?

解析:每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector、Stack、HashTable和Array。


随着集合的广泛使用,Java1.2提出了囊括所有集合接口、实现和算法的集合框架。在保证线程安全的情况下使用泛型和并发集合类,Java已经经历了很久。它还包括在Java并发包中,阻塞接口以及它们的实现。


集合框架的部分优点如下:

(1)使用核心集合类降低开发成本,而非实现我们自己的集合类。

(2)随着使用经过严格测试的集合框架类,代码质量会得到提高。

(3)通过使用JDK附带的集合类,可以降低代码维护成本。

(4)复用性和可操作性。


175、Java集合框架的基础接口有哪些?

解析:Collection为集合层级的根接口。一个集合代表一组对象,这些对象即为它的元素。Java平台不提供这个接口任何直接的实现。

Set是一个不能包含重复元素的集合。这个接口对数学集合抽象进行建模,被用来代表集合,就如一副牌。

List是一个有序集合,可以包含重复元素。你可以通过它的索引来访问任何元素。List更像长度动态变换的数组。

Map是一个将key映射到value的对象.一个Map不能包含重复的key:每个key最多只能映射一个value。

一些其它的接口有Queue、Dequeue、SortedSet、SortedMap和ListIterator。


176、集合框架中的泛型有什么优点?

解析:Java1.5引入了泛型,所有的集合接口和实现都大量地使用它。泛型允许我们为集合提供一个可以容纳的对象类型。

因此,如果你添加其它类型的任何元素,它会在编译时报错。这避免了在运行时出现ClassCastException,因为你将会在编译时得到报错信息。

泛型也使得代码整洁,我们不需要使用显式转换和instanceOf操作符。它也给运行时带来好处,因为不会产生类型检查的字节码指令。


177、Enumeration和Iterator接口的区别?

解析:Enumeration的速度是Iterator的两倍,也使用更少的内存。Enumeration是非常基础的,也满足了基础的需要。

但是,与Enumeration相比,Iterator更加安全,因为当一个集合正在被遍历的时候,它会阻止其它线程去修改集合。

迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者从集合中移除元素,而Enumeration不能做到。为了使它的功能更加清晰,迭代器方法名已经经过改善。


178、Iterater和ListIterator之间有什么区别?

解析:

1、我们可以使用Iterator来遍历Set和List集合,而ListIterator只能遍历List。

2、Iterator只可以向前遍历,而LIstIterator可以双向遍历。

3、ListIterator从Iterator接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。


179、我们如何对一组对象进行排序?

解析:如果我们需要对一个对象数组进行排序,我们可以使用Arrays.sort()方法。如果我们需要排序一个对象列表,我们可以使用Collection.sort()方法。

两个类都有用于自然排序(使用Comparable)或基于标准的排序(使用Comparator)的重载方法sort()。

Collections内部使用数组排序方法,所有它们两者都有相同的性能,只是Collections需要花时间将列表转换为数组。


180、与Java集合框架相关的有哪些最好的实践?

解析:

1、根据需要选择正确的集合类型。比如,如果指定了大小,我们会选用Array而非ArrayList。如果我们想根据插入顺序遍历一个Map,我们需要使用TreeMap。如果我们不想重复,我们应该使用Set。

2、一些集合类允许指定初始容量,所以如果我们能够估计到存储元素的数量,我们可以使用它,就避免了重新哈希或大小调整。

3、基于接口编程,而非基于实现编程,它允许我们后来轻易地改变实现。

4、总是使用类型安全的泛型,避免在运行时出现ClassCastException。

5、使用JDK提供的不可变类作为Map的key,可以避免自己实现hashCode()和equals()。

6、尽可能使用Collections工具类,或者获取只读、同步或空的集合,而非编写自己的实现。它将会提供代码重用性,它有着更好的稳定性和可维护性。


181、什么是事务?

解析:事务是恢复和并发控制的基本单位。事务的四个基本特征:原子性,一致性,隔离性,持久性

  • 原子性和一致性差不多,意思是要么全部成功,要么就失败
  • 一致性是说,从一个一致性状态到另一个一致性状态
  • 隔离性是说一个事务执行的过程中不能被另一个事务干扰
  • 持久性也就是事务一旦提交,他对数据库中数据的改变就应该是永久的,不能变的(这里只是面试简单的说一下理解,详细理解问度娘)


182、堆和栈在内存中的区别是什么?

解析:

概念

栈(stack)是为执行线程留出的内存空间。当函数被调用的时候,栈顶为局部变量和一些 bookkeeping 数据预留块。当函数执行完毕,块就没有用了,可能在下次的函数调用的时候再被使用。栈通常用后进先出的方式预留空间;因此最近的保留块通常最先被释放。这么做可以使跟踪堆栈变的简单;从栈中释放块只不过是指针的偏移而已。

堆(heap)是为动态分配预留的内存空间。和栈不一样,从堆上分配和重新分配块没有固定模式;你可以在任何时候分配和释放它。这样使得跟踪哪部分堆已经被分配和被释放变的异常复杂;有许多定制的堆分配策略用来为不同的使用模式下调整堆的性能。

区别

  • 内存分配

栈:由编译器自动分配和释放,存放函数的参数、局部变量、临时变量、函数返回地址等。

堆:一般人为分配和释放,对Java而言由系统释放回收,但对于C++等,必须手动释放,如果没有手动释放会引起内存泄漏。


  • 系统响应

栈:只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则将报异常提示栈溢出。

堆:在记录空闲内存地址的链表中寻找一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。


  • 大小限制

栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在Windows下,栈的大小是2M,如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。

堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。


结论:堆获得的空间比较灵活,也比较大。

  • 分配效率

栈:由系统自动分配,速度较快,无法人为控制。

堆:由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。


  • 存储内容

栈:在栈中,第一个进栈的是主函数下一条指令的地址,然后是函数的各个参数,在大多数编译器中,参数是由右往左入栈,然后是函数中的局部变量。注意,静态变量不入栈。出栈则刚好顺序相反。

堆:一般在堆的头部用一个字节存放堆的大小,具体内容受人为控制。


183、一个以”.java”为后缀的源文件,正确的是()

A、只能包含一个类,类名必须与文件名相同

B、只能包含与文件名相同的类以及其中的内部类

C、只能有一个与文件名相同的类,可以包含其他类

D、可以包含任意类

答案:C

解析:一个.java文件中,只能存在一个类是用public修饰的,并且这个类必须与类名一致,文件中其他的类不能是public权限的,但可以有很多个类。

补充:但是解析里说“只能存在一个类是用 public 修饰的”,这结论不一定吧!静态内部类也可以出现多个 public 呀?所以题目的限定应该是外部类,不包含内部类!


184、以下哪些定义的变量是正确的()

A、int 1abc

B、char abc1

C、long #abc

D、boolean $abc

E、String _123456asdfghjklqwertyuiopzmnbvasdf12345

答案:BD

解析: 因为java中变量名必须是一个以字母开头并由字母或者数字构成的序列。字母包括 A-Z,a-z,_,$或在某种语言中表示的字母的任何Unicode字符(这里所谓的“Unicode字符”包含了中文)。变量名中所有的字符都是有意义的,并且大小写敏感,变量名基本上没有限制。


185、String能被继承吗?为什么?

解析:不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。平常我们定义的 String  str=”a”; 其实和 String  str=new String(“a”) 还是有差异的。


前者默认调用的是String.valueOf来返回String实例对象,至于调用哪个则取决于你的赋值,比如 String num = 1 + "",调用的是

publicstaticStringvalueOf(inti) { 
returnInteger.toString(i);
}

后者则是调用如下部分

publicString(Stringoriginal) { 
this.value=original.value; 
this.hash=original.hash;
}

最后我们的变量都存储在一个 char 数组中

privatefinalcharvalue[];


目录
相关文章
|
2天前
|
Java
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
12 0
|
2天前
|
安全 Java 程序员
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
6 0
|
5天前
|
Java
三个可能的Java面试题
Java垃圾回收机制自动管理内存,回收无引用对象的内存,确保内存有效利用。多态性允许父类引用操作不同子类对象,如Animal引用可调用Dog的方法。异常处理机制通过try-catch块捕获和处理程序异常,例如尝试执行可能导致ArithmeticException的代码,catch块则负责处理异常。
26 9
|
15天前
|
Java
【JAVA面试题】static的作用是什么?详细介绍
【JAVA面试题】static的作用是什么?详细介绍
|
15天前
|
Java
【JAVA面试题】final关键字的作用有哪些
【JAVA面试题】final关键字的作用有哪些
|
15天前
|
JavaScript 前端开发 Java
【JAVA面试题】什么是引用传递?什么是值传递?
【JAVA面试题】什么是引用传递?什么是值传递?
|
15天前
|
安全 Java
【JAVA面试题】什么是对象锁?什么是类锁?
【JAVA面试题】什么是对象锁?什么是类锁?
|
15天前
|
存储 自然语言处理 Java
【JAVA面试题】什么是代码单元?什么是码点?
【JAVA面试题】什么是代码单元?什么是码点?
|
15天前
|
Java 程序员
【JAVA面试题】基本类型的强制类型转换是否会丢失精度?引用类型的强制类型转换需要注意什么?
【JAVA面试题】基本类型的强制类型转换是否会丢失精度?引用类型的强制类型转换需要注意什么?
|
15天前
|
Java
【JAVA面试题】什么是深拷贝?什么是浅拷贝?
【JAVA面试题】什么是深拷贝?什么是浅拷贝?