Java基础面试题(三)
Java基础面试题(三)
1、&和&&的作用和区别
&
逻辑与,&两边的表达式都会进行计算
整数的位运算符
&&
短路与,&&左边的表达式结果位false时,&&右边的表达式不参与计算
(|和||短路或和类似,||左边位true,右边比参与计算)
2、计算机高效的算2乘8
2 << 3
3、Java中数组的特征
-
在内存中申请一块连续的空间
-
数组下标从 0 开始
-
每个数组元素都有默认值,基本类型的默认值为 0、0.0、false,引用类型的默认值为 null
-
数组的类型只能是一个,且固定,在申明时确定
-
数组的长度一经确定,无法改变,即定长。要改变长度,只能重新申明一个
4、可变参数的特点
1)无法仅通过改变可变参数的类型来重载方法
2)通过对class文件反编译可以发现,可变参数被编译器处理成了数组
5、面向过程和面向对象的理解
1)软件开发思想,先有面向过程,后有面向对象
2)在大型软件系统中,面向过程的做法不足,从而推出了面向对象
3)都是解决实际问题的思维方式
4)相辅相成,宏观上面向对象把握复杂事物的关系;微观上面向过程去处理
5)面向过程以实现功能的函数开发为主;面向对象要首先抽象出类、属性及其方法,然后通过实例化类、执行订单来完成功能
6)面向过程是封装功能,面向对象是封装的是数据和功能
7)面型对象具有继承性和多态性;面向过程没有
6、this和super关键字的作用
this:
-
对象内部指代自身的引用
-
解决成员变量和局部变量同名问题
-
可以调用成员变量
-
不能调用局部变量
-
可以调用成员方法
-
在普通方法中可以省略 this
-
在静态方法当中不允许出现 this 关键字
super:
-
代表对当前对象的直接父类对象的引用
-
可以调用父类的非 private 成员变量和方法
-
super(); 可以调用父类的构造方法,只限构造方法中使用,且必须是第一条语句
7、java.lang.Object的常用方法
-
public final native Class<?> getClass(); 获取类结构信息
-
public native int hashCode() 获取哈希码
-
public boolean equals(Object) 默认比较对象的地址值是否相等,子类可以重写比较规则
-
protected native Object clone() throws CloneNotSupportedException 用于对象克隆
-
public String toString() 把对象转变成字符串
-
public final native void notify() 多线程中唤醒功能
-
public final native void notifyAll() 多线程中唤醒所有等待线程的功能
-
public final void wait() throws InterruptedException 让持有对象锁的线程进入等待
-
public final native void wait(long timeout) throws InterruptedException 让持有对象锁的线程进入等待,设置超时毫秒数时间
-
public final void wait(long timeout, int nanos) throws InterruptedException 让持有对象锁的线程进入等待,设置超时纳秒数时间
-
protected void finalize() throws Throwable 垃圾回收前执行的方法
8、子类构造器的执行过程
子类构造方法的调用规则:
-
如果子类的构造方法中没有通过 super 显式调用父类的有参构造方法,也没有通过 this 显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。这种情况下,写不写 super(); 语句,效果是一样的
-
如果子类的构造方法中通过 super 显式调用父类的有参构造方法,将执行父类相应的构造方法,不执行父类无参构造方法
-
如果子类的构造方法中通过 this 显式调用自身的其他构造方法,将执行类中相应的构造方法
-
如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行顶级父类 Object 类的无参构造方法为止
9、Java垃圾回收机制
垃圾回收机制,简称 GC
-
Java 语言不需要程序员直接控制内存回收,由 JVM 在后台自动回收不再使用的内存
-
提高编程效率
-
保护程序的完整性
-
JVM 需要跟踪程序中有用的对象,确定哪些是无用的,影响性能
特点
-
回收 JVM 堆内存里的对象空间,不负责回收栈内存数据
-
无法处理一些操作系统资源的释放,如数据库连接、输入流输出流、Socket 连接
-
垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行
-
可以将对象的引用变量设置为 null,垃圾回收机制可以在下次执行时回收该对象。
-
JVM 有多种垃圾回收 实现算法,表现各异
-
垃圾回收机制回收任何对象之前,会先调用对象的 finalize() 方法
-
可以通过 System.gc() 或 Runtime.getRuntime().gc() 通知系统进行垃圾回收,会有一些效果,但系统是否进行垃圾回收依然不确定
-
不要主动调用对象的 finalize() 方法,应该交给垃圾回收机制调用
10、java.lang.Date 和java.lang.Date的区别
-
java.sql.Date 是 java.util.Date 的子类
-
java.util.Date 是 JDK 中的日期类,精确到时、分、秒、毫秒
-
java.sql.Date 与数据库 Date 相对应的一个类型,只有日期部分,时分秒都会设置为 0,如:2019-10-23 00:00:00
-
要从数据库时间字段取 时、分、秒、毫秒数据,可以使用 java.sql.Timestamp
11、面向对象的理解
对 Java 语言来说,一切皆是对象。
对象有以下特点:
-
对象具有属性和行为
-
对象具有变化的状态
-
对象具有唯一性
-
对象都是某个类别的实例
-
一切皆为对象,真实世界中的所有事物都可以视为对象
面向对象的特性:
-
抽象性:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。
-
继承性:指子类拥有父类的全部特征和行为,这是类之间的一种关系。Java 只支持单继承。
-
封装性:封装是将代码及其处理的数据绑定在一起的一种编程机制,该机制保证了程序和数据都不受外部干扰且不被误用。封装的目的在于保护信息。
-
多态性:多态性体现在父类的属性和方法被子类继承后或接口被实现类实现后,可以具有不同的属性或表现方式。
12、内存溢出和内存泄漏的区别
1)内存溢出(out of memory):指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory
2)内存泄漏(memory leak):指程序在申请内存后,无法释放一申请的内存空间,内存泄漏堆积会导致内存被占光。
3)memory leak最终会导致out of memory
13、同步代码块和同步方法的区别
-
同步方法就是在方法前加关键字 synchronized;同步代码块则是在方法内部使用 synchronized
-
加锁对象相同的话,同步方法锁的范围大于等于同步方法块。一般加锁范围越大,性能越差
-
同步方法如果是 static 方法,等同于同步方法块加锁在该 Class 对象上
14、静态内部类和非静态内部类的区别
-
静态内部类不需要有指向外部类的引用;非静态内部类需要持有对外部类的引用
-
静态内部类可以有静态方法、属性;非静态内部类则不能有静态方法、属性
-
静态内部类只能访问外部类的静态成员,不能访问外部类的非静态成员;非静态内部类能够访问外部类的静态和非静态成员
-
静态内部类不依赖于外部类的实例,直接实例化内部类对象;非静态内部类通过外部类的对象实例生成内部类对象
15、可序列化对象为什么要定义serialversionUID值
-
SerialVersionUid 是为了序列化对象版本控制,告诉 JVM 各版本反序列化时是否兼容
-
如果在新版本中这个值修改了,新版本就不兼容旧版本,反序列化时会抛出InvalidClassException异常
-
仅增加了一个属性,希望向下兼容,老版本的数据都保留,就不用修改
-
删除了一个属性,或更改了类的继承关系,就不能不兼容旧数据,这时应该手动更新 SerialVersionUid
16、Class类的getDeclaredFields()与getFields()方法的区别
-
getDeclaredFields(): 获取所有本类自己声明的属性, 不能获取父类和实现的接口中的属性
-
getFields(): 只能获取所有 public 声明的属性, 包括获取父类和实现的接口中的属性
17、正则表达式
-
\d 匹配一个数字字符,等价于[0-9]
-
\D 匹配一个非数字字符,等价于0-9
-
\s 匹配任何空白字符,包括空格、制表符、换页符等,等价于 [ \f\n\r\t\v]
-
. 匹配除换行符 \n 之外的任何单字符,匹配 . 字符需要转译,使用 .
-
* 匹配前面的子表达式零或多次,匹配 * 字符,需要转译使用 *
-
? 匹配前面子表达式零或一次,或表示指明表达式为非贪婪模式的限定符。匹配 ? 字符,需要转译使用 \?
-
| 将两个匹配条件进行逻辑 或 运算
-
+ 匹配前面的子表达式一次或多次,要匹配 + 字符需要转译,使用 +
-
[0-9]{6} 匹配连续6个0-9之间的数字
18、日期类型如何格式化?字符串如何转日期?
1 //日期格式为字符串 2 DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 3 String s = sdf.format(new Date()); 4 //字符串转日期 5 DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 6 String s = "2019-10-31 22:53:10"; 7 Date date = sdf.parse(s);
19、静态与非静态成员变量的区别
-
生命周期不同:非静态成员变量随着对象的创建而存在;静态成员变量随着类的加载而存在
-
调用方式不同:非静态成员变量用 对象名.变量名 调用;静态成员变量用 类名.变量名,JDK1.7 以后也能用对象名.变量名调用
-
别名不同:非静态成员变量也称为实例变量;静态变量称为类变量
-
数据存储位置不同:成员变量数据存储在堆内存的对象中,对象的特有数据;JDK1.6 静态变量数据存储在方法区(共享数据区)的静态区,对象的共享数据,JDK1.7 静态变量移到堆中存储
20、反射主要实现类有哪些
在JDK中,主要由以下类来实现 Java 反射机制,除了 Class 类,一般位于 java.lang.reflect 包中
-
java.lang.Class :一个类
-
java.lang.reflect.Field :类的成员变量(属性)
-
java.lang.reflect.Method :类的成员方法
-
java.lang.reflect.Constructor :类的构造方法
-
java.lang.reflect.Array :提供了静态方法动态创建数组,访问数组的元素
21、面向对象设计原则
-
单一职责原则 SRP
-
开闭原则 OCP
-
里氏替代原则 LSP
-
依赖注入原则 DIP
-
接口分离原则 ISP
-
迪米特原则 LOD
-
组合/聚合复用原则 CARP
其他原则可以看作是开闭原则的实现手段或方法,开闭原则是理想状态
22、String s = new String("xyz");创建了几个对象
两个或一个
-
第一次调用 new String("xyz"); 时,会在堆内存中创建一个字符串对象,同时在字符串常量池中创建一个对象 "xyz"
-
第二次调用 new String("xyz"); 时,只会在堆内存中创建一个字符串对象,指向之前在字符串常量池中创建的 "xyz"
23、Java和JavaScript的对比
JavaScript 与 Java 是两个公司开发的不同的两个产品。
-
Java 是 Sun 公司推出的面向对象的编程语言,现在多用于于互联网服务端开发,前身是 Oak
-
JavaScript 是 Netscape 公司推出的,为了扩展 Netscape 浏览器功能而开发的一种可以嵌入Web 页面中运行的基于对象和事件驱动的解释性语言,前身是 LiveScript
区别:
-
面向对象和基于对象:Java是一种面向对象的语言;JavaScript 是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言,提供了丰富的内部对象供开发者使用
-
编译和解释:Java 的源代码在执行之前,必须经过编译;JavaScript 是一种解释型编程语言,其源代码不需经过编译,由浏览器直接解释执行
-
静态与动态语言:Java 是静态语言(编译时变量的数据类型即可确定的语言);JavaScript 是动态语言(运行时确定数据类型的语言)
-
强类型变量和类型弱变量:Java 采用强类型变量检查,所有变量在编译之前必须声明类型;JavaScript 中变量声明,采用弱类型,即变量在使用前不需作声明类型,解释器在运行时检查其数据类型
24、类实例化方法调用顺序
类加载器实例化时进行的操作步骤:
加载 -> 连接 -> 初始化
-
代码书写顺序加载父类静态变量和父类静态代码块
-
代码书写顺序加载子类静态变量和子类静态代码块
-
父类非静态变量(父类实例成员变量)
-
父类非静态代码块
-
父类构造函数
-
子类非静态变量(子类实例成员变量)
-
子类非静态代码块
-
子类构造函数
25、JDK8中Stream接口的常用方法
中间操作:
-
filter:过滤元素
-
map:映射,将元素转换成其他形式或提取信息
-
flatMap:扁平化流映射
-
limit:截断流,使其元素不超过给定数量
-
skip:跳过指定数量的元素
-
sorted:排序
-
distinct:去重 终端操作:
-
anyMatch:检查流中是否有一个元素能匹配给定的谓词
-
allMatch:检查谓词是否匹配所有元素
-
noneMatch:检查是否没有任何元素与给定的谓词匹配
-
findAny:返回当前流中的任意元素(用于并行的场景)
-
findFirst:查找第一个元素
-
collect:把流转换成其他形式,如集合 List、Map、Integer
-
forEach:消费流中的每个元素并对其应用 Lambda,返回 void
-
reduce:归约,如:求和、最大值、最小值
-
count:返回流中元素的个数