文章目录
深入理解OOP思想
面向对象的三大特征是封装、继承、多态。
封装是指一个类可以有一些私有的属性和方法,可以把功能封装起来,对外只提供一部分接口。
继承是指:一个类可以继承另一个类的非私有属性和方法,这样的话,被继承的类的属性和方法就可以被复用。
多态是指:同一个类实例化出来的子对象,通过调用同一个方法,可以得到不同的结果,这就是多态。
重载和重写的区别
重载:发生在同一个类中,方法名必须相同,参数类型、个数、顺序可以不同,方法返回值和访问修饰符可以不同
// 重载,方法名必须相同,参数列表,顺序不同,方法返回值和访问修饰符可以不同
public void a(){
}
private int a(int a){
return 1;
}
重写:发生在父类和子类中,方法名、参数列表,返回值类型必须相同,抛出的异常范围小于等于父类,访问权限不能比父类中被重写的方法的访问权限更低,父类中方法的访问修饰符为private,则子类就不能重写该方法
public String a (){
return null;
}
// 重写,方法名,参数列表,顺序,返回值类型必须相同。子访问修饰符必须大于等于父类,抛出的异常范围小于等于父类
@Override
public String a(){
return null;
}
Java接口和抽象类有什么区别?
-
首先,接口中的所有方法默认都是抽象的,而抽象类中可以存在普通的成员函数
-
接口中声明的变量默认是public static final修饰的,方法的访问修饰符默认是public。而抽象类的成员变量可以是各种类型的。
-
一个类可以实现多个接口,但只能继承一个抽象类。接口和抽象类都不能实例化。
接口的设计目的是对类进行约束,而抽象类的设计目的是代码复用。当你关注一个事物的本质的时候,用抽象类;当关注一个操作的时候用接口。
什么是单例模式?有几种?
单例模式是:某个类的实例在多线程环境下只会被创建一次出来
- 饿汉式单例模式:线程安全,比较常用,但容易产生垃圾,因为一开始就初始化
class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
- 懒汉式单例模式:非线程安全,延迟初始化,严格意义上不是单例模式
class Singleton{
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
- 双锁机制的懒汉式单例模式:线程安全,延迟初始化。这种方式采用双锁机制,安全且在多线程的情况下还能保证高性能
- 进行了两次判断,第一次是为了避免不必要的实例
- 第二次是为了进行同步,避免多线程问题。使用volatile修饰signleton实例变量有效,解决该问题
class Singleton{
private static volatile Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if(instance==null){
synchroniced(Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
}
String,StringBuilder和StringBuffer的区别?
提示:区别的问题?相同点 不同点 为什么不同
String,String Builder和StringBuffer三者都可以用来操作字符串,但是在效率上区别比较大。String因为底层是由final修饰的char数组,导致内容不可变,因此在字符串拼接的时候,会创建多个对象,并且数组长度确定后不可以更改,涉及到内容的赋值,因此带来大量的性能和内存开销,效率太低。
而StringBuilder与StringBuffer在拼接字符串,返回值是当前操作对象,不会创建多个对象,因此效率相对较高。但是StringBuffer由于底层使用synchornized同步锁,保证了线程安全,因此效率相对StringBuilder较低一些。因此在平常的工作中如果没有涉及到线程安全我们都是使用的String Builder。
==和equals的区别
双等号和equals都可以比较对象是否相等。
但是双等号在判断基本数据类型
的时候比较的是值,判断引用数据类型
的时候比较的是内存地址。
equals的话,它在类中没有被重写的话,其作用和双等号一样;如果在类中重写了equals()方法的话,则只比较两个对象的内容是否相等。
hashCode和equals
hashCode的作用是获取哈希值,能够根据键快速的检索出对应的值
为什么要有hashCode,单独的equals不行吗?
- 当对象加入的时候,hashCode值会先来判断对象加入的位置
- 如果该位置没有值,hashSet会假设该对象没有出现过。
- 如果有值,这时候会调用equals()方法来检查两个对象是否真的相同
- 如果相同则加入失败,
- 不同的话就会重新散列到其他位置进行比较。
- 可以大大减少equals()的次数,相应的就大大提高了执行速度。
-
如果两个对象相等,则hashCode也一定相同的,对象分别调用equals方法都返回true
-
如果两个对象有相同的hashCode值,他们不一样相同。
-
所以,equals被重写过,则hashcode方法也要重写
-
hashCode() 的默认行为是对堆上的对象产生独特值,如果没有重写则改class的2个对象无论如果都不会相等。
Java的异常体系?受检查和非受检查异常区别?
首先Java中的所有异常都来自顶级父类Throwable,有2个子类Error和Exception,其中error表示JVM无法处理的错误,如栈溢出,内存溢出;Exception又分为受检异常和非受检异常,其中受检异常指的是在编写代码的时候必须处理的异常,需要用try…catch语句捕获并进行处理。非受检异常指的是程序运行时的错误,例如下标越界异常,空指针异常。
final关键字
首先final关键字它可以修饰类,方法和变量。当修饰类的时候,说明这个类不能被继承。当修饰方法的时候,说明这个方法不能被重写。当修饰变量的时候,说明这个变量只能赋值一次,不能再次被更改。
final、finally、finalize三个关键字的区别?
final关键字
一个基本数据类型声明为final,就只能进行一次赋值(初始化)
,编译器会自动检查代码,如果需要修改final的初始化,就会编译报错。final声明的引用数据类型,当前引用是不能改变的,但是可以改变引用指向的内存空间的值
。final一般和static搭配使用
作为常量。
final关键字的三种用法:
- 1)修饰类:表示该类不能被继承(extends);
- 2)修饰方法:表示方法不能被重写(override);
- 3)修饰变量: 表示变量只能一次赋值以后值不能被修改(常量)(final修饰成员变量必须在声明时初始化或者再构造器中初始化,否则报编译错误,而且final修饰的变量通常都是常量,常量名全部大写)
如果一个类被声明为final,意味着它不能再派生出新的子类,即
不能被继承
,因此它和abstract是反义词。
将变量声明为final,可以保证它们在使用中不被改变,被声明为final 的变量必须在声明时给定初值
,而在以后的引用中只能读取不可修改。
被声明为final 的方法也同样只能使用,不能在子类中被重写
。
final优势:
- 1)final关键字可以
提高性能
,JVM和Java应用都会缓存final变量。 - 2)final变量
可以在安全的多线程环境下进行资源共享
,而不需要额外的同步开销。
finally
通常放在try…catch…的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM 不关闭都能执行,可以将释放.
try { }
catch(Excetption e){ }
finally{ }
finalize
Object 类中定义的方法,Java 中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
这个方法是由垃圾收集器在销毁对象时调用的
,通过重写finalize()方法可以整理系统资源或者执行其他清理工作
。
Java中的泛型是什么 ? 使用泛型的好处是什么?(重点)
我所理解的泛型就是编写的代码可以被不同类型的对象重复利用。
泛型的运行机制类型擦除。在生成的Java字节码中是不包含泛型中的类型信息的,虽然在使用泛型的时候加上了类型参数,但是在编译阶段会去掉,这就叫类型擦除。
冒泡排序
核心思想就是循环遍历,比较相邻的数,当前面的数大于后面的数的时候,将前面的数先存到临时变量里面,然后将后面的数赋值到到前一位的数字上,再将临时值赋值到后面的数的位置上。
int[] arr = {1,33,2,333,44,0};
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
BIO、NIO、AIO有什么区别?了解
BIO(Blocking I/O):是同步阻塞IO,数据的读取和写入必须阻塞在一个线程内等待其完成。
NIO(Non-blocking io,也叫New io),是一种同步非阻塞IO模型。它支持面向缓冲机制。
AIO(Asynchronous IO): 也就是NIO2,是异步非阻塞的IO模型。
Java反射机制及使用场景
Java反射的话可以动态的获取类的所有信息就叫做Java的反射机制。
使用场景:
- JDBC中,利用反射动态加载了数据库驱动程序
- spring框架通过反射来创建对象