java面试题
1. Java的特点有哪些
Java 语言是一种分布式的面向对象语言,具有
面向对象,平台无关性,解释性。简单性,多线程
解释执行:虚拟机将字节码转换成二进制机器码执行
简单性:抛弃了C++中的指针,多重继承,手动内存回收
多线程:jvm有自己的线程实现,和系统线程一一映射
安全性:没有指针
2.java程序运行过程
3. a=a+b与a+=b有什么区别吗?
+= 操作符会隐式的进行自动类型转换
4. final 在 Java 中有什么作用?
可以用于三个地方:修饰类、类属性和类方法。
可以修饰属性,方法和类,分别表示属性不可改变,方法不可覆盖,被其修饰的类不可继承。
5. static都有哪些用法?
修饰类:静态内部类,可以直接通过类来调用,而不需要new
修饰变量:静态变量
修饰方法:静态方法
也就是被static所修饰的变量/方法都属于类的静态资源,被类实例所共享
修饰块:静态块,多用于初始化操作
修饰包:静态导包,可以用来指定导入某个类中的静态资源,并且不需要使用类名,可以直接使用资源名
8.==和equals()的区别
== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重写了equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下equals 比较的是值是否相等。
9.hashCode()
hashCode方法可以这样理解:它返回的就是根据对象的内存地址换算出的一个值。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次
10. 面向对象的特征
抽风极多:抽象,封装,继承,多态
11.访问修饰符
default:包权限访问控制符
我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,
要将java对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个java
对象变成某个格式的字节流再传输。
2.方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同
3.访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)
4.重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常
重载:(运行时多态)
2.重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序)
3.重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准
19. Java 中 IO 流分为几种?
流的方向:输入流/输出流 操作单元:字节流/字符流 流的角色:节点流/处理流(低级流/高级流)
(节点流:直接连接数据源节点进行读写 处理流:对节点流进行封装,程序连接到已存在的流上,不会连接到数据源)
Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的。
InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
20. String、StringBuffer和StringBuilder区别
1、数据可变和不可变
String 不可变
StringBuffer 和 StringBuilder 可变
2、线程安全
StringBuilder 是线程不安全的,效率较高;而 StringBuffer 是线程安全的,效率较低
3、 性能
操作可变字符串速度: StringBuilder > StringBuffer > String
性能:每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将
指针指向新的 String 对象。 StringBuffer 每次都会对 StringBuffer 对象本身
进行操作,而不是生成新的对象并改变对象引用。相同情况下使用
StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,
但却要冒多线程不安全的风险
使用总结:
1. 操作少量的数据 = String
2. 单线程操作字符串缓冲区下操作大量数据 = StringBuilder
3. 多线程操作字符串缓冲区下操作大量数据 = StringBuffer
22. 阐述静态变量和实例变量的区别?
静态变量: 是被 static 修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,他被所有类实例所共享
实例变量: 必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。
23.&和&&的区别?
&运算符有两种用法:(1)按位与;(2)逻辑与(两边有一边是boolean的时候)
&&:短路与。
24、内存中的栈(stack)、堆(heap)和方法区(method area)
的用法
栈:变量,引用(保存 基本数据类型的变量,对象的引用,函数调用的现场)
堆:对象
方法区:(方法区中有常量池)常量,静态变量。保存 已经被JVM加载的 类信息,常量,静态变量,JIT编译器编译后的代码
程序中的字面量(literal)如直接书写的 100,“hello”和常量都是放在常量池中,常量池是方法区的一部分
25.math.round()
四舍五入的原理:在参数上加 0.5 然后进行下取整
26.java异常
error:程序无法处理的错误。代码运行时jvm出现的问题
exception:程序本身可以处理的异常。
Exception 类有一个重要子类 RuntimeException。 RuntimeException 异常由 Java 虚拟机抛出。
NullPointerException(要访问的变量没有引用任何对象时,抛出该异常)、
ArithmeticException(算术运算异常,一个整数除以 0 时,抛出该异常)和
ArrayIndexOutOfBoundsException (下标越界异常)。
try:捕获异常
catch:处理异常
finally:无论是否捕获或处理异常, finally 块里的语句都会被执行
27. Java 中实现多态的机制是什么?
靠的是父类定义的引用变量可以指向子类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法
28. 字符串的+操作其本质是创建了 StringBuilder 对象进行 append 操作,
29.java5大改动,加入了很多新东西
30.自动装箱/自动拆箱
Integer a = 5; //装箱 int b=a; //拆箱
(2)自动装箱的时候,对于-128~127之间的数,会将对象保存到缓存中。所以创建对象的时候会先在缓存里面取
byte,short,int,long,char对应的包装类都是这样。float,double不是的。boolean也用了缓存机制
(3)自动装箱,自动拆箱有时候触发会很频繁
31.字符串和基本数据类型间的转化
(1)、 字符串如何转基本数据类型?
调用基本数据类型对应的包装类中的方法 parseXXX(String)或 valueOf(String)即可返回相应基本类型。
(2) 、基本数据类型如何转字符串?
一种方法是将基本数据类型与空字符串(“”)连接(+)即可获得其所对应的字符串;另一种方法是调用 String
类中的 valueOf()方法返回相应字符串。
在 java 中能够被序列化的类必须先实现 Serializable 接口,该接口没有任何抽象方法只是起到一个标记作用。
33. 字节流和字符流的区别(2017-11-23-wzz)
字节流读取的时候,读到一个字节就返回一个字节; 字符流使用了字节流读到一个或多个字节(中文对应的字节
数是两个,在 UTF-8 码表中是 3 个字节)时。先去查指定的编码表,将查到的字符返回。 字节流可以处理所有类型数
据,如:图片, MP3, AVI 视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符
流,除此之外都用字节流。 字节流主要是操作 byte 类型数据,以 byte 数组为准,主要操作类就是 OutputStream、
InputStream
34. 如何实现对象克隆?
1). 实现 Cloneable 接口并重写 Object 类中的 clone()方法;
2). 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,
35.集合分类
36. List a=new ArrayList()和 ArrayList a =new ArrayList()的区别?
第一个:向上转型,运用了多态机制,但ArrayList中特有的方法不可以使用。第二个所有的方法都可以使用
37.反射
反射首先要获取 Class 对象
取得Class对象的三种方法:
方式一:通过Object类的getClass()方法取得,基本不用:
有了Class类对象之后,现在又提供了另外一种对象的实例化方法:
作用:·
(1)通过反射实例化对象:
类的私有变量和方法不能被继承。构造方法也不能被继承,所以构造方法不能被重写,但可以重载
1、使用 new 关键字;
2、反射机制:使用 Class 类的 newInstance 方法,该⽅法调用⽆参的构造器创建对象
3、使⽤ clone() 方法;
4、反序列列化,⽐如调用 ObjectInputStream 类的 readObject() ⽅法。
clone ⽅法:⽤于创建并返回当前对象的⼀一份拷贝;
getClass ⽅法:⽤用于返回当前运行时对象的 Class;
toString ⽅法:返回对象的字符串表示;
finalize ⽅法:实例被垃圾回收器回收时触发的方法;
equals ⽅法:⽤于⽐较两个对象的内存地址是否相等,一般需要重写;
hashCode 方法:⽤于返回对象的哈希值;
notify ⽅法:唤醒一个在此对象监视器上等待的线程。如果有多个线程在等待只会唤醒⼀一个。
notifyAll 方法:作用跟 notify() ⼀一样,只不过会唤醒在此对象监视器上等待的所有线程,⽽不是一个线程。
wait ⽅法:让当前对象等待;
.......
final:⽤于声明属性、方法和类,分别表示属性不可变、⽅法不可覆盖、被其修饰的类不可继承;
finally:异常处理理语句结构的一部分,表示总是执行;
finallize: Object类的一个方法,在圾回收时会调用被回收对象的finalize
(1)实现 Cloneable 接口并重写 Object 类中的 clone() ⽅方法;
(2)实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深克隆。
动态代理理:当想要给实现了了某个接⼝口的类中的⽅方法,加一些额外的处理。比如说加日志,加事务等。可以给这个类
创建一个代理,故名思议就是创建⼀一个新的类,这个类不仅包含原来类方法的功能,⽽且还在原来的基础上添加了了
额外处理的新功能。这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强。
动态代理理的应用: Spring 的 AOP 、加事务、加权限、加日志。
不一定。下⾯两种情况不到:
(1)当程序进入 try 块之前就出现异常,会直接结束,不会执行 finally 块中的代码
(2)当程序在 try 块中调用System.exit(int)强制退出程序,也不会执行 finally 块中的代码
时,被 transient 修饰的变量值不会被恢复。
序在⽗类中找不到没有参数的构造⽅法可供执⾏。解决办法是在⽗类⾥加上⼀个不做事且没有参数的构造⽅法。
(1)==
情况 1:类没有覆盖 equals() ⽅法。则通过 equals() ⽐较该类的两个对象时,等价于通过
“==”⽐较这两个对象。
情况 2:类覆盖了 equals() ⽅法。⼀般,我们都覆盖 equals() ⽅法来⽐较两个对象的内容是
否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)
2、如果两个对象hashCode()相等,这两个对象并不一定相等