参考 公众号 Java团长~~~
以下是我校招面试会问的问题及答案,大部分公司问的都差不多,导致当时某人对答如流~~~
答:JRE 是Java的 运行环境,JDK 是Java的 开发环境和运行环境。
其实JDK包含JRE ,如果你只要运行Java程序 ,只需要安装 JRE即可,但如果要 编写Java程序 ,就需要 安装JDK了。
- ==
基本数据类型: 比较的值 是否 相等;
引用数据类型:比较的 引用 是否相等; - equals
一般情况下比较的是值是否相等。
不一定,两个对象的 hashCode相同,则 equals不 一定为 true;
因为 hashCode 相同只是代表 hash值相同,然而 hash值相同,并不代表 得出的键值对 相等。
- final 标识的类是最终类,不能被继承
- final 标识的方法 是 最终方法,不能被重写
- final 标识的变量叫常量,值不能被修改;
byte,char ,short,long,double,float,int,boolean,
String 是 对象
操作字符串的有 String,StringBuffer,StringBuilder.
- String : String 声明的是不可变的对象,对其操作都会产生新的对象,然后指针指向新的对象。
- StringBuffer: 声明的是可变对象,可以对值进行修改,但不会产生新的对象
它是线程安全的,对线程可以使用 StringBuffer - StringBuilder.: 声明的是可变对象,可以对值进行修改,但不会产生新的对象
它是线程不安全的 ,单线程使用 StringBuilder,
StringBuilder 的性能 > StringBuffer.
7、String str="i"与 String str=new String(“i”)一样吗?不一样 。内存的分配方式不一样
String str=“i” ,分配到了 常量池中
String str=new String(“i”) 分配到了 堆内存中
抽象类用 abstract标识,可以有抽象方法,普通类不能用抽象方法,
抽象类不能直接实例化,普通类可以实例化。
抽象类不能被 final 标识,因为其就要被继承使用,final 标识后就不能被继承了;
普通类可以被 final 标识。
实现:抽象类用 extend 来继承,接口用 implements 来实现;
构造方法,抽象类可以有 构造方法,接口不能有;
main 抽象类可以有main 方法,接口不能有;
实现数量 类 可以实现多个接口,但只能 继承一个抽象类
方法体:接口中的方法定义为default或static或private方法,它就可以有方法体,抽象类的抽象方法不能有 方法体。
List:ArrayList,LinkedList
Set:HashSet,TreeSet
Map:HashMap,TreeMap,HashTable;
Collection 是一个集合的接口,提供了对集合操作的通用方法,
Collections 是集合类的 工具类,提供了一些静态方法,对集合对象进行操作。
HashTable 是同步的,HashMap 是不同步的,HashMap 比 HashTable 效率高。
HashMap 允许有空键值,HashTable 不允许有空键值。
HashTable 是线程安全的
在 Map 中 插入 删除 定位元素 用 HashMap;
对有序的key的集合进行遍历,用 TreeMap
HashMap 在put 元素的时候,先根据元素的HashCode计算出他的hash值,再根据hash值得到在Map中的下标,如果该位置有元素,就在该位置采用链表的形式,新的放表头,当链表的结点数量超过8个之后,链表会转为 红黑树在存放数据,如果该位置没有元素则直接放进去。
16、HashSet的实现原理- HashSet 底层是有HashMap 实现的
- HashSet 的值存放在 HashMap 的 key上
- HashMap 的 value 统一为 present;
ArrayList 是 底层是数组 ,便于查询元素,直接通过下标进行查询,不便于插入删除,每次插入删除元素,其他元素会移动。
LinkedList 底层是链表;,便于插入删除元素,直接改变链表指针的指向元素,不便于查询,查询的话需要指针一个个的查询,效率低;
- Array 数组可以容纳基本类型和对象,ArrayList集合 只能容纳对象
- Array 指定大小,ArrayLIst 是固定大小的。
同步:完成一个 在做下一个
异步:任务一起接,那个完成 就输出哪个
并发和并行表示的是CPU执行多个任务的方式
并行:多个事件在同一时刻同时发生,系统必须有多个CPU,在不同的CPU上运行不同的任务,任务之间不抢占资源。
并发: 多个事件在 同一时间段内同时发生 ,如听音乐和打游戏同时在一个CPU上进行,采用时间片轮转的方式进行任务调度,
形象解释:
并发:你在吃饭的过程中,吃了米饭、牛肉、羊肉, 这个过程就可以看作是并发,对你来说是同时进行的(吃饭),但你是在吃不同食物直接切换的
并行:你和我同时吃饭,你吃了米饭羊肉,我也吃了米饭羊肉,我们可以看做是并行的。我们在同一时间点吃饭,互不影响。
一个CPU同时做多个事 是并发,多个CPU 同时做多个事,是并行
一个程序至少有一个进程,一个进程至少有一个线程
21、创建线程的方式-
继承Thread类 — >创建 线程类
线程类继承Thread 重写其run方法,run方法里就是线程的方法体,new 线程类创建线程类对象,调用 start方法启动线程类 -
通过 Runnable接口 创建线程类
线程类 实现 Runnable接口,重写其 run方法,实例化 该线程类,start 启动线程 -
通过 Callable 和 Future 创建线程 【做了解】
线程类实现 Callable 接口,重写其 call 方法,这个是有返回值的,实例化该线程类 ,使用get方法获取其返回值
runnable 的run 方法没有返回值
callable 的 call 方法有返回值的
五大状态:
创建、生成线程对象,没有执行 start方法
就绪、执行 start 方法,等待线程调度,在等待和睡眠回来后 也是这个状态
运行、执行 该线程
阻塞、线程运行中,阻塞、暂停、睡眠的时状态
死亡:线程 run方法执行结束,或调用 stop方法后线程死亡
sleep:使线程进入 睡眠状态、当一个synchronized块中调用了sleep() 方法,对象锁没有被释放,其他线程依然无法访问这个对象,sleep 睡眠时间到后会自动进入 就绪状态,等待 线程调度
wait()::使线程进入等待状态,同时 释放锁对象,需要使用 notify 或者 notifyAll 来唤醒等待的线程
notify() :随机唤醒一个等待的线程
notifyAll():唤醒全部线程
-
原子性 :同一时刻 只能有体格线程对对象进行访问 ,可使用 synchronized 锁
-
可见性: 一个线程的修改对其他线程可见,可使用 volatile 标识
-
有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)。
在多线程中,多个线程对一个资源竞争 产生的一个阻塞的状态,若无外力作用,无法继续下去,称为死锁。
28、怎么防止死锁产生死锁的必要条件:
-
互斥条件:进程 对 分配的资源不允许其他进程访问,如果要访问,只能等该进程使用完成,释放资源l
-
请求保持条件:进行获得一定资源,又向其他资源发出请求,但该资源被占用,此时请求阻塞,又对以获取的资源保持不放。
-
不可剥夺条件:进程以获取的资源,在未完成使用之前,不可剥夺其使用权,除了使用完成,自动释放
-
环路等待条件:进程发生死锁,若干个进程之间形成一种头尾相连的循环等待资源的关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之 一不满足,就不会发生死锁。
29、synchronized同步锁 和 volatile总结死锁原因:进程分配的资源,其他进程不能访问,也不能剥夺其使用权。一个进程对自己的资源保持不放 ,又去请求被其他进程占用的资源,从而陷入等待状态 就会进入死锁。
synchronized 保证同一时刻只有一个方法进入 临界区【可能会造成堵塞】,还能保证变量的可见性。可以表示变量、方法、类
volatile :标识变量,其的改变对其他线程是可见的。
反射:在Java运行时环境中,对于任意一个类都能知道它的属性和方法,对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。
功能:
- 在运行时判断任意对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断一个类所具有的成员变量和方法
- 在运行时调用任意对象的方法
序列化:将 Java 对象转换成字节流的过程。
反序列化:将字节流转换成 Java 对象的过程。
当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。
序列化的实现:类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化。
注意事项:
- 某个类可以被序列化,则其子类也可以被序列化
- 声明为 static 和 transient 的成员变量,不能被序列化。static 成员变量是描述类级别的属性,transient 表示临时数据
- 反序列化读取序列化对象的顺序要保持一致



