Java面试题(持续更新)
CoreJava
1.Java语言的三个版本?
JavaSE JavaEE JavaME
1995.5.23 jdk1.0发布
1.JSE 指标准版一般用于用户学习JAVA语言的基础也是使用其他两个版本的基础主要用于编写C/S项目和提供标准的JAVA类库,是所有基于Java语言开发的基础,该版本主要用于开发桌面应用程序。
2.JEE 指企业版依托互连网技术提供企业级平台应用说白了就是用来构建大型网站和B/S系统 ,作为一个企业版本,主要是给出一个开发企业级应用架构的解决方案,同时给出了在这个架构中相关组件以供开发人员使用,例如我们连接数据库所用的JDBC。
3.JME 指移动版为小型移动器械搭建使用平台主要是用来为手机编程,制作手机相关软件的 三个版本一个是做C/S项目如QQ 一个是做网站如163 一个是做手机系统如大部分手机的小游戏 ,是针对移动设备,嵌入式系统的开发。
B/S C/S 结构 ***
B/S 浏览器服务器。比如:百度
优点:用户不需要更新
缺点:用户粘性低
C/S 客户端服务器。比如:京东App
优点:用户粘性高
缺点:需要频繁更新
2.Java语言的特点?
简单,跨平台,面向对象
一、与平台的无关性
在Java语言中,最大的优点就是具有与平台无关性,这样在使用的时候能够进行跨平台使用。大多数编程语言都不是跨平台的。所谓的平台,我们可以理解为操作系统,在其他的操作系统下不可以运行其他文件。但是Java语言不一样,Java程序不是直接运行在操作系统上面,而是在JVM中进行运行。
二、可靠性
Java语言是一种强类型语言,需要在使用变量之前对其进行定义。为变量分配数据类型后,如果未进行转换,则始终为数据类型。这样,Java可以在编译时检查语法是否正确。
三、面向对象
Java语言是支持封装,继承,多态和面向对象的编程语言,这使得程序只有很少的耦合,能够更具凝聚力。每个模块都执行自己的功能,不会通过公共接口相互干扰。
四、多线程
进程是操作系统中分配的最小内存资源单元。每个进程可以同时拥有两个或多个线程,允许它们同时执行。并且它提供了Rannable接口及其实现类Thread,提供了许多控制线程操作的方法,以及线程同步控制。
3.Java语言的运行机制?
JDK(开发工具包) JRE(运行环境) JVM (虚拟机)
先编译后解释运行
①首先采用通用的java编译器将java源程序编译为与平台无关的字节码文件(.class文件)
②然后由java虚拟机(JVM)对字节码文件解释执行
注意:java字节码具有平台无关性,可以在各种不同系统平台中运行,但是需要有不同版本的java虚拟机,不同平台的java环境其Java虚拟机是不一样的。
4.什么是jvm?
java 虚拟机
(1)JVM是java字节码执行的引擎,为java程序的执行提供必要的支持,还能优化java字节码文件,使之转化成效率更高的机器指令。程序员编写的程序最终都要在JVM上执行,JVM中的类的装载是由类加载器(ClassLoader)和它的子类来实现的。
(2)ClassLoader是java运行时一个重要的系统组件,负责在运行时查找和装入类文件的类。
(3)JVM屏蔽了与具体操作系统平台相关的信息,从而实现了java程序只需要生成在JVM上运行的字节码文件(class文件),就可以在多种平台上不加修饰的运行。不同平台对应着不同的JVM,在执行字节码时,JVM负责将每一条要执行的字节码发送给解释器,解释器再将其翻译成特定平台环境的机器指令并执行。java语言最重要的特点是跨平台运行,使用JVM就是为了支持与操作系统无关,实现跨平台运行。
5.Java的命名规范?
包名小写,类名首字母大写,方法/变量驼峰命名,常量全大写多个单词使用_分隔
1、项目名,包名全部小写
2、方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头
3、使用驼峰命名法命名多个单词组成的变量名
4、常量命名时需要遵循名称全部大写的原则。
5、对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部的实现类用Impl 的后缀与接口区别。
6、如果模块、 接口、类、方法使用了设计模式,在命名时需体现出具体模式
说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。
正例:public class OrderFactory;
public class LoginProxy;
public class ResourceObserver;
7、定义数组时,类型与中括号紧挨相连
正例:
int[] array = new int[10];
int array[] = new int[10]; // 不建议这样写
8、所有命名规则必须遵循以下规则:
1)、名称只能由字母、数字、下划线、$符号组成
2)、命名时不能以数字开头
3)、在命名是绝对不能出现Java关键字。
4)、绝对不允许在命名时出现中文及拼音命名。
6.常见的八种基本数据类型? 所占的字节数? ***
基本类型 | 默认值 | 所占字节 | 取值范围 |
---|---|---|---|
byte | 0 | 1Byte | -128~127 |
short | 0 | 2B | -32768~32767 |
int | 0 | 4B | -2147483648~2147483647 |
long | 0L | 8B | -263~263-1 |
float | 0.0f | 4B | 单精度 支持科学计数法如1E29 float类型的数值有一个后缀F(例如:3.14F) |
double | 0.0d | 8B | 双精度 没有后缀F的浮点数值(如3.14)默认为double类型 |
char | ‘\u0000’ | 2B | |
boolean | false | 1B | true|false |
0.5556 是什么类型? double
short的取值范围是多少?
int a=32766 a=a+3 a=? -32767
double a=12.12 float a=12.2f|F
short a=12; a++(√) a=a+1(×) 那个是错的? 自增自减不会类型提升,1默认是int类型的
操作小数类型,要求计算结果必须精确。 BigDecimal
7.自动类型提升?***
当两个操作数有一个为double时,运算结果为 double
没有double,出现float,结果为float
没有float,出现long,结果为long
没有long,出现int,结果为int
除long类型外,其余整数类型运算结果均为int类型
Byte -> short -> int -> long -> float -> double
8.&&(短路) 与 &(非短路)(并且) || 和 | (或者)有什么区别? ***
1)&& || 是逻辑运算符 $ 位运算
2)&(与)从最高位运算,运算符两个位都为1,结果才为1,否则结果为0
|(或)运算符两个位只要有一个为1,那么结果就是1,否则就为0
“~”(非)表示位为0,结果是1,如果位为1,结果是0
“^”(异或)表示的两个的位,相同则结果为0,不同则结果为1
请用两种方式判断奇偶数 int q=10 q%2==0 (q&1)==0
用最有效率的方法计算2乘以8?
2<<3 (左移三位相当于乘以2的三次方,右移三位相当于除以2的三次方)
9.请写出冒泡排序的算法? ***
冒泡排序: 相邻运算两两比较,互换位置。
for (int i = 0; i < a.length-1; i++) {
for (int j = 0; j < a.length-i-1; j++) {
if(a[j] < a[j+1]){
int temp = a[j];
a[j] = a[j+1];
a[j+1] =temp;
}
}
}
//选择排序: 固定值和后面的值依次比较互换位置
for(int i=1;i<=aaa.length-1;i++){
for(int j=i ;j<=aaa.length-1;j++){
if(aaa[i-1]>aaa[j]){
int temp = aaa[i-1];
aaa[i-1] = aaa[j];
aaa[j] = temp;
}
}
}
排序方法:Arrays.sort(aaa);
10.数组扩容的步骤?
1、准备一个容量更大的新数组
2、将原数组元素拷贝到新数组中
3、将新数组的引用赋值给原数组引用(替换原数组)
java.util.Arrays.copyOf(原数组名,新数组长度);
System.arraycopy(原数组名,起始下标,新数组名,起始下标,复制长度);
11.面向对象三大特性? ***
面向对象的三大特征是封装,继承,多态。
封装有利于提高类和系统的安全性;
继承可以建立类的层次或等级;
多态实现同一操作作用与不同类的实例,将产生不同的执行结果。
谁最重要: 多态最重要。继承是多态的铺垫。
多态的应用场景: 父类作为方法形参: 接收所有的实现类对象
父类作为方法的返回值类型: 返回所有子类对象
12.编译时多态,运行时多态? ***
1)编译时多态:引用只能调用其引用类中声明的方法和属性。
2)运行时多态:运行时调用子类覆盖之后的方法
dog extends Animal
sleep(){}
eat(){}
Animal
eat(){}
Animal a=new Dog()
13. 关于构造方法?
1)方法名 必须和 类名完全一致 没有返回值
2)不允许手动调用,在每次创建对象时 由解释器自动调用
3)当在类中没定义任何构造方法时,系统会默认分配一个 公共无参的 构造方法
4)如果定义了构造方法,则不再分配 公共无参构造
14.This和super关键字
1)This 引用, 代表当前对象(相当于“我”),this. 用于在构造方法或普通方法中,调用当前对象的属性或方法, this() 只能用在构造方法中,用于 调用该类中的其它构造方法。
2)Super 引用,代表直接父类对象。Super.用在子类的构造方法或普通方法中,调用父类的属性或方法。Super()只能用在子类的构造方法中,用于调用父类的构造方法
15.继承时对象的创建过程? ***
创建子类对象优先创建父类对象。因为子类对象的组成 = 父类的共性 + 子类独有
过程:
1.开辟父子类空间
2.初始化父类属性
3.执行父类构造方法
4.初始化子类属性
5.执行子类构造方法
16.java中是单继承,接口可以多继承多实现? (对) ***
类可以单继承类和多实现接口,接口与接口的多继承和类多实现接口效果是一样的
3、为什么接口可以继承多个接口?
因为接口定义的都是抽象的方法,而且不能在接口中实现方法。所以,接口继承多个接口,并不会使接口的结构变得很复杂。相反,这样做,还 能给一个团队在开发的过程中,提供很多便利。
4、为什么JAVA改成只能单继承?
因为在C++中一个类是可以继承自多个类,但这样的机制会使类的结构变的很复杂,所以JAVA将C++这一机制通过接口得以改善。
JAVA中不允许类多重继承,只能单一继承,但有些情况单一继承并不能表达出现实世界中的某些逻辑关系,所以就提出了通过接口来实现多重继承。
17.什么是方法重载(overload) 什么是方法的覆盖(override)? ***
1)重载:方法名相同参数表不同 返回值无要求 参数表(个数,顺序,类型)
2)覆盖:方法名,返回值 ,参数表 相同 修饰符 (相同或者更宽) 异常(不能比父类抛出更广泛的异常)
18.instanceof关键字作用? transient关键字作用? ***
1)判断引用指向的实际对象类型 和 后面的类型 是否兼容,是-true;否则-false
2)修饰属性 指明当前属性不参与序列化
19.三个关键字 ***
一.static 关键字修饰类,属性,方法的特点?
1)属性:类属性,被所有对象共享(与对象无关),只初始化1次。
2)方法: 被static修饰的方法 称为类方法(静态方法)
3)静态初始代码块, 被static 修饰的 初始代码块。用于在类加载时,和 初始化静态属性 按代码的先后顺序 进行初始化工作。
二.final 修饰类 属性 方法特点?
1)变量: final修饰的变量 是常量,只允许赋1次值,不允许修改。
2)方法:final修饰的方法 不能被 覆盖。
3)类:final修饰的类 不能被 继承。
三.abstract 修饰类 修饰方法抽象方法?
1)方法:被abstract修饰的方法,称为 抽象方法
注意:1) 抽象方法 没有方法体(连{}都没有 直接;结束)
2) 抽象方法 必须定义在 抽象类中
a.类:被abstract修饰的类,称为 抽象类。
注意:1)抽象类 不能 实例化; 可以声明引用
2)子类 继承 抽象类时, 必须 实现/覆盖 抽象类中的所有抽象方(除非该子类还是抽象的)
3)抽象类中 既可以有抽象方法 也可以有 非抽象方法
20.什么是类加载? ***
类加载,在JVM第1次使用某个类时,先在classpath下 找到对应的.class文件,读取 该.class文件中的内容(包/名/属性/方法...)到内存中 并且保存(类对象)起来 的过程。 类加载 只进行1次
21.简述 final finalized finally 的区别? ***
1)Final修饰符
2)Finalized 垃圾回收在释放对象占用的内存之前,垃圾收集器会调用对象的 finalize()方法。一般建议在该方法中 释放对象持有的资源。
3)Finally finally代码一定会执行
Try{
逻辑代码 有可能出现异常的代码
Return 程序的出口
}catch(){
捕获异常 打印异常信息
}Fianlly{
一定会之行的代码
}
22.接口的特点?
解耦合 多继承 多实现
23. ”==”与equal有何区别? ***
1)== 比较基本数据类型比较的是值。比较引用数据类型比较的是地址。
2)equals 只能比较引用类型,默认比较地址,覆盖后比较内容。
24.SringBuilder与Springbuffer的区别? ***
StringBuilder JDK1.5 速度快 线程不安全
StringBuffer JDK1.0 速度慢 线程安全
String: 不可变长字符串。 StringBuilder StringBuffer: 可变长字符串
常用方法:append(v) 将v拼接到字符串结尾
25. 简述ArrayList LinkedList Vector三者的区别? ***
1)ArrayList
版本 JDK1.2产物 操作速度快,线程不安全
2)存储结构:数组
3)存储特点:增删慢、查询快
2)LinkedList
版本 JDK1.2产物 操作速度快,线程不安全
2)存储结构:链表
3)存储特点:增删块、查询慢
3)Vector
版本 JDK1.0 操作速度慢,线程安全
2)存储结构:数组
3)存储特点:增删慢、查询快
26.HashMap和HashTable的区别? ***
HashMap 允许key value同时为空 线程不安全 效率高
hashtable 不允许key value 为空 线程安全的 效率低 整个表加锁
ConcurrentHashMap: java.concurrent jdk并发包
Hashtable和ConcurrentHashMap有什么分别呢?它们都可以用于多线程的环境,
但是当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。
因为ConcurrentHashMap引入了分割(segmentation),不论它变得多么大,仅仅需要锁定map的某个部分,对表进行分段加锁16段
而其它的线程不需要等到迭代完成才能访问map。简而言之,在迭代的过程中,ConcurrentHashMap仅仅锁定map的某个部分,
而Hashtable则会锁定整个map。
27.简述流的分类?
1)方向
输入流:用以将外部的数据读入到JVM中。
输出流:将JVM中的数据输出到外部。
2)单位
字节流:以字节为单位,可以读取所有类型的数据。
字符流:以字符为单位,只能读写文本数据。
3)功能
节点流:实际负责传输数据的流
过滤流:增强节点流功能(处理流、装饰类),依赖节点流
流分类 | 使用分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer | |
节点流 | 访问文件 | *FileInputStream* | *FileOutStream* | *FileReader* | *FileWriter* |
访问数值 | *ByteArrayInputStream* | *ByteArrayOutStream* | *CharArrayReader* | *CharArrayWriter* | |
访问管道 | *PipedInputStream* | *PipedOutStream* | *PipedReader* | *PipedWriter* | |
访问字符串 | *StringReader* | *StringWriter* | |||
处理流 | 缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | OutputStreamWriter | |||
对象流 | ObjectInputStream | ObjectOutputStream | |||
抽象基类(过滤) | FilterInputStream | FilterOutputStream | FilterReader | FilterWriter | |
打印流 | PrintStream | PrintWriter | |||
推回输入流 | PushbackInputStream | PushbackReader | |||
特殊流 | DataInputStream | DataOutputStream |
28.线程的生命周期? ***
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zKJ7mTMJ-1660828020429)(C:\Users\asus\AppData\Roaming\Typora\typora-user-images\image-20220806154911460.png)]
线程 线程的状态 线程池 创建线程 并发操作怎么保证数据安全(使用线程安全的类,方法,在临界资源上加锁)
高并发:状态 多线程 线程安全 数据一致
线程的状态:https://blog.csdn.net/xingjing1226/article/details/81977129
线程池:
29.什么是线程安全?Vector是一个线程安全类吗?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。一个线程安全的计数器类的同一个实例对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分成两组,线程安全和非线程安全的。Vector 是用同步方法来实现线程安全的, 而和它相似的ArrayList不是线程安全的。
30.Java多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? ***
1)继承Thread
Thread1 extends Thread {
public void run(){
// 线程的功能代码
}
}
使用:a. 创建线程对象
Thread1 t1 = new Thread1();
b. 启动线程
t1.start(); // 启动线程,JVM自动调用run方法
// t1.run(); //error. 相当于调用了一个对象中的方法
2)实现Runnable 接口
Thread2 implements Runnable{
//实现run方法
@Override
public void run(){
//线程的代码功能
}
}
//使用
Thread thread = new Thread(new Thread2());
thread.start();
3.实现 Callable 接口
Thread1 implements Callable {
public void run(){
// 线程的功能代码
}
}
使用:a. 创建线程对象
Thread1 t1 = new Thread1();
b. 启动线程
t1.start(); // 启动线程,JVM自动调用run方法
// t1.run(); //error. 相当于调用了一个对象中的方法
31.sleep() 和 wait() 有什么区别? ***
1)sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间(休息),把执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复,时间到了会继续运行。
2)调用sleep不会释放对象锁。
3)wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待队列
4)只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
32.通过反射获取类对象的3种方式? ***
1)通过类名.class 获取 Class对象
Class s = Student.class;
2)创建对象,通过对象 . getClass() 获取Class对象
Strudet student = new Student();
Class s = student.getClass();
3)通过 Class.forName("包名.类名"); 获取Class对象
Class s = Class.forName(“java.util.HashSet”);
33.单例模式 ***
概念: 保证内存中只能有一个该类型对象。
// 1)饿汉式 : 类加载立刻创建对象。
class Student{
private static final Student stu = new Student();
private Student(){} //私有构造
public static Student getInstance(){
return stu;
}
}
// 2)懒汉式
class Student{
private static Student stu;
private Student(){} //私有构造
public synchronized static Student getInstance(){
if (stu == null){
stu = new Student();
}
return stu;
}