jre和jdk区别
jdk(java development kit) 开发工具
- 基本类库
- javac
- javap
- javadoc
- 运行环境 jre(java runtimr environment):单单运行一个java程序,只安装jre即可
==与equals的区别
- ==:
- 基本类型(8种):short int long float double byte boolen char 比较值相等。
- 引用类型:比较的是地址,看引用的对象是不是同一个
- equals:
- 重写object的equals方法:自己定义比较规则。我们常见的对象都已经重写了equals方法
- 不重写object的equals方法:就是比较引用地址是否相同,相当与==
解释: object下面的一个方法。 如果没重写这个方法,那么比较的是地址。
如果重写了这个方法,比如string这个类型的对象重写了这个方法,不再比较地址了。
string a="abf"; string b=new string("abf"); a.equals(b); //true
hashcode和equals相同吗
final有什么作用
final作用在类、方法、变量上
- 类:不能被继承
- 方法:不能被重写
- 变量:基本类型的话:值不能变;引用类型:地址不可变,引用的对象内部的值可以变
操作字符串有那些类?他们之间的区别
- String:值不可变
- StringBuilder:值可变,不加锁,不安全,速度快
- StringBuffer:值可变,加锁synchronized,线程安全
string a="qwe";
a="wer";
//stringPool["que","wer"];
//方法区里面有一个字符串常量池,“que”放到常量池里面,a直接指向“quw”,a再指向“wer”,如果常量池有“wer”,就指向,没有的话就创建哥“wer”,然后a指向“wer”
StringBuilder sb=new StringBuilder();
StringBuffer sb2=new StringBuffer();
//StringBuilder和StringBuffer都继承AbstractStringBuilder类,他们两个值改变,其实是改变里面都数组都值,比如append方法,源码如下
java种的math.round(-1,5)等于多少
答案:-1
- round:返回四舍五入,负.5小数返回较大整数,如-1.5返回-1。
- ceil:返回小数所在两整数间的较大值,如-1.5返回-1。
- tail:返回小数所在两整数间的较小值,如-1.5返回-2。
java种的math.round(1,5)等于多少 --2
hashmap和hashtable的区别
都是map的实现类,都是存储键值对的<key,value>
|_hashMap:线程不安全,速度快。允许放入空值,hashmap.put(null.null)。
|_hashtable:加锁,线程安全,速度相对慢。不允许放空值。
简单聊一聊hashmap
- 存储结构:entry的数组,entry<key,value>,entry本身也是一种链表结构,长度大于等于8,变成红黑树。
- 存储逻辑:根据计算hash值放到对应位置。
- 扩容方案:达到域值的话,进行扩容,自身容量扩大一倍,成倍增长
Vector和ArrayList的区别
都实现了List的接口。
- Vector:加锁,线程安全。扩容:2倍增长。
- ArrayList:线程不安全。扩容:1.5倍增长
为什么Vector用的少: 1.线程安全,牺牲了速度 2.扩容大,需要连续存储空间比较大 3.因为内部是一个数组,所以插入、删除比较慢。可以用LinkedList来实现快速插入删除操作
java虚拟机之JVM内存区域
java虚拟机之Java类加载机制
类的生命周期、类的加载过程
类加载器
java虚拟机之垃圾回收机制
1.什么是垃圾回收
对资源有效利用。资源:java运行内存,垃圾:不再被使用但是还残留在内存中对对象。
2.java内存很大,残留在哪块内存里面呢?
- 线程私有:虚拟机栈、程序计数器、本地方法栈(随着线程创建而被开辟出来,线程一旦结束,这些内存会被释放。不需要垃圾回收)
- 线程共有:堆、方法区(99%的对象实例都是被存放在堆里面的)
3.什么样子的对象被视为垃圾?
1.引用计数器算法
堆中每个对象都有一个计数器,当对象被被其他对象引用时,计数器+1,当引用失效时-1,如果引用计数器为0时,该对象就会被回收。 缺点:当两个对象互相引用,而他们两个没有被用到时,这两个对象不会被回收。
2.可达性分析算法
以GCRoot作为起点开始搜索,在引用链上的对象不可被回收,不在引用链上的对象可以被回收。
哪些可以作为GCRoot对象呢?
- 活的线程
- 方法区中的静态变量和常量引用的对象
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 本地方法栈中(即一般说的native方法)引用的对象
垃圾回收算法
- 标记-清除:产生内存碎片
描述:把可回收的内存进行标记,然后直接回收
- 复制:又一半空间被浪费
描述:把内存分成一半一半,把存活的内存全部放到另一半上,这样原先的内存剩下的都是可回收的,然后进行回收。
- 标准-整理:速度比较慢
描述:把可回收和不可回收的标记,然后将内存移动整理成一大块整体连续的内存,把另一边可回收的内存回收。
- 分代回收算法:
- 新生代(存活时间短的对象):复制算法
- 老生代(存活时间长的对象):标记清除算法、标记整理算法
线程和进程区别
- 进程:是系统运行分配和管理资源的单位
- 线程:进程的一个执行单位,是进程内调度的实体、是CPU调度和分配的基本单位,是比进程更小的独立运动的基本单位。线程也被称为轻量级进程,线程是执行程序的最小的单位。
一个程序至少一个进程,一个进程至少一个线程。
进程有自己独立地址空间,每启动一个进程,系统就会为他分配地址空间,建立数据表来维护代码段、堆栈段、数据段,这种操作非常昂贵。 而线程共享进程中的数据的,使用相同的地址空间,因此cpu切换一个线程的花费远比进程要小很多,同时创建一个线程的开销比进程要小很多。
多线程之线程的三种创建方式
- 重写Thread的run方法
- 实现runnable
- 实现callable
runnable和callable
callable是runnable的延伸,callable接口可以返回结果值,需要在定义的时候执行类型
线程的六种状态
- new :初始化态/新建状态。线程创建且没有执行start方法时的状态。
Thread a= new Thread();
- runnale:可运行状态。
-
- ready:可运行状态/准备态,线程已经启动,但是等待相应的资源(比如IO或者时间片切换)才能开始执行
-
- running:运行态,线程获取了CPU,执行程序代码。
-
a.start();
- blocked:阻塞态。 运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中
- waiting 运行(running)的线程执行wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
- timed_waiting:超时等待。等待固定的时间,比如wait(3000)
- terminated:结束态。线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
多线程之 wait 、sleep、yield的区别
-
sleep:
- 暂停当前线程执行,但是不释放锁
- sleep是在thread中的一个静态方法,thread.sleep();
- sleep可以在任何场景下使用
- 只有睡够时间才能醒
-
wait
- 暂停当前线程执行,但是释放锁
- wait是Object的对象,object.wait
- wait只能在同步代码块中使用
- wait可以随时唤醒(notify、notifyAll)
- yield
- 给相同优先级的线程让出 cpu 资源,让步的线程还有可能被线程调度程序再次选中。如果没有相同优先级的线程,那么它还是会得到执行。
线程同步的方法
线程同步概念:即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,实现线程同步的方法有很多,临界区对象就是其中一种。
用synchronized关键字。因为java为每一个对象都设置了内置锁,当使用synchronized关键字修饰方法时,内置锁就会保护这个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
- 非静态方法:锁住的是当前对象
- 静态方法,此时如果调用该静态方法,将会锁住整个类。
- 代码块:同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。
//锁代码块的几种情况
public void test(){
//传this,是对象锁
synchronized (this) {
// TODO
}
}
public void method2(){
//传类,类锁。作用:这个类的所有对象
synchronized (ObjectLock.class) {
try {
System.out.println("do method2..");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private Object lock = new Object();
public void method3(){ //任何对象锁
synchronized (lock) {
try {
System.out.println("do method3..");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
多线程之java线程池
多线程之生产者-消费者模型
生产者生产数据,消费者消费数据。生产者和消费者数据共享。内存满的时候,需要生产者需要等待,内存中没有数据时候,消费者需要等待。
volatile关键字
原子性&&可见性
可见性:当一个线程修改了线程共享变量的值,其它线程能够立即得知这个修改。用volatile 原子性:一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行。用锁。
java中实现多态的机制是什么
靠的是父类的引用指向子类的对象(多态性)。调用的方法是内存中正在运行的那个对象的方法,若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法。
异常分为哪些种类
编译时异常、运行时异常
java异常处理机制
finally里面有异常
finally return
1.public int getNum(){
2. try {
3. int a = 1/0;
4. return 1;
5. }catch (Exception e){
6. return 2;
7. }finally{
8. return 3;
9. }
代码在走到第 3 行的时候遇到了一个 MathException,这时第四行的代码就不会执行了,代码直接跳转到 catch 语句中,走到第 6 行的时候,异常机制有这么一个原则如果在 catch 中遇到了 return 或者异常等能使该函数终止的话那么有 finally 就必须先执行完 finally 代码块里面的代码然后再返回值。因此代码又跳到第 8 行,可惜第 8 行是一个 return 语句,那么这个时候方法就结束了,因此第 6 行的返回结果就无法被真正返回。如果 finally 仅仅是处理了一个释放资源的操作,因此上面返回值是3。
finally和return
如何将java对象序列化到文件里
泛型原理,并举例
泛型中extends和super区别
抽象类和接口的区别
抽象类 :
- 抽象类不可以被实例化,实例化由子类去完成
- 抽象方法必须由子类重写(非抽象子类,抽象子类可不重写)
- 只要有抽象方法,就是抽象类
- 可以实现具体的方法,也可以不实现
- abstract 不能与private、static、final或native并列修饰同一个方法
- 可以和普通方法一样有成员变量,常量等。
接口:
- interface 是 public 的
- 接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误)
- 接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。java 8 以后可以加 default 关键字实现方法
- 不能使用new操作符实例化一个接口,但可以声明一个接口变量,该变量必须引用(refer to)一个实现该接口的类的对象。
- 可以使用 instanceof 检查一个对象是否实现了某个特定的接口。例如:if(anObject instanceof Comparable){}
- 在实现多接口的时候一定要避免方法名的重复
区别:
- 抽象类不能被多继承,接口可以被多实现。也可以被多继承。
- 抽象类是对类抽象,而接口是对行为的抽象
- 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型; 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法。
string转乘integer的方式和原理
哈希冲突
容器(hashmap、hashset、linkedList、hashset)
java反射的理解
什么是线程池,如何使用,为什么使用
java引用类型有哪些
blog.csdn.net/baidu_22254… Java中4种引用的级别和强度由高到低依次为:强引用 -> 软引用 -> 弱引用 -> 虚引用 ①强引用(StrongReference) ②软引用(SoftRefernce) ③弱引用(WeakReference) ④虚引用(PhantomReference)
- 强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。
- 如果一个对象只具有软引用,则内存空间充足时,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。
- 软引用可以和一个引用队列(ReferenceQueue)联合使用。如果软引用所引用对象被垃圾回收,JAVA虚拟机就会把这个软引用加入到与之关联的引用队列中。
- 弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
- 同样,弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。可见WeakReference对象的生命周期基本由垃圾回收器决定,一旦垃圾回收线程发现了弱引用对象,在下一次GC过程中就会对其进行回收
- 虚引用顾名思义,就是形同虚设。与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。
重载和重写的区别
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。
设计模式
单例模式
饿汉式 (可用)
就是在类定义的时候就实例化了(因为饿,主观能动性强 - . -)。
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
普通的懒汉式 (线程不安全,不可用)
这种写法有个致命的问题,就是多线程的安全问题。假设对象还没被实例化,然后有两个线程同时访问,那么就可能出现多次实例化的结果,所以这种写法不可采用。
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
同步方法的懒汉式 (可用)
这种写法是对getInstance()加了锁的处理,保证了同一时刻只能有一个线程访问并获得实例,但是缺点也很明显,因为synchronized是修饰整个方法,每个线程访问都要进行同步,而其实这个方法只执行一次实例化代码就够了,每次都同步方法显然效率低下,为了改进这种写法,就有了下面的双重检查懒汉式。
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重检查懒汉式 (可用,推荐)
这种写法用了两个if判断,也就是Double-Check,并且同步的不是方法,而是代码块,效率较高,是对第三种写法的改进。为什么要做两次判断呢?这是为了线程安全考虑,还是那个场景,对象还没实例化,两个线程A和B同时访问静态方法并同时运行到第一个if判断语句,这时线程A先进入同步代码块中实例化对象,结束之后线程B也进入同步代码块,如果没有第二个if判断语句,那么线程B也同样会执行实例化对象的操作了。
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
静态内部类 (可用,推荐)
因为类的静态属性只会在第一次加载类的时候初始化,也就保证了SingletonInstance中的对象只会被实例化一次,并且这个过程也是线程安全的。
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
观察者模式
实现:
适配器模式
装饰器模式
实现:
代理模式