1.面向对象的特点
封装,继承,多态,抽象。
2.Java的基本数据类型
数据类型 | 字节数 | 位数 |
---|---|---|
byte | 1字节 | 8位 |
short | 2字节 | 16位 |
int | 4字节 | 32位 |
long | 8字节 | 64位 |
float | 4字节 | 32位 |
double | 8字节 | 64位 |
boolean | 1字节 | 8位 |
char | 2字节 | 16位 |
3.JVM,JRE,JDK的区别
JVM:Java虚拟机,是Java实现跨平台的核心部分。
JRE:Java运行时环境,包含Java程序运行必须的环境集合。
JDK:Java开发工具包,包含JRE,Java工具包和Java基础类库。
4.重载和重写的区别
重载:一般发生在同一个类中,方法名必须相同,参数列表不同,返回值类型和访问修饰符可以不同,一般发生在编译的时候。
重写:一般发生在父类和子类中,方法名和参数列表必须相同,返回值类型范围子类小于父类,抛出异常范围子类小于等于父类,访问而修饰符范围子类大于等于父类,如果父类方法的访问修饰符是private,子类不能重写该方法。
5.= =和equals的区别
= =的作用:比较基本数据类型时:= =比较的是两边的值;比较引用数据类型时,= =比较的两边的内存地址。
equals的作用:比较基本数据类型时:作用等同于= =,是比较两边的值;比较引用数据类型时分两种情况,如果方法没有重写equals方法,比较的是两边的内存地址,如果方法重写equals方法,比较的就是两边的值。
附:请解释String的比较中= =和equals的区别:= =比较的两边字符串的内存地址是否一致;equals比较的是两边字符串的值是否一致,因为String中重写了equals方法。
6.String,StringBuffer和StringBuilder三者的区别
String:String被final关键字修饰,所以String对象是不可变的,可以理解为是字符串常量,线程也是安全的。
StringBuffer:字符串变量,StringBuffer的方法中加入了同步锁,所以线程是安全的。
StringBuilder:字符串变量,没有同步锁机制,线程不安全。
一般情况下,数据量较小的时候推荐使用String;多线程中数据量较大的时候推荐使用StringBuffer;单线程中数据量较大的时候推荐使用StringBuilder。
7.接口和抽象类的区别
抽象类的子类只能通过extends来继承,接口只能通过implements来实现;抽象类中可以有构造函数和main方法,接口中没有;一个类只能继承一个抽象类,一个类可以实现多个接口;抽象类的访问修饰符可以任意,接口的访问修饰符一般是public。
8.String中常用的方法
equals():比较字符串的值。
subString():截取字符串。
length():获取字符串的长度。
split():分割字符串,返回字符串数组。
replace():字符串替换。
9.什么是单例模式
单例模式:一个类在多线程环境中只会被创建一次。单例模式有饿汉式,懒汉式,双检索模式。
饿汉式:一开始就初始化,线程安全。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
}
懒汉式:延迟初始化,线程非安全。
public class Singleton {
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
双检索模式:延迟初始化,线程安全。
public class Singleton {
private volatile static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
10.什么是反射
Java中的反射就是指在运行过程中,对于任意一个类都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用这个对象的任意一个方法,这种动态获取信息以及动态调用对象方法的功能就是Java中的反射。
附:获取class对象的三种方法:
// 1.实例化对象,调用对象的getClass()方法
User user = new User();
Class userAClass = user.getClass();
// 2.直接使用类的class属性
Class userBClass = User.class;
// 3.使用Class类中的forName()方法,参数为类的全路径名。
Class userCClass = Class.forName("com.hospital.warehouse.entity.User");
11.Java中的异常
Throwable是Java中所有错误处理的父类,有两个子类,分别是Error和Exception。
Error是有JVM侦测到的无法预期的错误,一旦发生就会导致JVM无法继续运行,所以,Error无法捕捉,无法采取任何恢复操作,只能显示错误信息。
Exception是可以恢复的异常,可以捕捉。Exception可以分为运行时异常和非运行时异常。运行时异常包含RuntimeException及其子类,运行时异常是不检查异常,一般是由于程序逻辑错误引起的,运行时异常的特点就是编译器不会检查它。非运行时异常就是除了RuntimeException及其子类之外的异常,非运行时异常的特点就是从程序语法角度必须处理的异常,例如IOException,SQLException。
常见的运行时异常:
异常名称 | 异常含义 |
---|---|
NullPointerException | 空指针异常 |
ClassCastException | 类型强制转换异常 |
IndexOutOfBoundsException | 下标越界异常 |
NumberFormatException | 数字格式异常 |
SecurityException | 安全异常 |
12.BIO,NIO和AIO三者有什么区别
BIO:同步阻塞式IO,就是传统IO,它的特点就是模式简单,使用方便,但是并发处理能力较低。
NIO:同步非阻塞式IO,是BIO的升级版,它的特点就是客户端和服务器通过channel通讯,实现了多路复用。
AIO:异步非阻塞式IO,NIO的升级版,它的特点就是实现了异步IO,异步IO的操作时基于事件和回调机制。
13.同步锁,死锁,乐观锁和悲观锁
同步锁:当多个线程同时访问同一个数据时,很容易出现问题,为了避免这种情况出现,我们需要保证线程同步互斥,就是指并发执行多个线程时,同一时间内只允许一个线程访问共享数据,Java中使用synchronized关键字实现同步锁。
死锁:死锁就是多个线程同时被阻塞,它们中的一个或者全部都在等待某一资源的释放。
乐观锁:总是假设最好的情况,每次去拿数据的时候都会认为别人不会修改,所以不会上锁,但是更新的时候会判断别人在此期间有没有更新这个数据,是通过版本号机制和CAS算法实现的。乐观锁适用于多读的应用类型,这样可以提高吞吐量。数据库提供的WRITE_CONDITION机制就是基于乐观锁,Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁,是基于CAS算法实现的。
悲观锁:总是假设最坏的情况,每次去拿数据时都认为别人会修改,所以每次拿数据的时候都会上锁,这样别人想拿这个数据时就会被阻塞,直到他拿到锁。传统的关系型数据库中就有很多利用了悲观锁,比如行锁,表锁,读锁,写锁等,都是在操作之前先上锁,Java中的synchronized和reentrantLock[ˌriˈɛntrənt]等独占锁就是利用悲观锁的思想实现的。
14.synchronized底层实现原理
synchronized关键字可以保证同步方法或者同步代码块在运行时,同一时间内只有一个方法可以进入临界区,同时它还可以保证共享变量的内存可见性。Java中的每一个对象都可以作为锁,这就是synchronized实现同步的基础,普通同步方法,锁就是当前实例对象;静态同步方法,锁就是当前class对象,同步代码块,锁就是括号里面的对象。