校招面经(一)
Java基础
Java(英式发音[ˈʤɑːvə],美式发音[ˈʤɑvə])是一种广泛使用的计算机编程语言,拥有跨平台、面向对象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。
任职于Sun微系统的詹姆斯·高斯林等人于1990年代初开发Java语言的雏形,最初被命名为Oak,目标设置在家用电器等小型系统的编程语言,应用在电视机、电话、闹钟、烤面包机等家用电器的控制和通信。由于这些智能化家电的市场需求没有预期的高,Sun微系统放弃了该项计划。随着1990年代互联网的发展,Sun微系统看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。
Java编程语言的风格十分接近C++ 语言。继承了C语言面向对象技术的核心,舍弃了容易引起错误的指针,以引用取代;移除了C中的运算符重载和多重继承特性,用接口取代;增加垃圾回收器功能。在Java SE 1.5版本中引入了泛型编程、类型安全的枚举、不定长参数和自动装/拆箱特性。Sun微系统对Java语言的解释是:“Java编程语言是个简单、面向对象、分布式、解释性、健壮、安全、与系统无关、可移植、高性能、多线程和动态的语言”。
Java不同于一般的编译语言或解释型语言。它首先将源代码编译成字节码,再依赖各种不同平台上的虚拟机来解释执行字节码,从而具有 “一次编写,到处运行” 的跨平台特性。在早期JVM中,这在一定程度上降低了Java程序的运行效率。但在J2SE1.4.2发布后,Java的执行速度有了大幅提升。
与传统类型不同,Sun微系统在推出Java时就将其作为开放的技术。全球的Java开发公司被要求所设计的Java软件必须相互兼容。“Java语言靠群体的力量而非公司的力量”是Sun微系统的口号之一,并获得了广大软件开发商的认同。这与微软公司所倡导的注重精英和封闭式的模式完全不同,此外,微软公司后来推出了与之竞争的 .NET平台以及模仿Java的C# 语言。后来Sun微系统被甲骨文公司并购,Java也随之成为甲骨文公司的产品。
现时,移动操作系统Android大部分的代码采用Java编程语言编程。
static关键字?
static关键字可以用来修饰代码块表示静态代码块,修饰成员变量表示全局静态成员变量,修饰方法表示静态方法。(注意:不能修饰普通类,除了内部类,这是为什么?)
静态是相对于动态的,动态是指Java程序在JVM上运行时,JVM会根据程序的需要动态创建对象并存储对象(分配内存),对象使命结束后,对象会被垃圾回收器销毁,即内存回收由JVM统一管理并分配给其他新创建的对象;
静态是指Java程序还没有运行时,JVM就会为加载的类分配空间存储被static关键字修饰的内容;
如静态成员变量,Java类加载到JVM中,JVM会把类以及类的静态成员变量存储在方法区,我们知道方法区是线程共享且很少发生GC的区域,所以被static关键字修饰的内容都是全局共享的,且只会为其分配一次存储空间。
String、StringBuffer和StringBuilder的区别?
他们都是继承AbstractStringBuilder类,也是使用字符数组来保存字符串,但是没有用final来修饰,因此这两个对象都是可变的。
从线程安全来说:String对象不可变,相当于常量,线程安全。StringBuffer对方法加了同步锁,因此线程安全的。StringBuilder没有对方法加同步锁,所以是非线程安全的。
从性能来说:每次对String类型进行改变的时候,都会生成一个虚拟的String对象,然后将指针指向这个新的String对象,然后将指针指向这个新的String对象。StringBuffer对自己进行改变时,是在对自己本身操作,不会生成新的对象和改变对象的引用。StringBuilder和StringBuffer一样,但是因为没有使用同步锁,所以性能相对StringBuffer还一点,但是会冒着线程不安全的风险。
String更适合操作少量数据,大量数据操作根据线程情况选择。
接口和抽象类的区别是什么?
接口的方法默认是public ,接口里的方法不能有实现 JDK8 后可以使用 default 关键字,让其有实现 )),抽象类可以有非抽象方法。接口中除了 static 、 final 变量 ,不能有其他变量抽象类不一定。一个类可以实现多个接口,但一个类只能实现一个抽象类。抽象是对类的抽象,接口是对行为的抽象。
获取Class对象的几种方式?
知道具体类的情况下可以直接使用类名.class。
可以通过Class.forName()传入类的路径获取。
通过对象实例.getClass() 获取。
通过类加载器获取xxxClassLoader.loadClass()传入类路径。
List、Set、Map三者的区别?
List:存储的元素是有序的、可重复
Set:存储的元素是无序的、不可重复
Map:使用键值对(Key-Value)存储,Key是无序的、不可重复的,Value是无序的、可重复的,每个键最多映射到一个值
ArrayList与LinkedList区别?
1、ArrayList和LinkedList都是线程不安全的。
2、 ArrayList底层使用的是Object的数组实现的,LinkedList底层使用的是双向链表数据结构(JDK1.6之前是循环链表,jdk1.7取消了循环)。
3、 ArrayList支持快速随机访问,LinkedList不支持快速随机访问。
4、 ArrayList的空间浪费主要体现在会预留一定的容量空间,LinkedList 的空间浪费主要体现在它需要 保存直接前驱和直接后驱,每个元素都会比ArrayList 消耗更多的空间。
5、 ArrayList插入和删除数据受元素位置影响,如果调用带下标的插入方法,则需要向将插入位置后面的元素后移,然后插入。LinkedList则只需要移动到对应下标的位置即可。
Java多线程实现的方式?
1、集成Thread类,重写run方法。
2、实现Runable接口,重写run方法,然后将这个对象作为参数传入Thread。
3、实现Callable接口,重写call方法,通过FutureTask对callable对象进行包装,然后作为参数传入Thread类。
4、使用线程池创建。
常用的线程池?
1、FixedThreadPool,固定线程数的线程池,当运行的线程数小于我们指定的线程数,有新任务来的时候,就立即创建线程执行。如果多余我们制定的线程数,则把新任务放在队列里等待。
2、SingleThreadExcutor,只有一个线程的线程池,新来的任务放在队列里。
3、CachedThreadPool,核心线程数为0,最大线程数 为 Integer 的最大值,即无界的。意味着主线程提交的任务速度高于线程处理任务的速度,会不断创建线程,导致CPU和内存被耗尽。
4、ThreadPoolExecutor,有七个参数,其中核心参数为 corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、 workQueue(工作队列大小) 。当线程执行达到核心线程数之和,再来任务就会进入到队列中等待,当达到队列指定的数量之后,会开启最大线程数,通过threadFactor创建线程来执行队列中的任务最大线程数的线程都执行好了,空闲 的线程会根据配置的存活时间(两个参数,时间大小和单位) 去销毁,最终保持只有核心线程数的线程。还可以配置拒绝策略,当最大线程数被开启之后,新来的任务可以拒绝。