基础:
1.抽象类和接口的区别
1.接口描述了方法的特征,不给出实现,一方面解决java的单继承问题,实现了强大的可接插性
2.抽象类提供了部分实现,抽象类是不能实例化的,抽象类的存在主要是可以把公共的代码移植到抽象类中
3.面向接口编程,而不是面向具体编程
4.开发中优先选择接口(因为继承抽象类后,此类将无法再继承,所以会丧失此类的灵活性)
2.集合
SET LIST MAP
一、
1.Set:,无序,元素不可重复(但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)
2.List:有序,列表存储,元素可重复
3.Map:无序,元素可重复
二、
1.Set接口:有两个实现类(HashSet(底层由HashMap实现),LinkedHashSet)
2.List接口:有三个实现类(
LinkedList:基于链表实现,链表内存是散乱的,每一个元素存储本身内存地址的同时还存储下一个元素的地址。链表增删快,查找慢;
ArrayList:非线程安全的,效率高;基于数组;便于索引,但不便于插入删除
Vector:基于线程安全的,效率低;基于数组; )
3.Map接口:有三个实现类(HashMap,HashTable,LinkedHashMap)
HashMap:非线程安全,高效,支持null;
HashTable:线程安全,低效,不支持null;
LinkedHashMap:是HashMap的一个子类,保存了记录的插入顺序
SortMap接口:TreeMap,能够把它保存的记录根据键排序,默认是键值的升序排序
注:最常用的,冷门的除外)
3.常用的集合有哪些,谈谈对它们的理解? ?
SET ,LIST, MAP
1.1、特点
1.Set:,无序,元素不可重复(但是元素在 set 中的位置是有该元素
的 HashCode 决定的,其位置其实是固定的)
2.List:有序,列表存储,元素可重复
3.Map:无序,元素可重复
1.2、实现类
1.t Set 接口:有两个实现类(HashSet(底层由 HashMap 实现),
LinkedHashSet)
2.t List 接口:有三个实现类(
LinkedList:基于链表实现,链表内存是散乱的,每一个元素存
储本身内存地址的同时还存储下一个元素的地址。链表增删快,查找慢;
ArrayList:非线程安全的,效率高;基于数组;便于索引,但不
便于插入删除
Vector:基于线程安全的,效率低;基于数组; )
- Map 接口:有三个实现类(HashMap,HashTable,LinkedHashMap)
HashMap:非线程安全,高效,支持 null;
HashTable:线程安全,低效,不支持 null;
LinkedHashMap:是 HashMap 的一个子类,保存了记录的插入顺序
SortMap 接口:TreeMap,能够把它保存的记录根据键排序,默认是键值
的升序排序。
4.List 和 和 Set 、Map 的区别?
Java 中的集合包括三大类:它们是 Set、List 和 Map,它们都处于
Java.util 包中,Set、List 和 Map 都是接口,它们有各自的实现类。Set
的实现类主要有 HashSet 和 TreeSet,List 的实现类主要有 ArrayList,
Map 的实现类主要有 HashMap 和 TreeMap。
Set 中的对象不按特定方式排序,并且没有重复对象。但它的有些实现
类能对集合中的对象按特定方式排序,例如 TreeSet 类,它可以按照默认
排序,也可以通过实现 Java.util.Comparator<Type>接口来自定义排序方
式。
List 中的对象按照索引位置排序,可以有重复对象,允许按照对象在
集合中的索引位置检索对象,如通过 list.get(i)方式来获得 List 集合中
的元素。
Map 中的每一个元素包含一个键对象和值对象,它们成对出现。键对象
不能重复,值对象可以重复
5.= =和 equals()的区别?
==:用于比较基本数据类型,比较变量值是否相等,若相同,则为 true
用于比较引用数据类型,比较的是指向内存中的引用对象地址是否相同,若相同,
则为 true。
equals()方法:是用来比较两个对象是否相等,即实际比较的是两个对象的内容是否相
同。
注意:equals 方法不能用于基本数据类型的变量,如果没有对 equals 方法进行重写,
则比较的是引用类型的变量所指向的对象的地址;
6.方法重写( Overloading)和方法重载( Overwrite)的区别?
方法重写:一般出现在继承(不同类)中,是子类对父类方法的重新实现;
重写规则:
1)参数列表必须完全与被重写方法的一致,返回类型必须完全与被重写方法的返回类型一
致
2)构造方法不能被重写,声明为 final 的方法不能被重写,声明为 static 的方法不能被重写,
但是能够被再次声明
3)访问权限不能比父类中被重写的方法的访问权限更高
4)重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的
方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以
方法重载:在同一个类中,方法名字相同,参数不同,方法体不同,是一个类中多态性的一
种表现;
注意:每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表
重载规则:
方法名一致,参数列表中参数的顺序,类型,个数不同
重载与方法的返回值无关,存在于父类和子类,同类中
可以抛出不同的异常,可以有不同修饰符
7.w throw 和 s throws 的区别?
throw:是用在语句抛出异常
特点:
throw 语句用在方法体内,表示抛出异常,由方法体内的语句处理。
throw 是具体向外抛异常的动作,所以它是抛出一个异常实例,执行 throw 则一定抛出了某
种异常
throws 是用在声明方法时,表示该方法可能要抛出异常
特点:
1)throws 语句用在方法声明后面,表示再抛出异常,由该方法的调用者来处理
- throws 主要是声明这个方法会抛出这种类型的异常,使它的调用者知道要捕获这个
异常 - throws 表示出现异常的一种可能性,并不一定会发生这些异常
注意:抛出的异常可以使系统定义,也可以是自定义;使用 try,catch,finally 捕获异常。
- 描述遇到过的异常有哪些?
(1)Error(错误类):是程序无法处理的错误,错误的发生属于系统级别
(2)Exception(异常类): 是程序本身可以处理的异常,一般是程序在操作数据错误
时引发,分为运行时异常(RuntimeException)和非运行时异常(编译时异常)
注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理
常见异常:
(1)java.lang.NullPointerException 空指针异常;出现原因:调用了未经初始化的对
象或者是不存在的对象
(2)java.lang.ClassNotFoundException 指定的类找不到;出现原因:类的名称和路
径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发异常
(3)java.lang.NumberFormatException 字符串转换为数字异常;出现原因:字符型
数据中包含非数字型字符
(4)java.lang.IndexOutOfBoundsException 数组角标越界异常;
(5)java.lang.IllegalArgumentException 方法传递参数错误
(6)java.lang.ClassCastException 数据类型转换异常
(7)java.lang.NoClassDefFoundException 未找到类定义错误
(8)SQLException 操作数据库异常
(9)java.lang.InstantiationException 实例化异常
(10)java.lang.NoSuchMethodException 方法不存在异常 - final, , finally, e finalize 的区别? ?
final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,被其修饰的类
不可继承。
Finally:异常处理语句结构的一部分,表示总是执行。
finalize:Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,
可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
- S tring、 StringBuffer、 StringB Br uilder 的区别?
(1)可变,不可变:
String:字符串常量,在修改时不会改变自身;若修改,等于重新生成新的字符串
对象
StringBuffer:在修改时会改变对象自身,每次操作都是对 StringBuffer 对象本身进
行修改,不是生成新的对象
使用场景:对字符串经常改变情况下,主要方法:append(),insert()
等;
(2)线程是否安全:
String 对象定义后不可变,线程安全
StringBuffer 是线程安全的(对调用方法加入同步锁),执行效率较慢,适用于多
线程下操作字符串缓冲区大量数据
StringBuilder 是线程不安全的,适用于单线程下操作字符串缓冲区大量数据
共同点:StringBuilder 与 StringBuffer 有公共父类 AbstractStringBuilder(抽象类)
StringBuilder、StringBuffer 的方法都会调用 AbstractStringBuilder 中的公共方法,如
super.append(...)。只是 StringBuffer 会在方法上加 synchronized 关键字,进行同步。最后,
如果程序不是多线程的,那么使用 StringBuilder 效率高于 StringBuffer。
9.O IO 流
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在
两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便
更直观的进行数据操作。
10.Java 中有几种类型的流?分别是什么?
a Java 中的流,可以从不同的角度进行分类。
按流的方向分:输入流和输出流。
按处理数据单位分:字节流和字符流。
按实现功能分:节点流和处理流。
2.字节流和字符流的区别
1.字节流读取的时候,读到一个字节就返回一个字节; 字符流使用了字节流读到一个
或多个字节(中文对应的字节数是两个,在 UTF-8 码表中是 3 个字节)时。先去查指定的
编码表,将查到的字符返回。
2.字节流可以处理所有类型数据,如:图片,MP3,AVI 视频文件,而字符流只能处理
字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。
11.k break 和 e continue 的区别?
break 和 continue 都是用来控制循环,主要是终止循环;
break 用于完全结束一个循环,跳出循环体执行循环后面的语句;
continue 用于跳过本次循环,执行下次循环;
12.如何实现对象克隆?
1). 实现 Cloneable 接口并重写 Object 类中的 clone()方法;
2). 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现 真正的深度克隆
13.数据类型之间的转换?
1)字符串如何转基本数据类型?
调用基本数据类型对应的包装类中的方法 parseXXX(String)或 valueOf(String)即可返回相应
基本类型;
2)基本数据类型如何转字符串?
一种方法是将基本数据类型与空字符串(“”)连接(+)即可获得其所对应的字符串;另一
种方法是调用 String 类中的 valueOf()方法返回相应字符串
多线程网络编程
14.线程和进程的区别?
进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行
资源分配和调度的一个独立单位
线程:是进程的一个实体,是 cpu 调度和分派的基本单位,是比进程更小的可以独立
运行的基本单位
特点:线程的划分尺度小于进程,这使多线程程序拥有高并发性
进程在运行时各自内存单元相互独立,线程之间内存共享,这使多线程编程可以拥
有更好的性能和用户体验
注意:多线程编程对于其它程序是不友好的,占据大量 cpu 资源。
15.编写多线程程序的几种实现方式(换个问法:创建多线程的
方式)?
(1)通过继承 Thread 类
(2)通过实现 Runnable 接口(推荐使用,因为 Java 中是单继承,一个类只有 一个父类,若继承了 Thread 类,就无法在继承其它类,显然实现 Runnable 接口更为灵活)
(3)通过实现 Callable 接口(Java 5 之后)
. 15.请说出同步线程及线程调度相关的方法?
1)wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
2)sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理
InterruptedException 异常;
3)notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒
某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且与优先级无关;
4)notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而
是让它们竞争,只有获得锁的线程才能进入就绪状态;
注意:java 5 通过 Lock 接口提供了显示的锁机制,Lock 接口中定义了加锁(lock()方法)
和解锁(unLock()方法),增强了多线程编程的灵活性及对线程的协调
17.启动一个线程是调用 run) ()方法还是 start()方法?
启动一个线程是调用 start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由 JVM 调度并执行,这并不意味着线程就会立即运行。
run()方法是线程启动后要进行回调(callback)的方法。
18.什么是线程池,有哪些常用线程池?
就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程
不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开
销。
常用线程池:
(1)newSingleThreadExecutor:创建一个单线程的线程池,此线程池保证所有任务的
执行顺序按照任务的提交顺序执行。
(2)newFixedThreadPool:创建固定大小的线程池,每次提交一个任务就创建一个线
程,直到线程达到线程池的最大大小。
(3)newCachedThreadPool:创建一个可缓存的线程池,此线程池不会对线程池大小
做限制,线程池大小完全依赖于操作系统(或者说 JVM)能够创建的最大线程大小。
(4)newScheduledThreadPool:创建一个大小无限的线程池,此线程池支持定时以及
周期性执行任务的需求。
(5)newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持定时以及周
期性执行任务的需求。
19.什么是死锁?
两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程 都陷入了无限的等待中。
20.如何确保 N N 个线程可以访问 N N 个资源同时又不导致死锁?
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。
21.获得一个类的类对象有哪些方式?
1):类型.class,例如:String.class
2):对象.getClass(),例如:”hello”.getClass()
3):Class.forName(),例如:Class.forName(“java.lang.String”)
22.简述下你了解的设计模式?
一、设计模式的分类(加粗为常用)
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模
式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、
命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
二、单例模式
单例设计模式
单例模式的好处:
1.某些类的创建比较频繁,对于一些大型的对象,这是一笔很大的开销。
2.省去了new的操作,节省了内存的开销,减轻了GC的压力。
3.有些情况只能用单例的设计模式,例如,一些交易核心,只能用一个对象,不然就会乱套了。
饿汉式:(线程安全的)
// 私有的构造方法
private Singleton(){
}
// 指向自己实例的私有静态引用
private static Singleton singleton = new Singleton();
// 以自己实例为返回值的静态的公有的方法
public static Singleton getInstance() {
return singleton;
}
}
懒汉式(线程不安全)
public class Singleton {
// 私有的构造方法
private Singleton() {
}
// 不建立对象
private static Singleton singleton = null;
// 以自己实例为返回值的静态的公有的方法
public static Singleton getInstance() {
if (singleton == null) {// 先判断是否为空
singleton = new Singleton();// 如果为空建立对象
}
return singleton;
}
}
注:可以通过枚举实现单例模式的绝对单例
三、工厂模式
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其
创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
关键代码:创建过程在其子类执行
四、适配器模式
意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不
兼容而不能一起工作的那些类可以一起工作。
主要解决:主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环
境要求的接口是现对象不能满足的。
何时使用: 1、系统需要使用现有的类,而此类的接口不符合系统的需要。 2、想要建立
一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引
进的类一起工作,这些源类不一定有一致的接口。 3、通过接口转换,将一个类插入另一个类
系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在
里面包容一个虎对象,实现飞的接口。)
如何解决:继承或依赖(推荐)。
关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。
作者:天道灬酬勤
来源:简书