面向对象三大特征:
封装:把对象的属性和行为(方法)封装为一个整体。
继承:子类继承父类的数据属性和行为,并且还可以拥有自己的独有的行为,提高了代码的复用性。
多态:父类引用指向子类对象,子类拥有父类所有的方法,封装和继承几乎都是为了多态准备的。
JDK,JRE,JVM的区别:
JDK:是整个Java的核心,里面包含了JRE,和Java开发工具包(java工具和Java基础类库)。
JRE:是Java的运行环境,包含了Java虚拟机和核心类库。
JVM:是Java虚拟机,因为jvm所以才实现了java的跨平台性。
方法重载和方法重写的区别(重要):
重载:指在同一个类中,方法名相同,参数列表不同 个数不同,顺序不同。
重写:指发生在子父类里,方法名,参数列表必须相同,返回值和抛出的异常要小于等于父类,访问修饰符要大于等于父类,如果父类方法是private修饰则子类不能重写该方法。
Java 中==和 equals 的区别:
==的作用:
基本数据类型:比较的是它们的内容。
引用数据类型:比较的是它们的地址值。
equals的作用:
引用数据类型:默认情况比较的是地址值,
特殊情况: String,Integer,Date这些类库中重写了equals方法 它们对比的时候是直接比较的内容而不是地址值。
String,StringBuffer,StringBuilder 三者之间的区别:
String:字符串常量
StringBuffer:字符串变量(线程安全):对方法加了同步锁或者对调用的方法加了同步锁,所以线程是安全的。
StringBuilder:字符串变量(非线程安全):并没用对方法加同步锁,所以是非线程安全的。
接口和抽象类的区别:
实现:抽象类的子类使用extends来继承,接口必须用implements来实现接口
构造函数:抽象类可以有构造函数,接口不能有构造函数。
main方法:抽象类可以有main方法并且可以运行,接口不能有main方法。
实现类数量:接口可以有多个接口实现,抽象类只能继承一个。
访问修饰符:接口默认使用public修饰,抽象类中的方法可以使用任意修饰符。
String的常用方法:
indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。
什么是单例模式:
单列模式:某个类的实例在多线程环境下只会被创建一次出来
单例模式有 饿汉式,懒汉式,双检索三种模式
饿汉式:线程安全,一开始就会被初始化。
懒汉式:非线程安全,延迟初始化。
双检索:线程安全,延迟初始化。
反射:在 Java 中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的
属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动
态调用对象方法的功能成为 Java 语言的反射机制。
获取 Class 对象的 3 种方法:
1.调用某个对象的 getClass()方法
Personp=newPerson();
Classclazz=p.getClass();
2.调用某个类的 class 属性来获取该类对应的 Class 对象
Classclazz=Person.class;
3.使用 Class 类中的 forName()静态方法(最安全/性能最好)
Classclazz=Class.forName("类的全路径");(最常用)
jdk1.8的新特性:
1.lambda表达式:lambda允许把函数作为一个方法的参数
2.方法引用:发法引用允许直接引用已有Java类或对象或构造方法。
3.函数式接口:有且仅有一个抽象方法的接口叫函数式接口,函数式接口可以被隐式转换为Lambda表达式 。通常函数式接口上会添加@FunctionalInterface注解。
4.接口允许定义默认方法和静态方法
5.StreamAPI:新添加的 StreamAPI(java.util.stream)把真正的函数式编程风格引入到 Java 中。这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选,排序,聚合等。
6.日期时间类:java.time 包下,方法:LocalDate/LocalTime/LocalDateTime。
7.Optional类:Optional 类是一个可以为 null 的容器对象。如果值存在则 isPresent()方 法会返回 true,调用get()方法会返回该对象。
8.Java8Base64 实现
Java8 内置了 Base64 编码的编码器和解码器。
Java的异常:
Throwable是Java程序中错误处理的父类,有两种子类,Error和Exception。
Error:表示JVM所检测到的无法预期的错误 是由JVM层次的严重错误,导致无法继续执行,不可捕获的错误。
Exception:表示可以恢复,捕捉的错误 有两种情况
1.运行期的异常:都是RuntimeException类及其子类异常,常见的有ullPointerException(空指针异常),IndexOutBoundsException(下标索引越界异常),这些异常是不检查异常 ,可以选择捕获也可以不处理,是由程序逻辑错误引起的。
2.非运行期异常(编译时异常):是 RuntimeException 以外的异常,类型都是Exception类及其子类。从程序语法来讲是必须处理的异常 否则编译不会通过。如IOException,SQLException等以及用户自定义的Exception异常。
常见的异常:
BIO,NIO,AIO的区别:
BIO:BlockIO同步阻塞式IO,传统IO,特点是简单使用方便,并发处理能力低
NIO:NewIO 同步非阻塞式IO 是传统IO的升级,客户端和服务端通过Channel(通道)通讯,实现了多路复用。
AIO:AsynchronousIO是NIO的升级,也叫NIO2,实现了异步非阻塞IO,异步IO的操作基于事件和回调机制。
ThreadLocal的原理:
ThreadLocal为共享变量在每个线程中创建了一个副本,每个线程都可以访问自己的副本变量,保证了线程安全性。
在ThreadLocal类中有一个静态内部类ThreadlocalMap(类似于Map集合),用健值对的形式储存每个副本变量,ThreadLocalMap中元素的key为当前ThreadLocal对象,而Value对应线程的变量副本。
Threadlocal本身并不储存值,只是作为key保存到ThreadLocalMap中 ,要注意的是它作为key用的是弱引用,因为没有强引用链,所以在GC的时候可能会被回收这样就导致ThreadLocalMap中存在一些key为null的键值对(Entry)。因为key变成null了,所以无法访问这些Entry。但是这些Entry本身不会被清除。如果不手动删除这些对应key则会导致这块内存既不会回收也无法访问,也就是内存泄露。
解决方法:使用完ThreadLocal之后,记得调用remove方法,在不使用线程池的前提下,即使不调用remove方法,线程的“变量副本”也会被gc回收,就不会造成内存泄露的问题了。