简介
本文主要为复习Java基础面试题的记录博客,会持续更新
面试题
JDK和JRE的区别
JDK 是功能齐全的 Java SDK ,它拥有 JRE的一切,还有编译器和工具。它能够创建和编译程序。
JRE 是 Java 运行时环境,包括 JRE和java常用的类库,是Java运行时环境。
重载和重写的区别
区别
重载
重写
发生范围
同一个类
父子类
参数列表
必须修改
不能改
返回类型
可以修改
子类方法返回值类型应比父类方法返回值类型更小或相等
异常
可以修改
可以抛出相同的或者更小的异常
访问修饰符
可以修改
降低限制
发生时期
编译时期
运行时期
String,StringBuffer和StringBuilder的区别
String 是用 final修饰的char数组,所以String是不可变的。
StringBuffer和StringBuilder 都继承了 AbstractStringBuilder ,而AbstractStringBuilder中的char数组没有被被final修饰,所以是可以改变的,
而StringBuffer和StringBuilder 的区别在于是否线程安全,StringBuffer是线程安全的,因为其所有的方法都用synchronized修饰。
总结:
对于单线程下少量的数据可以使用String。
对于单线程下大量数据使用StringBuilder。
对于多线程下大量数据使用StringBuffer。
下面是对应的源码图:
String源码:
AbstractStringBuilder源码:
StringBuffer 源码的方法添加sychronized
接口和抽象类的区别
相同点:
都不能被实例化;
只有在接口被实现了,或者抽象类被继承了才可以实例化。
不同点:
接口只能定义方法,不能实现方法(Java8中可以有default方法可以被实现),抽象类可以有普通的方法实现)
一个类可以实现的多个接口但只能继承一个抽象类
接口更像一种行为设计,而抽象类则是一种模板的设计。
接口的成员变量默认是 static final的 并且必须赋值,不能修改,方法都是被public或abstract修饰的。
抽象类中变量默认是default的,在子类中可以被重新定义或者赋值,抽象方法被abstract 修饰,不可被private,default、static、native和synchronized修饰。
静态方法和实例方法有何不同
静态方法属于类,可以使用 类名.方法名 来实现调用,可以使用 对象名.方法名 来实现调用。
静态方法只能调用本类的静态成员(静态变量和静态方法),实例方法没有限制。
==和equals的区别
==:基本类型比较数值,引用类型比较地址
equals:没有重写,比较的是地址
重写了以后比较的是,重写的规则(一般是内容,比如String)
Object的equals方法:
String重写后的equals方法:
hashCode和equals
hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
线程,程序,进程的区别
线程是执行任务的最小单位,一个进程至少包含一个线程
线程是由CPU调度的,占用进程资源
进程是由操作系统进行资源分配的,程序执行的最小单位
一个进程可以创建多个线程,多个线程共享一块内存空间和一组系统资源
线程和进程资源如图:
线程的基本状态
初始,运行,阻塞,超时等待,等待,终止
如图:
运行时常量池和堆
关于一个对象是在堆中创建还是说在运行时常量池中创建,
String a = new String("123");
String b = "123";
对于a,JVM会直接在堆中创建一个对象
而对于b ,JVM首先会在字符串常量池中查找是否有相同的,如果有,则直接引用字符串常量池中的引用,如果没有则会则会在堆中创建一个对象,并且在字符串常量池中注册一个。
Object常用方法
clone():
返回当前对象的一个拷贝
getClass():
返回当前对象的Class对象
hashCode():
返回本对象的哈希码,主要用在哈希表中,如HashMap
toString():
返回实例名称@哈希码
notify():
随机唤醒一个正在等待的线程
notifyAll():
唤醒所有等待的线程
wait():重载无参,一个参数,两个参数
暂停线程的运行,会释放锁,但是sleep()方法不会释放锁
finalize():
实例被垃圾回收时执行的方法。
如图所示:
Class类常用的方法
forName(String name):
返回指定name的Class对象
newInstance():
返回对象的一个实例
getName():
返回此Class对象的名称
getSuperClass():
返回当前对象的父类的Class对象
getInterfaces():
返回当前Class对象的接口
getClassLoader():
返回该类的类加载器
getSuperclass:
返回该类对应的超类
反射机制
在程序运行时期,我们可以知道这个类中所有的方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为 java 语言的反射机制。
静态编译: 在编译时确定类型,绑定对象
动态编译:运行时确定类型,绑定对象
优缺点:
优点:运行期类型的判断,动态加载类,提高代码灵活度。
缺点: 1,性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的 java 代码要慢很多。2,安全问题,让我们可以动态操作改变类的属性同时也增加了类的安全隐患。
类加载器
类加载器就是把类的信息装载到JVM中去,类加载器包括用户自定义加载器和启动类加载器
异常
异常和错误的父类是Throwable,
分为 Error和 Exception
Errors:
栈溢出
堆溢出
虚拟机错误
Exception:
检查异常:
IO异常
SQL异常
文件未找到异常
非检查异常:
数组下界超出异常
空指针异常
除零异常
异常结构图:
IO
按流向分为输入流和输出流
按操作单元分为子接口和字符流
按照流的角色分为节点流和处理流
如图所示:
常见关键字
final关键字
修饰类:不能被继承
修饰方法:不能被重写
修饰变量:只能被赋值一次,不能修改
transient 关键字
当一个类中的某个属性不想被序列化时可以使用 transient关键字,transient 只能修饰变量
instanceof 关键字
判断一个对象是否为一个类(接口,父类)的实例
自动装箱和拆箱
装箱:将普通类型用他们的包装类包装起来
拆箱:将包装类型转化为普通类型
Integer i = 10; //装箱
int n = i; //拆箱
包装类的大部分都使用了常量池技术:
Byte,Short,Integer,Long:包装类默认创建了数值[-128,127] 的相应类型的缓存数据
Character 创建了数值在[0,127]范围的缓存数据
Boolean 直接返回 True Or False
浮点类型没有使用缓存技术