01
- 练习一:Object类equals方法
一、简述String类中的equals方法与Object类中的equals方法的不同点。
答:String类中的equals方法是用来判断两个对象的内容是否相同,而Object 类中的equals方法是用来判断两个对象是否是同一个对象,所谓同一个对象指的是内存中的同一块存储空间。
- 练习四:StringBuilder类与String类的区别
四、简述StringBuilder类与String类的区别。
答:String类的对象内容不可改变,所以每当进行字符串拼接时,总是会在内存中创建一个新的对象,所以经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响。
StringBuilder又称为可变字符序列,是JDK5.0中新增加的一个类,它是一个类似于String的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。即它是一个容器,容器中可以装很多字符串,并且能够对其中的字符串进行各种操作。它的内部拥有一个数组用来存放字符串内容,进行字符串拼接时,直接在数组中加入新内容,StringBuilder会自动维护数组的扩容。
Day02
练习一:集合框架
- 一、请简述集合框架。
集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map。
Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.List和java.util.Set。其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,Set接口的主要实现类有java.util.HashSet和java.util.TreeSet。
- 练习七:简述迭代器的实现原理
七、请简述迭代器的实现原理
当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。
Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。
Day03
- 练习一:List接口的特点
一、请简述List接口的特点。
它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。
它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
- 练习二:hashCode和equals方法
二、请简述HashSet去除重复元素的原理。
调用被添加元素的hashCode(),和HashSet中已有元素的hashCode比较是否相同
如果不相同,直接存储
如果相同,调用equals方法比较是否相同
不相同,直接存储元素
相同,认为是同一元素.不存储
- 练习三:数据结构
三、简述常见的数据结构中元素的存取特点。
栈:stack,又称堆栈,对元素的存取特点是:先进后出。即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素。
队列:queue,简称队,对元素的存取特点是:先进先出。即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素。
数组:Array,是有序的元素序列,对元素的存取特点是:
1、查找元素快:通过索引,可以快速访问指定位置的元素
2、增删元素慢
(1)指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索 引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。
(2)指定索引位置删除元素:需要创建一个新数组,把原数组元素根据索引,复 制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中。
链表:linked list,对元素的存取有如下的特点:
1、多个结点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的 右手拉住下个人的左手,依次类推,这样多个人就连在一起了。
2、查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素。
3、增删元素快:
增加元素:只需要修改连接下个元素的地址即可。
删除元素:只需要修改连接下个元素的地址即可。
- 练习四:Comparable和Comparator比较器
四、简述Comparable和Comparator两个接口的区别。
Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
Day04
- 练习一:Map接口的特点
一、请简述Map 的特点。
1、Map每个元素由键与值两部分组成
2、Map键不能重复,每个键对应一个值
键3、和值可以为null
- 练习二:Entry键值对对象
二、说出Entry键值对对象遍历Map集合的原理。
Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在Map中是一一对应关系,这一对对象又称做Map 中的一个Entry(项)。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对(Entry)对象中获取对应的键与对应的值
Day05
练习一:异常的体系
问题:
- 请描述异常的继承体系
- 请描述你对错误(Error)的理解
- 请描述你对异常(Expection的理解)
- 请描述你对运行时异常(RuntimeException)的理解
答:
- 异常继承体系为:异常的根类是 java.lang.Throwable,其下有两个子类:
java.lang.Error 与 java.util.Exception 。而Exception又分为编译时期异常:checked异常,与运行时期异常:runtime异常。 - Error:表示不可修复的恶性的错误,只能通过修改代码规避错误的产生,通常是系统级别的,所以很严重。
- Exception:表示可修复的良性(相对于错误)的异常,异常产生后程序员可以并且应该通过代码的方式纠正,使程序继续运行,是必须要处理的。
- 运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。
练习二:throw与throws的区别
问题:
- 请描述throw的使用位置,作用是什么?
- 请描述throws的使用位置,作用是什么?
答:
- throw关键字通常用在方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即停止,它后面的语句都不执行。
- throws关键字通常被应用在声明方法时,用来指定可能抛出的异常。多个异常可以使用逗号隔开。当在主函数中调用该方法时,如果发生异常,就会将异常对象抛给方法调用处。
练习三:异常的处理方式
问题:
1. 异常处理方式有几种,分别是什么?
2. 详细阐述每种方式对异常是如何处理的
答:
- 异常的处理方式有两种,分别是使用throws和try…catch…finally
- throws用在方法的声明上后接异常类名,是把异常抛给调用者进行处理
- try…catch…finally是捕获异常,自己处理,处理完毕后面的程序可以继续运行
a) try代码块中是可能出现异常的代码
b) catch代码块,是遇到异常,对异常进行处理的代码
c) finally代码块是无论是否发生异常,都必须执行的代码,用于释放资源.
练习四:常见异常,及产生原因
问题:请列举常见异常,并说明产生原因。
答:
NullPointerException:空指针异常。
当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度等等。
ArrayIndexOutOfBoundsException:数组索引越界异常。
当对数组的索引值为负数或大于等于数组大小时抛出此异常。
ArithmeticException:算术运算异常。
程序中出现了除以零这样的运算就会出这样的异常,对这种异常,大家就要好好检查一下自己程序中涉及到数学运算的地方,公式是不是有不妥了。
NumberFormatException:数字格式异常。
当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常。
注意:答案不唯一,合理即可。
Day06
练习一:多线程开启
问题:
请描述Thread类中的start()方法与run()方法的区别。
答:
线程对象调用run()方法不开启线程,仅是对象调用方法。线程对象调用start()方法开启线程,并让jvm调用run()方法在开启的线程中执行。
练习二:创建多线程
问题:
请描述创建线程的两种方式。
答:
第一种方式是将类声明为 Thread 的子类。
-
定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。
-
创建Thread子类的实例,即创建了线程对象。
-
调用线程对象的start()方法来启动该线程。
第二种方式是声明一个类实现Runnable 接口。
-
定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
-
创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,Thread对象才是真正的线程对象。
-
调用线程对象的start()方法来启动线程。
练习四:实现Runnable接口的优势
问题:
请描述实现Runnable接口比继承Thread类所具有的优势:
答:
- 适合多个相同的程序代码的线程去共享同一个资源。
- 可以避免java中的单继承的局限性。
- 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和数据独立。
- 线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
练习五:线程状态
问题:请描述在线程的生命周期中, 有几种状态呢 ?
答:
- NEW(新建) 线程刚被创建,但是并未启动。
- Runnable(可运行)
线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。 - Blocked(锁阻塞)
当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。 - Waiting(无限等待)
一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。 - Timed Waiting(计时等待)
同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。 - Teminated(被终止)
因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。
Day07
练习一:线程池概念
问题:
请描述什么是线程池。
答:
线程池:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
练习二:线程池优点
问题:
请描述合理利用线程池能够带来的三个好处。
答:
- 降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
- 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
- 提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
练习三:Lambda表达式
问题:
请列举Lambda语法的省略规则
答:
在Lambda标准格式的基础上,使用省略写法的规则为:
- 小括号内参数的类型可以省略;
- 如果小括号内有且仅有一个参,则小括号可以省略;
- 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
练习四:Lambda表达式
问题:
请列举Lambda表达式的3个组成部分,并解释说明。
答:
Lambda标准格式 Lambda省去面向对象的条条框框,格式由3个部分组成:一些参数,一个箭头,一段代码。
Lambda表达式的标准格式为:格式说明:
- 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
- ->是新引入的语法格式,代表指向动作。
- 大括号内的语法与传统方法体要求基本一致。
练习五:Lambda表达式
问题:
请描述Lambda的使用前提
答:
Lambda的语法非常简洁,完全没有面向对象复杂的束缚。但是使用时有几个问题需要特别注意:
- 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。无论是JDK内置的 Runnable 、 Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
- 使用Lambda必须具有上下文推断。也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。