Java基础学习记录

**Java基础学习记录**

为什么重写equals还要重写hashcode?

首先,任何对象的Hashcode的值都是不相等的,如果只重写equals不重写Hashcode,就会导致相同的key值也被hashcode认为是不同的key值(因为没有重写hashCode(),则任何对象的hashCode()值都不相等),就会在hashmap中存储相同的key值(map中key值不能相同),这就不符合条件了。

final关键字

类:修饰后该类不可被继承(比如String)

方法:修饰后该方法不可被重写;

变量:修饰后该变量必须被初始化,且初始化后不能在被修改;

Java中操作字符串的的类有哪些

有String、StringBUffer、StringBuilder;其中String声明的是不可变的对象,一次赋值后,再次赋值引用指针会指向新的内容,初始值将会被冲掉;

StringBuffer和StringBuilder都是声明的可变的对象;但是StringBUffer是线程安全的,而StringBuilder则是线程不安全的;但StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

快速字符串反转

StringBuilder 或者 String Buffer的reverse方法

抽象类和普通类的区别

抽象方法

普通类不可以包含,抽象类可以

直接实例化

普通类可以,抽象类不可以

抽象类和接口的区别

实现

抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。

构造函数

抽象类可以有构造函数;接口不能有.

可被实现的数量

一个类可以实现很多个接口;但是只能继承一个抽象类。

访问修饰符

接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。

BIO、NIO、AIO 有什么区别?(Java的IO模型)

BIO 是同步阻塞时IO,传统的IO,特点使用方便,并发处理能力低;

NIO 是同步非阻塞式IO,是传统IO的升级,客户端和服务端通过通道通讯,实现了多路复用;

AIO 是NIO的升级,实现了异步非阻塞式IO,异步IO的操作基于事件和回调机制;

collection 和 collections 有什么区别

collection 是一个集合接口,它提供了对集合对象进行基本操作的通用方法,所有集合都是其子类;

collections 是一个包装类,类似一个工具类,不能直接实例化。比如,sort函数;

集合

List 、Set、Map 之间的区别是什么?

元素是否有序

list集合是有序的,TreeSet以及TreeMap元素是有序的;HashSet和HashMap元素不允许重复;

是否允许元素重复

list集合允许元素的重复,set集合不允许元素的重复,Map集合中Key必须唯一,Value可以重复;

HashMap 和 Hashtable 有什么区别?

HashTable不允许key和value为空,而HashMap允许;HashTable线程安全,但效率低,容易阻塞,hashMap线程不安全;

ConcurrentHashMap 和 HashTable的区别?

ConcurrentHashMap

是一个非阻塞式的,更新数据时会锁柱部分数据,不会锁住整张表;效率高,但是,get的时候会有延迟(多线程模式,同一时刻,get和put同时使用)

HashTable

任何操作都会锁住整张表,所以会造成阻塞,同一时刻put允许,get需要等待,效率较低 ;

如何决定使用 HashMap 还是 TreeMap?

对于在 Map 中插入、删除、定位一个元素这类操作,HashMap 是最好的选择,因为相对而言 HashMap 的插入会更快,但如果你要对一个 key 集合进行有序的遍历,那 TreeMap 是更好的选择。

说一下 HashMap 的实现原理?

HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。

说一下 HashSet 的实现原理?

HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,将传入的元素存储到Map的Key中,value是一个final的Object对象,所以,HashSet 不允许重复的值。相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,

ArrayList 和 LinkedList 的区别是什么?

ArrayList

底层实现

动态数组

效率

查询或者读取快,增删改慢

LinkList

底层实现

双向链表

效率

查询慢,增删改快

ArrayList 和 Vector 的区别是什么?

线程安全:

Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。

性能:

ArrayList 在性能方面要优于 Vector。

扩容:

ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。

Array 和 ArrayList 有何区别?

• Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。

• Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。

• Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。

在 Queue 中 poll()和 remove()有什么区别?

• 相同点:都是返回第一个元素,并在队列中删除返回的对象。

• 不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。

哪些集合类是线程安全的?

Vector、Hashtable、Stack ConcurrentHashMap。

怎么确保一个集合不能被修改?

可以使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java. lang. UnsupportedOperationException 异常。

多线程

并行和并发有什么区别?

• 并行:多个处理器或多核处理器同时处理多个任务。

• 并发:多个任务在同一个 CPU 核上,按细分的时间片轮流(交替)执行,从逻辑上来看那些任务是同时执行。

  1. 并发 = 两个队列和一台咖啡机。
  2. 并行 = 两个队列和两台咖啡机。

线程和进程的区别?

一个程序下至少有一个进程,一个进程下至少有一个线程,一个进程下也可以有多个线程来增加程序的执行速度

守护线程是什么?

守护线程是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。在 Java 中垃圾回收线程就是特殊的守护线程。

创建线程有哪几种方式?

创建线程有三种方式:

• 继承 Thread 重写 run 方法;

• 实现 Runnable 接口;

• 实现 Callable 接口;

说一下 runnable 和 callable 有什么区别?

runnable 没有返回值,callable 可以拿到有返回值,callable 可以看作是 runnable 的补充。

线程有哪些状态?

sleep() 和 wait() 有什么区别?

• 类的不同:sleep() 来自 Thread,wait() 来自 Object。

• 释放锁:sleep() 不释放锁;wait() 释放锁。

• 用法不同:sleep() 时间到会自动恢复;wait() 可以使用 notify()/notifyAll()直接唤醒。

notify() 和 notifyAll() 有什么区别?

notifyAll() 会唤醒所有的线程,notify() 只会唤醒一个线程。notifyAll() 调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而 notify()只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。

线程的 run() 和 start() 有什么区别?

start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复调用,而 start() 只能调用一次。

创建线程池有哪几种方式?

ThreadPoolExecutor():是最原始的线程池创建,上面1-3创建方式都是对ThreadPoolExecutor的封装。

线程池都有哪些状态?

• RUNNING:这是最正常的状态,接受新的任务,处理等待队列中的任务。

• SHUTDOWN:不接受新的任务提交,但是会继续处理等待队列中的任务。

• STOP:不接受新的任务提交,不再处理等待队列中的任务,中断正在执行任务的线程。

• TIDYING:所有的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()。

• TERMINATED:terminated()方法结束后,线程池的状态就会变成这个。

线程池中 submit() 和 execute() 方法有什么区别?

• execute():只能执行 Runnable 类型的任务。

• submit():可以执行 Runnable 和 Callable 类型的任务

在 Java 程序中怎么保证多线程的运行安全?

• 方法一:使用安全类,比如 Java. util. concurrent 下的类。

• 方法二:使用自动锁 synchronized。

• 方法三:使用手动锁 Lock。

多线程中 synchronized 锁升级的原理是什么?

synchronized 锁升级原理:在锁对象的对象头里面有一个 threadid 字段,在第一次访问的时候 threadid 为空,jvm 让其持有偏向锁,并将 threadid 设置为其线程 id,再次进入的时候会先判断 threadid 是否与其线程 id 一致,如果一致则可以直接使用此对象,如果不一致,则升级偏向锁为轻量级锁,通过自旋循环一定次数来获取锁,执行一定次数之后,如果还没有正常获取到要使用的对象,此时就会把锁从轻量级升级为重量级锁,此过程就构成了 synchronized 锁的升级。

锁的升级的目的:锁升级是为了减低了锁带来的性能消耗。在 Java 6 之后优化 synchronized 的实现方式,使用了偏向锁升级为轻量级锁再升级到重量级锁的方式,从而减低了锁带来的性能消耗。

什么是死锁?

当线程 A 持有独占锁a,并尝试去获取独占锁 b 的同时,线程 B 持有独占锁 b,并尝试获取独占锁 a 的情况下,就会发生 AB 两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁

怎么防止死锁?

• 尽量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。

• 尽量使用 Java. util. concurrent 并发类代替自己手写锁。

• 尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。

• 尽量减少同步的代码块。

怎么防止死锁?

• 尽量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。

• 尽量使用 Java. util. concurrent 并发类代替自己手写锁。

• 尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。

• 尽量减少同步的代码块。

ThreadLocal 是什么?有哪些使用场景?

ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
ThreadLocal 的经典使用场景是数据库连接和 session 管理等。

synchronized 和 Lock 有什么区别?

• synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。

• synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不当没有 unLock()去释放锁就会造成死锁。

• 通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。

synchronized 和 ReentrantLock 区别是什么?

• ReentrantLock 使用起来比较灵活,但是必须有释放锁的配合动作;

• ReentrantLock 必须手动获取与释放锁,而 synchronized 不需要手动释放和开启锁;

• ReentrantLock 只适用于代码块锁,而 synchronized 可用于修饰方法、代码块等。

反射

什么是反射?

反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制

什么是 Java 序列化?什么情况下需要序列化?

Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来。
以下情况需要使用 Java 序列化:

• 想把的内存中的对象状态保存到一个文件中或者数据库中时候;

• 想用套接字在网络上传送对象的时候;

• 想通过RMI(远程方法调用)传输对象的时候。

深拷贝和浅拷贝区别是什么

深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
假设B复制了A,修改A的时候,看B是否发生变化:

如果B跟着也变了,说明是浅拷贝,拿人手短!(修改堆内存中的同一个值)

如果B没有改变,说明是深拷贝,自食其力!(修改堆内存中的不同的值)

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务