Java基础整理(一)
- Java基础
- 1、Java与JavaScript的比较
- 2、正则表达式的介绍
- 3、&与&&的区别
- 4、String、StringBuffer和StringBuilder的区别
- 5、数组(Array)和数组列表(ArrayList)的比较
- 6、Lamda表达式的了解
- 7、重写equals()时还重写hashcode()的原因
- 8、List、Set、Map、Queue的比较
- 9、ArrayList和LinkedList(链表)的比较
- 10、Set的介绍
- 11、Map的分类和常见情况的介绍
- 12、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
- 13、重载和重写的比较
- 14、接口和类的区别
- 15、面向对象的特征
- 16、基本数据类型和包装类型
- 17、面向对象(设计模式)的”六原则一法则”介绍
- 18、阐述自己所了解的设计模式
- 19、Java集合框架图
- 20、Hashtable和HashMap的区别
- 21、遍历ArrayList时移除一个元素应该使用什么remove()
- 22、Comparable 与Comparator的区别
- 23、TCP 协议与 UDP 协议的区别
- 24、HTTP和HTTPS的区别
- 25、HTTPS的实现
- 26、三次握手、四次挥手
- 27、cookie和session的区别
- # 杂点
Java基础
准备面试,整理的一些Java基础面试题目!
1、Java与JavaScript的比较
Java和JavaScript是由两个不同公司开发的两个不同的产品。Java是一种面向对象的程序设计语言,JavaScript是一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言。其中,两者的异同如下:
- 面向对象和基于对象:Java是一种面向对象的语言,即使是开发简单的程序,也必须设计对象;JavaScript是一种脚本语言,可以用来制作与网络无关、与用户 交互的复杂软件。
- 编译和解释:Java的源代码在执行之前,必须经过编译;JavaScript的源代码不需要经过编译,由浏览器解释执行,现在几乎所有的浏览器都是用JIT(即时编译)技术来提升JavaScript的运行效率。
- 强类型变量和弱类型变量:Java采用强类型变量,即所有变量在编译前都必须声明;JavaScript采用弱类型变量。使用变量前可以不作声明,JavaScript的解释器在运行时检查推断其数据类型。
- 代码格式不一样。
2、正则表达式的介绍
在编写处理字符串的程序时,我们经常需要查找符合某些规则的字符串,而正则表达式是一种用于描述这些规则的工具。也就是说,正则表达式就是用于记录文本规则的代码。
【用途】主要应用于字符串的匹配和处理。
【Java的支持方法】Java的String类提供了支持正则表达式操作的方法:matches()、replaceAll()、replaceFirst()、split()。还可以用Pattern类表示正则表达式的对象。
3、&与&&的区别
- &运算符用法:
(1)、在位运算时(按位与),&表示按位与;
(2)、在算术运算时(逻辑与):先运算&两边的表达式,再作&运算; - &&运算符是一种短路与运算。&&左边表达式为false时,右边的表达式会被直接短路,不进行运算。
【 | 和 || 的原理同上】
4、String、StringBuffer和StringBuilder的区别
- 可变性:String类提供了数值不可变的字符串;StringBuffer和StringBuilder是可变的。
- 线程安全:String不可变,因此String是线程安全的;StringBuffer内部使用了synchronized进行同步,因此StringBuffer也是线程安全的;StringBuilder不是线程安全的。
- String类是final类型的,不能继承也不能修改这个类;StringBuffer类的运行速率比StringBuilder稍高;但是一般使用StringBuilder。
5、数组(Array)和数组列表(ArrayList)的比较
Array和ArrayList的区别:
- 存储内容上:Array可包含基本类型和对象类型;ArrayList只包含对象类型。
- 空间大小上:Array的大小不可变,ArrayList的大小是动态变化的。
- 方法上:ArrayList提供了更多的方法和特性,如addAll()、removeAll()、iterator()等
【适用场景】
- 如果想要保存一些在整个程序运行期间都会存在而且不变的数据,可以将它们放进一个全局数组里。
- 如果单纯只是想要以数组的形式保存数据,而不对数据进行增加等操作,只是方便进行查找的话,那么,就选择ArrayList。
- 如果需要对元素进行频繁的移动或删除,或者是处理的是超大量的数据,那么,可以考虑选择LinkedList。
6、Lamda表达式的了解
- Lambda 表达式,也可称为闭包,是Java 8 的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
- 语法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
· 其中 - > 为Lamda表达式的运算符,读作goes to。
· 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
· 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
· 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
· 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
【注意】:Lambda 表达式主要用来定义行内执行的方法类型接口,同时,Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。
- Lamda表达式的优缺点:
- 优点:代码简洁;非常容易并行计算
- 缺点:不容易调试;若不用并行计算,计算速度没有比传统的for循环快
基础的详细介绍可以点击这里:Lamda表达式详细介绍
7、重写equals()时还重写hashcode()的原因
- equals()的作用:equals()方法比较的是对象的引用地址是否相等,如何你需要判断对象里的内容是否相等,则需要重写equals()方法。
- hashcode()的作用:hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称为散列值。
- 调用的过程:主要是针对HashSet和Map集合类型。HashMap是用来判断key是否相等的方法,其实就是调用HashSet来判断加入的元素是否相等。在向HashSet集合里边添加新元素的时候,由于set集合里边不允许元素重复,所以在插入新元素之前需要先判断插入元素是否存在。首先根据hashCode()方法得到该对象的hashCode值,这样HashMap就可以定位到指定的key上。如果集合里不存在该值,直接插入。如果已经存在,则需要调用equals()来判断元素是否逻辑上相同。
- 两者都需要重写的原因:以此保证当两个对象通过equals()方法比较相等时,同时也保证他们的hashCode值也一定相等。
8、List、Set、Map、Queue的比较
- List、Set和Queue都继承自Collection接口,而Map没有继承Collection接口,Map是键值对的映射容器。
- List:元素有放入顺序,元素可重复 。List是线性结构的容器,按元素进入的顺序保存元素,不做排序或编辑操作,适合于按数值索引访问的情形。
- Set:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的),有内置的排序方法。
- Map:元素按键值对存储,无放入顺序 。也有内置的排序,因而不关心元素添加的顺序。
- Queue:用于模拟"队列"这种数据结构(先进先出 FIFO)。新元素插入(offer)到队列的尾部,访问元素(poll)操作会返回队列头部的元素,队列不允许随机访问队列中的元素。(poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。)
(1)PriorityQueue:保存队列元素的顺序并不是按照加入队列的顺序,而是按照队列元素的大小进行重新排序。
(2)Deque:Deque接口代表一个“双端队列”,双端队列可以同时从两端添加、删除元素,因此Deque既可以当做队列使用,也可以当做栈使用。
(3)ArrayDeque:是一个基于数组的双端队列,和ArrayList类似,他们的底层都采用一个动态的、可重分配的Object[]数组来存储集合元素,当集合元素超出该数组的容量时,系统会在底层重新分配一个Object[]数组来存储集合元素。
9、ArrayList和LinkedList(链表)的比较
ArrayList优点在于随机快速访问元素,但是向List中间插入与移除元素的速度很慢。LinkedList对顺序访问进行了优化,但随机访问则相比较慢。
ArrayLisr和LinkedList都实现了List接口,它们的区别如下:
- ArrayList是基于索引的数据接口,其底层是数组。可以以O(1)时间复杂度对元素进行随机访问。不适合于频繁的插入和删除操作。
- LinkedList是以元素列表的形式来存储数据,每一个元素都和它的前一个和后一个元素相链接,其查找某个元素的时间复杂度为O(n),其不适合于随机访问,适合于频繁的插入和删除操作的
- **在内存上:**LinkedList 需要更多的内存,因为 ArrayList 的每个索引的位置是实际的数据,而 LinkedList 中的每个节点中存储的是实际的数据和前后节点的位置。
【适用场景】
- 应用不会随机访问数据,更适宜使用 LinkedList 。
- 应用有频繁的插入和删除操作,更少的读取操作时,更加适宜使用LinkedList。
换句话说,ArrayList的实现用的是数组,适合查找;LinkedList是基于链表,适合增删。
10、Set的介绍
Set具有与Collection完全一样的接口,实际上Set就是Collection,只是行为不同。Set中的元素不按特定的方式排序,并且Set中不允许出现重复度的元素,即存入Set的每个元素都是唯一的。加入Set的元素必须定义equals()方法以确保对象的唯一性。
Set接口主要实现了三个实现类:
- HashSet:为快速查找设计的Set。通过存入元素的HashCode决定该元素在Set中的位置。
- TreeSet:保存次序的Set, 底层为树结构。TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。
- LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
11、Map的分类和常见情况的介绍
Map是个接口(java.util.Map),其常见的实现类有4个:HashTable、HashMap、TreeMap、LinkedHashMap
Map主要用于键值对,根据健得到相应的值,因此健不允许重复,即一个Map中不能包含相同key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当做一组key集合,一组value集合,或者一组key-value映射。
(1)HashMap
- HashMap是最常用的Map,它根据健的Hashcode值存储数据,可以根据健来直接获取相应的数值,访问速度快,遍历时,随机获取数据。
- HashMap最多只允许一条记录的健为Null,但允许多条记录的值为Null
- HashMap不支持线程同步(即任一时刻可以有多个线程同时写HashMap),但可能导致数据的不一致。
- 可以用Collections的synchronizedMap方法来使得HashMap具有同步的能力,或使用ConcurrentHashMap。
(2)HashTable
HashTable继承于Dictionary类。不同的是:
- 它不允许记录的健或值为空
- 支持线程的同步(即任一时刻只有一个线程能写HashTable),因此HashTable的写入速度较慢。
(3)TreeMap
TreeMap实现SortMap接口,能够把它保存的记录根据健进行排序(默认升序),也可以指定排序的比较器,但使用Iterator遍历TreeMap时,得到的记录是排过序的。
(4)LinkedHashMap
LinkedHashMap是HashMap的一个子类,保存了记录的插入顺序,其遍历的速度比HashMap慢。
【总结】
- 一般情况下,使用HashMap居多,一般用于Map中插入、删除和定位元素。
- 若需要按自然顺序或自定义顺序遍历健,可使用TreeMap。
- 若需要输出的顺序和输入的相同,可使用LinkedHashMap,还可按读取顺序来排列。
12、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
- TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会调用该方法比较元素大小。
- TreeMap要求存放的健值对中映射的健必须实现Compareable接口,从而根据健对元素进行排序。
- Collecions工具类的sort()方法有两种重载的形式:1)只需传入待排序的集合,便会为它自然排序。2)可自定义排序,在调用sort()时,把待排序的集合和比较器同时传入,就可以按照自定义的方式排序。
13、重载和重写的比较
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
【总结】
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
- (1)、方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
- (2)、方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
- (3)、方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
14、接口和类的区别
- 接口不能用于实例化对象,且没有构造方法。
- 接口中所有的方法必须都是抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现,接口支持多继承。
15、面向对象的特征
16、基本数据类型和包装类型
Java 是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型。为了能够将这些基本数据类型当成对象操作,Java 为每一个基本数据类型都引入了对应的包装类型。
【以int和Integer为例】:
class AutoUnboxingTest {
public static void main(String[] args) {
Integer a = new Integer(3);
Integer b = 3;
// 将 3 自动装箱成 Integer 类型
int c = 3;
System.out.println(a == b);
// false 两个引用没有引用同一对
象
System.out.println(a == c);
// true a 自动拆箱成 int 类型再和 c
比较
}
}
17、面向对象(设计模式)的”六原则一法则”介绍
单一职责原则、开闭原则、依赖倒转原则、里氏替换原则、接口隔离原则、合成聚合复用原则;迪米特法则
- 单一职责原则:一个类只做它该做的事情。(即做到”高内聚“)
- 开闭原则:软件实体应当对扩展开发,对修改关闭。
- 依赖倒转原则:面向接口编程。
- 里氏替换原则:任何时候都可以用子类型替换掉父类型。
- 接口隔离原则:接口要小而专,绝不能大而全。
- 合成聚合复用原则:优先使用合成或聚合关系来复用代码。(即优先考虑Has-A关系而不是Is-A关系复用代码)
- 迪米特法则:又称最少知识原则,一个对象应当对其它对象有尽可能少的了解。(即做到”低耦合“)
18、阐述自己所了解的设计模式
设计模式就是一套反复使用的代码设计经验的总结。设计模式使人们可以更加简单方便地复用成功的设计和体系结构,而使用设计模型是为了可重用代码、让代码更容易被人理解、保证代码的可靠性。
下面是一些设计模式的介绍:
- 工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态方法)。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的时哪一个子类的实例。
- 代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用。实际开发中,按照使用目的的不同,代理又可以分为:远程代理、虚拟代理、保护代理、防火墙代理、同步化代理等。
- 适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起的类能够一起工作。
19、Java集合框架图
20、Hashtable和HashMap的区别
- Hashtable是同步的,比较慢;而HashMap没有同步策略,所以会更快。
- Hashtable不允许健和值为null;而HashMap最多只允许一条记录的健为Null,但允许多条记录的值为Null。
- Hashtable直接使用对象的hashCode;而HashMap冲洗计算hash值。
- HashTable在不指定容量的情况下的默认容量为11,而HashMap为16;Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
21、遍历ArrayList时移除一个元素应该使用什么remove()
正确了解ArrayList的remove()方法和Iterator的remove()方法。
- 在使用迭代器遍历集合的过程中,使用集合对象的remove方法删除数据时,会破坏迭代器结构,导致遍历停止。
List<String> all = new ArrayList<String>();
all.add("a");
all.add("b");
all.add("c");
Iterator<String> iterator=all.iterator();//实例化迭代器
while(iterator.hasNext()){
String str=iterator.next();//读取当前集合数据元素
if("b".equals(str)){
all.remove(str);
}else{
System.out.println( str+" ");
}
}
System.out.println("\n删除\"b\"之后的集合当中的数据为:"+all);
结果如下:
a
删除“b”之后的集合当中的数据为:[a,c]
- 在使用迭代器遍历集合的过程中,使用迭代器的 remove 方法删除数据,迭代器可正常运行,遍历正常。
List<String> all = new ArrayList<String>();
all.add("a");
all.add("b");
all.add("c");
Iterator<String> iterator = all.iterator();//实例化迭代器
while(iterator.hasNext()){
String str=iterator.next();//读取当前集合数据元素
if("b".equals(str)){
//all.remove(str);
//使用集合当中的remove方法对当前迭代器当中的数据元素值进行删除操作(注:此操作将会破坏整个迭代器结构)使得迭代器在接下来将不会起作用
iterator.remove();
}else{
System.out.println( str+" ");
}
}
System.out.println("\n删除\"b\"之后的集合当中的数据为:"+all);
结果如下:
a
c
删除“b”之后的集合当中的数据为:[a,c]
22、Comparable 与Comparator的区别
- Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户定制的顺序。
- Comparable是在集合内部定义的方法实现的排序,位于java.lang下。Comparator是在集合外部实现的排序,位于java.util下。
- Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。
23、TCP 协议与 UDP 协议的区别
TCP(传输控制协议) UDP(用户数据报协议)
- TCP是一种连接协议;而UDP是一种非连接协议。
- TCP对系统资源的要求较多,而UDP少。
- TCP是流模式;而UDP是数据报模式。
- TCP保证数据正确性;而UDP可能丢包。
- TCP保证数据顺序;而UDP不保证。
24、HTTP和HTTPS的区别
HTTP:超文本传输协议是互联网上应用最为广泛的一种网络协议。设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法。它可以使浏览器更加高效,其中,HTTP 协议是以明文方式发送信息的。
HTTPS:是以安全为目标的 HTTP 通道,是 HTTP 的安全版。HTTPS 的安全基础是 SSL。SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。
HTTP 与 HTTPS 的区别
- HTTPS 协议需要到 CA (Certificate Authority,证书颁发机构)申请证书。
- HTTP 是超文本传输协议,信息是明文传输;HTTPS 是HTTP的安全版,具有 SSL 加密传输协议,为数据通讯提供安全支持。
- HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- HTTP 的连接很简单,是无状态的。HTTPS 是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。
【注】无状态的意思是其数据包的发送、传输和接收都是相互独立的。无连接的意思是指通信双方都不长久的维持对方的任何信息。
25、HTTPS的实现
26、三次握手、四次挥手
握手
(1)第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
(2)第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。
(3)第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。
挥手
- 首先客户端想要释放连接,向服务器端发送一段TCP报文
- 服务器端接收到从客户端发出的TCP报文之后,确认了客户端想要释放连接,随后服务器端进入CLOSE-WAIT阶段(半关闭状态)并返回一段TCP报文。客户端收到从服务器端发出的TCP报文之后,确认了服务器收到了客户端发出的释放连接请求,随后客户端进入FIN-WAIT-2阶段。
- 当服务器端已经没有数据再发送的时候,会再次向客户端发出一段TCP报文
- A收到B发来的FIN,知道B的数据也发送完了,回复ACK,A等待2MSL以后,没有收到B传来的任何消息,知道B已经收到自己的ACK了,A就关闭链接,B也关闭链接了。
27、cookie和session的区别
由于http 协议是无状态的,服务器无法确定这次请求和上次的请求是否来自同一个客户端。利用session和cookie可以让服务器知道不同的请求是否来自同一个客户端。
- Cookie和Session都是会话技术,Cookie是运行在客户端;Session是运行在服务器端。
- Cookie有大小限制以及浏览器在存cookie的个数也有限制;Session是没有大小限制,但和服务器的内存大小有关。
- Cookie有安全隐患,通过拦截或本地文件找得到你的cookie后可以进行攻击。而Session保存在服务端较为安全。
- Session是保存在服务器端上会存在一段时间才会消失,如果session过多会增加服务器的压力。
# 杂点
- Java支持带标签的break和continue语句,如在多层循环得最外层前加一个标签A,可以break A;跳出多重循环。