SE基础
JDK、JRE、JVM之间的区别
JDK(Java SE Development Kit), Java标准开发包,它提供了编译、运行Java程序所需的各种工具和资源。
包括Java编译器、Java运行时环境,以及常用的Java类库等
JRE(Java Runtime Environment) ,Java运行环境,用于运行Java的字节码文件。JRE中包括了JVM以及JVM工作所需要的类库。
普通用户而只需要安装JRE来运行Java程序,而程序开发者必须安装JDK来编译、调试程序。
JVM(Java Virtual Mechinal),Java虚拟机,是JRE的一部分,它是整个Java实现跨平台的最核心的部分,负责运行字书码文件(*.class)。
JVM在执行Java字节码时,把字节码解释为机器指令,而不同操作系统的机器指令有可能不一样,所以不同操作系统上的JVM是不一样的,在安装JDK时需要选择操作系统。
写java代码,可以用txt写,但是需要先编译成字节码才能运行。
JDK中的编译器javac可以把文本编译成字节码,JVM是专门用来执行Java字节码的程序。
重载和重写的区别
重载:发生在同一个类中,方法名必须相同,参数类型、个数、顺序至少一个不同。方法返回值和访问修饰符没有关系。
重写:发生在父子类中,方法名、参数列表必须相同,返回值范围、抛出的异常范围<=父类,访问修饰符范围>=父类;如果父类方法访问修饰符为private则子类就不能重写该方法。
1)public :公共权限,可以被任意类访问,不同包不同类依然可以访问
可修饰:类、成员变量、方法,内部类
2)protected:受保护的权限,可以被同包类访问,如果不是同包类,必须是该类的子类才可以访问
可修饰:成员变量、方法、内部类
3)default:默认的(无),同包权限,只能被同包的类访问
可修饰:类、成员变量、方法,内部类
4)private:私有权限,只能在本类中访问,同包其他类也不能访问
可修饰:成员变量、方法、内部类
List和Set的区别
List:有序可重复,保持了每个元素的插入顺序,允许多个null元素对象,可以使用Iterator取出所有元素,在逐—遍历,还可以使用get(int index)获取指定下标的元素
Set:无序不可重复,最多允许有一个Null元素对象,只能用lterator接口(迭代器)取得所有元素,在逐一遍历各个元素
Java基础篇:Iterator迭代器_迭代器 iterator 是什么?_张维鹏的博客-CSDN博客
什么是字节码?采用字节码的好处是什么?
编译器(javac)将Java源文件(*.java)文件编译成为字节码文件(*.class),可以做到一次编泽到处运行。windows上编译好的class文件,可以直接在linux上运行,通过这种方式做到跨平台。
前提条件:虽然字节码是通用的,但是需要把字节码解释成各个操作系统的机器码是需要不同的解释器的,所以针对各个操作系统需要有各自的JDK或JRE。
采用字节码的好处,1实现了跨平台,2也提高了代码执行的性能。编泽器在编译源代码时可以做一些编译期的优化,比如锁消除、标量替换、方法内联等。
Jdk1.7到Jdk1.8 HashMap发生了什么变化(底层)?
1.7中底层是数组+链表,1.8中底层是数组+链表+红黑树,加红黑树的目的是提高HashMap插入和查询整体效率
1.7中链表插入使用的是头插法,1.8中链表插入使用的是尾插法。因为1.8中插入key和value时需要判断链表元素个数,需要遍历链表统计
1.7中哈希算法比较复杂,存在各种右移与异或运算,1.8中进行了简化,因为复杂的哈希算法的目的就是提高散列性(HashMap的整体效率),而1.8中新增了红黑树,所以可以适当的简化哈希算法,节省CPU资源
【数据结构】史上最好理解的红黑树讲解,让你彻底搞懂红黑树_小七mod的博客-CSDN博客
Java单链表头插法和尾插法以及增删改查方法_java 链表头插法_这个名字先用着的博客-CSDN博客
多线程
线程池中提交一个任务的流程是怎么样的?
线程池由几种状态?分别是如何变化的?
线程池有五种状态,分别为:
RUNNING | 会接收新任务,会处理队列中的任务 |
SHUTDOWN | 不会接收新任务,会处理队列中的任务,任务处理完后会中断所有线程 |
STOP | 不会接收新任务,且不会处理队列中的任务,会直接中断所有线程 |
TIDYING | 所有线程都停止了之后,线程池的状态就会转为TIDYING,一旦达到此状态,就会调用线程池的terminated() |
TERMINATED | terminated()执行完之后就会转变为TERMINATED |
这五种状态并不能任意转换,只会有以下几种转换情况:
转变前 | 转变后 | 转变条件 |
RUNNING | SHUTDOWN | 手动调用shutdown()触发,或者线程池对象GC时会调用finalize()从而调用shutdown() |
RUNNING | STOP | 手动调用shutdownNow()触发 |
SHUTDOWN | STOP | 手动先调用shutdown()紧着调用shutdownNow()触发 |
SHUTDOWN | TIDYING | 线程池所有线程都停止后自动触发 |
STOP | TIDYING | 线程池所有线程都停止后自动触发 |
TIDYING | TERMINATED | 线程池自动调用terminated()后触发 |
Java中有哪几种方式来创建线程,执行任务?
继承Thread类
新建一个类,来继承Thread【丝瑞乐】,然后new出thread对象,去调用start()【丝哒】方法。这个时候会启用线程来执行run方法中间的任务
总结:重写的是run方法,而不是start方法,缺点是占用了继承的名额
public class ZhouyuThread extends Thread{
public static void main(String[] args) {
ZhouyuThread thread = new ZhouyuThread(
thread. start();
}
@Override
public void run() {
System.out.println("hello zhouyu");
}
}
实现Runnable接口
写一个类实现Runnable【run内波】接口,new一个thread对象,实现它的run方法。这个可以把runnable实现类的对象传进去,再调用thread的start方法开启一个线程。
第一种方式本质上也是实现runnable接口
java是单继承说的是类和类之间是单继承,接口和接口之家可以多继承。
一个接口只有一个方法,那么runnable是一个函数式接口。
使用依然要用到Thread,这种方式更常用
总结:new一个thread对象,把runnable实现类的对象传进去,再调用thread的start方法开启一个线程,实现它的run方法。
public class ZhouyuThread implements Runnable{
public static void main(String[] args) {
Thread thread = new Thread(new ZhouyuThread());
thread.start();
}
public void run() {
System.out.print1n("hello zhouyu");
}
}
也可以直接使用匿名内部或者lambda【朗姆哒】表达式的方式来实现runnable接口
public class ZhouyuThread {
public static void main(String[] args) {
Thread thread = new Thread( new Runnable() {
public void run() {
System.out.println("hello zhouyu");
}
});
thread.start();
}
}
public class ZhouyuThread {
public static void main(String[] args) {
Thread thread = new Thread( () -> System.out.println( "hello zhouyu") );
thread.start();
}
}
实现Callable
【kou欸波】
这个和runnable很像,也是实现一个接口。
但是实现的是callable,可以开启一个线程,去实行任务并且可以拿到那个任务的结果。
如果用callable,要接合futuretask【 塌丝特】
实现一个callable的类,生成他的一个对象,传给futuretask,再把futuretask传给我们thread,启动线程(其实就是实现callable跨方法实现call()的任务) ,用调用get方法可以阻塞式可以拿到结果。
总结:实现callable接口,实现call方法,需要使用thread+futuretask配合,这种方式支持拿到异步执行任务的结果。
实际上也是runnable的实现方式
public class ZhouyuThread implements callable<String> {
public static void main(String[ ] args) throws ExecutionException,Interr
FutureTask<String> futureTask = new FutureTask<> (new ZhouyuThread())
Thread thread = new Thread( futureTask);
thread.start();
String result = futureTask.get();
System.out.print1n(result);
}
public String call() {
return "hello zhouyu";
}
}
利用线程池来创建线程
Executors【衣颗丝Q特丝】
总结:实现callable接口或者runnable接口都可以,由executorservice来创建线程
public class ZhouyuThread implements Runnable {
public static void main(String[ ] args) throws ExecutionException,Interr{
ExecutorService executorService = Executors-newF ixedThreadPool(10);
executorService.execute(new ZhouyuThread());
}
public void run() {
System.out.println( "he1lo zhouyu");
}
}