java基础,集合,多线程,JVM四部分
- 一、JAVA:
- (一)三大特征以及理解:
- (二)JDK/JRE/JVM三者的关系:
- (三)成员变量和局部变量的区别:
- (四)基本数据类型及其默认值:
- (五) 重写与重载的区别:
- (六)object类中的方法:
- (七) 重写与重载的区别:
- (八)hashCode()和equals()的关系:
- (九)为什么要重写hashCode()和equals():
- (十)==和equals方法的区别:
- (十一)Java创建对象有以下几种方式:
- (十二)final关键字的作用:
- (十三)String类有哪些方法:
- (十四)接口和抽象类的区别:
- (十五)String、StringBuffer、StringBuilder区别:
- (十六)执行顺序问题:
- (十七)static关键字:
- (十八)说说你对Java反射机制的理解:
- 二、集合:
- 三、多线程:
- 四、JVM:
- 五、接下来的问题:
一、JAVA:
(一)三大特征以及理解:
封装:隐藏实现细节。
继承:对象可以有子对象,子对象有自己的独特特征。
多态:是指不同对象在执行同一方法,表现出不同特征。
(二)JDK/JRE/JVM三者的关系:
JDK:JAVA开发工具包。JRE:JAVA运行时环境。JVM:JAVA虚拟机。
JRE = JVM + Java 核心类库
JDK = JRE + Java工具 + 编译器 + 调试器
(三)成员变量和局部变量的区别:
成员变量:
(1)定义再类中
(2)有默认初始值
(3)未被static修饰,是实例变量,放在对象的堆内存中,随对象一起销毁。
(4)被static修饰,是类变量,放在方法区中,生命周期和当前对象相同。
局部变量:
(1)定义在方法中
(2)没有默认初始值
(3)放在栈内存中,作用域结束后,被销毁。
(四)基本数据类型及其默认值:
基本数据类型:
- byte:0; short:0; int: 0; long:0L; float:0.0F; double:0.0;
char:‘\u0000’; boolean: false;
(五) 重写与重载的区别:
重载: 发生在同一个类中,两个方法参数不同但方法名相同就叫重载,
重写: 发生在父子类关系中,两个参数方法体相同,子类的修饰符作用域大于父类,子类的抛出异常和返回值要小于父类。
(六)object类中的方法:
常用的: toString()、equals()、hashCode()、clone();
ToString: 默认输出对象地址,可以重写,输出对象值。
Equals: 默认比较两个引用变量是否指向同一个对象(内存地址)。String: 类重写了这个方法使用值来比较是否相等。
hashCode: 返回对象的 hash 码。
Clone: 拷贝当前对象, 必须实现 Cloneable 接口。浅拷贝对基本类型进行值拷贝,对引用类型拷贝引用;深拷贝对基本类型进行值拷贝,对引用类型对象不但拷贝对象的引用还拷贝对象的相关属性和方法。两者不同在于深拷贝创建了一个新的对象。
getClass: 获取当前运行时对象的 Class 对象。
Notify: 唤醒一个线程。
NotifyAll: 唤醒所有线程。
Wait: 暂停线程的执行;
Finalize: 对象被垃圾回收器回收时执行的方法。
(七) 重写与重载的区别:
重载: 发生在同一个类中,两个方法参数不同但方法名相同就叫重载,
重写: 发生在父子类关系中,两个参数方法体相同,子类的修饰符作用域大于父类,子类的抛出异常和返回值要小于父类。
(八)hashCode()和equals()的关系:
如果两个对象相等,那么它们的哈希值一定相同。如果两个对象的哈希值相同,这个两个对象不一定相等。
(九)为什么要重写hashCode()和equals():
再objec对象中,默认的equals方法指的是,只有当两个对象是指向的同一个对象时,才返回相同的结果。在实际开发中我们需要的只是值相同就返回相同,所以我们并不需要默认的euqals方法,需要重写。而hascode和equals方法是配套的,所以hascode也需要重写。
(十)==和equals方法的区别:
== 方法:
作用于基本数据类型:比较的是值是否相同。
作用于引用类型时:比较的是对象的内存地址是否相同。
equals方法:
没有重写时,按照==号比较,
重写后,比较的是对象的内容。
(十一)Java创建对象有以下几种方式:
- 用new语句创建对象。
- 反射,使用Class.newInstance()创建对象。
- 调用对象的clone()方法。
- 反序列化。
(十二)final关键字的作用:
类不能被继承,方法不能重写,变量不可改值。
(十三)String类有哪些方法:
Char charAt(int index)返回指定索引处的字符串
String subString(int firstindex,int endindex):从此字符串中截取一部分字符串
String[]split(String regex)按照指定类型切割成相应的字符串
String trim()去掉字符串首尾的空格
Boolean startSwith(String prefix)看看是否以指定的字符串开头
Boolean endSwith(String suffix)看看是否以指定的字符串结尾
(十四)接口和抽象类的区别:
设计目的上:
- 接口体现的是规范,规范了可以调用哪些服务,实现哪些方法。
- 抽象类体现的时模板化设计,这个抽象类可以看作中间件产品,等待子类具体实现。
使用方式上:
- 接口里只能有静态方法和静态变量,抽象类既可以有静态方法也可以有普通方法。
- 接口不能包含构造器,抽象类可以有。
- 抽象类有构造方法;接口没有构造方法
- 抽象类属于继承,只能继承一个;接口可以实现多个
(十五)String、StringBuffer、StringBuilder区别:
String: final 修饰,不可变。修改实质是生成新对象,然后把指针指向新的引用对象。
StringBuffer: 可变并且线程安全。
StringBuiler 可变但线程不安全。
使用范围: 少量字符String;单线程大量用StringBuilder;多线程大量用 StringBuffer。
(十六)执行顺序问题:
先静态在普通。先代码块,再构造器,载普通方法。先父类再子类。
静态代码块 > 构造块 > 构造方法。
三者叠加:
父类静态变量>父类静态代码块
子类静态变量>子类静态代码块
父类普通变量>父类普通代码块>父类构造函数
子类普通变量>子类普通代码块>子类构造函数
(十七)static关键字:
- static修饰成员:static修饰的成员变量 称之为静态变量或类变量。
- static修饰方法:调用该方法只需类名.方法名;静态方法不依赖于任何对象就可以进行访问。
- static修饰代码块:在类初次被加载的时候,会按照static块的顺序来依次执行每个static块,并且只会执行一次。
- static修饰内部类:静态内部类不能直接访问外部类的非静态成员,但,可以通过new 外部类().成员的方式访问。
(十八)说说你对Java反射机制的理解:
- (Java程序对对象表现出两种类型既编译时类型和运行时类型。例如Person p=new
Student(),编译时类型时为person,运行时必须通过反射机制获取出对象为Student类型。 - 通过反射机制可以实现如下三种操作:
① 获取类对象
② 获取实例对象
③ 生成类的动态代理类或动态代理对象。 - 应用场景:
① JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序
② Eclispe、IDEA等开发工具利用反射动态解析对象的类型与结构,动态提示对象的属性和方法
③ Web服务器中利用反射调用了Sevlet的service方法
④ JDK动态代理底层依赖通过反射实现
二、集合:
(一)Java中有哪些容器:
1.两个接口: Collection和Map.
2.四大类:
Set:无序,不可重复的集合。
list:有序,可重复的集合。
Queue:代表先进先出的队列。
Map:代表有映射关系的集合。(key-value)
3.七结构: HashSet、TreeSet、ArrayList、LinkedList、ArrayDeque、HashMap、TreeMap
4.这七个结构都不是线程安全的。以Concurrent开头的容器都是线程安全的。
(二)List(3个对比):
1.ArrayList: 数组,默认大小 10 ,连续内存。
2.Vector : 数组,线程安全,扩容增2 倍。
3.LinkedList : 链表实现, 线程不安全。
4.比较: ArrayList实现是基于数组,LinkedList实现是基于双向链表。
对于随机访问查询,ArrayList是根据下标进行访问,比LinkedList只能按顺序访问要效率高
对于插入和删除操作,LinkedList要优于ArrayList因为元素要插入时,需要重新计算大小或者更新索引。
(三)Map(3个对比):
1.HashMap: 线程不安全。无序。底层:数组 + 链表 + 红黑树。
2.HashTable: 线程安全。无序。底层:数组 + 链表 。
3.TreeMap: 线程不安全。有序。底层:红黑树。
4.比较:
(1)HashTable与HashMap的区别
HashTable线程安全的,读写效率很低,Key不允许为null。
HashTable只对key进行一次hash,HashMap进行了两次Hash
HashTable底层:数组+链表,HashMap:底层:数组 + 链表 + 红黑树。
(四)Set(3个对比):
1、HashSet: 基于 HashMap ,K 作为元素存储,可为空。
2、TreeSet:基于红黑树,有序唯一,不可为空。
三、多线程:
(一)创建线程方式:
继承Thread类,实现runnable接口,实现Callable接口。
1.继承Thread类:
(1)定义Thread类的子类,重写run方法;
(2)创建Thread类的实例,既创建该对象。
(3)调用该线程对象的start方法并启动该线程。
2.实现runnable接口:
(1)定义runnable接口的实现类,并实现run方法,该run()方法作为线程执行体
(2)创建runnable子类的实例,并将其作为thread类的target对象
(3)调用该线程的start方法来启动该线程。
3.实现callable接口:
(1)创建callable接口的实现类,并实现call()方法,call()方法有返回值。
(2)使用FutureTask()类来包装callable对象,该对象封装了call()方法的返回值。
(3)使用futuretask对象作为thread的target的返回值创建并启动该线程
(4)调用futuretask的get()方法来获得该线程的返回值。
(二)死锁和形成的必要条件:
死锁:多个进程争夺同一进程。
互斥条件: 同一资源同时只能由一个线程读取
不可抢占条件: 不能强行剥夺线程占有的资源
请求和保持条件: 请求其他资源的同时对自己手中的资源保持不放
循环等待条件: 在相互等待资源的过程中,形成一个闭环
(三)Synchrpnized和lock的区别:
synchronized中文意思是同步,名词解释:可用来给对象或者代码块加锁,当它锁住一个方法或者代码块的时候,同一时刻最多有一个线程执行改代码。简而言之,被synchronized修饰的代码,同一时刻,最多有一个线程执行这个代码。
首先定义一个卖票的任务,我们不用synchronized代码,三个同步线程会同时卖出三张10号车票,但是加上之后就没了这个bug。
- Synchronized是一个Java关键字,JVM底层都帮我们做了。Lock是一个接口,是JDK底层有丰富的API
- Synchronized可以写在代码快上,方法上,Lock只能写在方法里面。
- Synchronized会自动释放锁,Lock必须手动释放;
- Synchronized是不可中断的,Lock是可中断的。
- Synchronized是非公平,Lock是公平/非公平。
(五)线程的生命周期:
(六)sleep()和wait()的区别:
- sleep()是Thread类中的静态方法,而wait()是Object类中的成员方法;
- sleep()可以在任何地方使用,而wait()只能在同步方法或同步代码块中使用
- leep()不会释放锁,而wait()会释放锁,并需要通过notify()/notifyAll()重新获取锁。
(七)volatile:
作用:变量修改后会立即同步到主存,每次用这个变量前会从主存刷新;
(八)乐观锁和悲观锁的区别:
悲观锁: 拿数据认为别人会改,都上锁,基于synchronized和Lock阻塞算法来实现的。
乐观锁: 拿数据认为不会改,不上锁,更新的时候判断别人会不会改。
(九)公平锁和非公平锁的区别:
- 公平锁排队,非公平所插队。
- 实现锁的两种方式:Synchronized和ReentranLock。
四、JVM:
(一)JVM通常包含哪几个部分:
类加载器,运行时数据区,执行引擎,本地库接口。
类加载器:只负责加载类文件。
执行引擎:负责执行程序,执行之后的指令集给操作系统。
运行数据区: 五部分:Heap堆,Stack虚拟机栈,PCRegister程序计数器,method area方法区,native method stack本地方法栈
本地方法栈:通过执行引擎给操作系统用。为JVM需要调用的本地方法时服务的。
(二)JAVA内存的分布情况:
Java根据内存分布情况把运行时数据区分为5部分:堆,虚拟机栈,本地方法栈,方法区,程序计数器。
堆: 几乎所有对象放在堆中,最大的内存区域。
虚拟机栈: 栈是用来形容方法执行过程中的线程过程模型。线程私有
本地方法栈: 虚拟机栈为执行的Java方法服务。本地方法栈为Java虚拟机的方法执行时调用本地方法服务。
方法区: 存储类加载信息,常量静态变量等
程序计数器: 内存特别小记录各个执行过程中执行到的行数。线程私有。
(三)双亲委派机制:
类加载器收到类加载的请求后,每次加载自己时,都允许父类进行先加载,这样保证Java方法最顶级的父类是一样的,也就是说最基本的方法都是一样的。
(四)GC算法
标记-清除算法: 先标记堆中所有需要清除的对象再进行清除。
缺点:
- 需要标记清除的对象很多时,标记和清除的效率会越来越低。
- 产生很多的标记清除后的小对象碎片,对于大对象很不友好。
标记复制算法:
就是把内存分半,在标记清除之后,把存活的对象统一整理到另一半内存中。减少碎片化空间。缺点:减少了空间占用。
标记整理算法:
标记后的存活对象向一端移动,移动之后,把边界外的空间在清空一遍,防止碎片。在标记清除算法之后不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。
五、接下来的问题:
1、计算机网络:TCP,http/https,三次握手四次挥手。
2、常见开发框架系列:Spring,Spring MVC,MyBatis,VUE,MyBatisPlus。
3、工具:说说工作中Linux,Git和SVN的常用命令。
4、从来没了解过的:Redis,Zookerper,Spring Cloud,RocketMQ,Docker。