面试总结(一)——Java基础相关知识
最近在面试,所以总结下面试容易问到的知识点,用来备份查看用。
若需转载,请注明出处。
1.面向对象的特点;
1.将复杂的事情简单化
2.面向对象将以前过程中的执行者,变成了指挥者
3.面向对象思想是符合人们思考习惯的思想
2.面向对象特征;
1.封装:隐藏对象的属性和实现的细节,仅对外提供公共访问方式
好处:将变化隔离,便于使用,提高复用和安全性。
原则:将不需要对外提供的内容隐藏起来,隐藏属性,提供公共方法对其访问。
2.继承:提高代码复用性,继承是多态的前提。子类中所有的构造函数都会默认访问父类中空参的构造函数,默认第一行有super(),若无空参数构造函数,子类中需指定。另外,子类的构造函数可以用this访问自身的其他构造函数。
3.多态:是父类或接口定义的引用变量,可以指向子类或具体实现类的实例对象。
好处:提高程序的扩展性
弊端:当父类引用指向子类对象时,虽然提高了扩展性,但只能访问父类中具有的方法,不可以访问子类中独有的方法,即访问的局限性。
前提:实现或继承关系,复写父类方法。
3.抽象类
1.特点:由abstract修饰,描述类和方法,作为方法的声明,不具体实现。抽象类里可以有非抽象方法,但不可被实例化。子类单继承抽象类,必须实现所有抽象方法才能实例化,否则子类仍为抽象类。
2.相关知识点:
a.抽象类可以有构造函数,用于对子类对象的初始化,即使不定义构造函数,也会默认一个空参的构造函数。
b.可定义非抽象方法,属性和行为。
c.抽象类中可以没有抽象方法,抽象的目的是不让该类被实例化。
d.abstract不可以和final,private,static,native共存。
4.内部类
1.内部类被定义在局部时,定义在方法中的内部类是局部内部类。
不可以被成员修饰符修饰:public,static,private等。可以直接访问外部类成员,因为有外部类的引用。只能访问它所占局部中的那些被final修饰的局部变量,如BaseAdapter里new OnClickListener时如果需要用到position,需要改成final类型。
2.匿名内部类,内部类的一种简写方式,该内部类必须继承一个类或实现一个接口。
5.final关键字
1.可以修饰类,方法和变量
2.被修饰的类不可被继承
3.被修饰的方法不可被复写
4.被修饰的变量:a.基本数据类型->值不可变;b.引用型变量->不能被赋值,但是指向的对象可以被改变。
6.继承和实现的区别
表面区别:单继承,多实现。
继承:如果多个类某个部分功能相同,那么可以抽象出一个类,把它们相同部分都放在父类里,让它们都继承这个类。提供代码复用性,多态前提。
实现:如果多个类处理的目标是一样的,但是处理的方式方法不同,那么就定义一个接口,也就是一个标准,让它们实现这个接口,各自实现自己的具体方法来处理目标。
7.抽象类和接口的区别
抽象类只可以被单继承,接口可以被多实现。
抽象类中可以定义非抽象方法,子类可以直接继承使用,接口全部为抽象方法,需要被子类实现。
抽象类是is a关系,接口是like a 关系。
抽象类的成员修饰符可以自定义,接口全部为public
抽象类可以有构造方法,静态方法,接口不可以。
8.重载overload和重写override的区别
重载:在同一个类允许存在一个以上的相同函数名,但参数个数或类型不同的方法。
特点:与返回类型无关,只看参数列表
重写:当子类出现和父类一样的函数时,子类对象调用时,会运行子类该方法中的功能,如同父类函数被覆盖一样。
重载只看同名函数的参数列表,是针对一个类中的两个函数说的。重写是子类与父类的同名函数,是两个类。
9.StringBuilder和StringBuffer的区别
StringBuffer是线程同步的,通常用于多线程。StringBuilder是线程不同步的,通常用于单线程。
10.异常Exception
1.异常处理原则:可以处理的进行捕获,抛出几个异常就捕获几个,catch异常要具体,处理不了的转为新异常抛出。
2.含有多个catch块时,父类异常要放在子类异常之下,因为子类更详细。
3.throws,throw,try,catch,finally意义:
a.throws:定义在函数上,用于抛出异常。可以抛出多个,需要逗号隔开,抛出的异常越具体越好,可以有针对性的解决。
b.throw:定义在函数内,用于抛出异常对象,throw单独存在时,下面不可以定义语句,因为执行不到,编译失败。
c.try:可以理解为检测异常,里面放可能产生异常的代码
d.catch:捕获异常或异常对象,当有异常抛出时,需要进行捕捉,并进行处理,在这里可以抛异常,抛给可以解决的调用者处理。
e.finally:最终一定会执行的代码块,即使有return也会执行。
11.多线程
线程的创建方式:Thread,Runnable,线程池(Pool)。
1.为什么要复写run方法?
因为run方法中存放线程运行的代码
2.Thread和Runnable创建的区别?
继承方式:线程代码放在Thread子类run方法中。
实现方式:线程代码放在接口子类的run方法中,避免了单继承的局限性,建议使用。
3.线程状态:
新建:start
临时状态:具备cpu的执行资格,无执行权
运行状态:具备cpu的执行权,可执行
冻结状态:通过sleep或者wait(还有其他方法,后面会有面试专题——多线程专门介绍)使线程不具备执行资格,需要notify唤醒,唤醒后处于临时状态
消亡状态:run方法之行结束或中断线程,使线程死亡。
4.线程安全:
多个线程共享数据,当某个线程执行多条语句时,其他线程也执行进来,导致数据在某条语句上被修改多次,执行后续代码时,产生错误数据。
因素:多个线程操作共享数据
解决:
原理:某一时间内,只让一个线程执行完所有关于共享数据的操作。
方法:锁机制->synchronized或lock对象
5.线程同步
当两个或两个以上的线程需要共享资源,他们需要某种方法来确定资源在某一刻仅被一个线程占用,达到此目的的过程叫做同步。
同步代码块:synchronized(Object){};将需要同步的打吗放在大括号中,括号中的对象即为锁。
同步函数:synchronized放在函数上,修饰符之后,返回类型之前。同步函数的锁是this,静态同步函数的锁是class对象,如懒汉式的同步锁为Single.class。
6.wait和sleep的区别
wait:可指定等待时间,如果不指定,需要由notify/notifyAll唤醒。等待期间线程释放执行权,释放锁。
sleep:必须指定等待时间,时间到了会自动处于临时(阻塞)状态,睡眠期间仍持有锁,不释放执行权。
wait只能在同步中使用,sleep可以在任意地方(Object的方法)。
12.集合
Collection
| |–ArrayList
|—-List -|
| |–LinkedList
|
| |-TreeSet
|—-Set-|
|-HashSet
Map
|
|—-HashMap
|
|—-TreeMap
1.Collection :
List:有序的,元素可重复,有索引。
ArrayList:底层是数组结构,查找快,增删慢,不同步。
LinkedList:底层是链表结构,增删快,查找慢,不同步。
Vector:底层是数组结构,线程同步,被ArrayList取代。
Set:无序,无索引,元素不可重复
HashSet:底层是哈希表,线程不同步,无序,搞笑。
TreeSet:底层是二叉树,可以对元素进行排序,默认是自然顺序。
2.Map:
HashTable:底层是哈希表,线程同步,不可以存入null键和null值。
HashMap:底层是哈希表,允许使用null键和null值,不同步,效率高
TreeMap:底层是二叉树,不同步,可排序,与set很像。Set底层使用了map集合。
3.Collection和Map的区别
Collection:单列集合,一次存一个元素。
Map:双列集合,一次存一对元素,两个元素之间存在映射关系。
13.正则表达式
概述:正则表达式是用来操作字符串的一些规范,它是使用一些符号代表指定一些代码,从而可简化字符串的基本操作。
匹配:String类中的matches(String Regex)
切割:String split
替换:String replaceAll
获取:
封装正则表达式成对象:Pattern p = Pattern.compile(regex);
关联字符串获取匹配器:Matcher m = p.mathcer(str);
使用matcher的方法获取:find();group();
14.XML解析
dom和sax解析都是全部读入内存之后在解析,dom适合增删改,sax适合查找。如果XML文件很大,容易造成内存溢出
pull解析是边度边解析。
15.Java中变量的存储
实例变量和静态变量在堆上,局部变量在栈上